[PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers

Terry Bowman posted 16 patches 11 months, 2 weeks ago
There is a newer version of this series
[PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Terry Bowman 11 months, 2 weeks ago
Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.

Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
pointer to the CXL Upstream Port's mapped RAS registers.

Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
register mapping. This is similar to the existing
cxl_dport_init_ras_reporting() but for USP devices.

The USP may have multiple downstream endpoints. Before mapping AER
registers check if the registers are already mapped.

Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
 drivers/cxl/core/pci.c | 15 +++++++++++++++
 drivers/cxl/cxl.h      |  4 ++++
 drivers/cxl/mem.c      |  8 ++++++++
 3 files changed, 27 insertions(+)

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 1af2d0a14f5d..97e6a15bea88 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
 	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
 }
 
+void cxl_uport_init_ras_reporting(struct cxl_port *port)
+{
+	/* uport may have more than 1 downstream EP. Check if already mapped. */
+	if (port->uport_regs.ras)
+		return;
+
+	port->reg_map.host = &port->dev;
+	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
+				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
+		dev_err(&port->dev, "Failed to map RAS capability.\n");
+		return;
+	}
+}
+EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
+
 /**
  * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
  * @dport: the cxl_dport that needs to be initialized
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 727429dfdaed..c51735fe75d6 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -601,6 +601,7 @@ struct cxl_dax_region {
  * @parent_dport: dport that points to this port in the parent
  * @decoder_ida: allocator for decoder ids
  * @reg_map: component and ras register mapping parameters
+ * @uport_regs: mapped component registers
  * @nr_dports: number of entries in @dports
  * @hdm_end: track last allocated HDM decoder instance for allocation ordering
  * @commit_end: cursor to track highest committed decoder for commit ordering
@@ -621,6 +622,7 @@ struct cxl_port {
 	struct cxl_dport *parent_dport;
 	struct ida decoder_ida;
 	struct cxl_register_map reg_map;
+	struct cxl_component_regs uport_regs;
 	int nr_dports;
 	int hdm_end;
 	int commit_end;
@@ -773,8 +775,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
 
 #ifdef CONFIG_PCIEAER_CXL
 void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
+void cxl_uport_init_ras_reporting(struct cxl_port *port);
 #else
 static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
+static inline void cxl_uport_init_ras_reporting(struct cxl_port *port) { }
 #endif
 
 struct cxl_decoder *to_cxl_decoder(struct device *dev);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index dd39f4565be2..97dbca765f4d 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
 static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
 {
 	struct cxl_dport *dport = ep->dport;
+	struct cxl_port *port = ep->next;
 
 	if (dport) {
 		struct device *dport_dev = dport->dport_dev;
@@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
 		    dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
 			cxl_dport_init_ras_reporting(dport);
 	}
+
+	if (port) {
+		struct device *uport_dev = port->uport_dev;
+
+		if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM))
+			cxl_uport_init_ras_reporting(port);
+	}
 }
 
 static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
-- 
2.34.1
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Gregory Price 10 months, 2 weeks ago
On Tue, Jan 07, 2025 at 08:38:45AM -0600, Terry Bowman wrote:
> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> 
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
> 
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
> 
> The USP may have multiple downstream endpoints. Before mapping AER
> registers check if the registers are already mapped.
> 
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>

Reviewed-by: Gregory Price <gourry@gourry.net>
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Ira Weiny 11 months, 1 week ago
Terry Bowman wrote:
> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> 
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
> 
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
> 
> The USP may have multiple downstream endpoints. Before mapping AER
> registers check if the registers are already mapped.
> 
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> ---
>  drivers/cxl/core/pci.c | 15 +++++++++++++++
>  drivers/cxl/cxl.h      |  4 ++++
>  drivers/cxl/mem.c      |  8 ++++++++
>  3 files changed, 27 insertions(+)
> 
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 1af2d0a14f5d..97e6a15bea88 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>  }
>  
> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> +{
> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
> +	if (port->uport_regs.ras)
> +		return;
> +
> +	port->reg_map.host = &port->dev;
> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
> +		return;

Why return here?  Actually I think 8/16 had the same issue now that I see
this.

Other than that:

Reviewed-by: Ira Weiny <ira.weiny@intel.com>

[snip]
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Bowman, Terry 11 months, 1 week ago


On 1/14/2025 4:02 PM, Ira Weiny wrote:
> Terry Bowman wrote:
>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>>
>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
>> pointer to the CXL Upstream Port's mapped RAS registers.
>>
>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
>> register mapping. This is similar to the existing
>> cxl_dport_init_ras_reporting() but for USP devices.
>>
>> The USP may have multiple downstream endpoints. Before mapping AER
>> registers check if the registers are already mapped.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> ---
>>  drivers/cxl/core/pci.c | 15 +++++++++++++++
>>  drivers/cxl/cxl.h      |  4 ++++
>>  drivers/cxl/mem.c      |  8 ++++++++
>>  3 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 1af2d0a14f5d..97e6a15bea88 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>>  }
>>  
>> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
>> +{
>> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
>> +	if (port->uport_regs.ras)
>> +		return;
>> +
>> +	port->reg_map.host = &port->dev;
>> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
>> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
>> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
>> +		return;
> Why return here?  Actually I think 8/16 had the same issue now that I see
> this.
>
> Other than that:
>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
>
> [snip]
If RAS registers fail mapping then exit to avoid CXL Port error handler initialization.
The CXL Port error handlers rely on RAS registers for logging and without mapped RAS
registers the error handlers will return immediately.

Regards,
Terry
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Ira Weiny 11 months, 1 week ago
Bowman, Terry wrote:
> 
> 
> 
> On 1/14/2025 4:02 PM, Ira Weiny wrote:
> > Terry Bowman wrote:
> >> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> >>
> >> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> >> pointer to the CXL Upstream Port's mapped RAS registers.
> >>
> >> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> >> register mapping. This is similar to the existing
> >> cxl_dport_init_ras_reporting() but for USP devices.
> >>
> >> The USP may have multiple downstream endpoints. Before mapping AER
> >> registers check if the registers are already mapped.
> >>
> >> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> >> ---
> >>  drivers/cxl/core/pci.c | 15 +++++++++++++++
> >>  drivers/cxl/cxl.h      |  4 ++++
> >>  drivers/cxl/mem.c      |  8 ++++++++
> >>  3 files changed, 27 insertions(+)
> >>
> >> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> >> index 1af2d0a14f5d..97e6a15bea88 100644
> >> --- a/drivers/cxl/core/pci.c
> >> +++ b/drivers/cxl/core/pci.c
> >> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> >>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
> >>  }
> >>  
> >> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> >> +{
> >> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
> >> +	if (port->uport_regs.ras)
> >> +		return;
> >> +
> >> +	port->reg_map.host = &port->dev;
> >> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> >> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> >> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
> >> +		return;
> > Why return here?  Actually I think 8/16 had the same issue now that I see
> > this.
> >
> > Other than that:
> >
> > Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> >
> > [snip]
> If RAS registers fail mapping then exit to avoid CXL Port error handler initialization.
> The CXL Port error handlers rely on RAS registers for logging and without mapped RAS
> registers the error handlers will return immediately.

Sorry I was not clear and I should not have clipped the text so much.  You
return in a block which is at the end of the function:


+void cxl_uport_init_ras_reporting(struct cxl_port *port)
+{
+       /* uport may have more than 1 downstream EP. Check if already mapped. */
+       if (port->uport_regs.ras)
+               return;
+
+       port->reg_map.host = &port->dev;
+       if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
+                                  BIT(CXL_CM_CAP_CAP_ID_RAS))) {
+               dev_err(&port->dev, "Failed to map RAS capability.\n");
+               return;
+       }
+}

