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