1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
4 #include <linux/errno.h>
6 #include <linux/utsname.h>
10 int pdsc_err_to_errno(enum pds_core_status_code code)
58 bool pdsc_is_fw_running(struct pdsc *pdsc)
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);
67 /* Firmware is useful only if the running bit is set and
68 * fw_status != 0xff (bad PCI read)
70 return (pdsc->fw_status != PDS_RC_BAD_PCI) &&
71 (pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING);
74 bool pdsc_is_fw_good(struct pdsc *pdsc)
76 bool fw_running = pdsc_is_fw_running(pdsc);
79 /* Make sure to update the cached fw_status by calling
80 * pdsc_is_fw_running() before getting the generation
82 gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION;
84 return fw_running && gen == pdsc->fw_generation;
87 static u8 pdsc_devcmd_status(struct pdsc *pdsc)
89 return ioread8(&pdsc->cmd_regs->comp.status);
92 static bool pdsc_devcmd_done(struct pdsc *pdsc)
94 return ioread32(&pdsc->cmd_regs->done) & PDS_CORE_DEV_CMD_DONE;
97 static void pdsc_devcmd_dbell(struct pdsc *pdsc)
99 iowrite32(0, &pdsc->cmd_regs->done);
100 iowrite32(1, &pdsc->cmd_regs->doorbell);
103 static void pdsc_devcmd_clean(struct pdsc *pdsc)
105 iowrite32(0, &pdsc->cmd_regs->doorbell);
106 memset_io(&pdsc->cmd_regs->cmd, 0, sizeof(pdsc->cmd_regs->cmd));
109 static const char *pdsc_devcmd_str(int 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";
125 return "PDS_CORE_CMD_UNKNOWN";
129 static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)
131 struct device *dev = pdsc->dev;
132 unsigned long start_time;
133 unsigned long max_wait;
134 unsigned long duration;
141 start_time = jiffies;
142 max_wait = start_time + (max_seconds * HZ);
144 while (!done && !timeout) {
145 running = pdsc_is_fw_running(pdsc);
149 done = pdsc_devcmd_done(pdsc);
153 timeout = time_after(jiffies, max_wait);
157 usleep_range(100, 200);
159 duration = jiffies - start_time;
161 if (done && duration > HZ)
162 dev_dbg(dev, "DEVCMD %d %s after %ld secs\n",
163 opcode, pdsc_devcmd_str(opcode), duration / HZ);
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,
170 pdsc_devcmd_clean(pdsc);
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,
183 int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
184 union pds_core_dev_comp *comp, int max_seconds)
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);
195 if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
196 queue_work(pdsc->wq, &pdsc->health_work);
198 memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
203 int pdsc_devcmd(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
204 union pds_core_dev_comp *comp, int max_seconds)
208 mutex_lock(&pdsc->devcmd_lock);
209 err = pdsc_devcmd_locked(pdsc, cmd, comp, max_seconds);
210 mutex_unlock(&pdsc->devcmd_lock);
215 int pdsc_devcmd_init(struct pdsc *pdsc)
217 union pds_core_dev_comp comp = {};
218 union pds_core_dev_cmd cmd = {
219 .opcode = PDS_CORE_CMD_INIT,
222 return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
225 int pdsc_devcmd_reset(struct pdsc *pdsc)
227 union pds_core_dev_comp comp = {};
228 union pds_core_dev_cmd cmd = {
229 .reset.opcode = PDS_CORE_CMD_RESET,
232 return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
235 static int pdsc_devcmd_identify_locked(struct pdsc *pdsc)
237 union pds_core_dev_comp comp = {};
238 union pds_core_dev_cmd cmd = {
239 .identify.opcode = PDS_CORE_CMD_IDENTIFY,
240 .identify.ver = PDS_CORE_IDENTITY_VERSION_1,
243 return pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
246 static void pdsc_init_devinfo(struct pdsc *pdsc)
248 pdsc->dev_info.asic_type = ioread8(&pdsc->info_regs->asic_type);
249 pdsc->dev_info.asic_rev = ioread8(&pdsc->info_regs->asic_rev);
250 pdsc->fw_generation = PDS_CORE_FW_STS_F_GENERATION &
251 ioread8(&pdsc->info_regs->fw_status);
253 memcpy_fromio(pdsc->dev_info.fw_version,
254 pdsc->info_regs->fw_version,
255 PDS_CORE_DEVINFO_FWVERS_BUFLEN);
256 pdsc->dev_info.fw_version[PDS_CORE_DEVINFO_FWVERS_BUFLEN] = 0;
258 memcpy_fromio(pdsc->dev_info.serial_num,
259 pdsc->info_regs->serial_num,
260 PDS_CORE_DEVINFO_SERIAL_BUFLEN);
261 pdsc->dev_info.serial_num[PDS_CORE_DEVINFO_SERIAL_BUFLEN] = 0;
263 dev_dbg(pdsc->dev, "fw_version %s\n", pdsc->dev_info.fw_version);
266 static int pdsc_identify(struct pdsc *pdsc)
268 struct pds_core_drv_identity drv = {};
273 drv.drv_type = cpu_to_le32(PDS_DRIVER_LINUX);
274 /* Catching the return quiets a Wformat-truncation complaint */
275 n = snprintf(drv.driver_ver_str, sizeof(drv.driver_ver_str),
276 "%s %s", PDS_CORE_DRV_NAME, utsname()->release);
277 if (n > sizeof(drv.driver_ver_str))
278 dev_dbg(pdsc->dev, "release name truncated, don't care\n");
280 /* Next let's get some info about the device
281 * We use the devcmd_lock at this level in order to
282 * get safe access to the cmd_regs->data before anyone
283 * else can mess it up
285 mutex_lock(&pdsc->devcmd_lock);
287 sz = min_t(size_t, sizeof(drv), sizeof(pdsc->cmd_regs->data));
288 memcpy_toio(&pdsc->cmd_regs->data, &drv, sz);
290 err = pdsc_devcmd_identify_locked(pdsc);
292 sz = min_t(size_t, sizeof(pdsc->dev_ident),
293 sizeof(pdsc->cmd_regs->data));
294 memcpy_fromio(&pdsc->dev_ident, &pdsc->cmd_regs->data, sz);
296 mutex_unlock(&pdsc->devcmd_lock);
299 dev_err(pdsc->dev, "Cannot identify device: %pe\n",
304 if (isprint(pdsc->dev_info.fw_version[0]) &&
305 isascii(pdsc->dev_info.fw_version[0]))
306 dev_info(pdsc->dev, "FW: %.*s\n",
307 (int)(sizeof(pdsc->dev_info.fw_version) - 1),
308 pdsc->dev_info.fw_version);
310 dev_info(pdsc->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n",
311 (u8)pdsc->dev_info.fw_version[0],
312 (u8)pdsc->dev_info.fw_version[1],
313 (u8)pdsc->dev_info.fw_version[2],
314 (u8)pdsc->dev_info.fw_version[3]);
319 int pdsc_dev_init(struct pdsc *pdsc)
324 /* Initial init and reset of device */
325 pdsc_init_devinfo(pdsc);
326 pdsc->devcmd_timeout = PDS_CORE_DEVCMD_TIMEOUT;
328 err = pdsc_devcmd_reset(pdsc);
332 err = pdsc_identify(pdsc);
336 pdsc_debugfs_add_ident(pdsc);
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);
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) {
349 err = pci_alloc_irq_vectors(pdsc->pdev, nintrs, nintrs, PCI_IRQ_MSIX);
351 dev_err(pdsc->dev, "Can't get %d intrs from OS: %pe\n",
352 nintrs, ERR_PTR(err));
356 pdsc->nintrs = nintrs;
361 kfree(pdsc->intr_info);
362 pdsc->intr_info = NULL;