So no need for this specific statement?

Ira
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Bowman, Terry 11 months, 1 week ago


On 1/14/2025 5:38 PM, Ira Weiny wrote:
> Bowman, Terry wrote:
>>
>>
>> On 1/14/2025 4:02 PM, Ira Weiny wrote:
>>> Terry Bowman wrote:
>>>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>>>>
>>>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
>>>> pointer to the CXL Upstream Port's mapped RAS registers.
>>>>
>>>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
>>>> register mapping. This is similar to the existing
>>>> cxl_dport_init_ras_reporting() but for USP devices.
>>>>
>>>> The USP may have multiple downstream endpoints. Before mapping AER
>>>> registers check if the registers are already mapped.
>>>>
>>>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>>>> ---
>>>>  drivers/cxl/core/pci.c | 15 +++++++++++++++
>>>>  drivers/cxl/cxl.h      |  4 ++++
>>>>  drivers/cxl/mem.c      |  8 ++++++++
>>>>  3 files changed, 27 insertions(+)
>>>>
>>>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>>>> index 1af2d0a14f5d..97e6a15bea88 100644
>>>> --- a/drivers/cxl/core/pci.c
>>>> +++ b/drivers/cxl/core/pci.c
>>>> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>>>>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>>>>  }
>>>>  
>>>> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
>>>> +{
>>>> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
>>>> +	if (port->uport_regs.ras)
>>>> +		return;
>>>> +
>>>> +	port->reg_map.host = &port->dev;
>>>> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
>>>> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
>>>> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
>>>> +		return;
>>> Why return here?  Actually I think 8/16 had the same issue now that I see
>>> this.
>>>
>>> Other than that:
>>>
>>> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
>>>
>>> [snip]
>> If RAS registers fail mapping then exit to avoid CXL Port error handler initialization.
>> The CXL Port error handlers rely on RAS registers for logging and without mapped RAS
>> registers the error handlers will return immediately.
> Sorry I was not clear and I should not have clipped the text so much.  You
> return in a block which is at the end of the function:
>
>
> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> +{
> +       /* uport may have more than 1 downstream EP. Check if already mapped. */
> +       if (port->uport_regs.ras)
> +               return;
> +
> +       port->reg_map.host = &port->dev;
> +       if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> +                                  BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> +               dev_err(&port->dev, "Failed to map RAS capability.\n");
> +               return;
> +       }
> +}
>
> So no need for this specific statement?
>
> Ira

