From: Manish Honap <[email protected]> The Register Locator DVSEC (CXL r4.0 8.1.9) describes register blocks by BAR index (BIR) and offset within the BAR. CXL core currently only stores the resolved HPA (resource + offset) in struct cxl_register_map, so callers that need pci_iomap() or want to report the BAR to userspace must reverse-engineer the BAR from the HPA.
Add bar_index and bar_offset to struct cxl_register_map and fill them in cxl_decode_regblock() when the regblock is BAR-backed (BIR 0-5). Add cxl_regblock_get_bar_info() so cxl drivers (vfio-cxl, in-kernel accelerator drivers) can read the values without touching the struct internals. Export under the CXL namespace. Signed-off-by: Manish Honap <[email protected]> --- drivers/cxl/core/pci.c | 2 ++ drivers/cxl/core/regs.c | 34 ++++++++++++++++++++++++++++++++++ include/cxl/cxl.h | 12 ++++++++++++ 3 files changed, 48 insertions(+) diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index c44595447bd8..9b9b17db9ee4 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -764,6 +764,8 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev, *map = (struct cxl_register_map) { .host = &pdev->dev, .resource = CXL_RESOURCE_NONE, + .bar_index = 0xff, + .bar_offset = 0, }; component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport); diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index e828df0629d0..6af5739aa776 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -285,12 +285,46 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, return false; } + if (bar >= 0 && bar <= 5) { + map->bar_index = (u8)bar; + map->bar_offset = offset; + } else { + map->bar_index = 0xff; + map->bar_offset = 0; + } + map->reg_type = reg_type; map->resource = pci_resource_start(pdev, bar) + offset; map->max_size = pci_resource_len(pdev, bar) - offset; return true; } +/** + * cxl_regblock_get_bar_info - read BAR index and offset for a regblock + * @map: regblock map produced by cxl_find_regblock() + * @bar_index: out, PCI BAR index (0-5) + * @bar_offset: out, byte offset of the regblock within the BAR + * + * Exported for cxl drivers (vfio-cxl, in-kernel accelerator drivers) + * that need to map the regblock via pci_iomap() or report the BAR to + * userspace. + * + * Return: 0 on success, -EINVAL if the regblock is not BAR-backed or + * if any out pointer is NULL. + */ +int cxl_regblock_get_bar_info(const struct cxl_register_map *map, + u8 *bar_index, resource_size_t *bar_offset) +{ + if (!map || !bar_index || !bar_offset) + return -EINVAL; + if (map->bar_index > 5) + return -EINVAL; + *bar_index = map->bar_index; + *bar_offset = map->bar_offset; + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_regblock_get_bar_info, "CXL"); + /* * __cxl_find_regblock_instance() - Locate a register block or count instances by type / index * Use CXL_INSTANCES_COUNT for @index if counting instances. diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h index 3dcc034360af..3bcb71d80c91 100644 --- a/include/cxl/cxl.h +++ b/include/cxl/cxl.h @@ -100,9 +100,16 @@ struct cxl_pmu_reg_map { * @resource: physical resource base of the register block * @max_size: maximum mapping size to perform register search * @reg_type: see enum cxl_regloc_type + * @bar_index: PCI BAR index (0-5) when regblock is BAR-backed; 0xff otherwise + * @bar_offset: offset within the BAR; only valid when bar_index <= 5 * @component_map: cxl_reg_map for component registers * @device_map: cxl_reg_maps for device registers * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units + * + * When the register block is described by the Register Locator DVSEC with + * a BAR Indicator (BIR 0-5), bar_index and bar_offset are set so callers + * can use pci_iomap(pdev, bar_index, size) and base + bar_offset instead + * of ioremap(resource). */ struct cxl_register_map { struct device *host; @@ -110,6 +117,8 @@ struct cxl_register_map { resource_size_t resource; resource_size_t max_size; u8 reg_type; + u8 bar_index; + resource_size_t bar_offset; union { struct cxl_component_reg_map component_map; struct cxl_device_reg_map device_map; @@ -234,4 +243,7 @@ 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); + +int cxl_regblock_get_bar_info(const struct cxl_register_map *map, + u8 *bar_index, resource_size_t *bar_offset); #endif /* __CXL_CXL_H__ */ -- 2.25.1

