Skip to contentSkip to conversation

ACPI/PCI/CXL: Enforce _DEP ordering between ACPI0016 and ACPI0017

PATCH In review Chen Pei 5 participants 9 messages May 26 – Jun 1

Subsystems (2)
lore
Share & tools
lore

Chen Pei

author
#0 lore raw

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
author
#1 lore raw

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
index a0ba64e45e8a..4c06c3ffd0cb 100644
@@ -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
#2 lore raw

Re: [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
index a0ba64e45e8ab..4c06c3ffd0cbb 100644
@@ -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 -0
 	if (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
author
#3 lore raw

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 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;
Quoted 8 lines

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?

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

author
#4 lore raw

PATCH 2/2 ACPI: scan: Honor _DEP for ACPI0016 PCI/CXL host bridge

In reply to Chen Pei

CXL 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
index 530547cda8b2..5f20e7748f36 100644
@@ -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
#5 lore raw

Re: [PATCH 2/2] ACPI: scan: Honor _DEP for ACPI0016 PCI/CXL host bridge

Quoted 29 lines · Chen Pei

CXL 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 +0 -0
index 530547cda8b2..5f20e7748f36 100644

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!

Reviewed-by on the v1 series
#6 lore raw
In reply to Chen Pei
Quoted 34 lines · Chen Pei

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]/

Quoted 8 lines

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(+)

For the series

Are Fixes tags needed?

Tested-by Reviewed-by on the v1 series
#7 lore raw
In reply to Chen Pei
Quoted 30 lines · Chen Pei

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.

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 _DEP dependencies after PCI root bridge attach
ACPI: scan: honor _DEP for ACPI0016 PCI/CXL host bridge

For the set:

#8 lore raw
Quoted 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 _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]/

Quoted 7 lines
Quoted 3 lines

Chen Pei (2):
ACPI: PCI: clear _DEP dependencies after PCI root bridge attach
ACPI: scan: honor _DEP for ACPI0016 PCI/CXL host bridge

For the set:

And so applied as 7.2 material, thanks!