[PATCH v4 04/27] cxl: Establish media readiness in cxl_mem_probe()

<[email protected]>
Newsgroups org.kernel.vger.linux-hardening,org.kernel.vger.kvm,org.kernel.vger.linux-cxl,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-pci
Message-ID <[email protected]>
From: Manish Honap <[email protected]>

media_ready was only ever set by cxl_pci, in advance of registering a
memdev and with CXL Memory Device register assumptions. A consumer that
creates a memdev without cxl_pci, such as a mailbox-less Type-2
accelerator brought up through devm_cxl_probe_mem(), therefore handed
cxl_mem a device with media_ready still false, and cxl_mem_probe()
rejected it with -EBUSY. __devm_cxl_add_memdev() turns that into -ENXIO
back to the caller and the bind fails.

Move the readiness wait into cxl_mem_probe() so every memdev consumer
gets a ready resource regardless of how the memdev was created. When
media_ready is not already set, wait on the device's DVSEC
Mem_Info_Valid and Mem_Active bits and mark it ready. cxl_pci keeps
setting media_ready before it registers its memdev, so that path skips
the wait.

The CXL Memory Device register group is optional and many Type-2 devices
do not implement it, so cxl_await_media_ready() must not read the Memdev
Status register unless the group is mapped. Reading regs.memdev on a
device that lacks it would fault. Gate that read on regs.memdev; the
DVSEC bits already prove readiness for such devices.

Signed-off-by: Manish Honap <[email protected]>
---
 drivers/cxl/core/pci.c | 15 +++++++++++----
 drivers/cxl/mem.c      |  9 +++++++--
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 08d4c955137d..9b372d5a1aa4 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -151,7 +151,6 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds)
 	struct pci_dev *pdev = to_pci_dev(cxlds->dev);
 	int d = cxlds->cxl_dvsec;
 	int rc, i, hdm_count;
-	u64 md_status;
 	u16 cap;
 
 	rc = pci_read_config_word(pdev,
@@ -172,9 +171,17 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds)
 			return rc;
 	}
 
-	md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET);
-	if (!CXLMDEV_READY(md_status))
-		return -EIO;
+	/*
+	 * It is possible some Type-2 devices (CXL_DEVTYPE_DEVMEM) do not
+	 * implement regs.memdev; only consult the Memdev Status register when
+	 * the group is actually present.
+	 */
+	if (cxlds->regs.memdev) {
+		u64 md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET);
+
+		if (!CXLMDEV_READY(md_status))
+			return -EIO;
+	}
 
 	return 0;
 }
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 798e5c369cfc..9c6e99b9124c 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -105,8 +105,13 @@ static int cxl_mem_probe(struct device *dev)
 	struct dentry *dentry;
 	int rc;
 
-	if (!cxlds->media_ready)
-		return -EBUSY;
+	if (!cxlds->media_ready) {
+		rc = cxl_await_media_ready(cxlds);
+		if (rc)
+			return rc;
+		cxlds->media_ready = true;
+		dev_dbg(dev, "CXL media ready\n");
+	}
 
 	/*
 	 * Someone is trying to reattach this device after it lost its port
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.