Jonathan Cameron wrote:
> On Thu, 01 Dec 2022 13:34:05 -0800
> Dan Williams <dan.j.willi...@intel.com> wrote:
> 
> > From: Robert Richter <rrich...@amd.com>
> > 
> > A downstream port must be connected to a component register block.
> > For restricted hosts the base address is determined from the RCRB. The
> > RCRB is provided by the host's CEDT CHBS entry. Rework CEDT parser to
> > get the RCRB and add code to extract the component register block from
> > it.
> > 
> > RCRB's BAR[0..1] point to the component block containing CXL subsystem
> > component registers. MEMBAR extraction follows the PCI base spec here,
> > esp. 64 bit extraction and memory range alignment (6.0, 7.5.1.2.1). The
> > RCRB base address is cached in the cxl_dport per-host bridge so that the
> > upstream port component registers can be retrieved later by an RCD
> > (RCIEP) associated with the host bridge.
> > 
> > Note: Right now the component register block is used for HDM decoder
> > capability only which is optional for RCDs. If unsupported by the RCD,
> > the HDM init will fail. It is future work to bypass it in this case.
> > 
> > Co-developed-by: Terry Bowman <terry.bow...@amd.com>
> > Signed-off-by: Terry Bowman <terry.bow...@amd.com>
> > Signed-off-by: Robert Richter <rrich...@amd.com>
> > Link: https://lore.kernel.org/r/Y4dsGZ24aJlxSfI1@rric.localdomain
> > [djbw: introduce devm_cxl_add_rch_dport()]
> > Signed-off-by: Dan Williams <dan.j.willi...@intel.com>
> 
> Trivial moans that may have something to do with it being near going home time
> on a Friday.
> 
> Otherwise looks sensible though this was a fairly superficial look.
> 
> Reviewed-by: Jonathan Cameron <jonathan.came...@huawei.com>
> 
> 
> 
> > ---
> >  drivers/cxl/acpi.c            |   51 ++++++++++++++++++++++++++++-----
> >  drivers/cxl/core/port.c       |   53 ++++++++++++++++++++++++++++++----
> >  drivers/cxl/core/regs.c       |   64 
> > +++++++++++++++++++++++++++++++++++++++++
> >  drivers/cxl/cxl.h             |   16 ++++++++++
> >  tools/testing/cxl/Kbuild      |    1 +
> >  tools/testing/cxl/test/cxl.c  |   10 ++++++
> >  tools/testing/cxl/test/mock.c |   19 ++++++++++++
> >  tools/testing/cxl/test/mock.h |    3 ++
> >  8 files changed, 203 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> > index 50d82376097c..db8173f3ee10 100644
> > --- a/drivers/cxl/acpi.c
> > +++ b/drivers/cxl/acpi.c
> 
> >  struct cxl_chbs_context {
> > -   struct device *dev;
> > -   unsigned long long uid;
> > -   resource_size_t chbcr;
> > +   struct device           *dev;
> > +   unsigned long long      uid;
> > +   resource_size_t         rcrb;
> > +   resource_size_t         chbcr;
> > +   u32                     cxl_version;
> >  };
> 
> I'm not keen on this style change because it slightly obscures the meaningful
> changes in this diff + I suspect it's not consistent with rest of the file.

Copy and pasted from Robert's update. Looks much better after hitting it
with clang-format:

@@ -232,7 +239,9 @@ static int add_host_bridge_uport(struct device *match, void 
*arg)
 struct cxl_chbs_context {
        struct device *dev;
        unsigned long long uid;
+       resource_size_t rcrb;
        resource_size_t chbcr;
+       u32 cxl_version;
 };
 
 static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,

