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