mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ACPI: CPPC: Propagate errors from cross-CPU FFH calls
The arm64 and RISC-V CPPC FFH accessors ignore the return value of smp_call_function_single(). If the target CPU is offline, the call can return -ENXIO without running the callback. The accessors then consume callback output which was never initialized and may report success. CPU offlining leaves the CPU's CPPC sysfs attributes present. On arm64, the AMU feature mask does not exclude an offline CPU, so a paired counter read can expose uninitialized stack values through feedback_ctrs. RISC-V has the same problem in both SBI and CSR reads, and its write paths also inspect an uninitialized callback status after a failed cross-CPU call. Return the SMP call error before using callback output. The arm64 single and paired counter readers already check the helper's return value. For RISC-V, also check the callback status before copying a read value: an unsupported CSR sets the error but does not initialize the value. Fixes:68c5debcc0("arm64: implement CPPC FFH support using AMUs") Fixes:30f3ffbee8("ACPI: RISC-V: Add CPPC driver") Cc: All applicable <stable@vger.kernel.org> Signed-off-by: Christian Loehle <christian.loehle@arm.com> Tested-by: Sumit Gupta <sumitg@nvidia.com> Link: https://patch.msgid.link/20260916162805.1039247-18-christian.loehle@arm.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
6b016c5c96
commit
36e96b469d
|
|
@ -427,7 +427,7 @@ int counters_read_on_cpu(int cpu, smp_call_func_t func, void *val)
|
|||
return -EPERM;
|
||||
func(val);
|
||||
} else {
|
||||
smp_call_function_single(cpu, func, val, 1);
|
||||
return smp_call_function_single(cpu, func, val, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ bool cpc_ffh_supported(void)
|
|||
int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
|
||||
{
|
||||
struct sbi_cppc_data data;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
|
@ -107,19 +108,27 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
|
|||
|
||||
data.reg = FFH_CPPC_SBI_REG(reg->address);
|
||||
|
||||
smp_call_function_single(cpu, sbi_cppc_read, &data, 1);
|
||||
ret = smp_call_function_single(cpu, sbi_cppc_read, &data, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (data.ret.error)
|
||||
return sbi_err_map_linux_errno(data.ret.error);
|
||||
|
||||
*val = data.ret.value;
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
return 0;
|
||||
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
|
||||
data.reg = FFH_CPPC_CSR_NUM(reg->address);
|
||||
|
||||
smp_call_function_single(cpu, cppc_ffh_csr_read, &data, 1);
|
||||
ret = smp_call_function_single(cpu, cppc_ffh_csr_read, &data, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (data.ret.error)
|
||||
return data.ret.error;
|
||||
|
||||
*val = data.ret.value;
|
||||
|
||||
return data.ret.error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
|
@ -128,6 +137,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
|
|||
int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
|
||||
{
|
||||
struct sbi_cppc_data data;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
|
@ -139,14 +149,18 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
|
|||
data.reg = FFH_CPPC_SBI_REG(reg->address);
|
||||
data.val = val;
|
||||
|
||||
smp_call_function_single(cpu, sbi_cppc_write, &data, 1);
|
||||
ret = smp_call_function_single(cpu, sbi_cppc_write, &data, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
|
||||
data.reg = FFH_CPPC_CSR_NUM(reg->address);
|
||||
data.val = val;
|
||||
|
||||
smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
|
||||
ret = smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return data.ret.error;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user