All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: <linux-cxl@vger.kernel.org>, <linux-pci@vger.kernel.org>,
	<nvdimm@lists.linux.dev>
Subject: Re: [PATCH v3 32/40] cxl/core/port: Add switch port enumeration
Date: Tue, 1 Feb 2022 12:13:28 +0000	[thread overview]
Message-ID: <20220201121328.00006f3e@Huawei.com> (raw)
In-Reply-To: <164298428940.3018233.18042207990919432824.stgit@dwillia2-desk3.amr.corp.intel.com>

On Sun, 23 Jan 2022 16:31:29 -0800
Dan Williams <dan.j.williams@intel.com> wrote:

> So far the platorm level CXL resources have been enumerated by the
> cxl_acpi driver, and cxl_pci has gathered all the pre-requisite
> information it needs to fire up a cxl_mem driver. However, the first
> thing the cxl_mem driver will be tasked to do is validate that all the
> PCIe Switches in its ancestry also have CXL capabilities and an CXL.mem
> link established.
> 
> Provide a common mechanism for a CXL.mem endpoint driver to enumerate
> all the ancestor CXL ports in the topology and validate CXL.mem
> connectivity.
> 
> Multiple endpoints may end up racing to establish a shared port in the
> topology. This race is resolved via taking the device-lock on a parent
> CXL Port before establishing a new child. The winner of the race
> establishes the port, the loser simply registers its interest in the
> port via 'struct cxl_ep' place-holder reference.
> 
> At endpoint teardown the same parent port lock is taken as 'struct
> cxl_ep' references are deleted. Last endpoint to drop its reference
> unregisters the port.
> 
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

I've not done Qemu switch emulation yet, but should probably get on with
it to test his (not a big job, but lots of other stuff to do as ever!)
As such I haven't tested this beyond the not breaking cases without a
switch yet.

Comments inline. Mostly trivial but I think the error handling paths in
add_port_register_ep() need another look.

Jonathan


> ---
>  drivers/cxl/acpi.c      |   17 --
>  drivers/cxl/core/port.c |  379 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/cxl/cxl.h       |   20 ++
>  3 files changed, 400 insertions(+), 16 deletions(-)
> 


> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index 26c3eb9180cd..cd95d9f8c624 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -7,6 +7,7 @@

...


> +/**
> + * cxl_add_ep - register an endpoint's interest in a port
> + * @port: a port in the endpoint's topology ancestry
> + * @ep_dev: device representing the endpoint
> + *
> + * Intermediate CXL ports are scanned based on the arrival of endpoints.
> + * When those endpoints depart the port can be destroyed once all
> + * endpoints that care about that port have been removed.
> + */
> +static int cxl_add_ep(struct cxl_port *port, struct device *ep_dev)
> +{
> +	struct cxl_ep *ep;
> +	int rc;
> +
> +	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
> +	if (!ep)
> +		return -ENOMEM;
> +
> +	INIT_LIST_HEAD(&ep->list);
> +	ep->ep = get_device(ep_dev);
> +
> +	rc = add_ep(port, ep);
> +	if (rc)
> +		cxl_ep_release(ep);
> +	return rc;
> +}
> +


...

> +
> +static struct device *grandparent(struct device *dev)
> +{
> +	if (dev && dev->parent)
> +		return dev->parent->parent;
> +	return NULL;
> +}
> +
> +static void delete_switch_port(struct cxl_memdev *cxlmd, struct cxl_port *port,
> +			       struct list_head *dports)
> +{
> +	struct cxl_dport *dport, *_d;
> +

This hand manipulation of devm managed stuff could benefit from an explanatory
comment or two.

> +	dev_dbg(&cxlmd->dev, "delete %s\n", dev_name(&port->dev));
> +	list_for_each_entry_safe(dport, _d, dports, list) {
> +		devm_release_action(&port->dev, cxl_dport_unlink, dport);
> +		devm_release_action(&port->dev, cxl_dport_remove, dport);
> +		devm_kfree(&port->dev, dport);
> +	}
> +	devm_release_action(port->dev.parent, cxl_unlink_uport, port);
> +	devm_release_action(port->dev.parent, unregister_port, port);
> +}
> +
> +static void cxl_remove_ep(void *data)

Maybe naming needs a rethink.  Instinctively I'd expect this to do the opposite
of add_ep whereas it does a whole lot more. Mind you I can't think of
a better name...

