RE: [PATCH v4 3/3] cxl/pci: Add sysfs attribute for CXL 1.1 device link status

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

 



Kobayashi,Daisuke wrote:
> Add sysfs attribute for CXL 1.1 device link status to the cxl pci device.
> 
> In CXL1.1, the link status of the device is included in the RCRB mapped to
> the memory mapped register area. Critically, that arrangement makes the link
> status and control registers invisible to existing PCI user tooling.
> 
> Export those registers via sysfs with the expectation that PCI user
> tooling will alternatively look for these sysfs files when attempting to
> access to these CXL 1.1 endpoints registers.
> 
> Signed-off-by: "Kobayashi,Daisuke" <kobayashi.da-06@xxxxxxxxxxx>
> ---
>  drivers/cxl/pci.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 74 insertions(+)
> 
> diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
> index 2ff361e756d6..0ff15738b1ba 100644
> --- a/drivers/cxl/pci.c
> +++ b/drivers/cxl/pci.c
> @@ -786,6 +786,79 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
>  	return 0;
>  }
>  
> +static ssize_t rcd_link_cap_show(struct device *dev,
> +				   struct device_attribute *attr, char *buf)
> +{
> +	struct cxl_port *port;
> +	struct cxl_dport *dport;
> +	struct device *parent = dev->parent;
> +	struct pci_dev *parent_pdev = to_pci_dev(parent);
> +
> +	port = cxl_pci_find_port(parent_pdev, &dport);
> +	if (!port)
> +		return -EINVAL;

A few problems with this:

1/ No need to convert to the parent PCI device when there is a lookup
routine to go from cxl_memdev to its upstream port.

        struct cxl_dev_state *cxlds = dev_get_drvdata(dev);
        struct cxl_memdev *cxlmd = cxlds->cxlmd;

2/ The port reference is leaked Add a put_cxl_port() __free() routine
like this:

	diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
	index 534e25e2f0a4..d81bc4cc0a4c 100644
	--- a/drivers/cxl/cxl.h
	+++ b/drivers/cxl/cxl.h
	@@ -744,6 +744,7 @@ DEFINE_FREE(put_cxl_root, struct cxl_root *, if (_T) put_cxl_root(_T))
	 int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
	 void cxl_bus_rescan(void);
	 void cxl_bus_drain(void);
	+DEFINE_FREE(put_cxl_port, struct cxl_port *, if (_T) put_cxl_port(_T))
	 struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
	                                   struct cxl_dport **dport);
	 struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
	
...and then:

	struct cxl_port *port __free(put_cxl_port) = cxl_mem_find_port(cxlmd, &dport);

3/ The port corresponding to a memdev can disappear at any time so you
need to do the same validation the cxl_mem_probe() does to keep the port
active during the register access:

	guard(device)(&port->dev);
	if (!port->dev.driver)
		return -ENXIO;

...then you can read from the cached PCIe capability similar to how the
error handler path reads from aer_cap.




[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