[RFC 03/13] cxl: introduce cxl_find_comp_reglock_offset()

Zhi Wang
2024-09-20T22:35:13Z

CXL core has the information of what CXL register groups a device
has.When initializing the device, the CXL core probes the register
groups and saves the information. The probing sequence is quite
complicated.

vfio-cxl needs to handle the CXL MMIO BAR specially. E.g. emulate
the HDM decoder register inside the component registers. Thus it
requires to know the offset of the CXL component register to locate
the PCI BAR where the component register sits.

Introduce cxl_find_comp_regblock_offset() for vfio-cxl to leverage the
register information in the CXL core. Thus, it doesn't need to
implement its own probing sequence.

Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
drivers/cxl/core/regs.c | 22 ++++++++++++++++++++++
drivers/cxl/cxl.h | 1 +
include/linux/cxl_accel_mem.h | 1 +
3 files changed, 24 insertions(+)

diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 9d218ebe180d..7db3c8fcd66f 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -364,6 +364,28 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
}
EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);

+/**
+ * cxl_find_comp_regblock_offset() - Locate the offset of component
+ * register blocks
+ * @pdev: The CXL PCI device to enumerate.
+ * @offset: Enumeration output, clobbered on error
+ *
+ * Return: 0 if register block enumerated, negative error code otherwise
+ */
+int cxl_find_comp_regblock_offset(struct pci_dev *pdev, u64 *offset)
+{
+ struct cxl_register_map map;
+ int ret;
+
+ ret = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
+ if (ret)
+ return ret;
+
+ *offset = map.resource;
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_find_comp_regblock_offset, CXL);
+
/**
* cxl_count_regblock() - Count instances of a given regblock type.
* @pdev: The CXL PCI device to enumerate.
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 5e2b5b3e8f38..33dfdc278b47 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -300,6 +300,7 @@ int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map, int index);
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map);
+int cxl_find_comp_regblock_offset(struct pci_dev *pdev, u64 *offset);
int cxl_setup_regs(struct cxl_register_map *map, uint8_t caps);
struct cxl_dport;
resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
diff --git a/include/linux/cxl_accel_mem.h b/include/linux/cxl_accel_mem.h
index db4182fc1936..6f585aae7eb6 100644
--- a/include/linux/cxl_accel_mem.h
+++ b/include/linux/cxl_accel_mem.h
@@ -57,4 +57,5 @@ int cxl_accel_get_region_params(struct cxl_region *region,
resource_size_t *start, resource_size_t *end);
int cxl_get_hdm_info(struct cxl_dev_state *cxlds, u32 *hdm_count,
u64 *hdm_reg_offset, u64 *hdm_reg_size);
+int cxl_find_comp_regblock_offset(struct pci_dev *pdev, u64 *offset);
#endif
--
2.34.1