I wrote it this way to add the handler initialization (after the return) in later patch
without a diff removal. But, your correct, I can remove the 'return' statement in this patch
and add in later patch without cluttering the diff.

Thanks. I'll make the change.

Regards,
Terry
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Jonathan Cameron 11 months, 1 week ago
On Tue, 14 Jan 2025 17:49:44 -0600
"Bowman, Terry" <terry.bowman@amd.com> wrote:

> On 1/14/2025 5:38 PM, Ira Weiny wrote:
> > Bowman, Terry wrote:  
> >>
> >>
> >> On 1/14/2025 4:02 PM, Ira Weiny wrote:  
> >>> Terry Bowman wrote:  
> >>>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> >>>>
> >>>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> >>>> pointer to the CXL Upstream Port's mapped RAS registers.
> >>>>
> >>>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> >>>> register mapping. This is similar to the existing
> >>>> cxl_dport_init_ras_reporting() but for USP devices.
> >>>>
> >>>> The USP may have multiple downstream endpoints. Before mapping AER
> >>>> registers check if the registers are already mapped.
> >>>>
> >>>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> >>>> ---
> >>>>  drivers/cxl/core/pci.c | 15 +++++++++++++++
> >>>>  drivers/cxl/cxl.h      |  4 ++++
> >>>>  drivers/cxl/mem.c      |  8 ++++++++
> >>>>  3 files changed, 27 insertions(+)
> >>>>
> >>>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> >>>> index 1af2d0a14f5d..97e6a15bea88 100644
> >>>> --- a/drivers/cxl/core/pci.c
> >>>> +++ b/drivers/cxl/core/pci.c
> >>>> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> >>>>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
> >>>>  }
> >>>>  
> >>>> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> >>>> +{
> >>>> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
> >>>> +	if (port->uport_regs.ras)
> >>>> +		return;
> >>>> +
> >>>> +	port->reg_map.host = &port->dev;
> >>>> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> >>>> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> >>>> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
> >>>> +		return;  
> >>> Why return here?  Actually I think 8/16 had the same issue now that I see
> >>> this.
> >>>
> >>> Other than that:
> >>>
> >>> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> >>>
> >>> [snip]  
> >> If RAS registers fail mapping then exit to avoid CXL Port error handler initialization.
> >> The CXL Port error handlers rely on RAS registers for logging and without mapped RAS
> >> registers the error handlers will return immediately.  
> > Sorry I was not clear and I should not have clipped the text so much.  You
> > return in a block which is at the end of the function:
> >
> >
> > +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> > +{
> > +       /* uport may have more than 1 downstream EP. Check if already mapped. */
> > +       if (port->uport_regs.ras)
> > +               return;
> > +
> > +       port->reg_map.host = &port->dev;
> > +       if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> > +                                  BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> > +               dev_err(&port->dev, "Failed to map RAS capability.\n");
> > +               return;
> > +       }
> > +}
> >
> > So no need for this specific statement?
> >
> > Ira  
> 
> I wrote it this way to add the handler initialization (after the return) in later patch
> without a diff removal. But, your correct, I can remove the 'return' statement in this patch
> and add in later patch without cluttering the diff.
> 
> Thanks. I'll make the change.
> 
Leave it as it stands.  I'm sure Ira doesn't mind given the additions later.
I'd prefer we keep things clean across the series.

