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 10int 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 58bool 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 74bool 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 87static u8 pdsc_devcmd_status(struct pdsc *pdsc) 88{ 89 return ioread8(&pdsc->cmd_regs->comp.status); 90} 91 92static bool pdsc_devcmd_done(struct pdsc *pdsc) 93{ 94 return ioread32(&pdsc->cmd_regs->done) & PDS_CORE_DEV_CMD_DONE; 95} 96 97static void pdsc_devcmd_dbell(struct pdsc *pdsc) 98{ 99 iowrite32(0, &pdsc->cmd_regs->done); 100 iowrite32(1, &pdsc->cmd_regs->doorbell); 101} 102 103static 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 109static 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 129static 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 183int 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 203int 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 215int 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 225int 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 238static 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 249static 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 269static 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 322void pdsc_dev_uninit(struct pdsc *pdsc) 323{ 324 if (pdsc->intr_info) { 325 int i; 326 327 for (i = 0; i < pdsc->nintrs; i++) 328 pdsc_intr_free(pdsc, i); 329 330 kfree(pdsc->intr_info); 331 pdsc->intr_info = NULL; 332 pdsc->nintrs = 0; 333 } 334 335 pci_free_irq_vectors(pdsc->pdev); 336} 337 338int pdsc_dev_init(struct pdsc *pdsc) 339{ 340 unsigned int nintrs; 341 int err; 342 343 /* Initial init and reset of device */ 344 pdsc_init_devinfo(pdsc); 345 pdsc->devcmd_timeout = PDS_CORE_DEVCMD_TIMEOUT; 346 347 err = pdsc_devcmd_reset(pdsc); 348 if (err) 349 return err; 350 351 err = pdsc_identify(pdsc); 352 if (err) 353 return err; 354 355 pdsc_debugfs_add_ident(pdsc); 356 357 /* Now we can reserve interrupts */ 358 nintrs = le32_to_cpu(pdsc->dev_ident.nintrs); 359 nintrs = min_t(unsigned int, num_online_cpus(), nintrs); 360 361 /* Get intr_info struct array for tracking */ 362 pdsc->intr_info = kcalloc(nintrs, sizeof(*pdsc->intr_info), GFP_KERNEL); 363 if (!pdsc->intr_info) 364 return -ENOMEM; 365 366 err = pci_alloc_irq_vectors(pdsc->pdev, nintrs, nintrs, PCI_IRQ_MSIX); 367 if (err != nintrs) { 368 dev_err(pdsc->dev, "Can't get %d intrs from OS: %pe\n", 369 nintrs, ERR_PTR(err)); 370 err = -ENOSPC; 371 goto err_out; 372 } 373 pdsc->nintrs = nintrs; 374 375 return 0; 376 377err_out: 378 kfree(pdsc->intr_info); 379 pdsc->intr_info = NULL; 380 381 return err; 382} 383