pds_core: pass opcode to devcmd_wait
[sfrench/cifs-2.6.git] / drivers / net / ethernet / amd / pds_core / dev.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
3
4 #include <linux/errno.h>
5 #include <linux/pci.h>
6 #include <linux/utsname.h>
7
8 #include "core.h"
9
10 int pdsc_err_to_errno(enum pds_core_status_code code)
11 {
12         switch (code) {
13         case PDS_RC_SUCCESS:
14                 return 0;
15         case PDS_RC_EVERSION:
16         case PDS_RC_EQTYPE:
17         case PDS_RC_EQID:
18         case PDS_RC_EINVAL:
19         case PDS_RC_ENOSUPP:
20                 return -EINVAL;
21         case PDS_RC_EPERM:
22                 return -EPERM;
23         case PDS_RC_ENOENT:
24                 return -ENOENT;
25         case PDS_RC_EAGAIN:
26                 return -EAGAIN;
27         case PDS_RC_ENOMEM:
28                 return -ENOMEM;
29         case PDS_RC_EFAULT:
30                 return -EFAULT;
31         case PDS_RC_EBUSY:
32                 return -EBUSY;
33         case PDS_RC_EEXIST:
34                 return -EEXIST;
35         case PDS_RC_EVFID:
36                 return -ENODEV;
37         case PDS_RC_ECLIENT:
38                 return -ECHILD;
39         case PDS_RC_ENOSPC:
40                 return -ENOSPC;
41         case PDS_RC_ERANGE:
42                 return -ERANGE;
43         case PDS_RC_BAD_ADDR:
44                 return -EFAULT;
45         case PDS_RC_EOPCODE:
46         case PDS_RC_EINTR:
47         case PDS_RC_DEV_CMD:
48         case PDS_RC_ERROR:
49         case PDS_RC_ERDMA:
50         case PDS_RC_EIO:
51         default:
52                 return -EIO;
53         }
54 }
55
56 bool pdsc_is_fw_running(struct pdsc *pdsc)
57 {
58         pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
59         pdsc->last_fw_time = jiffies;
60         pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat);
61
62         /* Firmware is useful only if the running bit is set and
63          * fw_status != 0xff (bad PCI read)
64          */
65         return (pdsc->fw_status != 0xff) &&
66                 (pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING);
67 }
68
69 bool pdsc_is_fw_good(struct pdsc *pdsc)
70 {
71         bool fw_running = pdsc_is_fw_running(pdsc);
72         u8 gen;
73
74         /* Make sure to update the cached fw_status by calling
75          * pdsc_is_fw_running() before getting the generation
76          */
77         gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION;
78
79         return fw_running && gen == pdsc->fw_generation;
80 }
81
82 static u8 pdsc_devcmd_status(struct pdsc *pdsc)
83 {
84         return ioread8(&pdsc->cmd_regs->comp.status);
85 }
86
87 static bool pdsc_devcmd_done(struct pdsc *pdsc)
88 {
89         return ioread32(&pdsc->cmd_regs->done) & PDS_CORE_DEV_CMD_DONE;
90 }
91
92 static void pdsc_devcmd_dbell(struct pdsc *pdsc)
93 {
94         iowrite32(0, &pdsc->cmd_regs->done);
95         iowrite32(1, &pdsc->cmd_regs->doorbell);
96 }
97
98 static void pdsc_devcmd_clean(struct pdsc *pdsc)
99 {
100         iowrite32(0, &pdsc->cmd_regs->doorbell);
101         memset_io(&pdsc->cmd_regs->cmd, 0, sizeof(pdsc->cmd_regs->cmd));
102 }
103
104 static const char *pdsc_devcmd_str(int opcode)
105 {
106         switch (opcode) {
107         case PDS_CORE_CMD_NOP:
108                 return "PDS_CORE_CMD_NOP";
109         case PDS_CORE_CMD_IDENTIFY:
110                 return "PDS_CORE_CMD_IDENTIFY";
111         case PDS_CORE_CMD_RESET:
112                 return "PDS_CORE_CMD_RESET";
113         case PDS_CORE_CMD_INIT:
114                 return "PDS_CORE_CMD_INIT";
115         case PDS_CORE_CMD_FW_DOWNLOAD:
116                 return "PDS_CORE_CMD_FW_DOWNLOAD";
117         case PDS_CORE_CMD_FW_CONTROL:
118                 return "PDS_CORE_CMD_FW_CONTROL";
119         default:
120                 return "PDS_CORE_CMD_UNKNOWN";
121         }
122 }
123
124 static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)
125 {
126         struct device *dev = pdsc->dev;
127         unsigned long start_time;
128         unsigned long max_wait;
129         unsigned long duration;
130         int timeout = 0;
131         int done = 0;
132         int err = 0;
133         int status;
134
135         start_time = jiffies;
136         max_wait = start_time + (max_seconds * HZ);
137
138         while (!done && !timeout) {
139                 done = pdsc_devcmd_done(pdsc);
140                 if (done)
141                         break;
142
143                 timeout = time_after(jiffies, max_wait);
144                 if (timeout)
145                         break;
146
147                 usleep_range(100, 200);
148         }
149         duration = jiffies - start_time;
150
151         if (done && duration > HZ)
152                 dev_dbg(dev, "DEVCMD %d %s after %ld secs\n",
153                         opcode, pdsc_devcmd_str(opcode), duration / HZ);
154
155         if (!done || timeout) {
156                 dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n",
157                         opcode, pdsc_devcmd_str(opcode), done, timeout,
158                         max_seconds);
159                 err = -ETIMEDOUT;
160                 pdsc_devcmd_clean(pdsc);
161         }
162
163         status = pdsc_devcmd_status(pdsc);
164         err = pdsc_err_to_errno(status);
165         if (err && err != -EAGAIN)
166                 dev_err(dev, "DEVCMD %d %s failed, status=%d err %d %pe\n",
167                         opcode, pdsc_devcmd_str(opcode), status, err,
168                         ERR_PTR(err));
169
170         return err;
171 }
172
173 int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
174                        union pds_core_dev_comp *comp, int max_seconds)
175 {
176         int err;
177
178         memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
179         pdsc_devcmd_dbell(pdsc);
180         err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds);
181         memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
182
183         if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
184                 queue_work(pdsc->wq, &pdsc->health_work);
185
186         return err;
187 }
188
189 int pdsc_devcmd(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
190                 union pds_core_dev_comp *comp, int max_seconds)
191 {
192         int err;
193
194         mutex_lock(&pdsc->devcmd_lock);
195         err = pdsc_devcmd_locked(pdsc, cmd, comp, max_seconds);
196         mutex_unlock(&pdsc->devcmd_lock);
197
198         return err;
199 }
200
201 int pdsc_devcmd_init(struct pdsc *pdsc)
202 {
203         union pds_core_dev_comp comp = {};
204         union pds_core_dev_cmd cmd = {
205                 .opcode = PDS_CORE_CMD_INIT,
206         };
207
208         return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
209 }
210
211 int pdsc_devcmd_reset(struct pdsc *pdsc)
212 {
213         union pds_core_dev_comp comp = {};
214         union pds_core_dev_cmd cmd = {
215                 .reset.opcode = PDS_CORE_CMD_RESET,
216         };
217
218         return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
219 }
220
221 static int pdsc_devcmd_identify_locked(struct pdsc *pdsc)
222 {
223         union pds_core_dev_comp comp = {};
224         union pds_core_dev_cmd cmd = {
225                 .identify.opcode = PDS_CORE_CMD_IDENTIFY,
226                 .identify.ver = PDS_CORE_IDENTITY_VERSION_1,
227         };
228
229         return pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
230 }
231
232 static void pdsc_init_devinfo(struct pdsc *pdsc)
233 {
234         pdsc->dev_info.asic_type = ioread8(&pdsc->info_regs->asic_type);
235         pdsc->dev_info.asic_rev = ioread8(&pdsc->info_regs->asic_rev);
236         pdsc->fw_generation = PDS_CORE_FW_STS_F_GENERATION &
237                               ioread8(&pdsc->info_regs->fw_status);
238
239         memcpy_fromio(pdsc->dev_info.fw_version,
240                       pdsc->info_regs->fw_version,
241                       PDS_CORE_DEVINFO_FWVERS_BUFLEN);
242         pdsc->dev_info.fw_version[PDS_CORE_DEVINFO_FWVERS_BUFLEN] = 0;
243
244         memcpy_fromio(pdsc->dev_info.serial_num,
245                       pdsc->info_regs->serial_num,
246                       PDS_CORE_DEVINFO_SERIAL_BUFLEN);
247         pdsc->dev_info.serial_num[PDS_CORE_DEVINFO_SERIAL_BUFLEN] = 0;
248
249         dev_dbg(pdsc->dev, "fw_version %s\n", pdsc->dev_info.fw_version);
250 }
251
252 static int pdsc_identify(struct pdsc *pdsc)
253 {
254         struct pds_core_drv_identity drv = {};
255         size_t sz;
256         int err;
257
258         drv.drv_type = cpu_to_le32(PDS_DRIVER_LINUX);
259         snprintf(drv.driver_ver_str, sizeof(drv.driver_ver_str),
260                  "%s %s", PDS_CORE_DRV_NAME, utsname()->release);
261
262         /* Next let's get some info about the device
263          * We use the devcmd_lock at this level in order to
264          * get safe access to the cmd_regs->data before anyone
265          * else can mess it up
266          */
267         mutex_lock(&pdsc->devcmd_lock);
268
269         sz = min_t(size_t, sizeof(drv), sizeof(pdsc->cmd_regs->data));
270         memcpy_toio(&pdsc->cmd_regs->data, &drv, sz);
271
272         err = pdsc_devcmd_identify_locked(pdsc);
273         if (!err) {
274                 sz = min_t(size_t, sizeof(pdsc->dev_ident),
275                            sizeof(pdsc->cmd_regs->data));
276                 memcpy_fromio(&pdsc->dev_ident, &pdsc->cmd_regs->data, sz);
277         }
278         mutex_unlock(&pdsc->devcmd_lock);
279
280         if (err) {
281                 dev_err(pdsc->dev, "Cannot identify device: %pe\n",
282                         ERR_PTR(err));
283                 return err;
284         }
285
286         if (isprint(pdsc->dev_info.fw_version[0]) &&
287             isascii(pdsc->dev_info.fw_version[0]))
288                 dev_info(pdsc->dev, "FW: %.*s\n",
289                          (int)(sizeof(pdsc->dev_info.fw_version) - 1),
290                          pdsc->dev_info.fw_version);
291         else
292                 dev_info(pdsc->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n",
293                          (u8)pdsc->dev_info.fw_version[0],
294                          (u8)pdsc->dev_info.fw_version[1],
295                          (u8)pdsc->dev_info.fw_version[2],
296                          (u8)pdsc->dev_info.fw_version[3]);
297
298         return 0;
299 }
300
301 int pdsc_dev_reinit(struct pdsc *pdsc)
302 {
303         pdsc_init_devinfo(pdsc);
304
305         return pdsc_identify(pdsc);
306 }
307
308 int pdsc_dev_init(struct pdsc *pdsc)
309 {
310         unsigned int nintrs;
311         int err;
312
313         /* Initial init and reset of device */
314         pdsc_init_devinfo(pdsc);
315         pdsc->devcmd_timeout = PDS_CORE_DEVCMD_TIMEOUT;
316
317         err = pdsc_devcmd_reset(pdsc);
318         if (err)
319                 return err;
320
321         err = pdsc_identify(pdsc);
322         if (err)
323                 return err;
324
325         pdsc_debugfs_add_ident(pdsc);
326
327         /* Now we can reserve interrupts */
328         nintrs = le32_to_cpu(pdsc->dev_ident.nintrs);
329         nintrs = min_t(unsigned int, num_online_cpus(), nintrs);
330
331         /* Get intr_info struct array for tracking */
332         pdsc->intr_info = kcalloc(nintrs, sizeof(*pdsc->intr_info), GFP_KERNEL);
333         if (!pdsc->intr_info) {
334                 err = -ENOMEM;
335                 goto err_out;
336         }
337
338         err = pci_alloc_irq_vectors(pdsc->pdev, nintrs, nintrs, PCI_IRQ_MSIX);
339         if (err != nintrs) {
340                 dev_err(pdsc->dev, "Can't get %d intrs from OS: %pe\n",
341                         nintrs, ERR_PTR(err));
342                 err = -ENOSPC;
343                 goto err_out;
344         }
345         pdsc->nintrs = nintrs;
346
347         return 0;
348
349 err_out:
350         kfree(pdsc->intr_info);
351         pdsc->intr_info = NULL;
352
353         return err;
354 }