]> git.itanic.dy.fi Git - linux-stable/commitdiff
Merge branch 'for-6.5/cxl-rch-eh' into for-6.5/cxl
authorDan Williams <dan.j.williams@intel.com>
Mon, 26 Jun 2023 01:56:13 +0000 (18:56 -0700)
committerDan Williams <dan.j.williams@intel.com>
Mon, 26 Jun 2023 01:56:13 +0000 (18:56 -0700)
Pick up the first half of the RCH error handling series. The back half
needs some fixups for test regressions. Small conflicts with the PMU
work around register enumeration and setup helpers.

15 files changed:
1  2 
drivers/cxl/acpi.c
drivers/cxl/core/core.h
drivers/cxl/core/hdm.c
drivers/cxl/core/pci.c
drivers/cxl/core/port.c
drivers/cxl/core/region.c
drivers/cxl/core/regs.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
drivers/cxl/mem.c
drivers/cxl/pci.c
drivers/cxl/port.c
tools/testing/cxl/Kbuild
tools/testing/cxl/test/cxl.c
tools/testing/cxl/test/mock.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index b7d8db922fd9090e49bd2f9d98d202b4c9700970,e68848075bb62b0a25ad639dfe22cdda9704046e..6281127b3e9d97223d9a4c733c98b9a1fb2271c7
@@@ -200,11 -199,13 +200,13 @@@ void __iomem *devm_cxl_iomap_block(stru
        return ret_val;
  }
  
- int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
-                          const struct cxl_register_map *map, unsigned long map_mask)
 -int cxl_map_component_regs(struct cxl_register_map *map,
++int cxl_map_component_regs(const struct cxl_register_map *map,
+                          struct cxl_component_regs *regs,
+                          unsigned long map_mask)
  {
+       struct device *dev = map->dev;
        struct mapinfo {
 -              struct cxl_reg_map *rmap;
 +              const struct cxl_reg_map *rmap;
                void __iomem **addr;
        } mapinfo[] = {
                { &map->component_map.hdm_decoder, &regs->hdm_decoder },
  }
  EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
  
- int cxl_map_device_regs(struct device *dev,
-                       struct cxl_device_regs *regs,
-                       const struct cxl_register_map *map)
 -int cxl_map_device_regs(struct cxl_register_map *map,
++int cxl_map_device_regs(const struct cxl_register_map *map,
+                       struct cxl_device_regs *regs)
  {
+       struct device *dev = map->dev;
        resource_size_t phys_addr = map->resource;
        struct mapinfo {
 -              struct cxl_reg_map *rmap;
 +              const struct cxl_reg_map *rmap;
                void __iomem **addr;
        } mapinfo[] = {
                { &map->device_map.status, &regs->status, },
@@@ -297,16 -296,19 +299,20 @@@ static bool cxl_decode_regblock(struct 
   * Return: 0 if register block enumerated, negative error code otherwise
   *
   * A CXL DVSEC may point to one or more register blocks, search for them
 - * by @type.
 + * by @type and @index.
   */
 -int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
 -                    struct cxl_register_map *map)
 +int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
 +                             struct cxl_register_map *map, int index)
  {
        u32 regloc_size, regblocks;
 +      int instance = 0;
        int regloc, i;
  
-       map->resource = CXL_RESOURCE_NONE;
+       *map = (struct cxl_register_map) {
+               .dev = &pdev->dev,
+               .resource = CXL_RESOURCE_NONE,
+       };
        regloc = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
                                           CXL_DVSEC_REG_LOCATOR);
        if (!regloc)
        map->resource = CXL_RESOURCE_NONE;
        return -ENODEV;
  }
 +EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL);
 +
 +/**
 + * cxl_find_regblock() - Locate register blocks by type
 + * @pdev: The CXL PCI device to enumerate.
 + * @type: Register Block Indicator id
 + * @map: Enumeration output, clobbered on error
 + *
 + * Return: 0 if register block enumerated, negative error code otherwise
 + *
 + * A CXL DVSEC may point to one or more register blocks, search for them
 + * by @type.
 + */
 +int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
 +                    struct cxl_register_map *map)
 +{
 +      return cxl_find_regblock_instance(pdev, type, map, 0);
 +}
  EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);
  
- resource_size_t cxl_rcrb_to_component(struct device *dev,
-                                     resource_size_t rcrb,
-                                     enum cxl_rcrb which)
 +/**
 + * cxl_count_regblock() - Count instances of a given regblock type.
 + * @pdev: The CXL PCI device to enumerate.
 + * @type: Register Block Indicator id
 + *
 + * Some regblocks may be repeated. Count how many instances.
 + *
 + * Return: count of matching regblocks.
 + */
 +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
 +{
 +      struct cxl_register_map map;
 +      int rc, count = 0;
 +
 +      while (1) {
 +              rc = cxl_find_regblock_instance(pdev, type, &map, count);
 +              if (rc)
 +                      return count;
 +              count++;
 +      }
 +}
 +EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
 +
 +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
 +                   struct cxl_register_map *map)
 +{
 +      struct device *dev = &pdev->dev;
 +      resource_size_t phys_addr;
 +
 +      phys_addr = map->resource;
 +      regs->pmu = devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE);
 +      if (!regs->pmu)
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL);
 +
