ACPI/PCI/CXL: Enforce _DEP ordering between ACPI0016 and ACPI0017
cover ACPI/PCI/CXL: Enforce _DEP ordering between ACPI0016 and ACPI0017
On platforms whose ACPI namespace exposes a CXL host bridge (ACPI0016) with an ACPI0017 CXL root device declaring _DEP on the host bridge, cxl_acpi can probe before acpi_pci_root has attached the PCI root. acpi_pci_find_root() then returns NULL, decoder targets read as 0, and no port/endpoint device shows up under /sys/bus/cxl/devices/.
The root cause is twofold:
1. acpi_pci_root_add() never calls acpi_dev_clear_dependencies(), so _DEP suppliers downstream of a PCI root are never released.
2. ACPI0016 is not on acpi_honor_dep_ids[], so even when ACPI0017 declares _DEP on it, acpi_dev_ready_for_enumeration() bypasses the dep_unmet check and lets cxl_acpi probe early.
On x86 the bug is usually masked by link order (acpi_pci_root is built in and probed before cxl_acpi). On architectures like RISC-V that ordering is not guaranteed, so the standard ACPI _DEP mechanism must actually work.
This series fixes both sides and the two patches must be applied together; applying only patch 2 would prevent cxl_acpi from ever probing on ACPI0016 systems, because the supplier would never clear the dependency.
Patch 1 makes acpi_pci_root_add() clear _DEP on the supplier once
the PCI root bus has been added.
Patch 2 adds ACPI0016 to acpi_honor_dep_ids[] so the dependency
declared by ACPI0017 is enforced.
The approach in this series follows the discussion of an earlier posting:
https://lore.kernel.org/linux-cxl/[email protected]/
Chen Pei (2):
ACPI: PCI: clear _DEP dependencies after PCI root bridge attach
ACPI: scan: honor _DEP for ACPI0016 PCI/CXL host bridge
drivers/acpi/pci_root.c | 4 ++++ drivers/acpi/scan.c | 1 + 2 files changed, 5 insertions(+)
Signature · 1 line
2.50.1
PATCH 1/2 ACPI: PCI: Clear _DEP dependencies after PCI root bridge attach
PCI root bridges enumerated by acpi_pci_root_add() can be the _DEP supplier for other ACPI consumers, most notably ACPI0017 CXL root devices whose probe path depends on acpi_pci_find_root() succeeding. Once the root bus has been added, those consumers can safely be enumerated, so notify them by clearing the dependency.
Call acpi_dev_clear_dependencies() at the end of acpi_pci_root_add(), after pci_bus_add_devices(), following the same pattern used by other ACPI suppliers such as the EC (drivers/acpi/ec.c) and the ACPI PCI Link device (drivers/acpi/pci_link.c). The clear is intentionally done only on the success path; on the error paths the supplier did not attach and consumers must keep dep_unmet set.
This is a prerequisite for honoring _DEP on ACPI0016 host bridges, which matters on architectures where the probe order of acpi_pci_root relative to cxl_acpi is not guaranteed (e.g. RISC-V).
--- drivers/acpi/pci_root.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/acpi/pci_root.c +4 -0
@@ -755,6 +755,10 @@ static int acpi_pci_root_add(struct acpi_device *device,pci_lock_rescan_remove ();pci_bus_add_devices (root->bus);pci_unlock_rescan_remove (); + +/* Clear _DEP dependencies to allow consumers to enumerate */ +acpi_dev_clear_dependencies (device); +return 1 ; remove_dmar:
Signature · 1 line
2.50.1
[email protected]
AI reviewRe: [PATCH 1/2] ACPI: PCI: Clear _DEP dependencies after PCI root bridge attach
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] acpi_pci_root_add() leaves a dangling pointer in device->driver_data on the dmar_device_add() error path. --
commit c50bc9cc7a48e4b92d2f6107b97e5bdf5d2b47a4
Author: Chen Pei <[email protected]>
ACPI: PCI: Clear _DEP dependencies after PCI root bridge attach
This commit clears _DEP dependencies at the end of acpi_pci_root_add(), allowing consumers like ACPI0017 CXL root devices to safely enumerate once the PCI root bridge has been attached.
Quoted 15 lines
drivers/acpi/pci_root.c +4
-0@@ -755,6 +755,10 @@ static int acpi_pci_root_add(struct acpi_device *device,pci_lock_rescan_remove ();pci_bus_add_devices (root->bus);pci_unlock_rescan_remove (); + +/* Clear _DEP dependencies to allow consumers to enumerate */ +acpi_dev_clear_dependencies (device); +return 1 ; remove_dmar:
drivers/acpi/pci_root.c
Quoted 4 lines
drivers/acpi/pci_root.c +0
-0if (hotadd)dmar_device_remove (handle); end:kfree (root);
[Severity: High]
This is a pre-existing issue, but does the dmar_device_add() error path leave a dangling pointer in device->driver_data?
Earlier in acpi_pci_root_add(), the allocated root object is assigned to device->driver_data:
root->device = device; root->segment = segment & 0xFFFF; device->driver_data = root;
If dmar_device_add() fails during a hot-add, the code jumps to the end label and frees the root pointer via kfree().
However, it doesn't explicitly reset device->driver_data to NULL, unlike the later pci_acpi_scan_root() error path. Since the ACPI core does not automatically clear driver_data on an attach failure, could subsequent calls to acpi_pci_find_root() by other subsystems fetch and dereference this freed pointer?
Quoted 2 lines
return result;
}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCH] cxl/acpi: Defer probe when ACPI0016 PCI root bridge is not ready
Quoted 23 lines · On Tue, 26 May 2026 03:12:00 +0000, [email protected] wrote:
drivers/acpi/pci_root.c static int acpi_pci_root_add(struct acpi_device *device,
Quoted 11 lines
drivers/acpi/pci_root.c +4
-0+ +/* Clear _DEP dependencies to allow consumers to enumerate */ +acpi_dev_clear_dependencies (device); +return 1 ; remove_dmar:if (hotadd)dmar_device_remove (handle); end:kfree (root);[Severity: High]
This is a pre-existing issue, but does thedmar_device_add()error path leave a dangling pointer indevice->driver_data?Earlier in
acpi_pci_root_add(), the allocated root object is assigned todevice->driver_data:root->device = device; root->segment = segment & 0xFFFF; device->driver_data = root;
Quoted 8 lines
If
dmar_device_add()fails during a hot-add, the code jumps to the end label and frees the root pointer viakfree().However, it doesn't explicitly reset
device->driver_datato NULL, unlike the laterpci_acpi_scan_root()error path. Since the ACPI core does not automatically cleardriver_dataon an attach failure, could subsequent calls toacpi_pci_find_root()by other subsystems fetch and dereference this freed pointer?
Good catch — you're right. On the dmar_device_add() failure path, the code jumps to end: and frees root via kfree(), but device->driver_data is left pointing at the freed memory. The later pci_acpi_scan_root() failure path explicitly clears it to NULL, which makes the omission on the dmar path look like an oversight rather than intentional.
Since this is unrelated to the _DEP clearing change in this patch, I'd prefer to keep it out of this patch and send a separate fix on top. Both failure paths converge at end: and need the same cleanup, so I plan to consolidate the NULL assignment there:
@@ -724,7 +724,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (!root->bus) {
dev_err(&device->dev,
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
- device->driver_data = NULL;
result = -ENODEV;
goto remove_dmar;
}
@@ -764,6 +763,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
remove_dmar:
if (hotadd)
dmar_device_remove(handle);
end:
+ device->driver_data = NULL;
kfree(root);
return result;
}This way every path reaching end: clears driver_data before freeing root, and any future error path that does goto end; is automatically correct. Does that split sound OK to you?
Thanks,
Pei
PATCH 2/2 ACPI: scan: Honor _DEP for ACPI0016 PCI/CXL host bridge
In reply to Chen PeiCXL root devices (ACPI0017) declare _DEP on their parent ACPI0016 PCI/CXL host bridge so that cxl_acpi probes only after acpi_pci_root has attached the PCI root and registered it for acpi_pci_find_root(). However, acpi_dev_ready_for_enumeration() only consults dep_unmet when the supplier's HID is on acpi_honor_dep_ids[]; otherwise the dependency is silently ignored.
Without honoring the dependency, cxl_acpi can probe before the PCI root is ready. The resulting CXL topology is broken: decoder targets read as 0 and no port/endpoint devices appear under /sys/bus/cxl/devices/.
Add ACPI0016 to acpi_honor_dep_ids[] so the _DEP declared by ACPI0017 is enforced. This relies on the preceding patch ("ACPI: PCI: clear _DEP dependencies after PCI root bridge attach"), which releases the dependency once the PCI root is fully enumerated; the two patches must be applied together.
--- drivers/acpi/scan.c | 1 + 1 file changed, 1 insertion(+)
drivers/acpi/scan.c +1 -0
@@ -866,6 +866,7 @@ static const char * const acpi_honor_dep_ids[] = {"RSCV0005" ,/* RISC-V SBI MPXY MBOX */ "RSCV0006" ,/* RISC-V RPMI SYSMSI */ "PNP0C0F" ,/* PCI Link Device */ +"ACPI0016" ,/* CXL/PCIe host bridge: CXL root (ACPI0017) depends on PCI root attach */ NULL };
Signature · 1 line
2.50.1
Rafael J. Wysocki
maintainerRe: [PATCH 2/2] ACPI: scan: Honor _DEP for ACPI0016 PCI/CXL host bridge
Quoted 29 lines · Chen Pei
CXL root devices (ACPI0017) declare
_DEPon their parent ACPI0016 PCI/CXL host bridge so thatcxl_acpiprobes only afteracpi_pci_roothas attached the PCI root and registered it foracpi_pci_find_root(). However,acpi_dev_ready_for_enumeration()only consultsdep_unmetwhen the supplier's HID is on acpi_honor_dep_ids[]; otherwise the dependency is silently ignored.Without honoring the dependency,
cxl_acpican probe before the PCI root is ready. The resulting CXL topology is broken: decoder targets read as 0 and no port/endpoint devices appear under/sys/bus/cxl/devices/.Add ACPI0016 to acpi_honor_dep_ids[] so the
_DEPdeclared by ACPI0017 is enforced. This relies on the preceding patch ("ACPI: PCI: clear_DEPdependencies after PCI root bridge attach"), which releases the dependency once the PCI root is fully enumerated; the two patches must be applied together.Signed-off-by Chen Pei <[email protected]>--- drivers/acpi/scan.c | 1 + 1 file changed, 1 insertion(+)drivers/acpi/scan.c +0
-0
drivers/acpi/scan.c static const char * const acpi_honor_dep_ids[] = {
Quoted 8 lines
drivers/acpi/scan.c +1
-1@@ -866,6 +866,7 @@ static const char * const acpi_honor_dep_ids[] = {"RSCV0005" ,/* RISC-V SBI MPXY MBOX */ "RSCV0006" ,/* RISC-V RPMI SYSMSI */ "PNP0C0F" ,/* PCI Link Device */ +"ACPI0016" ,/* CXL/PCIe host bridge: CXL root (ACPI0017) depends on PCI root attach */ NULL }; --
If anyone has any objections or comments on this one, please let me know. In the absence of any, it will be queued up (as 7.2 material) next week.
Thanks!
Quoted 34 lines · Chen Pei
On platforms whose ACPI namespace exposes a CXL host bridge (ACPI0016) with an ACPI0017 CXL root device declaring
_DEPon the host bridge,cxl_acpican probe beforeacpi_pci_roothas attached the PCI root.acpi_pci_find_root()then returns NULL, decoder targets read as 0, and no port/endpoint device shows up under/sys/bus/cxl/devices/.The root cause is twofold:
1.
acpi_pci_root_add()never callsacpi_dev_clear_dependencies(), so_DEPsuppliers downstream of a PCI root are never released.2. ACPI0016 is not on acpi_honor_dep_ids[], so even when ACPI0017 declares
_DEPon it,acpi_dev_ready_for_enumeration()bypasses thedep_unmetcheck and letscxl_acpiprobe early.On x86 the bug is usually masked by link order (
acpi_pci_rootis built in and probed beforecxl_acpi). On architectures like RISC-V that ordering is not guaranteed, so the standard ACPI_DEPmechanism must actually work.This series fixes both sides and the two patches must be applied together; applying only patch 2 would prevent
cxl_acpifrom ever probing on ACPI0016 systems, because the supplier would never clear the dependency.Patch 1 makes
acpi_pci_root_add()clear_DEPon the supplier once
the PCI root bus has been added.
Patch 2 adds ACPI0016 to acpi_honor_dep_ids[] so the dependency
declared by ACPI0017 is enforced.The approach in this series follows the discussion of an earlier posting:
https://lore.kernel.org/linux-cxl/[email protected]/
Quoted 8 lines
Chen Pei (2):
ACPI: PCI: clear_DEPdependencies after PCI root bridge attach
ACPI: scan: honor_DEPfor ACPI0016 PCI/CXL host bridgedrivers/acpi/pci_root.c | 4 ++++ drivers/acpi/scan.c | 1 + 2 files changed, 5 insertions(+)
For the series
Are Fixes tags needed?
Quoted 30 lines · Chen Pei
On platforms whose ACPI namespace exposes a CXL host bridge (ACPI0016) with an ACPI0017 CXL root device declaring
_DEPon the host bridge,cxl_acpican probe beforeacpi_pci_roothas attached the PCI root.acpi_pci_find_root()then returns NULL, decoder targets read as 0, and no port/endpoint device shows up under/sys/bus/cxl/devices/.The root cause is twofold:
1.
acpi_pci_root_add()never callsacpi_dev_clear_dependencies(), so_DEPsuppliers downstream of a PCI root are never released.2. ACPI0016 is not on acpi_honor_dep_ids[], so even when ACPI0017 declares
_DEPon it,acpi_dev_ready_for_enumeration()bypasses thedep_unmetcheck and letscxl_acpiprobe early.On x86 the bug is usually masked by link order (
acpi_pci_rootis built in and probed beforecxl_acpi). On architectures like RISC-V that ordering is not guaranteed, so the standard ACPI_DEPmechanism must actually work.This series fixes both sides and the two patches must be applied together; applying only patch 2 would prevent
cxl_acpifrom ever probing on ACPI0016 systems, because the supplier would never clear the dependency.Patch 1 makes
acpi_pci_root_add()clear_DEPon the supplier once
the PCI root bus has been added.
Patch 2 adds ACPI0016 to acpi_honor_dep_ids[] so the dependency
declared by ACPI0017 is enforced.
Quoted 7 lines
The approach in this series follows the discussion of an earlier posting:
https://lore.kernel.org/linux-cxl/[email protected]/Chen Pei (2):
ACPI: PCI: clear_DEPdependencies after PCI root bridge attach
ACPI: scan: honor_DEPfor ACPI0016 PCI/CXL host bridge
For the set:
Rafael J. Wysocki
maintainerQuoted 36 lines · Alison Schofield
Quoted 34 lines · Chen Pei
On platforms whose ACPI namespace exposes a CXL host bridge (ACPI0016) with an ACPI0017 CXL root device declaring
_DEPon the host bridge,cxl_acpican probe beforeacpi_pci_roothas attached the PCI root.acpi_pci_find_root()then returns NULL, decoder targets read as 0, and no port/endpoint device shows up under/sys/bus/cxl/devices/.The root cause is twofold:
1.
acpi_pci_root_add()never callsacpi_dev_clear_dependencies(), so_DEPsuppliers downstream of a PCI root are never released.2. ACPI0016 is not on acpi_honor_dep_ids[], so even when ACPI0017 declares
_DEPon it,acpi_dev_ready_for_enumeration()bypasses thedep_unmetcheck and letscxl_acpiprobe early.On x86 the bug is usually masked by link order (
acpi_pci_rootis built in and probed beforecxl_acpi). On architectures like RISC-V that ordering is not guaranteed, so the standard ACPI_DEPmechanism must actually work.This series fixes both sides and the two patches must be applied together; applying only patch 2 would prevent
cxl_acpifrom ever probing on ACPI0016 systems, because the supplier would never clear the dependency.Patch 1 makes
acpi_pci_root_add()clear_DEPon the supplier once
the PCI root bus has been added.
Patch 2 adds ACPI0016 to acpi_honor_dep_ids[] so the dependency
declared by ACPI0017 is enforced.The approach in this series follows the discussion of an earlier posting:
https://lore.kernel.org/linux-cxl/[email protected]/
Quoted 7 lines
Quoted 3 lines
Chen Pei (2):
ACPI: PCI: clear_DEPdependencies after PCI root bridge attach
ACPI: scan: honor_DEPfor ACPI0016 PCI/CXL host bridgeFor the set:
Tested-by Alison Schofield <[email protected]>Reviewed-by Alison Schofield <[email protected]>
And so applied as 7.2 material, thanks!