> +{
> +	struct cxl_memdev *cxlmd = data;
> +	struct device *iter;
> +
> +	for (iter = &cxlmd->dev; iter; iter = grandparent(iter)) {
> +		struct device *dport_dev = grandparent(iter);
> +		struct cxl_port *port, *parent_port;
> +		LIST_HEAD(reap_dports);
> +		struct cxl_ep *ep;
> +
> +		if (!dport_dev)
> +			break;
> +
> +		port = find_cxl_port(dport_dev);
> +		if (!port || is_cxl_root(port)) {
> +			put_device(&port->dev);
> +			continue;
> +		}
> +
> +		parent_port = to_cxl_port(port->dev.parent);
> +		cxl_device_lock(&parent_port->dev);
> +		if (!parent_port->dev.driver) {

Might be good to have a comment here on 'why' this condition might be hit.
In similar path in setup there happens to be a dev_dbg() that does
the job of a comment.

> +			cxl_device_unlock(&parent_port->dev);
> +			put_device(&port->dev);
> +			continue;
> +		}
> +
> +		cxl_device_lock(&port->dev);
> +		ep = find_ep(port, &cxlmd->dev);
> +		dev_dbg(&cxlmd->dev, "disconnect %s from %s\n",
> +			ep ? dev_name(ep->ep) : "", dev_name(&port->dev));
> +		cxl_ep_release(ep);
> +		if (ep && !port->dead && list_empty(&port->endpoints) &&
> +		    !is_cxl_root(parent_port)) {
> +			/*
> +			 * This was the last ep attached to a dynamically
> +			 * enumerated port. Block new cxl_add_ep() and garbage
> +			 * collect the port.
> +			 */
> +			port->dead = true;
> +			list_splice_init(&port->dports, &reap_dports);
> +		}
> +		cxl_device_unlock(&port->dev);
> +
> +		if (!list_empty(&reap_dports))
> +			delete_switch_port(cxlmd, port, &reap_dports);
> +		put_device(&port->dev);
> +		cxl_device_unlock(&parent_port->dev);
> +	}
> +}
> +
> +static resource_size_t find_component_registers(struct device *dev)
> +{
> +	struct cxl_register_map map;
> +	struct pci_dev *pdev;
> +
> +	/*
> +	 * Theoretically, CXL component registers can be hosted on a
> +	 * non-PCI device, in practice, only cxl_test hits this case.
> +	 */
> +	if (!dev_is_pci(dev))
> +		return CXL_RESOURCE_NONE;
> +
> +	pdev = to_pci_dev(dev);
> +
> +	cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
> +	return cxl_regmap_to_base(pdev, &map);
> +}
> +
> +static int add_port_register_ep(struct cxl_memdev *cxlmd,
> +				struct device *uport_dev,
> +				struct device *dport_dev)
> +{
> +	struct cxl_port *port, *parent_port;
> +	resource_size_t component_reg_phys;
> +	int rc;
> +
> +	parent_port = find_cxl_port(grandparent(dport_dev));
> +	if (!parent_port) {
> +		/*
> +		 * The root CXL port is added by the CXL platform driver, fail
> +		 * for now to be re-probed after platform driver attaches.
> +		 */
> +		if (!grandparent(dport_dev)) {

Possibly worth a local variable for grandparent(dport_dev)?
Could you pull this out before trying to call find_cxl_port(NULL)?
Obviously that's safe, but this seems more complex than it needs to be.

	struct device *gp = grandparent(dport_dev);

	if (!gp) {
		/*
		 * The root CXL port is added by the CXL platform driver, fail
		 * for now to be re-probed after platform driver attaches.
		 */
		dev_dbg(&cxlmd->dev, "%s is a root dport\n",
			dev_name(dport_dev));
			return -ENXIO;
	}
	parent_port = find_cxl_port(gp);
	if (!parent_port) {
		/* iterate to create this parent port */
		return -EAGAIN;
	}


> +			dev_dbg(&cxlmd->dev, "%s is a root dport\n",
> +				dev_name(dport_dev));
> +			return -ENXIO;
> +		}
> +		/* ...otherwise, iterate to create this parent_port */
> +		return -EAGAIN;
> +	}
> +
> +	cxl_device_lock(&parent_port->dev);
> +	if (!parent_port->dev.driver) {
> +		dev_warn(&cxlmd->dev,
> +			 "port %s:%s disabled, failed to enumerate CXL.mem\n",
> +			 dev_name(&parent_port->dev), dev_name(uport_dev));
> +		rc = -ENXIO;
> +		goto out;

In this path, port isn't initialized (see below)

> +	}
> +
> +	port = find_cxl_port_at(parent_port, dport_dev);
> +	if (!port) {
> +		component_reg_phys = find_component_registers(uport_dev);
> +		port = devm_cxl_add_port(&parent_port->dev, uport_dev,
> +					 component_reg_phys, parent_port);
> +		if (!IS_ERR(port))
> +			get_device(&port->dev);
> +	}
> +out:
> +	cxl_device_unlock(&parent_port->dev);
> +
> +	if (IS_ERR(port))

Port isn't initialized in all paths above...
I think you want to skip on to the put_device(&parent_port->dev) if
rc is set..

> +		rc = PTR_ERR(port);
> +	else {

We could enter this path with rc set and continue as if it wasn't.

> +		dev_dbg(&cxlmd->dev, "add to new port %s:%s\n",
> +			dev_name(&port->dev), dev_name(port->uport));
> +		rc = cxl_add_ep(port, &cxlmd->dev);
> +		if (rc == -EEXIST) {
> +			/*
> +			 * "can't" happen, but this error code means
> +			 * something to the caller, so translate it.
> +			 */
> +			rc = -ENXIO;
> +		}
> +		put_device(&port->dev);
> +	}
> +
> +	put_device(&parent_port->dev);
> +	return rc;
> +}
> +
> +int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
> +{
> +	struct device *dev = &cxlmd->dev;
> +	struct device *iter;
> +	int rc;
> +
> +	rc = devm_add_action_or_reset(&cxlmd->dev, cxl_remove_ep, cxlmd);
> +	if (rc)
> +		return rc;
> +
> +	/*
> +	 * Scan for and add all cxl_ports in this device's ancestry.
> +	 * Repeat until no more ports are added. Abort if a port add
> +	 * attempt fails.
> +	 */
> +retry:
> +	for (iter = dev; iter; iter = grandparent(iter)) {
> +		struct device *dport_dev = grandparent(iter);
> +		struct device *uport_dev;
> +		struct cxl_port *port;
> +
> +		if (!dport_dev)
> +			break;
> +		uport_dev = dport_dev->parent;
> +		dev_dbg(dev, "scan: iter: %s dport_dev: %s parent: %s\n",
> +			dev_name(iter), dev_name(dport_dev),
> +			uport_dev ? dev_name(uport_dev) : "'none'");

Given the uport_dev is something we don't expect to happen and it'll be warned
on anyway, maybe move this dev_dbg() after the check and possibly augment that
dev_warn with iter so all the information is there as well.

Will end up with a simpler dev_dbg()


> +		if (!uport_dev) {
> +			dev_warn(dev, "unexpected topology, no parent for %s\n",
> +				 dev_name(dport_dev));
> +			rc = -ENXIO;
> +			break;

This rc isn't returned below.
return -ENOXIO; here is probably better option anyway.

> +		}
> +
> +		port = find_cxl_port(dport_dev);
> +		if (port) {
> +			dev_dbg(&cxlmd->dev,
> +				"found already registered port %s:%s\n",
> +				dev_name(&port->dev), dev_name(port->uport));
> +			rc = cxl_add_ep(port, &cxlmd->dev);
> +
> +			/*
> +			 * If the endpoint already exists in the port's list,
> +			 * that's ok, it was added on a previous pass.
> +			 * Otherwise, retry in add_port_register_ep() after
> +			 * taking the parent_port lock as the current port may
> +			 * be being reaped.
> +			 */
> +			if (rc && rc != -EEXIST) {
> +				put_device(&port->dev);
> +				return rc;
> +			}
> +
> +			if (is_cxl_port(port->dev.parent) &&
> +			    !is_cxl_root(to_cxl_port(port->dev.parent))) {

I'd like a comment on what this is matching.  What types of port will
result in us following this path?

> +				put_device(&port->dev);
> +				continue;
> +			}
> +
> +			put_device(&port->dev);
> +			break;
> +		}
> +
> +		rc = add_port_register_ep(cxlmd, uport_dev, dport_dev);
> +		/* port missing, try to add parent */
> +		if (rc == -EAGAIN)
> +			continue;
> +		/* failed to add ep or port */
> +		if (rc)
> +			return rc;
> +		/* port added, new descendants possible, start over */
> +		goto retry;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL);
> +
> +struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd)
> +{
> +	return find_cxl_port(grandparent(&cxlmd->dev));
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_mem_find_port, CXL);
> +

