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