Jonathan

> Regards,
> Terry
> 
> 
>
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Jonathan Cameron 11 months, 1 week ago
On Tue, 7 Jan 2025 08:38:45 -0600
Terry Bowman <terry.bowman@amd.com> wrote:

> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> 
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
> 
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
> 
> The USP may have multiple downstream endpoints. Before mapping AER
> registers check if the registers are already mapped.
> 
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> ---
>  drivers/cxl/core/pci.c | 15 +++++++++++++++
>  drivers/cxl/cxl.h      |  4 ++++
>  drivers/cxl/mem.c      |  8 ++++++++
>  3 files changed, 27 insertions(+)
> 
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 1af2d0a14f5d..97e6a15bea88 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>  }
>  
> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> +{
> +	/* uport may have more than 1 downstream EP. Check if already mapped. */

Is it worth a lockdep check in here on whatever lock is stoping this racing?

> +	if (port->uport_regs.ras)
> +		return;
> +
> +	port->reg_map.host = &port->dev;
> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
> +		return;
> +	}
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
> +
>  /**
>   * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>   * @dport: the cxl_dport that needs to be initialized
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index 727429dfdaed..c51735fe75d6 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -601,6 +601,7 @@ struct cxl_dax_region {
>   * @parent_dport: dport that points to this port in the parent
>   * @decoder_ida: allocator for decoder ids
>   * @reg_map: component and ras register mapping parameters
> + * @uport_regs: mapped component registers
>   * @nr_dports: number of entries in @dports
>   * @hdm_end: track last allocated HDM decoder instance for allocation ordering
>   * @commit_end: cursor to track highest committed decoder for commit ordering
> @@ -621,6 +622,7 @@ struct cxl_port {
>  	struct cxl_dport *parent_dport;
>  	struct ida decoder_ida;
>  	struct cxl_register_map reg_map;
> +	struct cxl_component_regs uport_regs;
>  	int nr_dports;
>  	int hdm_end;
>  	int commit_end;
> @@ -773,8 +775,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
>  
>  #ifdef CONFIG_PCIEAER_CXL
>  void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
> +void cxl_uport_init_ras_reporting(struct cxl_port *port);
>  #else
>  static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
> +static inline void cxl_uport_init_ras_reporting(struct cxl_port *port) { }
>  #endif
>  
>  struct cxl_decoder *to_cxl_decoder(struct device *dev);
> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index dd39f4565be2..97dbca765f4d 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
>  static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
>  {
>  	struct cxl_dport *dport = ep->dport;
> +	struct cxl_port *port = ep->next;
>  
>  	if (dport) {
>  		struct device *dport_dev = dport->dport_dev;
> @@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
>  		    dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
>  			cxl_dport_init_ras_reporting(dport);
>  	}
> +
> +	if (port) {
> +		struct device *uport_dev = port->uport_dev;
> +
> +		if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM))
> +			cxl_uport_init_ras_reporting(port);
> +	}
>  }
>  
>  static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
Re: [PATCH v5 09/16] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
Posted by Bowman, Terry 11 months, 1 week ago


On 1/14/2025 5:35 AM, Jonathan Cameron wrote:
> On Tue, 7 Jan 2025 08:38:45 -0600
> Terry Bowman <terry.bowman@amd.com> wrote:
>
>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>>
>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
>> pointer to the CXL Upstream Port's mapped RAS registers.
>>
>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
>> register mapping. This is similar to the existing
>> cxl_dport_init_ras_reporting() but for USP devices.
>>
>> The USP may have multiple downstream endpoints. Before mapping AER
>> registers check if the registers are already mapped.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> ---
>>  drivers/cxl/core/pci.c | 15 +++++++++++++++
>>  drivers/cxl/cxl.h      |  4 ++++
>>  drivers/cxl/mem.c      |  8 ++++++++
>>  3 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 1af2d0a14f5d..97e6a15bea88 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -773,6 +773,21 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>>  	writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>>  }
>>  
>> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
>> +{
>> +	/* uport may have more than 1 downstream EP. Check if already mapped. */
> Is it worth a lockdep check in here on whatever lock is stoping this racing?


