Re: [PATCH 5/5] cpufreq: loongson3: Replace IOCSR read/write with MMIO ones
Huacai Chen <[email protected]>
| Newsgroups | dev.linux.lists.loongarch,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm,org.kernel.vger.stable |
|---|---|
| Message-ID | <CAAhV-H5gbyo3CHj+b5YwwU1GZG47hThx3OJRAXCDEoJ2KKSnXw@mail.gmail.com> |
Hi, Zhongqiu, On Thu, Aug 20, 2026 at 8:57 PM Zhongqiu Han <[email protected]> wrote: > > On 8/18/2026 8:39 PM, Huacai Chen wrote: > > Our server productions (e.g. Loongson-3D6000/3E6000) can have multiple > > nodes in one package and SMC mailboxes are also per-node. However, IOCSR > > read/write can only perform on the current node, while sometimes we want > > to perform on other nodes (e.g. when switch governor, the get and target > > callbacks are not run on target core). So replace IOCSR read/write with > > MMIO ones. > > > > Cc: [email protected] > > Signed-off-by: Huacai Chen <[email protected]> > > --- > > drivers/cpufreq/loongson3_cpufreq.c | 31 ++++++++++++++++++++++------- > > 1 file changed, 24 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c > > index c75c0e30e881..e5062cd62390 100644 > > --- a/drivers/cpufreq/loongson3_cpufreq.c > > +++ b/drivers/cpufreq/loongson3_cpufreq.c > > @@ -164,6 +164,12 @@ union smc_message { > > > > #define FREQ_MAX_LEVEL 16 > > > > +#define MMIO_SMCMBX(node) \ > > + ((void __iomem *)(IO_BASE | (u64)(node) << NODE_ADDRSPACE_SHIFT | LOONGSON_REG_BASE | LOONGARCH_IOCSR_SMCMBX)) > > + > > +#define MMIO_MISC_FUNC(node) \ > > + ((void __iomem *)(IO_BASE | (u64)(node) << NODE_ADDRSPACE_SHIFT | LOONGSON_REG_BASE | LOONGARCH_IOCSR_MISC_FUNC)) > > + > > struct loongson3_freq_data { > > unsigned int def_freq_level; > > struct cpufreq_frequency_table table[]; > > @@ -176,13 +182,25 @@ static DEFINE_PER_CPU(struct loongson3_freq_data *, freq_data); > > static inline int do_service_request(u32 id, u32 info, u32 cmd, u32 val, u32 extra) > > { > > int retries; > > - unsigned int cpu = raw_smp_processor_id(); > > - unsigned int nid = cpu_to_node(cpu); > > + unsigned int cpu, nid; > > union smc_message msg, last; > > > > + switch (cmd) { > > + case CMD_GET_FREQ_INFO: > > + case CMD_SET_FREQ_INFO: > > + case CMD_GET_FREQ_LEVEL_NUM: > > + case CMD_GET_FREQ_LEVEL_INFO: > > + case CMD_GET_FREQ_BOOST_LEVEL: > > + cpu = cpu_number_map(id); > > cpu_number_map() is undefined when CONFIG_SMP=n. Wouldn't that result in > a build failure? Yes, part of the code should be guarded by CONFIG_SMP here. > > > > + break; > > + default: > > + cpu = raw_smp_processor_id(); > > + } > > + nid = cpu_to_node(cpu); > > + > > mutex_lock(&cpufreq_mutex[nid]); > > > > - last.value = iocsr_read32(LOONGARCH_IOCSR_SMCMBX); > > + last.value = readl(MMIO_SMCMBX(nid)); > > if (!last.complete) { > > mutex_unlock(&cpufreq_mutex[nid]); > > return -EPERM; > > @@ -195,12 +213,11 @@ static inline int do_service_request(u32 id, u32 info, u32 cmd, u32 val, u32 ext > > msg.extra = extra; > > msg.complete = 0; > > > > - iocsr_write32(msg.value, LOONGARCH_IOCSR_SMCMBX); > > - iocsr_write32(iocsr_read32(LOONGARCH_IOCSR_MISC_FUNC) | IOCSR_MISC_FUNC_SOFT_INT, > > - LOONGARCH_IOCSR_MISC_FUNC); > > + writel(msg.value, MMIO_SMCMBX(nid)); > > + writel(readl(MMIO_MISC_FUNC(nid)) | IOCSR_MISC_FUNC_SOFT_INT, MMIO_MISC_FUNC(nid)); > > > > for (retries = 0; retries < 10000; retries++) { > > - msg.value = iocsr_read32(LOONGARCH_IOCSR_SMCMBX); > > + msg.value = readl(MMIO_SMCMBX(nid)); > > if (msg.complete) > > break; > > > > > Please ignore this comments if you do not think it is worth addressing: > > A separate issue, it seems that DVFS and Boost feature is set in > loongson3_cpufreq_probe(), what if about on other nodes (non-boot cpu > node) and what if cpu hotplug? Interesting question. After discussion with the firmware team, They told me that CMD_SET_FEATURE is a global command, the SMC firmware will align the settings for all nodes. Huacai > > static int loongson3_cpufreq_probe(struct platform_device *pdev) > { > int i, ret; > > for (i = 0; i < MAX_PACKAGES; i++) { > ret = devm_mutex_init(&pdev->dev, &cpufreq_mutex[i]); > if (ret) > return ret; > } > > ret = do_service_request(0, 0, CMD_GET_VERSION, 0, 0); > if (ret <= 0) > return -EPERM; > > ret = do_service_request(FEATURE_DVFS, 0, CMD_SET_FEATURE, > FEATURE_DVFS_ENABLE | FEATURE_DVFS_BOOST, 0); > if (ret < 0) > return -EPERM; > > ...... > > } > > > -- > Thx and BRs, > Zhongqiu Han