From: Manish Honap <[email protected]> Before accessing CXL device memory after reset or power-on, the driver must ensure media is ready. Not every CXL device implements the CXL Memory Device register group: many Type-2 devices do not. cxl_await_media_ready() reads cxlds->regs.memdev. Access to memdev registers on a Type-2 device that lacks them can result in a kernel panic.
Split the HDM DVSEC range-active poll out of cxl_await_media_ready() into a new helper cxl_await_range_active(). Type-2 cxl drivers (vfio-cxl, in-kernel accelerator drivers) that lack the CXLMDEV status register call this directly. cxl_await_media_ready() now calls cxl_await_range_active() for the DVSEC poll, then reads the memory device status as before. The 60 second per-range timeout from cxl_await_media_ready() (media_ready_timeout module param) applies. Export under the CXL namespace. Signed-off-by: Manish Honap <[email protected]> --- drivers/cxl/core/pci.c | 35 ++++++++++++++++++++++++++++++----- include/cxl/cxl.h | 2 ++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index c917608c16f9..c44595447bd8 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -142,16 +142,24 @@ static int cxl_dvsec_mem_range_active(struct cxl_dev_state *cxlds, int id) return 0; } -/* - * Wait up to @media_ready_timeout for the device to report memory - * active. +/** + * cxl_await_range_active - Wait for all HDM DVSEC memory ranges to be active + * @cxlds: CXL device state (DVSEC and HDM count must be valid) + * + * For each HDM decoder range reported in the CXL DVSEC capability, waits + * for the range to report MEM INFO VALID (up to 1s per range), then + * MEM ACTIVE (up to media_ready_timeout seconds per range, default 60s). + * Used by cxl_await_media_ready() and by cxl drivers that bind to Type-2 + * devices without the memdev mailbox (e.g. vfio-cxl, accelerator drivers). + * + * Return: 0 if all ranges become valid and active, -ETIMEDOUT if a + * timeout occurs, or a negative errno from config read on failure. */ -int cxl_await_media_ready(struct cxl_dev_state *cxlds) +int cxl_await_range_active(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,6 +180,23 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds) return rc; } + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_await_range_active, "CXL"); + +/* + * Wait up to @media_ready_timeout for the device to report memory + * active. + */ +int cxl_await_media_ready(struct cxl_dev_state *cxlds) +{ + u64 md_status; + int rc; + + rc = cxl_await_range_active(cxlds); + if (rc) + return rc; + md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); if (!CXLMDEV_READY(md_status)) return -EIO; diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h index 440ab09c640e..3dcc034360af 100644 --- a/include/cxl/cxl.h +++ b/include/cxl/cxl.h @@ -232,4 +232,6 @@ int cxl_set_capacity(struct cxl_dev_state *cxlds, u64 capacity); int cxl_get_hdm_info(struct cxl_dev_state *cxlds, u8 *count, resource_size_t *offset, resource_size_t *size); + +int cxl_await_range_active(struct cxl_dev_state *cxlds); #endif /* __CXL_CXL_H__ */ -- 2.25.1

