summaryrefslogtreecommitdiff
path: root/drivers/acpi/cppc_acpi.c
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-08-03 14:41:57 +0100
committerMark Brown <broonie@kernel.org>2026-08-03 14:41:57 +0100
commit20b9485d212a043ba92b5d788767628fd387c977 (patch)
tree0d00de1ac271ee765c770fea31e057522fd7491a /drivers/acpi/cppc_acpi.c
parent94382f24a3b888db45c78c939270836f0f741d91 (diff)
parentdf386fe6be46dce460d9366066a277ec8b45a01c (diff)
downloadlinux-next-20b9485d212a043ba92b5d788767628fd387c977.tar.gz
linux-next-20b9485d212a043ba92b5d788767628fd387c977.zip
Merge branch 'for-next/core' of https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
-rw-r--r--drivers/acpi/cppc_acpi.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 53d09ca98f06..a5892a501830 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1017,6 +1017,22 @@ int __weak cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val)
}
/**
+ * cpc_read_ffh_fb_ctrs() - Read FFH feedback counters together
+ * @cpunum: Target CPU
+ * @reg1: first CPPC register information
+ * @val1: place holder for first return value
+ * @reg2: second CPPC register information
+ * @val2: place holder for second return value
+ *
+ * Return: 0 on success, error code otherwise
+ */
+int __weak cpc_read_ffh_fb_ctrs(int cpunum, struct cpc_reg *reg1,
+ u64 *val1, struct cpc_reg *reg2, u64 *val2)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
* cpc_write_ffh() - Write FFH register
* @cpunum: CPU number to write
* @reg: cppc register information
@@ -1508,6 +1524,33 @@ bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu)
}
EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc_cpu);
+static int cppc_read_fb_ctrs(int cpunum,
+ struct cpc_register_resource *delivered_reg,
+ struct cpc_register_resource *reference_reg,
+ u64 *delivered, u64 *reference)
+{
+ int ret;
+
+ /*
+ * For FFH feedback counters, try a paired read first to reduce
+ * sampling skew between delivered and reference counters. Fall
+ * back to the existing per-register reads if unsupported.
+ */
+ if (CPC_IN_FFH(delivered_reg) && CPC_IN_FFH(reference_reg)) {
+ ret = cpc_read_ffh_fb_ctrs(cpunum,
+ &delivered_reg->cpc_entry.reg, delivered,
+ &reference_reg->cpc_entry.reg, reference);
+ if (ret != -EOPNOTSUPP)
+ return ret;
+ }
+
+ ret = cpc_read(cpunum, delivered_reg, delivered);
+ if (ret)
+ return ret;
+
+ return cpc_read(cpunum, reference_reg, reference);
+}
+
/**
* cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region.
*
@@ -1573,11 +1616,8 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
}
}
- ret = cpc_read(cpunum, delivered_reg, &delivered);
- if (ret)
- goto out_err;
-
- ret = cpc_read(cpunum, reference_reg, &reference);
+ ret = cppc_read_fb_ctrs(cpunum, delivered_reg, reference_reg,
+ &delivered, &reference);
if (ret)
goto out_err;