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
pdsc_err_to_errno(enum pds_core_status_code code)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
pdsc_is_fw_running(struct pdsc * pdsc)56 bool pdsc_is_fw_running(struct pdsc *pdsc)
57 {
58 if (!pdsc->info_regs)
59 return false;
60
61 pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
62 pdsc->last_fw_time = jiffies;
63 pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat);
64
65 /* Firmware is useful only if the running bit is set and
66 * fw_status != 0xff (bad PCI read)
67 */
68 return (pdsc->fw_status != 0xff) &&
69 (pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING);
70 }
71
pdsc_is_fw_good(struct pdsc * pdsc)72 bool pdsc_is_fw_good(struct pdsc *pdsc)
73 {
74 bool fw_running = pdsc_is_fw_running(pdsc);
75 u8 gen;
76
77 /* Make sure to update the cached fw_status by calling
78 * pdsc_is_fw_running() before getting the generation
79 */
80 gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION;
81
82 return fw_running && gen == pdsc->fw_generation;
83 }
84
pdsc_devcmd_status(struct pdsc * pdsc)85 static u8 pdsc_devcmd_status(struct pdsc *pdsc)
86 {
87 return ioread8(&pdsc->cmd_regs->comp.status);
88 }
89
pdsc_devcmd_done(struct pdsc * pdsc)90 static bool pdsc_devcmd_done(struct pdsc *pdsc)
91 {
92 return ioread32(&pdsc->cmd_regs->done) & PDS_CORE_DEV_CMD_DONE;
93 }
94
pdsc_devcmd_dbell(struct pdsc * pdsc)95 static void pdsc_devcmd_dbell(struct pdsc *pdsc)
96 {
97 iowrite32(0, &pdsc->cmd_regs->done);
98 iowrite32(1, &pdsc->cmd_regs->doorbell);
99 }
100
pdsc_devcmd_clean(struct pdsc * pdsc)101 static void pdsc_devcmd_clean(struct pdsc *pdsc)
102 {
103 iowrite32(0, &pdsc->cmd_regs->doorbell);
104 memset_io(&pdsc->cmd_regs->cmd, 0, sizeof(pdsc->cmd_regs->cmd));
105 }
106
pdsc_devcmd_str(int opcode)107 static const char *pdsc_devcmd_str(int opcode)
108 {
109 switch (opcode) {
110 case PDS_CORE_CMD_NOP:
111 return "PDS_CORE_CMD_NOP";
112 case PDS_CORE_CMD_IDENTIFY:
113 return "PDS_CORE_CMD_IDENTIFY";
114 case PDS_CORE_CMD_RESET:
115 return "PDS_CORE_CMD_RESET";
116 case PDS_CORE_CMD_INIT:
117 return "PDS_CORE_CMD_INIT";
118 case PDS_CORE_CMD_FW_DOWNLOAD:
119 return "PDS_CORE_CMD_FW_DOWNLOAD";
120 case PDS_CORE_CMD_FW_CONTROL:
121 return "PDS_CORE_CMD_FW_CONTROL";
122 default:
123 return "PDS_CORE_CMD_UNKNOWN";
124 }
125 }
126
pdsc_devcmd_wait(struct pdsc * pdsc,u8 opcode,int max_seconds)127 static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)
128 {
129 struct device *dev = pdsc->dev;
130 unsigned long start_time;
131 unsigned long max_wait;
132 unsigned long duration;
133 int timeout = 0;
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 done = pdsc_devcmd_done(pdsc);
143 if (done)
144 break;
145
146 timeout = time_after(jiffies, max_wait);
147 if (timeout)
148 break;
149
150 usleep_range(100, 200);
151 }
152 duration = jiffies - start_time;
153
154 if (done && duration > HZ)
155 dev_dbg(dev, "DEVCMD %d %s after %ld secs\n",
156 opcode, pdsc_devcmd_str(opcode), duration / HZ);
157
158 if (!done || timeout) {
159 dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n",
160 opcode, pdsc_devcmd_str(opcode), done, timeout,
161 max_seconds);
162 err = -ETIMEDOUT;
163 pdsc_devcmd_clean(pdsc);
164 }
165
166 status = pdsc_devcmd_status(pdsc);
167 err = pdsc_err_to_errno(status);
168 if (err && err != -EAGAIN)
169 dev_err(dev, "DEVCMD %d %s failed, status=%d err %d %pe\n",
170 opcode, pdsc_devcmd_str(opcode), status, err,
171 ERR_PTR(err));
172
173 return err;
174 }
175
pdsc_devcmd_locked(struct pdsc * pdsc,union pds_core_dev_cmd * cmd,union pds_core_dev_comp * comp,int max_seconds)176 int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
177 union pds_core_dev_comp *comp, int max_seconds)
178 {
179 int err;
180
181 if (!pdsc->cmd_regs)
182 return -ENXIO;
183
184 memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
185 pdsc_devcmd_dbell(pdsc);
186 err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds);
187
188 if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
189 queue_work(pdsc->wq, &pdsc->health_work);
190 else
191 memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
192
193 return err;
194 }
195
pdsc_devcmd(struct pdsc * pdsc,union pds_core_dev_cmd * cmd,union pds_core_dev_comp * comp,int max_seconds)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
pdsc_devcmd_init(struct pdsc * pdsc)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
pdsc_devcmd_reset(struct pdsc * pdsc)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
pdsc_devcmd_identify_locked(struct pdsc * pdsc)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
pdsc_init_devinfo(struct pdsc * pdsc)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
pdsc_identify(struct pdsc * pdsc)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
pdsc_dev_init(struct pdsc * pdsc)312 int pdsc_dev_init(struct pdsc *pdsc)
313 {
314 unsigned int nintrs;
315 int err;
316
317 /* Initial init and reset of device */
318 pdsc_init_devinfo(pdsc);
319 pdsc->devcmd_timeout = PDS_CORE_DEVCMD_TIMEOUT;
320
321 err = pdsc_devcmd_reset(pdsc);
322 if (err)
323 return err;
324
325 err = pdsc_identify(pdsc);
326 if (err)
327 return err;
328
329 pdsc_debugfs_add_ident(pdsc);
330
331 /* Now we can reserve interrupts */
332 nintrs = le32_to_cpu(pdsc->dev_ident.nintrs);
333 nintrs = min_t(unsigned int, num_online_cpus(), nintrs);
334
335 /* Get intr_info struct array for tracking */
336 pdsc->intr_info = kcalloc(nintrs, sizeof(*pdsc->intr_info), GFP_KERNEL);
337 if (!pdsc->intr_info) {
338 err = -ENOMEM;
339 goto err_out;
340 }
341
342 err = pci_alloc_irq_vectors(pdsc->pdev, nintrs, nintrs, PCI_IRQ_MSIX);
343 if (err != nintrs) {
344 dev_err(pdsc->dev, "Can't get %d intrs from OS: %pe\n",
345 nintrs, ERR_PTR(err));
346 err = -ENOSPC;
347 goto err_out;
348 }
349 pdsc->nintrs = nintrs;
350
351 return 0;
352
353 err_out:
354 kfree(pdsc->intr_info);
355 pdsc->intr_info = NULL;
356
357 return err;
358 }
359