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

From: Huacai Chen

Date: Wed Aug 26 2026 - 11:07:57 EST


Hi, Zhongqiu,

On Thu, Aug 20, 2026 at 8:24 PM Zhongqiu Han
<zhongqiu.han@xxxxxxxxxxxxxxxx> wrote:
>
> 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?
Cross-node accesses need the whole of this series. So:

For single node machines, with or without this patch are both correct.

For multi-nodes machines, this patch cannot solve all problems, but
doesn't make things worse.

>
> >
> > 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.
Yes, we need "return (ret < 0) ? 0 : ret * KILO" here.


Huacai

>
>
> > 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
>