Yes, it is. Thanks Jonathan.

Regards,
Terry

>> +	if (port->uport_regs.ras)
>> +		return;
>> +
>> +	port->reg_map.host = &port->dev;
>> +	if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
>> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
>> +		dev_err(&port->dev, "Failed to map RAS capability.\n");
>> +		return;
>> +	}
>> +}
>> +EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
>> +
>>  /**
>>   * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>>   * @dport: the cxl_dport that needs to be initialized
>> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
>> index 727429dfdaed..c51735fe75d6 100644
>> --- a/drivers/cxl/cxl.h
>> +++ b/drivers/cxl/cxl.h
>> @@ -601,6 +601,7 @@ struct cxl_dax_region {
>>   * @parent_dport: dport that points to this port in the parent
>>   * @decoder_ida: allocator for decoder ids
>>   * @reg_map: component and ras register mapping parameters
>> + * @uport_regs: mapped component registers
>>   * @nr_dports: number of entries in @dports
>>   * @hdm_end: track last allocated HDM decoder instance for allocation ordering
>>   * @commit_end: cursor to track highest committed decoder for commit ordering
>> @@ -621,6 +622,7 @@ struct cxl_port {
>>  	struct cxl_dport *parent_dport;
>>  	struct ida decoder_ida;
>>  	struct cxl_register_map reg_map;
>> +	struct cxl_component_regs uport_regs;
>>  	int nr_dports;
>>  	int hdm_end;
>>  	int commit_end;
>> @@ -773,8 +775,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
>>  
>>  #ifdef CONFIG_PCIEAER_CXL
>>  void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
>> +void cxl_uport_init_ras_reporting(struct cxl_port *port);
>>  #else
>>  static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
>> +static inline void cxl_uport_init_ras_reporting(struct cxl_port *port) { }
>>  #endif
>>  
>>  struct cxl_decoder *to_cxl_decoder(struct device *dev);
>> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
>> index dd39f4565be2..97dbca765f4d 100644
>> --- a/drivers/cxl/mem.c
>> +++ b/drivers/cxl/mem.c
>> @@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
>>  static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
>>  {
>>  	struct cxl_dport *dport = ep->dport;
>> +	struct cxl_port *port = ep->next;
>>  
>>  	if (dport) {
>>  		struct device *dport_dev = dport->dport_dev;
>> @@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
>>  		    dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
>>  			cxl_dport_init_ras_reporting(dport);
>>  	}
>> +
>> +	if (port) {
>> +		struct device *uport_dev = port->uport_dev;
>> +
>> +		if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM))
>> +			cxl_uport_init_ras_reporting(port);
>> +	}
>>  }
>>  
>>  static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,