> 
> 
> 
> > diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
> > index ec178e69b18f..28ed0ec8ee3e 100644
> > --- a/drivers/cxl/core/regs.c
> > +++ b/drivers/cxl/core/regs.c
> > @@ -307,3 +307,67 @@ int cxl_find_regblock(struct pci_dev *pdev, enum 
> > cxl_regloc_type type,
> >     return -ENODEV;
> >  }
> >  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)
> > +{
> > +   resource_size_t component_reg_phys;
> > +   u32 bar0, bar1;
> > +   void *addr;
> > +   u16 cmd;
> > +   u32 id;
> > +
> > +   if (which == CXL_RCRB_UPSTREAM)
> > +           rcrb += SZ_4K;
> > +
> > +   /*
> > +    * RCRB's BAR[0..1] point to component block containing CXL
> > +    * subsystem component registers. MEMBAR extraction follows
> > +    * the PCI Base spec here, esp. 64 bit extraction and memory
> > +    * ranges alignment (6.0, 7.5.1.2.1).
> > +    */
> > +   if (!request_mem_region(rcrb, SZ_4K, "CXL RCRB"))
> > +           return CXL_RESOURCE_NONE;
> > +   addr = ioremap(rcrb, SZ_4K);
> > +   if (!addr) {
> > +           dev_err(dev, "Failed to map region %pr\n", addr);
> > +           release_mem_region(rcrb, SZ_4K);
> > +           return CXL_RESOURCE_NONE;
> > +   }
> > +
> > +   id = readl(addr + PCI_VENDOR_ID);
> > +   cmd = readw(addr + PCI_COMMAND);
> > +   bar0 = readl(addr + PCI_BASE_ADDRESS_0);
> > +   bar1 = readl(addr + PCI_BASE_ADDRESS_1);
> > +   iounmap(addr);
> > +   release_mem_region(rcrb, SZ_4K);
> > +
> > +   /*
> > +    * Sanity check, see CXL 3.0 Figure 9-8 CXL Device that Does Not
> > +    * Remap Upstream Port and Component Registers
> > +    */
> > +   if (id == U32_MAX) {
> > +           if (which == CXL_RCRB_DOWNSTREAM)
> > +                   dev_err(dev, "Failed to access Downstream Port RCRB\n");
> > +           return CXL_RESOURCE_NONE;
> > +   }
> > +   if (!(cmd & PCI_COMMAND_MEMORY))
> > +           return CXL_RESOURCE_NONE;
> > +   if (bar0 & (PCI_BASE_ADDRESS_MEM_TYPE_1M | PCI_BASE_ADDRESS_SPACE_IO))
> 
> Trivial: A positive match on what we do want might be better...
> 
> I had to got look up MEM_TYPE_1M to find out what on earth it was (marked 
> obsolete which
> I guess isn't surprising.... )
> 
> Up to you though...

The polarity switch is not any prettier, but a comment would save
someone searching what PCI_BASE_ADDRESS_MEM_TYPE_1M is though. I
actually looked that up myself when I first read it.

> 
> > +           return CXL_RESOURCE_NONE;
> > +
> > +   component_reg_phys = bar0 & PCI_BASE_ADDRESS_MEM_MASK;
> > +   if (bar0 & PCI_BASE_ADDRESS_MEM_TYPE_64)
> > +           component_reg_phys |= ((u64)bar1) << 32;
> > +
> > +   if (!component_reg_phys)
> > +           return CXL_RESOURCE_NONE;
> > +
> > +   /* MEMBAR is block size (64k) aligned. */
> > +   if (!IS_ALIGNED(component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE))
> > +           return CXL_RESOURCE_NONE;
> > +
> > +   return component_reg_phys;
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL);
> > diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> > index 281b1db5a271..1342e4e61537 100644
> > --- a/drivers/cxl/cxl.h
> > +++ b/drivers/cxl/cxl.h
> 
> 
> 
> >  #define CXL_RESOURCE_NONE ((resource_size_t) -1)
> >  #define CXL_TARGET_STRLEN 20
> >  
> > @@ -486,12 +494,16 @@ cxl_find_dport_by_dev(struct cxl_port *port, const 
> > struct device *dport_dev)
> >   * @dport: PCI bridge or firmware device representing the downstream link
> >   * @port_id: unique hardware identifier for dport in decoder target list
> >   * @component_reg_phys: downstream port component registers
> > + * @rcrb: base address for the Root Complex Register Block
> > + * @rch: Indicate whether this dport was enumerated in RCH or VH mode
> 
> Clarify this as
>       Indicate this dport was enumerated in RCH rather than VH mode.
> 
> a boolean with an or in the comment is confusing!
> 
> >   * @port: reference to cxl_port that contains this downstream port
> >   */
> >  struct cxl_dport {
> >     struct device *dport;
> >     int port_id;
> >     resource_size_t component_reg_phys;
> > +   resource_size_t rcrb;
> > +   bool rch;
> >     struct cxl_port *port;
> >  };
> 




Reply via email to