Re: [PATCH 4/5] cpufreq: loongson3: Use global physical CPU ID in get/target callbacks

From: Zhongqiu Han

Date: Thu Aug 20 2026 - 08:24:22 EST


On 8/18/2026 8:39 PM, Huacai Chen wrote:
Our server productions (e.g. Loongson-3D6000/3E6000) can have discrete
global physical CPU IDs while the core ID inside the packages are always
continuous. In these cases we should use global physical CPU IDs to get
and set frequencies.

Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Hongliang Wang <wanghongliang@xxxxxxxxxxx>
Signed-off-by: Huacai Chen <chenhuacai@xxxxxxxxxxx>
---
drivers/cpufreq/loongson3_cpufreq.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c
index e3cd78a5ab18..c75c0e30e881 100644
--- a/drivers/cpufreq/loongson3_cpufreq.c
+++ b/drivers/cpufreq/loongson3_cpufreq.c
@@ -219,38 +219,40 @@ static inline int do_service_request(u32 id, u32 info, u32 cmd, u32 val, u32 ext
static unsigned int loongson3_cpufreq_get(unsigned int cpu)
{
- int ret;
+ int ret, core = cpu_logical_map(cpu);
- ret = do_service_request(cpu, FREQ_INFO_TYPE_FREQ, CMD_GET_FREQ_INFO, 0, 0);
+ ret = do_service_request(core, FREQ_INFO_TYPE_FREQ, CMD_GET_FREQ_INFO, 0, 0);

As patch 5/5 changelog:

"However, IOCSR read/write can only perform on the current node, while
sometimes we want to perform on other nodes"

However, patch 4/5 starts passing the global CPU number without updating
do_service_request(), which is only changed in patch 5/5. Doesn't that
mean patch 4/5 is broken on its own?

return ret * KILO;
}

A separate issue, do_service_request() can return errno such as -EPERM,
it will cause .get() func return a large unsigned integer value.


static int loongson3_cpufreq_target(struct cpufreq_policy *policy, unsigned int index)
{
- int ret;
+ int ret, core = cpu_logical_map(policy->cpu);
- ret = do_service_request(cpu_data[policy->cpu].core,
- FREQ_INFO_TYPE_LEVEL, CMD_SET_FREQ_INFO, index, 0);
+ ret = do_service_request(core, FREQ_INFO_TYPE_LEVEL, CMD_SET_FREQ_INFO,
+ index, 0);
return (ret >= 0) ? 0 : ret;
}
static int configure_freq_table(int cpu)
{
- int i, ret, boost_level, max_level, freq_level;
+ int i, ret, core, boost_level, max_level, freq_level;
struct platform_device *pdev = cpufreq_get_driver_data();
struct loongson3_freq_data *data;
if (per_cpu(freq_data, cpu))
return 0;
- ret = do_service_request(cpu, 0, CMD_GET_FREQ_LEVEL_NUM, 0, 0);
+ core = cpu_logical_map(cpu);
+
+ ret = do_service_request(core, 0, CMD_GET_FREQ_LEVEL_NUM, 0, 0);
if (ret < 0)
return ret;
max_level = ret;
- ret = do_service_request(cpu, 0, CMD_GET_FREQ_BOOST_LEVEL, 0, 0);
+ ret = do_service_request(core, 0, CMD_GET_FREQ_BOOST_LEVEL, 0, 0);
if (ret < 0)
return ret;
boost_level = ret;
@@ -263,7 +265,7 @@ static int configure_freq_table(int cpu)
data->def_freq_level = boost_level - 1;
for (i = 0; i < freq_level; i++) {
- ret = do_service_request(cpu, FREQ_INFO_TYPE_FREQ, CMD_GET_FREQ_LEVEL_INFO, i, 0);
+ ret = do_service_request(core, FREQ_INFO_TYPE_FREQ, CMD_GET_FREQ_LEVEL_INFO, i, 0);
if (ret < 0) {
devm_kfree(&pdev->dev, data);
return ret;


--
Thx and BRs,
Zhongqiu Han