cxl/pci: Prepare for mapping RAS Capability Structure
authorDan Williams <dan.j.williams@intel.com>
Tue, 29 Nov 2022 17:48:42 +0000 (10:48 -0700)
committerDan Williams <dan.j.williams@intel.com>
Sat, 3 Dec 2022 21:40:17 +0000 (13:40 -0800)
The RAS Capabilitiy Structure is a CXL Component register capability
block. Unlike the HDM Decoder Capability, it will be referenced by the
cxl_pci driver in response to PCIe AER events. Due to this it is no
longer the case that cxl_map_component_regs() can assume that it should
map all component registers. Plumb a bitmask of capability ids to map
through cxl_map_component_regs().

For symmetry cxl_probe_device_regs() is updated to populate @id in
'struct cxl_reg_map' even though cxl_map_device_regs() does not have a
need to map a subset of the device registers per caller.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/166974412214.1608150.11487843455070795378.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/hdm.c
drivers/cxl/core/regs.c
drivers/cxl/cxl.h

index 0615511..100d088 100644 (file)
@@ -97,7 +97,8 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
                return -ENXIO;
        }
 
-       return cxl_map_component_regs(&port->dev, regs, &map);
+       return cxl_map_component_regs(&port->dev, regs, &map,
+                                     BIT(CXL_CM_CAP_CAP_ID_HDM));
 }
 
 /**
index e4b0d52..97e8f42 100644 (file)
@@ -92,6 +92,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
                if (!rmap)
                        continue;
                rmap->valid = true;
+               rmap->id = cap_id;
                rmap->offset = CXL_CM_OFFSET + offset;
                rmap->size = length;
        }
@@ -159,6 +160,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
                if (!rmap)
                        continue;
                rmap->valid = true;
+               rmap->id = cap_id;
                rmap->offset = offset;
                rmap->size = length;
        }
@@ -187,17 +189,31 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
 }
 
 int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
-                          struct cxl_register_map *map)
+                          struct cxl_register_map *map, unsigned long map_mask)
 {
-       resource_size_t phys_addr;
-       resource_size_t length;
-
-       phys_addr = map->resource;
-       phys_addr += map->component_map.hdm_decoder.offset;
-       length = map->component_map.hdm_decoder.size;
-       regs->hdm_decoder = devm_cxl_iomap_block(dev, phys_addr, length);
-       if (!regs->hdm_decoder)
-               return -ENOMEM;
+       struct mapinfo {
+               struct cxl_reg_map *rmap;
+               void __iomem **addr;
+       } mapinfo[] = {
+               { &map->component_map.hdm_decoder, &regs->hdm_decoder },
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mapinfo); i++) {
+               struct mapinfo *mi = &mapinfo[i];
+               resource_size_t phys_addr;
+               resource_size_t length;
+
+               if (!mi->rmap->valid)
+                       continue;
+               if (!test_bit(mi->rmap->id, &map_mask))
+                       continue;
+               phys_addr = map->resource + mi->rmap->offset;
+               length = mi->rmap->size;
+               *(mi->addr) = devm_cxl_iomap_block(dev, phys_addr, length);
+               if (!*(mi->addr))
+                       return -ENOMEM;
+       }
 
        return 0;
 }
index 46299e7..fc16c9a 100644 (file)
@@ -170,6 +170,7 @@ struct cxl_regs {
 
 struct cxl_reg_map {
        bool valid;
+       int id;
        unsigned long offset;
        unsigned long size;
 };
@@ -209,7 +210,8 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
 void cxl_probe_device_regs(struct device *dev, void __iomem *base,
                           struct cxl_device_reg_map *map);
 int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
-                          struct cxl_register_map *map);
+                          struct cxl_register_map *map,
+                          unsigned long map_mask);
 int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
                        struct cxl_register_map *map);