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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).