| From 4f4179fcf420873002035cf1941d844c9e0e7cb3 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| Date: Thu, 21 Jul 2022 19:41:10 +0200 |
| Subject: ACPI: CPPC: Do not prevent CPPC from working in the future |
| |
| From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| |
| commit 4f4179fcf420873002035cf1941d844c9e0e7cb3 upstream. |
| |
| There is a problem with the current revision checks in |
| is_cppc_supported() that they essentially prevent the CPPC support |
| from working if a new _CPC package format revision being a proper |
| superset of the v3 and only causing _CPC to return a package with more |
| entries (while retaining the types and meaning of the entries defined by |
| the v3) is introduced in the future and used by the platform firmware. |
| |
| In that case, as long as the number of entries in the _CPC return |
| package is at least CPPC_V3_NUM_ENT, it should be perfectly fine to |
| use the v3 support code and disregard the additional package entries |
| added by the new package format revision. |
| |
| For this reason, drop is_cppc_supported() altogether, put the revision |
| checks directly into acpi_cppc_processor_probe() so they are easier to |
| follow and rework them to take the case mentioned above into account. |
| |
| Fixes: 4773e77cdc9b ("ACPI / CPPC: Add support for CPPC v3") |
| Cc: 4.18+ <stable@vger.kernel.org> # 4.18+ |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/acpi/cppc_acpi.c | 54 ++++++++++++++++++++--------------------------- |
| include/acpi/cppc_acpi.h | 2 - |
| 2 files changed, 25 insertions(+), 31 deletions(-) |
| |
| --- a/drivers/acpi/cppc_acpi.c |
| +++ b/drivers/acpi/cppc_acpi.c |
| @@ -626,33 +626,6 @@ int pcc_data_alloc(int pcc_ss_id) |
| return 0; |
| } |
| |
| -/* Check if CPPC revision + num_ent combination is supported */ |
| -static bool is_cppc_supported(int revision, int num_ent) |
| -{ |
| - int expected_num_ent; |
| - |
| - switch (revision) { |
| - case CPPC_V2_REV: |
| - expected_num_ent = CPPC_V2_NUM_ENT; |
| - break; |
| - case CPPC_V3_REV: |
| - expected_num_ent = CPPC_V3_NUM_ENT; |
| - break; |
| - default: |
| - pr_debug("Firmware exports unsupported CPPC revision: %d\n", |
| - revision); |
| - return false; |
| - } |
| - |
| - if (expected_num_ent != num_ent) { |
| - pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n", |
| - num_ent, expected_num_ent, revision); |
| - return false; |
| - } |
| - |
| - return true; |
| -} |
| - |
| /* |
| * An example CPC table looks like the following. |
| * |
| @@ -748,7 +721,6 @@ int acpi_cppc_processor_probe(struct acp |
| cpc_obj->type); |
| goto out_free; |
| } |
| - cpc_ptr->num_entries = num_ent; |
| |
| /* Second entry should be revision. */ |
| cpc_obj = &out_obj->package.elements[1]; |
| @@ -759,10 +731,32 @@ int acpi_cppc_processor_probe(struct acp |
| cpc_obj->type); |
| goto out_free; |
| } |
| - cpc_ptr->version = cpc_rev; |
| |
| - if (!is_cppc_supported(cpc_rev, num_ent)) |
| + if (cpc_rev < CPPC_V2_REV) { |
| + pr_debug("Unsupported _CPC Revision (%d) for CPU:%d\n", cpc_rev, |
| + pr->id); |
| goto out_free; |
| + } |
| + |
| + /* |
| + * Disregard _CPC if the number of entries in the return pachage is not |
| + * as expected, but support future revisions being proper supersets of |
| + * the v3 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)) { |
| + 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; |
| + } |
| + |
| + cpc_ptr->num_entries = num_ent; |
| + cpc_ptr->version = cpc_rev; |
| |
| /* Iterate through remaining entries in _CPC */ |
| for (i = 2; i < num_ent; i++) { |
| --- a/include/acpi/cppc_acpi.h |
| +++ b/include/acpi/cppc_acpi.h |
| @@ -16,7 +16,7 @@ |
| #include <acpi/pcc.h> |
| #include <acpi/processor.h> |
| |
| -/* Support CPPCv2 and CPPCv3 */ |
| +/* CPPCv2 and CPPCv3 support */ |
| #define CPPC_V2_REV 2 |
| #define CPPC_V3_REV 3 |
| #define CPPC_V2_NUM_ENT 21 |