+ static int cxl_map_regblock(struct cxl_register_map *map)
+ {
+       struct device *dev = map->dev;
+       map->base = ioremap(map->resource, map->max_size);
+       if (!map->base) {
+               dev_err(dev, "failed to map registers\n");
+               return -ENOMEM;
+       }
+       dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource);
+       return 0;
+ }
+ static void cxl_unmap_regblock(struct cxl_register_map *map)
+ {
+       iounmap(map->base);
+       map->base = NULL;
+ }
+ static int cxl_probe_regs(struct cxl_register_map *map)
+ {
+       struct cxl_component_reg_map *comp_map;
+       struct cxl_device_reg_map *dev_map;
+       struct device *dev = map->dev;
+       void __iomem *base = map->base;
+       switch (map->reg_type) {
+       case CXL_REGLOC_RBI_COMPONENT:
+               comp_map = &map->component_map;
+               cxl_probe_component_regs(dev, base, comp_map);
+               dev_dbg(dev, "Set up component registers\n");
+               break;
+       case CXL_REGLOC_RBI_MEMDEV:
+               dev_map = &map->device_map;
+               cxl_probe_device_regs(dev, base, dev_map);
+               if (!dev_map->status.valid || !dev_map->mbox.valid ||
+                   !dev_map->memdev.valid) {
+                       dev_err(dev, "registers not found: %s%s%s\n",
+                               !dev_map->status.valid ? "status " : "",
+                               !dev_map->mbox.valid ? "mbox " : "",
+                               !dev_map->memdev.valid ? "memdev " : "");
+                       return -ENXIO;
+               }
+               dev_dbg(dev, "Probing device registers...\n");
+               break;
+       default:
+               break;
+       }
+       return 0;
+ }
+ int cxl_setup_regs(struct cxl_register_map *map)
+ {
+       int rc;
+       rc = cxl_map_regblock(map);
+       if (rc)
+               return rc;
+       rc = cxl_probe_regs(map);
+       cxl_unmap_regblock(map);
+       return rc;
+ }
+ EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL);
+ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri,
+                                   enum cxl_rcrb which)
  {
        resource_size_t component_reg_phys;
+       resource_size_t rcrb = ri->base;
        void __iomem *addr;
        u32 bar0, bar1;
        u16 cmd;
index bc917a75333f60503168d60ae0a933d278c9fb3a,b1adca9b27ba56b3cc70980664648b8f39784e66..76d92561af29499d2fe14629bdd11247039d5dab
@@@ -241,21 -229,18 +241,23 @@@ struct cxl_device_reg_map 
        struct cxl_reg_map memdev;
  };
  
 +struct cxl_pmu_reg_map {
 +      struct cxl_reg_map pmu;
 +};
 +
  /**
   * struct cxl_register_map - DVSEC harvested register block mapping parameters
+  * @dev: device for devm operations and logging
   * @base: virtual base of the register-block-BAR + @block_offset
   * @resource: physical resource base of the register block
   * @max_size: maximum mapping size to perform register search
   * @reg_type: see enum cxl_regloc_type
   * @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
   */
  struct cxl_register_map {
+       struct device *dev;
        void __iomem *base;
        resource_size_t resource;
        resource_size_t max_size;
@@@ -271,28 -255,19 +273,24 @@@ void cxl_probe_component_regs(struct de
                              struct cxl_component_reg_map *map);
  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,
-                          const struct cxl_register_map *map,
 -int cxl_map_component_regs(struct cxl_register_map *map,
++int cxl_map_component_regs(const struct cxl_register_map *map,
+                          struct cxl_component_regs *regs,
                           unsigned long map_mask);
- int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
-                       const struct cxl_register_map *map);
 -int cxl_map_device_regs(struct cxl_register_map *map,
++int cxl_map_device_regs(const struct cxl_register_map *map,
+                       struct cxl_device_regs *regs);
 +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
 +                   struct cxl_register_map *map);
  
  enum cxl_regloc_type;
 +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
 +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);
- enum cxl_rcrb {
-       CXL_RCRB_DOWNSTREAM,
-       CXL_RCRB_UPSTREAM,
- };
- resource_size_t cxl_rcrb_to_component(struct device *dev,
-                                     resource_size_t rcrb,
-                                     enum cxl_rcrb which);
+ int cxl_setup_regs(struct cxl_register_map *map);
+ struct cxl_dport;
+ resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
+                                          struct cxl_dport *dport);
  
  #define CXL_RESOURCE_NONE ((resource_size_t) -1)
  #define CXL_TARGET_STRLEN 20
Simple merge
Simple merge
index 270d63d11e17dce786a8cec682e19b5dcdf5b7de,99a75c54ee39e0326d02666027297328c00b928f..48f88d96029d17648e0d100196ad03b12944f0bd
@@@ -543,21 -331,22 +524,9 @@@ static int cxl_pci_setup_regs(struct pc
        if (rc)
                return rc;
  
-       rc = cxl_probe_regs(pdev, map);
-       cxl_unmap_regblock(pdev, map);
-       return rc;
- }
- /*
-  * Assume that any RCIEP that emits the CXL memory expander class code
-  * is an RCD
-  */
- static bool is_cxl_restricted(struct pci_dev *pdev)
- {
-       return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
+       return cxl_setup_regs(map);
  }
  
 -/*
 - * CXL v3.0 6.2.3 Table 6-4
 - * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits
 - * mode, otherwise it's 68B flits mode.
 - */
 -static bool cxl_pci_flit_256(struct pci_dev *pdev)
 -{
 -      u16 lnksta2;
 -
 -      pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
 -      return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
 -}
 -
  static int cxl_pci_ras_unmask(struct pci_dev *pdev)
  {
        struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
Simple merge
Simple merge
Simple merge
Simple merge