From 3a59c3b772e5dc0cedecce8e7fbf7c2d6245b643 Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Tue, 26 May 2026 10:51:17 +0800 Subject: [PATCH 1/5] 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). Signed-off-by: Chen Pei Suggested-by: Dan Williams (nvidia) Tested-by: Alison Schofield Reviewed-by: Alison Schofield Link: https://patch.msgid.link/20260526025118.38935-2-cp0613@linux.alibaba.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index a0ba64e45e8a..4c06c3ffd0cb 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -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: From bf5418a5fe63f35da35941ae896d5df121d95ffc Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Tue, 26 May 2026 10:51:18 +0800 Subject: [PATCH 2/5] ACPI: scan: Honor _DEP for ACPI0016 PCI/CXL host bridge 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. Signed-off-by: Chen Pei Tested-by: Alison Schofield Reviewed-by: Alison Schofield Link: https://patch.msgid.link/20260526025118.38935-3-cp0613@linux.alibaba.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 530547cda8b2..5f20e7748f36 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -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 }; From 71e1815113f7e37e7e39ed69526cd7d399e5a0c9 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 28 May 2026 01:16:25 +0530 Subject: [PATCH 3/5] ACPI: CPPC: Add support for CPPC v4 CPPC v4 (ACPI 6.6, Section 8.4.6) adds two optional entries to the _CPC package: 1. OSPM Nominal Performance (8.4.6.1.2.6): A write-only register that lets OSPM inform the platform what it considers nominal performance. The platform classifies performance above this level as boost and below as throttle for its power/thermal decisions. 2. Resource Priority (8.4.6.1.2.7): A Package of Resource Priority Register Descriptor sub-packages that allow OSPM to set relative priority among processors for shared resources (boost, throttle, L2/L3 cache, memory bandwidth). Parsing the full structure is not yet supported; such entries are marked as unsupported. Add v4 _CPC table parsing (25 entries) and update REG_OPTIONAL to mark the two new registers as optional. Signed-off-by: Sumit Gupta Reviewed-by: Mario Limonciello (AMD) Reviewed-by: Pierre Gondois Link: https://patch.msgid.link/20260527194626.185286-2-sumitg@nvidia.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 23 +++++++++++++++++------ include/acpi/cppc_acpi.h | 8 ++++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index f370be8715ae..c76cfafa3589 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -134,7 +134,7 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr); * cpc_regs[] with the corresponding index. 0 means mandatory and 1 * means optional. */ -#define REG_OPTIONAL (0x1FC7D0) +#define REG_OPTIONAL (0x7FC7D0) /* * Use the index of the register in per-cpu cpc_regs[] to check if @@ -751,18 +751,19 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) /* * Disregard _CPC if the number of entries in the return package is not * as expected, but support future revisions being proper supersets of - * the v3 and only causing more entries to be returned by _CPC. + * the v4 and only causing more entries to be returned by _CPC. */ if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) || (cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) || - (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) { + (cpc_rev == CPPC_V4_REV && num_ent != CPPC_V4_NUM_ENT) || + (cpc_rev > CPPC_V4_REV && num_ent <= CPPC_V4_NUM_ENT)) { pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n", num_ent, pr->id); goto out_free; } - if (cpc_rev > CPPC_V3_REV) { - num_ent = CPPC_V3_NUM_ENT; - cpc_rev = CPPC_V3_REV; + if (cpc_rev > CPPC_V4_REV) { + num_ent = CPPC_V4_NUM_ENT; + cpc_rev = CPPC_V4_REV; } cpc_ptr->num_entries = num_ent; @@ -845,6 +846,16 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_BUFFER; memcpy(&cpc_ptr->cpc_regs[i-2].cpc_entry.reg, gas_t, sizeof(*gas_t)); + } else if (cpc_obj->type == ACPI_TYPE_PACKAGE && (i - 2) == RESOURCE_PRIORITY) { + /* + * ACPI 6.6, s8.4.6.1.2.7 defines Resource Priority as a + * Package of Resource Priority Register Descriptor sub-packages. + * Parsing the full structure is not yet supported. + * Mark the register as unsupported for now. + */ + pr_debug("CPU:%d Resource Priority not supported\n", pr->id); + cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_INTEGER; + cpc_ptr->cpc_regs[i-2].cpc_entry.int_value = 0; } else { pr_debug("Invalid entry type (%d) in _CPC for CPU:%d\n", i, pr->id); diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index d1f02ceec4f9..8693890a7275 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h @@ -17,16 +17,18 @@ #include #include -/* CPPCv2 and CPPCv3 support */ +/* CPPCv2, CPPCv3 and CPPCv4 support */ #define CPPC_V2_REV 2 #define CPPC_V3_REV 3 +#define CPPC_V4_REV 4 #define CPPC_V2_NUM_ENT 21 #define CPPC_V3_NUM_ENT 23 +#define CPPC_V4_NUM_ENT 25 #define PCC_CMD_COMPLETE_MASK (1 << 0) #define PCC_ERROR_MASK (1 << 2) -#define MAX_CPC_REG_ENT 21 +#define MAX_CPC_REG_ENT 23 /* CPPC specific PCC commands. */ #define CMD_READ 0 @@ -109,6 +111,8 @@ enum cppc_regs { REFERENCE_PERF, LOWEST_FREQ, NOMINAL_FREQ, + OSPM_NOMINAL_PERF, + RESOURCE_PRIORITY, }; /* From 1b1acf2dada0cc3931bb2cb9ff8832edfbee46a1 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Mon, 1 Jun 2026 18:58:08 -0500 Subject: [PATCH 4/5] ACPI: CPPC: Suppress UBSAN warning caused by field misuse The definition of reg->access_width changes depending on the reg->space_id type. Type ACPI_ADR_SPACE_PLATFORM_COMM uses access_width to indicate the PCC region, which can result in a UBSAN if the value is greater than 4. For example: UBSAN: shift-out-of-bounds in drivers/acpi/cppc_acpi.c:1090:9 shift exponent 32 is too large for 32-bit type 'int' CPU: 61 UID: 0 PID: 1220 Comm: (udev-worker) Not tainted 7.0.10-201.fc44.aarch64 #1 PREEMPT(lazy) Hardware name: To be filled by O.E.M. Call trace: ...(trimming) ubsan_epilogue+0x10/0x48 __ubsan_handle_shift_out_of_bounds+0xdc/0x1e0 cpc_write+0x4d0/0x670 cppc_set_perf+0x18c/0x490 cppc_cpufreq_cpu_init+0x1c8/0x380 [cppc_cpufreq] ... (trimming) Lets fix this by validating the region type, as well as whether access_width has a value. Then since we are returning bit_width directly for ACPI_ADR_SPACE_PLATFORM_COMM, drop the code correcting the size. Fixes: 2f4a4d63a193 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") Signed-off-by: Jeremy Linton Tested-by: Jarred White Reviewed-by: Jarred White Reviewed-by: Easwar Hariharan Cc: All applicable Link: https://patch.msgid.link/20260601235808.1113137-1-jeremy.linton@arm.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index c76cfafa3589..9f572f481241 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -185,8 +185,13 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_freq); show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time); -/* Check for valid access_width, otherwise, fallback to using bit_width */ -#define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width) +/* + * PCC reuses the access_width field as the subspace id, so only decode access + * size for non-PCC registers. Otherwise, use the bit_width. + */ +#define GET_BIT_WIDTH(reg) (((reg)->access_width && \ + (reg)->space_id != ACPI_ADR_SPACE_PLATFORM_COMM) ? \ + (8 << ((reg)->access_width - 1)) : (reg)->bit_width) /* Shift and apply the mask for CPC reads/writes */ #define MASK_VAL_READ(reg, val) (((val) >> (reg)->bit_offset) & \ @@ -1056,7 +1061,6 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) * by the bit width field; the access size is used to indicate * the PCC subspace id. */ - size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) @@ -1129,7 +1133,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) * by the bit width field; the access size is used to indicate * the PCC subspace id. */ - size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) From 66c62e6773c54ce5233eb21c6d48999c3747bd13 Mon Sep 17 00:00:00 2001 From: Tony W Wang-oc Date: Tue, 9 Jun 2026 03:03:59 +0800 Subject: [PATCH 5/5] ACPI: processor: Add cpuidle driver check in acpi_processor_register_idle_driver() Commit 7a8c994cbb2d ("ACPI: processor: idle: Optimize ACPI idle driver registration") moved the ACPI idle driver registration to acpi_processor_driver_init(), but it didn't check whether a cpuidle driver was already registered. For example, on Intel platforms, if the intel_idle driver is already loaded, the code would still evaluate the _CST object in the ACPI table and attempt to register the acpi_idle driver. This registration would fail with -EBUSY due to the existing check in cpuidle_register_driver. Add a check at the beginning of acpi_processor_register_idle_driver() to avoid unnecessary _CST evaluate and potential registration failures. Fixes: 7a8c994cbb2d ("ACPI: processor: idle: Optimize ACPI idle driver registration") Signed-off-by: Tony W Wang-oc Link: https://patch.msgid.link/20260608190359.3254-1-TonyWWang-oc@zhaoxin.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_idle.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ee5facccbe10..390ab5f1d313 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1355,6 +1355,15 @@ void acpi_processor_register_idle_driver(void) int ret = -ENODEV; int cpu; + /* + * If a cpuidle driver is already registered, there is no need to + * evaluate _CST or attempt to register the ACPI idle driver. + */ + if (cpuidle_get_driver()) { + pr_debug("cpuidle driver %pS already registered.\n", cpuidle_get_driver()); + return; + } + acpi_processor_update_max_cstate(); /*