[PATCH 5/8] ACPI: CPPC: Store optional flag in cpc_register_resource
From: Lifeng Zheng
Date: Thu Jul 16 2026 - 22:50:02 EST
The current optionality check uses a compile-time bitmask (REG_OPTIONAL)
applied at call sites via IS_OPTIONAL_CPC_REG(reg_idx). This requires
every caller to know the register index, which will not work for registers
accessed without a fixed index (e.g. entries inside Resource Priority
sub-packages).
Add a boolean 'optional' field to cpc_register_resource so that each
register element carries its own optionality. Populate the field during
_CPC probe (for main registers) and parse_priority_regs() (for Resource
Priority sub-packages), using the existing REG_OPTIONAL and
RES_PRIO_OPTIONAL bitmasks respectively.
Replace the IS_OPTIONAL_CPC_REG() check in cppc_get_reg_val() with a
direct test of reg->optional, and remove the IS_OPTIONAL_CPC_REG() macro.
Signed-off-by: Lifeng Zheng <zhenglifeng1@xxxxxxxxxx>
---
drivers/acpi/cppc_acpi.c | 13 ++++++++-----
include/acpi/cppc_acpi.h | 1 +
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 32829bb822dd..3f1b61c984d4 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -143,11 +143,11 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
#define REG_OPTIONAL (0x7FC7D0)
/*
- * Use the index of the register in per-cpu cpc_regs[] to check if
- * it's an optional one.
+ * Each bit indicates the optionality of the register in resource
+ * priority register descriptor with the corresponding index. 0 means
+ * mandatory and 1 means optional.
*/
-#define IS_OPTIONAL_CPC_REG(reg_idx) (REG_OPTIONAL & (1U << (reg_idx)))
-
+#define RES_PRIO_OPTIONAL (0x6)
/*
* Arbitrary Retries in case the remote processor is slow to respond
* to PCC commands. Keeping it high enough to cover emulators where
@@ -850,6 +850,7 @@ static int parse_priority_regs(union acpi_object *cpc_obj,
reg_elements[0].type = ACPI_TYPE_PACKAGE;
reg_elements[0].cpc_entry.package.count = resources_count;
+ reg_elements[0].optional = RES_PRIO_OPTIONAL & 1U;
for (j = 0; j < reg_elements[0].cpc_entry.package.count; j++) {
reg_elements[0].cpc_entry.package.elements[j].type = ACPI_TYPE_INTEGER;
@@ -858,6 +859,7 @@ static int parse_priority_regs(union acpi_object *cpc_obj,
}
for (j = 1; j < RESOURCE_PRIORITY_NUM; j++) {
+ reg_elements[j].optional = RES_PRIO_OPTIONAL & (1U << j);
ret = parse_cpc_element(®_desc_obj.package.elements[j], ®_elements[j],
pcc_subspace_id, cpu, RESOURCE_PRIORITY);
if (ret)
@@ -996,6 +998,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
/* Iterate through remaining entries in _CPC */
for (i = 2; i < num_ent; i++) {
cpc_obj = &out_obj->package.elements[i];
+ cpc_ptr->cpc_regs[i-2].optional = REG_OPTIONAL & (1U << (i-2));
/*
* Package-type entries are used for nested structures such as
@@ -1415,7 +1418,7 @@ static int cppc_get_reg_val(int cpu, enum cppc_regs reg_idx, u64 *val)
reg = &cpc_desc->cpc_regs[reg_idx];
- if ((reg->type == ACPI_TYPE_INTEGER && IS_OPTIONAL_CPC_REG(reg_idx) &&
+ if ((reg->type == ACPI_TYPE_INTEGER && reg->optional &&
!reg->cpc_entry.int_value) || (reg->type != ACPI_TYPE_INTEGER &&
IS_NULL_REG(®->cpc_entry.reg))) {
pr_debug("CPC register is not supported\n");
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
index 19f8a722654b..c0b8d52016cd 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -80,6 +80,7 @@ struct cpc_register_resource {
struct cpc_register_resource *elements;
} package;
} cpc_entry;
+ bool optional;
};
/* Container to hold the CPC details for each CPU */
--
2.33.0