summaryrefslogtreecommitdiff
path: root/drivers/cxl/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cxl/pci.c')
-rw-r--r--drivers/cxl/pci.c175
1 files changed, 5 insertions, 170 deletions
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 3f2182d66829..5a0ae46d4989 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -48,8 +48,7 @@
*/
static unsigned short mbox_ready_timeout = 60;
module_param(mbox_ready_timeout, ushort, 0644);
-MODULE_PARM_DESC(mbox_ready_timeout,
- "seconds to wait for mailbox ready / memory active status");
+MODULE_PARM_DESC(mbox_ready_timeout, "seconds to wait for mailbox ready");
static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
{
@@ -177,9 +176,10 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
mbox_cmd->return_code =
FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg);
- if (mbox_cmd->return_code != 0) {
- dev_dbg(dev, "Mailbox operation had an error\n");
- return 0;
+ if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) {
+ dev_dbg(dev, "Mailbox operation had an error: %s\n",
+ cxl_mbox_cmd_rc2str(mbox_cmd));
+ return 0; /* completed but caller must check return_code */
}
/* #7 */
@@ -386,164 +386,6 @@ static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
return rc;
}
-static int wait_for_valid(struct cxl_dev_state *cxlds)
-{
- struct pci_dev *pdev = to_pci_dev(cxlds->dev);
- int d = cxlds->cxl_dvsec, rc;
- u32 val;
-
- /*
- * Memory_Info_Valid: When set, indicates that the CXL Range 1 Size high
- * and Size Low registers are valid. Must be set within 1 second of
- * deassertion of reset to CXL device. Likely it is already set by the
- * time this runs, but otherwise give a 1.5 second timeout in case of
- * clock skew.
- */
- rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val);
- if (rc)
- return rc;
-
- if (val & CXL_DVSEC_MEM_INFO_VALID)
- return 0;
-
- msleep(1500);
-
- rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val);
- if (rc)
- return rc;
-
- if (val & CXL_DVSEC_MEM_INFO_VALID)
- return 0;
-
- return -ETIMEDOUT;
-}
-
-/*
- * Wait up to @mbox_ready_timeout for the device to report memory
- * active.
- */
-static int wait_for_media_ready(struct cxl_dev_state *cxlds)
-{
- struct pci_dev *pdev = to_pci_dev(cxlds->dev);
- int d = cxlds->cxl_dvsec;
- bool active = false;
- u64 md_status;
- int rc, i;
-
- rc = wait_for_valid(cxlds);
- if (rc)
- return rc;
-
- for (i = mbox_ready_timeout; i; i--) {
- u32 temp;
-
- rc = pci_read_config_dword(
- pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp);
- if (rc)
- return rc;
-
- active = FIELD_GET(CXL_DVSEC_MEM_ACTIVE, temp);
- if (active)
- break;
- msleep(1000);
- }
-
- if (!active) {
- dev_err(&pdev->dev,
- "timeout awaiting memory active after %d seconds\n",
- mbox_ready_timeout);
- return -ETIMEDOUT;
- }
-
- md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET);
- if (!CXLMDEV_READY(md_status))
- return -EIO;
-
- return 0;
-}
-
-static int cxl_dvsec_ranges(struct cxl_dev_state *cxlds)
-{
- struct cxl_endpoint_dvsec_info *info = &cxlds->info;
- struct pci_dev *pdev = to_pci_dev(cxlds->dev);
- int d = cxlds->cxl_dvsec;
- int hdm_count, rc, i;
- u16 cap, ctrl;
-
- if (!d)
- return -ENXIO;
-
- rc = pci_read_config_word(pdev, d + CXL_DVSEC_CAP_OFFSET, &cap);
- if (rc)
- return rc;
-
- rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl);
- if (rc)
- return rc;
-
- if (!(cap & CXL_DVSEC_MEM_CAPABLE))
- return -ENXIO;
-
- /*
- * It is not allowed by spec for MEM.capable to be set and have 0 legacy
- * HDM decoders (values > 2 are also undefined as of CXL 2.0). As this
- * driver is for a spec defined class code which must be CXL.mem
- * capable, there is no point in continuing to enable CXL.mem.
- */
- hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap);
- if (!hdm_count || hdm_count > 2)
- return -EINVAL;
-
- rc = wait_for_valid(cxlds);
- if (rc)
- return rc;
-
- info->mem_enabled = FIELD_GET(CXL_DVSEC_MEM_ENABLE, ctrl);
-
- for (i = 0; i < hdm_count; i++) {
- u64 base, size;
- u32 temp;
-
- rc = pci_read_config_dword(
- pdev, d + CXL_DVSEC_RANGE_SIZE_HIGH(i), &temp);
- if (rc)
- return rc;
-
- size = (u64)temp << 32;
-
- rc = pci_read_config_dword(
- pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(i), &temp);
- if (rc)
- return rc;
-
- size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK;
-
- rc = pci_read_config_dword(
- pdev, d + CXL_DVSEC_RANGE_BASE_HIGH(i), &temp);
- if (rc)
- return rc;
-
- base = (u64)temp << 32;
-
- rc = pci_read_config_dword(
- pdev, d + CXL_DVSEC_RANGE_BASE_LOW(i), &temp);
- if (rc)
- return rc;
-
- base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK;
-
- info->dvsec_range[i] = (struct range) {
- .start = base,
- .end = base + size - 1
- };
-
- if (size)
- info->ranges++;
- }
-
- return 0;
-}
-
static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct cxl_register_map map;
@@ -573,8 +415,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_warn(&pdev->dev,
"Device DVSEC not present, skip CXL.mem init\n");
- cxlds->wait_media_ready = wait_for_media_ready;
-
rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map);
if (rc)
return rc;
@@ -610,11 +450,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- rc = cxl_dvsec_ranges(cxlds);
- if (rc)
- dev_warn(&pdev->dev,
- "Failed to get DVSEC range information (%d)\n", rc);
-
cxlmd = devm_cxl_add_memdev(cxlds);
if (IS_ERR(cxlmd))
return PTR_ERR(cxlmd);