diff options
| author | Davidlohr Bueso <dave@stgolabs.net> | 2026-11-08 14:07:31 -0800 |
|---|---|---|
| committer | Dave Jiang <dave.jiang@intel.com> | 2026-11-09 15:25:19 -0700 |
| commit | ad9c5385f8e1dd18b0909534b78c9e92d3a66c69 (patch) | |
| tree | 707916a0902f9fcc7fa0fef3364b7a65010ec746 /scripts/Makefile.thinlto | |
| parent | d81c479843a2d6350c6aa6c1d9a15596b5c4a76e (diff) | |
| download | linux-next-ad9c5385f8e1dd18b0909534b78c9e92d3a66c69.tar.gz linux-next-ad9c5385f8e1dd18b0909534b78c9e92d3a66c69.zip | |
cxl/pci: Add BI topology enable/disable
Implement cxl_bi_setup() to enable BI flows on the device and every
component in the path, and its teardown counterpart cxl_bi_dealloc().
Setup runs from devm_cxl_endpoint_decoders_setup(), between the
port's HDM state and its decoders. Registered there, its devres
teardown brings BI down after the decoders quiesce and before the
HDM state is freed, and BI is settled before the decoders, and later
the regions, are looked at. The BI-ID and path enablement belong to
the endpoint port's lifetime.
Setup is safe in endpoint port probe context. The port probes
synchronously from cxl_mem_probe(), pinning the memdev state the
walk consumes, and the whole ancestor path already exists with BI
registers mapped (dports at dport-add time, the switch USP RT at
first-dport setup) because devm_cxl_enumerate_ports() completes
before the endpoint is created.
Dealloc is safe in endpoint devres context. Both setup and dealloc
walk the endpoint's parent_dport topology rather than getting the
port by bus lookup - an ancestor teardown delists the parent port
before the endpoint's devres runs.
The topology walk is stable as parent_dport pointers are fixed at
port creation; ancestors cannot be reaped while holding this
memdev's cxl_ep; and their own teardown frees dports only after
the endpoint is gone.
Likewise, the device state outlives the walk - cxlmd->cxlds is
nulled only after cxl_memdev_unregister() has torn the endpoint
down, and delete_endpoint() clears cxlmd->endpoint only after the
endpoint devres has run.
Each dport is programmed by its position - the one immediately above
the device takes BI Enable, every dport above it takes BI Forward
(Table 8-157, Table 9-13), at any switch depth (Table 7-97). Any
level can be shared, so nr_bi refcounts endpoints at every dport.
Registers are written on the first endpoint and cleared on the last,
but only downstream ports commit (Table 8-156), once per endpoint
(Table 8-152), and a failed commit undoes its write and commits the
undo. A USP advertising a BI Route Table that failed to map is
refused rather than treated as absent. nr_bi counts only the
endpoints this driver enabled; a level firmware brought up is kept,
see below.
A device firmware already enabled is taken up as found, with no
write.
A reset may wipe the device's BI Enable, whose reset default is 0
(Table 8-157). .reset_done reads the hardware rather than assume
which reset ran, and invalidates cxlds->bi, failing closed with
recovery by rebind as for decoder loss; dealloc unwinds the dport
refcounts regardless. It also clears cxlds->bi unconditionally - the
endpoint disable fails when the hardware already shows BI Enable
clear, from a reset .reset_done never saw, and the flag must not
outlive the BI Decoder mapping it describes, which the endpoint port
releases moments later.
With dealloc in the endpoint's devres, delete_endpoint() already
holds the parent port's device lock, so to avoid deadlocking, add a
per-port bi_lock, serializing the dports that share state (nr_bi and
the control register at any shared level, the switch USP's BI RT).
A locked HDM decoder is the main reason release cannot simply turn BI
off: once committed with Lock On Commit set (CXL 4.0 8.2.4.20.13) it
cannot be reset, so it keeps decoding after this driver lets go, as
does a committed decoder that never joined a region. While its BI bit
is set, the device still needs BI Enable to snoop that range.
So setup's unwind and teardown share one release, which reads the
decoders from the hardware. If one is still committed with BI set,
the device keeps BI Enable and every level on its path is held: each
level's nr_bi reference is dropped, but a held level is never
cleared, so a rebind finds the path enabled. An unwind holds nothing,
since the device's BI was never taken up.
A level found already up, with nothing this driver enabled below it,
is held too: firmware may have brought it up, or its dport was
re-created and cannot tell whether a device below still decodes. Only
a level this driver brought up from zero is ever cleared.
The BI Decoder mapping belongs to the endpoint port, which an unbind
of that port alone releases, so .reset_done reads it only while
holding the port with its driver still bound.
Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
Reviewed-by: Li Ming <ming.li@zohomail.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Link: https://patch.msgid.link/613ce49db78d0ae09443dc48730eff1f6a2d0223.1794172701.git.dave@stgolabs.net
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Diffstat (limited to 'scripts/Makefile.thinlto')
0 files changed, 0 insertions, 0 deletions
