From: Jonathan Cameron <jic23@kernel.org>
To: Dave Jiang <dave.jiang@intel.com>
Cc: linux-cxl@vger.kernel.org, dave@stgolabs.net,
alison.schofield@intel.com, ming.li@zohomail.com,
icheng@nvidia.com
Subject: Re: [PATCH 2/2] cxl/core: Hold the dport host lock across dport lookup and use
Date: Sat, 26 Sep 2026 00:07:41 +0100 [thread overview]
Message-ID: <20260926000741.7cd17073@jic23-hlaptop> (raw)
In-Reply-To: <20260924212159.52920-3-dave.jiang@intel.com>
On Thu, 24 Sep 2026 14:21:59 -0700
Dave Jiang <dave.jiang@intel.com> wrote:
> Callers of cxl_pci_find_port() and cxl_mem_find_port() can be handed a
> 'struct cxl_dport' that is already freed, and all four dereference it
> without the lock that would prevent that.
>
> A dport is kzalloc()'d into a devres group on its host device, so it dies
> when that host unbinds. The host is &port->dev for a switch port and
> port->uport_dev for the root port.
>
> Both helpers return the dport through an output parameter. The caller's
> port reference pins struct cxl_port, not the dport allocation, and the
> lookup itself is a bare xa_load() under no lock.
>
> Add cxl_port_dport_host() to name the device that pins a dport, and
> cxl_pci_find_dport() / cxl_mem_find_dport() to look one up with that
> device's lock held and asserted. Convert the four callers to use them and
> bail if the dport is gone. cxl_port_add_dport() already follows this rule.
>
> cxl_mem_probe() chose its endpoint devm host from dport->rch, which meant
> dereferencing the dport before taking any lock. Use cxl_port_dport_host():
> rch dports only ever land on the root port, so it selects the same device
> without needing the dport.
>
> Fixes: 733b57f262b0 ("cxl/pci: Early setup RCH dport component registers from RCRB")
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> Assisted-by: LLM
> ---
> Found by review, not from a failure report.
>
> Untested: two of the four converted sites add a new lock acquisition, and
> neither executed under test.
>
> cxl_pci_setup_regs() new guard() sits behind is_cxl_restricted(),
> which needs a PCI_EXP_TYPE_RC_END device
> cxl_handle_rdport_errors() needs an RCH dport AER error; cxl_test has no
> injection path
>
> Only cxl_pci_setup_regs() introduces a lock order lockdep has not already
> seen: device_lock(&pdev->dev) from probe, then the dport host lock.
>
> cxl_handle_rdport_errors() nests its new host lock inside the
> device_lock(&cxlmd->dev) that core/ras.c:274 and :298 hold, but
> cxl_mem_probe() takes that same pair in that same order and ran clean under
> PROVE_LOCKING, so the edge itself is covered. What is untested there is the
> path, not the ordering.
>
> Reaching either needs a cxl-type3 attached directly to a host bridge so
> pci_pcie_type() is PCI_EXP_TYPE_RC_END, which run_qemu.sh does not generate.
>
> Tested in QEMU with cxl_test, PROVE_LOCKING and KASAN on, 8 module
> load/unload cycles with concurrent sysfs readers. No lockdep splat, no
> device_lock_assert() firing, enumeration unchanged (15 memdev, 12 port,
> 192 decoder before and after).
>
> cxl_mem_find_dport() ran for 15 memdevs on each of 9 loads, covering both
> cxl_port_dport_host() branches. The rch branch is covered too: "cxl_mem
> mem2: endpoint9 added to root3" shows the new selection picking the same
> parent dport->rch did.
>
> Not fixed here, found by KASAN during the same run: emit_target_list()
> (port.c:158) dereferences cxlsd->target[i]->port_id under only
> cxl_rwsem.region, and cxl_dport_remove() (port.c:1091) never clears those
> cached pointers, so a switch decoder target array keeps dangling dports.
Given that is I think what you fix in previous patch, drop this paragraph.
>
> Same bug class, different mechanism - a stale cached pointer rather than an
> unlocked lookup - so it wants its own patch in dport teardown.
I think the fix is good, but one thing about wording of an
explanatory comment inline.
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index cab8ce39f465..508f590a08c4 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -701,6 +701,18 @@ static inline bool is_cxl_root(struct cxl_port *port)
> return port->uport_dev == port->dev.parent;
> }
>
> +/*
> + * The dports of @port are devm allocations of this device, so they live
> + * only as long as it stays bound to its driver. Hold its lock across any
what is 'its' here? Also 'this device' the one returned? Perhaps.
Return the owner device of the devm allocation of dports associated with
@port. device_lock() should be held for the returned device
across any lookup and use of any of these struct cxl_dport instances.
> + * lookup and use of a 'struct cxl_dport'.
> + */
> +static inline struct device *cxl_port_dport_host(struct cxl_port *port)
> +{
> + if (is_cxl_root(port))
> + return port->uport_dev;
> + return &port->dev;
> +}
> +
prev parent reply other threads:[~2026-09-25 23:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 21:21 [PATCH 0/2] cxl: dport fixes from sashiko reports Dave Jiang
2026-09-24 21:21 ` [PATCH 1/2] cxl/port: Clear cached dport pointers when a dport is removed Dave Jiang
2026-09-25 22:51 ` Jonathan Cameron
2026-09-24 21:21 ` [PATCH 2/2] cxl/core: Hold the dport host lock across dport lookup and use Dave Jiang
2026-09-25 23:07 ` Jonathan Cameron [this message]
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=20260926000741.7cd17073@jic23-hlaptop \
--to=jic23@kernel.org \
--cc=alison.schofield@intel.com \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=icheng@nvidia.com \
--cc=linux-cxl@vger.kernel.org \
--cc=ming.li@zohomail.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