static int sanitise_afu_regs(struct cxl_afu *afu) { u64 reg; /* * Clear out any regs that contain either an IVTE or address or may be * waiting on an acknowledgement to try to be a bit safer as we bring * it online */ reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An); if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#.16llx\n", reg); if (cxl_afu_reset(afu)) return -EIO; if (cxl_afu_disable(afu)) return -EIO; if (cxl_psl_purge(afu)) return -EIO; } cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0x0000000000000000); cxl_p1n_write(afu, CXL_PSL_IVTE_Limit_An, 0x0000000000000000); cxl_p1n_write(afu, CXL_PSL_IVTE_Offset_An, 0x0000000000000000); cxl_p1n_write(afu, CXL_PSL_AMBAR_An, 0x0000000000000000); cxl_p1n_write(afu, CXL_PSL_SPOffset_An, 0x0000000000000000); cxl_p1n_write(afu, CXL_HAURP_An, 0x0000000000000000); cxl_p2n_write(afu, CXL_CSRP_An, 0x0000000000000000); cxl_p2n_write(afu, CXL_AURP1_An, 0x0000000000000000); cxl_p2n_write(afu, CXL_AURP0_An, 0x0000000000000000); cxl_p2n_write(afu, CXL_SSTP1_An, 0x0000000000000000); cxl_p2n_write(afu, CXL_SSTP0_An, 0x0000000000000000); reg = cxl_p2n_read(afu, CXL_PSL_DSISR_An); if (reg) { dev_warn(&afu->dev, "AFU had pending DSISR: %#.16llx\n", reg); if (reg & CXL_PSL_DSISR_TRANS) cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); else cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); } reg = cxl_p1n_read(afu, CXL_PSL_SERR_An); if (reg) { if (reg & ~0xffff) dev_warn(&afu->dev, "AFU had pending SERR: %#.16llx\n", reg); cxl_p1n_write(afu, CXL_PSL_SERR_An, reg & ~0xffff); } reg = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); if (reg) { dev_warn(&afu->dev, "AFU had pending error status: %#.16llx\n", reg); cxl_p2n_write(afu, CXL_PSL_ErrStat_An, reg); } return 0; }
static ssize_t reset_store_afu(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { struct cxl_afu *afu = to_cxl_afu(device); int rc; /* Not safe to reset if it is currently in use */ spin_lock(&afu->contexts_lock); if (!idr_is_empty(&afu->contexts_idr)) { rc = -EBUSY; goto err; } if ((rc = cxl_afu_reset(afu))) goto err; rc = count; err: spin_unlock(&afu->contexts_lock); return rc; }
static int cxl_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) { struct cxl_afu *afu; bool free = true; int rc; if (!(afu = cxl_alloc_afu(adapter, slice))) return -ENOMEM; if ((rc = dev_set_name(&afu->dev, "afu%i.%i", adapter->adapter_num, slice))) goto err1; if ((rc = cxl_map_slice_regs(afu, adapter, dev))) goto err1; if ((rc = sanitise_afu_regs(afu))) goto err2; /* We need to reset the AFU before we can read the AFU descriptor */ if ((rc = cxl_afu_reset(afu))) goto err2; if (cxl_verbose) dump_afu_descriptor(afu); if ((rc = cxl_read_afu_descriptor(afu))) goto err2; if ((rc = cxl_afu_descriptor_looks_ok(afu))) goto err2; if ((rc = init_implementation_afu_regs(afu))) goto err2; if ((rc = cxl_register_serr_irq(afu))) goto err2; if ((rc = cxl_register_psl_irq(afu))) goto err3; /* Don't care if this fails */ cxl_debugfs_afu_add(afu); /* * After we call this function we must not free the afu directly, even * if it returns an error! */ if ((rc = cxl_register_afu(afu))) goto err_put1; if ((rc = cxl_sysfs_afu_add(afu))) goto err_put1; if ((rc = cxl_afu_select_best_mode(afu))) goto err_put2; adapter->afu[afu->slice] = afu; return 0; err_put2: cxl_sysfs_afu_remove(afu); err_put1: device_unregister(&afu->dev); free = false; cxl_debugfs_afu_remove(afu); cxl_release_psl_irq(afu); err3: cxl_release_serr_irq(afu); err2: cxl_unmap_slice_regs(afu); err1: if (free) kfree(afu); return rc; }