Re: [PATCH v4 08/15] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 12/12/2024 4:36 AM, Alejandro Lucero Palau wrote:
> On 12/11/24 23:39, Terry Bowman wrote:
>> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
>> registers for the endpoint's Root Port. The same needs to be done for
>> each of the CXL Downstream Switch Ports and CXL Root Ports found between
>> the endpoint and CXL Host Bridge.
>>
>> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
>> sub-topology between the endpoint and the CXL Host Bridge. This function
>> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
>> associated with this Port. The same check will be added in the future for
>> upstream switch ports.
>>
>> Move the RAS register map logic from cxl_dport_map_ras() into
>> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
>> function, cxl_dport_map_ras().
>>
>> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
>> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
>>
>> cxl_dport_init_ras_reporting() must check for previously mapped registers
>> before mapping. This is necessary because endpoints under a CXL switch
>> may share CXL Downstream Switch Ports or CXL Root Ports. Ensure the port
>> registers are only mapped once.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@xxxxxxx>
>
> Reviewed-by: Alejandro Lucero <alucerop@xxxxxxx>
>
>
> Just a nit but, regs mapping could fail, what is properly reported, and 
> the __cxl_handle_ras function checks for the regs iomem being there 
> before using them. But if the mapping failed, any report there is 
> silently dropped. If the AER is happening, maybe to add a WARN_ONCE there?
>

Good point. I'll add the WARN_ONCE().

- Terry
>> ---
>>   drivers/cxl/core/pci.c | 37 +++++++++++++++----------------------
>>   drivers/cxl/cxl.h      |  6 ++----
>>   drivers/cxl/mem.c      | 31 +++++++++++++++++++++++++++++--
>>   3 files changed, 46 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 5b46bc46aaa9..8540d1fd2e25 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -749,18 +749,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
>>   	}
>>   }
>>   
>> -static void cxl_dport_map_ras(struct cxl_dport *dport)
>> -{
>> -	struct cxl_register_map *map = &dport->reg_map;
>> -	struct device *dev = dport->dport_dev;
>> -
>> -	if (!map->component_map.ras.valid)
>> -		dev_dbg(dev, "RAS registers not found\n");
>> -	else if (cxl_map_component_regs(map, &dport->regs.component,
>> -					BIT(CXL_CM_CAP_CAP_ID_RAS)))
>> -		dev_dbg(dev, "Failed to map RAS capability.\n");
>> -}
>> -
>>   static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>>   {
>>   	void __iomem *aer_base = dport->regs.dport_aer;
>> @@ -788,22 +776,27 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>>   /**
>>    * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>>    * @dport: the cxl_dport that needs to be initialized
>> - * @host: host device for devm operations
>>    */
>> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
>> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
>>   {
>> -	dport->reg_map.host = host;
>> -	cxl_dport_map_ras(dport);
>> -
>> -	if (dport->rch) {
>> -		struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
>> -
>> -		if (!host_bridge->native_aer)
>> -			return;
>> +	struct device *dport_dev = dport->dport_dev;
>> +	struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
>>   
>> +	dport->reg_map.host = dport_dev;
>> +	if (dport->rch && host_bridge->native_aer) {
>>   		cxl_dport_map_rch_aer(dport);
>>   		cxl_disable_rch_root_ints(dport);
>>   	}
>> +
>> +	/* dport may have more than 1 downstream EP. Check if already mapped. */
>> +	if (dport->regs.ras)
>> +		return;
>> +
>> +	if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component,
>> +				   BIT(CXL_CM_CAP_CAP_ID_RAS))) {
>> +		dev_err(dport_dev, "Failed to map RAS capability.\n");
>> +		return;
>> +	}
>>   }
>>   EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, CXL);
>>   
>> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
>> index 5406e3ab3d4a..51acca3415b4 100644
>> --- a/drivers/cxl/cxl.h
>> +++ b/drivers/cxl/cxl.h
>> @@ -763,11 +763,9 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
>>   					 resource_size_t rcrb);
>>   
>>   #ifdef CONFIG_PCIEAER_CXL
>> -void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport);
>> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host);
>> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
>>   #else
>> -static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport,
>> -						struct device *host) { }
>> +static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
>>   #endif
>>   
>>   struct cxl_decoder *to_cxl_decoder(struct device *dev);
>> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
>> index a9fd5cd5a0d2..0ae89c9da71e 100644
>> --- a/drivers/cxl/mem.c
>> +++ b/drivers/cxl/mem.c
>> @@ -45,6 +45,31 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data)
>>   	return 0;
>>   }
>>   
>> +static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
>> +{
>> +	struct pci_dev *pdev;
>> +
>> +	if (!dev || !dev_is_pci(dev))
>> +		return false;
>> +
>> +	pdev = to_pci_dev(dev);
>> +
>> +	return (pci_pcie_type(pdev) == pcie_type);
>> +}
>> +
>> +static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
>> +{
>> +	struct cxl_dport *dport = ep->dport;
>> +
>> +	if (dport) {
>> +		struct device *dport_dev = dport->dport_dev;
>> +
>> +		if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) ||
>> +		    dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
>> +			cxl_dport_init_ras_reporting(dport);
>> +	}
>> +}
>> +
>>   static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
>>   				 struct cxl_dport *parent_dport)
>>   {
>> @@ -52,6 +77,9 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
>>   	struct cxl_port *endpoint, *iter, *down;
>>   	int rc;
>>   
>> +	if (parent_dport->rch)
>> +		cxl_dport_init_ras_reporting(parent_dport);
>> +
>>   	/*
>>   	 * Now that the path to the root is established record all the
>>   	 * intervening ports in the chain.
>> @@ -62,6 +90,7 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
>>   
>>   		ep = cxl_ep_load(iter, cxlmd);
>>   		ep->next = down;
>> +		cxl_init_ep_ports_aer(ep);
>>   	}
>>   
>>   	/* Note: endpoint port component registers are derived from @cxlds */
>> @@ -166,8 +195,6 @@ static int cxl_mem_probe(struct device *dev)
>>   	else
>>   		endpoint_parent = &parent_port->dev;
>>   
>> -	cxl_dport_init_ras_reporting(dport, dev);
>> -
>>   	scoped_guard(device, endpoint_parent) {
>>   		if (!endpoint_parent->driver) {
>>   			dev_err(dev, "CXL port topology %s not enabled\n",





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux