From: Dave Jiang <dave.jiang@intel.com>
To: Li Ming <ming.li@zohomail.com>, linux-cxl@vger.kernel.org
Cc: dave@stgolabs.net, jonathan.cameron@huawei.com,
alison.schofield@intel.com, vishal.l.verma@intel.com,
ira.weiny@intel.com, dan.j.williams@intel.com
Subject: Re: [PATCH v5 04/10] cxl: Defer dport allocation for switch ports
Date: Tue, 8 Jul 2025 14:47:05 -0700 [thread overview]
Message-ID: <a54c83fc-a0d2-449d-903c-2cc42e07d8b6@intel.com> (raw)
In-Reply-To: <32e809fe-ff98-4b27-96e3-119b8e83414f@zohomail.com>
On 7/7/25 11:21 PM, Li Ming wrote:
> On 7/4/2025 7:27 AM, Dave Jiang wrote:
>> The current implementation enumerates the dports during the cxl_port
>> driver probe. Without an endpoint connected, the dport may not be
>> active during port probe. This scheme may prevent a valid hardware
>> dport id to be retrieved and MMIO registers to be read when an endpoint
>> is hot-plugged. Move the dport allocation and setup to behind memdev
>> probe so the endpoint is guaranteed to be connected.
>>
>> In the original enumeration behavior, there are 3 phases (or 2 if no CXL
>> switches) for port creation. cxl_acpi() creates a Root Port (RP) from the
>> ACPI0017.N device. Through that it enumerate downstream ports composed
>> of ACPI0016.N devices through add_host_bridge_dport(). Once done, it
>> use add_host_bridge_uport() to create the ports that enumerates the PCI
>> RPs as the dports of these ports. Every time a port is created, the port
>> driver is attached and drv->probe() is called and
>> devm_cxl_port_enumerate_dports() is envoked to enumerate and probe
>> the dports.
>>
>> The second phase is if there are any CXL switches. When the pci endpoint
>> device driver (cxl_pci) calls probe, it will add a mem device and triggers
>> the cxl_mem->probe(). cxl_mem->probe() calls devm_cxl_enumerate_ports()
>> and attempts to discovery and create all the ports represent CXL switches.
>> During this phase, a port is created per switch and the attached dports
>> are also enumerated and probed.
>>
>> The last phase is creating endpoint port which happens for all endpoint
>> devices.
>>
>> In this commit, the port create and its dport probing in cxl_acpi is not
>> changed. That will be handled in a different patch later on. The behavior
>> change is only for CXL switch ports. Only the dport that is part of the
>> path for an endpoint device to the RP will be probed. This happens
>> naturally by the code walking up the device hierarchy and identifying the
>> upstream device and the downstream device.
>>
>> There are two points where the interception of dport creation happens
>> during the devm_cxl_enumerate_ports() path. The first location is right
>> before the function calls add_port_attach_ep() where it does the dport
>> allocation for the RP. Once the dport is allocated, the iteration path
>> is reset to the beginning to try again. The second location happens
>> in add_port_attach_ep() after the location where either the port is
>> discovered or allocated new if it does not exist.
>>
>> Locking of port device during __cxl_port_add_dport() protects modifications
>> against the port and its dports while multiple endpoints can be probing at
>> the same time and the same port is being modified concurrently.
>>
>> While the decoders are allocated during the port driver probe,
>> The decoders must also be updated since previously it's all done when all
>> the dports are setup and now every time a dport is setup per endpoint, the
>> switch target listing need to be updated with new dport. A
>> guard(rwsem_write) is used to update decoder targets. This is similar to
>> when decoder_populate_target() is called and the decoder programming
>> must be protected.
>>
>> Link: https://lore.kernel.org/linux-cxl/20250305100123.3077031-1-rrichter@amd.com/
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>> v5:
>> - Change cxl_port_get_total_dports() to cxl_port_update_total_dports(). (Jonathan)
>> - Return dport for the devm_cxl_port_add_dport() and friends. (Jonathan)
>> ---
>> drivers/cxl/core/core.h | 2 +
>> drivers/cxl/core/pci.c | 88 +++++++++++++++++++
>> drivers/cxl/core/port.c | 184 ++++++++++++++++++++++++++++++++++++++--
>> drivers/cxl/cxl.h | 5 ++
>> drivers/cxl/port.c | 8 +-
>> 5 files changed, 273 insertions(+), 14 deletions(-)
>>
> [snip]
>> +#define CXL_ITER_LEVEL_SWITCH 1
>> +
>> int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
>> {
>> struct device *dev = &cxlmd->dev;
>> struct device *iter;
>> - int rc;
>> + int rc, i;
>>
>> /*
>> * Skip intermediate port enumeration in the RCH case, there
>> @@ -1643,7 +1787,7 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
>> * attempt fails.
>> */
>> retry:
>> - for (iter = dev; iter; iter = grandparent(iter)) {
>> + for (i = 0, iter = dev; iter; i++, iter = grandparent(iter)) {
>> struct device *dport_dev = grandparent(iter);
>> struct device *uport_dev;
>> struct cxl_dport *dport;
>> @@ -1686,9 +1830,28 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
>> if (!dev_is_cxl_root_child(&port->dev))
>> continue;
>>
>> + /*
>> + * This is a corner case where the rootport is setup but
>> + * the switch dport is not. It needs to go back to the
>> + * beginning to setup the switch port.
>> + */
>> + if (i >= CXL_ITER_LEVEL_SWITCH) {
>> + struct cxl_port *pport __free(put_cxl_port) =
>> + cxl_mem_find_port(cxlmd, &dport);
>> + if (!port)
>> + goto retry;
> should be "if (!pport)" here?
Yes. Great catch!
>> + }
>> +
>> return 0;
>> }
>>
>> + dport = devm_cxl_add_dport_for_rp(uport_dev, dport_dev);
>> + /* Added a dport, restart enumeration */
>> + if (!IS_ERR_OR_NULL(dport))
>> + goto retry;
>> + if (IS_ERR(dport))
>> + return PTR_ERR(dport);
>> +
>
> This part is a little bit complicated. My understanding is that devm_cxl_add_dport_for_rp() is invoked only for uport_dev == cxl host bridge case, and below add_port_attach_ep() is invoked only for uport_dev == cxl switch USP case, is it?
>
> If yes, maybe it is better to use a if {} else {} block here? like
>
> if (uport_dev is host bridge) {
>
> devm_cxl_add_dport_for_rp();
>
> } else {
>
> add_switch_port_attach_ep();
>
> }
Yes I'll change to that. I can also drop devm_cxl_add_dport_for_rp() and directly call devm_cxl_add_dport_by_uport().
DJ
>
>
> Ming
>
> [snip]
>
next prev parent reply other threads:[~2025-07-08 21:47 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-03 23:27 [PATCH v5 00/10] cxl: Delay HB port and switch dport probing until endpoint dev probe Dave Jiang
2025-07-03 23:27 ` [PATCH v5 01/10] cxl/region: Add decoder check to check_commit_order() Dave Jiang
2025-07-03 23:27 ` [PATCH v5 02/10] cxl: Add helper to detect top of CXL device topology Dave Jiang
2025-07-03 23:27 ` [PATCH v5 03/10] cxl: Add helper to reap dport Dave Jiang
2025-07-03 23:27 ` [PATCH v5 04/10] cxl: Defer dport allocation for switch ports Dave Jiang
2025-07-04 9:52 ` Jonathan Cameron
2025-07-07 17:59 ` Dave Jiang
2025-07-07 22:48 ` Dave Jiang
2025-07-08 6:21 ` Li Ming
2025-07-08 21:47 ` Dave Jiang [this message]
2025-07-03 23:27 ` [PATCH v5 05/10] cxl/test: Add cxl_test support for cxl_port_update_total_ports() Dave Jiang
2025-07-03 23:27 ` [PATCH v5 06/10] cxl/test: Add mock version of devm_cxl_add_dport_by_dev() Dave Jiang
2025-07-04 9:57 ` Jonathan Cameron
2025-07-03 23:27 ` [PATCH v5 07/10] cxl: Change sslbis handler to only handle single dport Dave Jiang
2025-07-03 23:27 ` [PATCH v5 08/10] cxl: Create an xarray to tie a host bridge to the cxl_root Dave Jiang
2025-07-03 23:27 ` [PATCH v5 09/10] cxl: Move enumeration of hostbridge ports to the memdev probe path Dave Jiang
2025-07-04 10:07 ` Jonathan Cameron
2025-07-07 23:39 ` Dave Jiang
2025-07-03 23:27 ` [PATCH v5 10/10] cxl: Remove devm_cxl_port_enumerate_dports() that is no longer used Dave Jiang
2025-07-04 10:09 ` 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=a54c83fc-a0d2-449d-903c-2cc42e07d8b6@intel.com \
--to=dave.jiang@intel.com \
--cc=alison.schofield@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave@stgolabs.net \
--cc=ira.weiny@intel.com \
--cc=jonathan.cameron@huawei.com \
--cc=linux-cxl@vger.kernel.org \
--cc=ming.li@zohomail.com \
--cc=vishal.l.verma@intel.com \
/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.