>  static int decoder_populate_targets(struct cxl_decoder *cxld,
>  				    struct cxl_port *port, int *target_map)
>  {



  reply	other threads:[~2022-02-01 12:13 UTC|newest]

Thread overview: 172+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-24  0:28 [PATCH v3 00/40] CXL.mem Topology Discovery and Hotplug Support Dan Williams
2022-01-24  0:28 ` [PATCH v3 01/40] cxl: Rename CXL_MEM to CXL_PCI Dan Williams
2022-01-24  0:28 ` [PATCH v3 02/40] cxl/pci: Implement Interface Ready Timeout Dan Williams
2022-01-31 22:21   ` Ben Widawsky
2022-01-31 23:11     ` Dan Williams
2022-01-31 23:25       ` Ben Widawsky
2022-01-31 23:47         ` Dan Williams
2022-01-31 23:51   ` [PATCH v4 " Dan Williams
2022-01-24  0:28 ` [PATCH v3 03/40] cxl/pci: Defer mailbox status checks to command timeouts Dan Williams
2022-01-31 22:28   ` Ben Widawsky
2022-01-24  0:29 ` [PATCH v3 04/40] cxl: Flesh out register names Dan Williams
2022-01-24  0:29 ` [PATCH v3 05/40] cxl/pci: Add new DVSEC definitions Dan Williams
2022-01-24  0:29 ` [PATCH v3 06/40] cxl/acpi: Map component registers for Root Ports Dan Williams
2022-01-24  0:29 ` [PATCH v3 07/40] cxl: Introduce module_cxl_driver Dan Williams
2022-01-24  0:29 ` [PATCH v3 08/40] cxl/core/port: Rename bus.c to port.c Dan Williams
2022-01-31 22:34   ` Ben Widawsky
2022-01-24  0:29 ` [PATCH v3 09/40] cxl/decoder: Hide physical address information from non-root Dan Williams
2022-01-31 14:14   ` Jonathan Cameron
2022-01-31 22:34   ` Ben Widawsky
2022-01-24  0:29 ` [PATCH v3 10/40] cxl/core: Convert decoder range to resource Dan Williams
2022-01-24  0:29 ` [PATCH v3 11/40] cxl/core/port: Clarify decoder creation Dan Williams
2022-01-31 14:46   ` Jonathan Cameron
2022-01-31 21:17     ` Dan Williams
2022-01-31 21:33   ` [PATCH v4 " Dan Williams
2022-02-01 10:49     ` Jonathan Cameron
2022-01-24  0:29 ` [PATCH v3 12/40] cxl/core: Fix cxl_probe_component_regs() error message Dan Williams
2022-01-31 14:53   ` Jonathan Cameron
2022-01-31 22:29     ` Dan Williams
2022-01-31 22:39   ` Ben Widawsky
2022-01-24  0:29 ` [PATCH v3 13/40] cxl/core/port: Make passthrough decoder init implicit Dan Williams
2022-01-31 14:56   ` Jonathan Cameron
2022-01-24  0:29 ` [PATCH v3 14/40] cxl/core: Track port depth Dan Williams
2022-01-31 14:57   ` Jonathan Cameron
2022-01-24  0:29 ` [PATCH v3 15/40] cxl: Prove CXL locking Dan Williams
2022-01-31 15:48   ` Jonathan Cameron
2022-01-31 19:43     ` Dan Williams
2022-01-31 19:50   ` [PATCH v4 " Dan Williams
2022-01-31 23:23     ` Ben Widawsky
2022-01-24  0:30 ` [PATCH v3 16/40] cxl/core/port: Use dedicated lock for decoder target list Dan Williams
2022-01-26  2:54   ` [PATCH v4 " Dan Williams
2022-01-31 15:59     ` Jonathan Cameron
2022-01-31 23:31       ` Dan Williams
2022-01-31 23:34     ` Ben Widawsky
2022-01-31 23:38       ` Dan Williams
2022-01-31 23:42         ` Ben Widawsky
2022-01-31 23:58           ` Dan Williams
2022-01-31 23:35     ` [PATCH v5 " Dan Williams
2022-02-01 10:52       ` Jonathan Cameron
2022-01-24  0:30 ` [PATCH v3 17/40] cxl/port: Introduce cxl_port_to_pci_bus() Dan Williams
2022-01-31 16:04   ` Jonathan Cameron
2022-01-31 16:44   ` [PATCH v4 " Dan Williams
2022-01-31 23:41     ` Ben Widawsky
2022-01-24  0:30 ` [PATCH v3 18/40] cxl/pmem: Introduce a find_cxl_root() helper Dan Williams
2022-01-26 18:55   ` [PATCH v4 " Dan Williams
2022-01-26 23:59     ` [PATCH v5 " Dan Williams
2022-01-31 16:18       ` Jonathan Cameron
2022-02-01  0:22         ` Dan Williams
2022-02-01 10:58           ` Jonathan Cameron
2022-02-01  0:34       ` [PATCH v6 " Dan Williams
2022-02-01 10:59         ` Jonathan Cameron
2022-01-24  0:30 ` [PATCH v3 19/40] cxl/port: Up-level cxl_add_dport() locking requirements to the caller Dan Williams
2022-01-31 16:20   ` Jonathan Cameron
2022-01-31 23:47   ` Ben Widawsky
2022-02-01  0:43     ` Dan Williams
2022-02-01  1:07   ` [PATCH v4 " Dan Williams
2022-02-01 11:00     ` Jonathan Cameron
2022-01-24  0:30 ` [PATCH v3 20/40] cxl/pci: Rename pci.h to cxlpci.h Dan Williams
2022-01-31 16:22   ` Jonathan Cameron
2022-02-01  0:00     ` Dan Williams
2022-01-31 23:48   ` Ben Widawsky
2022-01-24  0:30 ` [PATCH v3 21/40] cxl/core: Generalize dport enumeration in the core Dan Williams
2022-01-31 17:02   ` Jonathan Cameron
2022-02-01  1:58     ` Dan Williams
2022-02-01  2:10   ` [PATCH v4 " Dan Williams
2022-02-01 11:03     ` Jonathan Cameron
2022-01-24  0:30 ` [PATCH v3 22/40] cxl/core/hdm: Add CXL standard decoder enumeration to " Dan Williams
2022-01-26  3:09   ` [PATCH v4 " Dan Williams
2022-01-31 14:26     ` Jonathan Cameron
2022-01-31 17:51     ` Jonathan Cameron
2022-02-01  5:10       ` Dan Williams
2022-02-01 20:24     ` [PATCH v5 " Dan Williams
2022-02-02  9:31       ` Jonathan Cameron
2022-02-01  0:24   ` [PATCH v3 " Ben Widawsky
2022-02-01  4:58     ` Dan Williams
2022-01-24  0:30 ` [PATCH v3 23/40] cxl/core: Emit modalias for CXL devices Dan Williams
2022-01-31 17:57   ` Jonathan Cameron
2022-02-01 15:11   ` Ben Widawsky
2022-01-24  0:30 ` [PATCH v3 24/40] cxl/port: Add a driver for 'struct cxl_port' objects Dan Williams
2022-01-26 20:16   ` [PATCH v4 " Dan Williams
2022-01-31 18:11     ` Jonathan Cameron
2022-02-01 20:43       ` Dan Williams
2022-02-02  9:33         ` Jonathan Cameron
2022-02-01 21:07     ` [PATCH v5 " Dan Williams
2022-01-24  0:30 ` [PATCH v3 25/40] cxl/core/port: Remove @host argument for dport + decoder enumeration Dan Williams
2022-01-31 14:32   ` Jonathan Cameron
2022-01-31 18:14   ` Jonathan Cameron
2022-02-01 15:17   ` Ben Widawsky
2022-02-01 21:09     ` Dan Williams
2022-02-01 21:23   ` [PATCH v4 " Dan Williams
2022-01-24  0:30 ` [PATCH v3 26/40] cxl/pci: Store component register base in cxlds Dan Williams
2022-01-31 18:15   ` Jonathan Cameron
2022-02-01 21:28   ` [PATCH v4 " Dan Williams
2022-01-24  0:31 ` [PATCH v3 27/40] cxl/pci: Cache device DVSEC offset Dan Williams
2022-01-31 18:19   ` Jonathan Cameron
2022-02-01 15:24     ` Ben Widawsky
2022-02-01 21:41       ` Dan Williams
2022-02-01 22:11         ` Ben Widawsky
2022-02-01 22:15           ` Dan Williams
2022-02-01 22:20             ` Ben Widawsky
2022-02-01 22:24               ` Dan Williams
2022-02-02  9:36                 ` Jonathan Cameron
2022-02-01 22:06   ` [PATCH v4 " Dan Williams
2022-02-02  9:36     ` Jonathan Cameron
2022-01-24  0:31 ` [PATCH v3 28/40] cxl/pci: Retrieve CXL DVSEC memory info Dan Williams
2022-01-31 18:25   ` Jonathan Cameron
2022-02-01 22:52     ` Dan Williams
2022-02-01 23:48   ` [PATCH v4 " Dan Williams
2022-02-02  9:39     ` Jonathan Cameron
2022-01-24  0:31 ` [PATCH v3 29/40] cxl/pci: Implement wait for media active Dan Williams
2022-01-31 18:29   ` Jonathan Cameron
2022-02-01 23:56     ` Dan Williams
2022-01-24  0:31 ` [PATCH v3 30/40] cxl/pci: Emit device serial number Dan Williams
2022-01-31 18:33   ` Jonathan Cameron
2022-01-31 21:43     ` Dan Williams
2022-01-31 21:56   ` [PATCH v4 " Dan Williams
2022-01-24  0:31 ` [PATCH v3 31/40] cxl/memdev: Add numa_node attribute Dan Williams
2022-01-31 18:41   ` Jonathan Cameron
2022-02-01 23:57     ` Dan Williams
2022-02-02  9:44       ` Jonathan Cameron
2022-02-02 15:44         ` Dan Williams
2022-02-03  9:41           ` Jonathan Cameron
2022-02-03 16:59             ` Dan Williams
2022-02-03 18:05               ` Jonathan Cameron
2022-02-04  4:25                 ` Dan Williams
2022-02-01 15:31   ` Ben Widawsky
2022-02-01 15:49     ` Jonathan Cameron
2022-02-01 16:35       ` Ben Widawsky
2022-02-01 17:38         ` Jonathan Cameron
2022-02-01 23:59     ` Dan Williams
2022-02-02  1:18     ` Dan Williams
2022-01-24  0:31 ` [PATCH v3 32/40] cxl/core/port: Add switch port enumeration Dan Williams
2022-02-01 12:13   ` Jonathan Cameron [this message]
2022-02-02  5:26     ` Dan Williams
2022-02-01 17:37   ` Ben Widawsky
2022-02-02  6:03     ` Dan Williams
2022-02-02 17:07   ` [PATCH v4 " Dan Williams
2022-02-03  9:55     ` Jonathan Cameron
2022-02-04 15:08     ` [PATCH v5 " Dan Williams
2022-01-24  0:31 ` [PATCH v3 33/40] cxl/mem: Add the cxl_mem driver Dan Williams
2022-01-26  3:16   ` [PATCH v4 " Dan Williams
2022-02-01 12:45     ` Jonathan Cameron
2022-02-01 17:44       ` Ben Widawsky
2022-02-03  2:49       ` Dan Williams
2022-02-03  9:59         ` Jonathan Cameron
2022-02-04 14:54           ` Dan Williams
2022-02-03  3:56     ` [PATCH v5 " Dan Williams
2022-02-03 12:07       ` Jonathan Cameron
2022-02-04 15:18       ` [PATCH v6 " Dan Williams
2022-01-24  0:31 ` [PATCH v3 34/40] cxl/core: Move target_list out of base decoder attributes Dan Williams
2022-01-31 18:45   ` Jonathan Cameron
2022-02-01 17:45   ` Ben Widawsky
2022-01-24  0:31 ` [PATCH v3 35/40] cxl/core/port: Add endpoint decoders Dan Williams
2022-02-01 12:47   ` Jonathan Cameron
2022-02-03  4:02   ` [PATCH v4 " Dan Williams
2022-02-14 17:45     ` Jonathan Cameron
2022-02-14 19:14       ` Dan Williams
2022-01-24  0:31 ` [PATCH v3 36/40] tools/testing/cxl: Mock dvsec_ranges() Dan Williams
2022-01-24  0:31 ` [PATCH v3 37/40] tools/testing/cxl: Fix root port to host bridge assignment Dan Williams
2022-01-24  0:32 ` [PATCH v3 38/40] tools/testing/cxl: Mock one level of switches Dan Williams
2022-01-24  0:32 ` [PATCH v3 39/40] tools/testing/cxl: Enumerate mock decoders Dan Williams
2022-01-24  0:32 ` [PATCH v3 40/40] tools/testing/cxl: Add a physical_node link Dan Williams
2022-02-01 12:53   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220201121328.00006f3e@Huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=dan.j.williams@intel.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=nvdimm@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.