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 } 366