2022-05-18 04:16:23

by Donghai Qiao

[permalink] [raw]
Subject: [PATCH v3 00/11] smp: cross CPU call interface

The motivation of this patch set is intended to make the existing
cross CPU call mechanism become a formal interface, more friendly
to the kernel developers.

For the simplicity self-explanatory less code redundancy and no
ambiguity, the set of functions below can satisfy any existing
demand for cross call, at the meantime they still carry over the
same semantics and the similar parameter lists.

int smp_call(int cpu, smp_call_func_t func, void *info, unsigned int flags)

int smp_call_cond(int cpu, smp_call_func_t func, void *info,
smp_cond_func_t condf, unsigned int flags)

void smp_call_mask(const struct cpumask *mask, smp_call_func_t func,
void *info, unsigned int flags)

void smp_call_mask_others(const struct cpumask *mask, smp_call_func_t func,
void *info, unsigned int flags)

void smp_call_mask_cond(const struct cpumask *mask, smp_call_func_t func,
void *info, smp_cond_func_t condf, unsigned int flags)

int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags)

Patch 1: The smp cross call related structures and definitions are
consolidated from smp.c smp_types.h to smp.h. As a result, smp_types.h
is deleted from the source tree.

Patch 2: The set of smp_call* functions listed above are defined.
But the details will be done with the subsequent patches in this set.

Patch 3: Removed SCF_WAIT and SCF_RUN_LOCAL and changed
smp_call_function_many_cond() accordingly. In order to differentiate
the cross calls that the local CPU needs to be included from those the
local CPU needs to be excluded, the interface provides two different
functions - smp_call_mask() and smp_call_mask_others(). As a result
of these changes, the on_each_cpu* functions and smp_call_function_many
smp_call_function will be eliminated with another patch in this series.

Patch 4: Eliminated the percpu global csd_data. Let
smp_call_function_single() temporarily hook up to smp_call().

Patch 5: Replaced smp_call_function_single_async() with smp_call_csd()
and also extended smp_call_csd() to support one CPU synchronous cross
call with preallocated csd structure

Patch 6: irq_work.c and core.c should use the cross interface rather
than using a unpublished internal function __smp_call_single_queue.

But this change also exposed unpublished types SMP_CALL_TYPE_TTWU and
SMP_CALL_TYPE_IRQ_WORK. However, this is a temporarily change so that
all kernel clients can call the interface as the first step. A
permanent solution should implement new cross call func() for both
and from there the TTWU and IRQ_WORK types of requests can be processed.
That way, the special TTWU and IRQ_WORK types will not be visible from
the cross call interface. Because this needs to change core.s and
irq_work.c, this should be done with a follow up patch set.

Patch 7: When a caller needs to send a cross call to a preferred CPU,
the caller should provide the CPU rather than having the cross call
interface pick up one because interface should do the common job for
the majority rather than cover every single special cases.

In the scenario of smp_call_function_any(), a preferred CPU is either
the local CPU or any CPU in the same node or any online CPU as long
as it is present in cpumask. However, the way of selecting a preferred
CPU should be done by the caller. Thus, the particular code which
deal with CPU selection is moved outside of smp_call_function_any()
and formed a utility function __smp_cpu_nearby() for this purpose.
So, the function smp_call_function_any() can be replaced with the
combination of __smp_cpu_nearby() and smp_call(). As a result, the
function smp_call_function_any() is eliminated.

Patch 8: Eliminated smp_call_function, smp_call_function_many,
smp_call_function_many_cond, on_each_cpu, on_each_cpu_mask,
on_each_cpu_cond, on_each_cpu_cond_mask.

Patch 9: Eliminated smp_call_function_single_async.

Patch 10: Eliminated smp_call_function_single.

Patch 11: modify up.c to adopt the same format of cross CPU call.

Note: Each patch in this set depends on its precedent patch only.
The kernel can be built and boot if it is patched with any
number of patches starting from 1 to 11.

v1 -> v2: Removed 'x' from the function names and change XCALL to
SMP_CALL from the new macros.
V2 -> v3: Modified the cover-letter since v2;
Addressed the issues that Peter has pointed out previously.

Donghai Qiao (11):
smp: consolidate the structure definitions to smp.h
smp: the definitions of cross call interface
smp: remove SCF_WAIT and SCF_RUN_LOCAL
smp: replace smp_call_function_single() with smp_call()
smp: replace smp_call_function_single_async with smp_call_csd
smp: use smp_call_csd() from irq_work.c and core.c
smp: eliminate smp_call_function_any
smp: replace smp_call_function_many_cond() with __smp_call_mask_cond()
smp: replace smp_call_function_single_async with smp_call_csd
smp: replace smp_call_function_single() with smp_call()
smp: up.c to adopt the same format of cross CPU call.

arch/alpha/kernel/process.c | 2 +-
arch/alpha/kernel/rtc.c | 4 +-
arch/alpha/kernel/smp.c | 13 +-
arch/arc/kernel/perf_event.c | 2 +-
arch/arc/mm/cache.c | 2 +-
arch/arc/mm/tlb.c | 14 +-
arch/arm/common/bL_switcher.c | 3 +-
arch/arm/kernel/machine_kexec.c | 3 +-
arch/arm/kernel/perf_event_v7.c | 18 +-
arch/arm/kernel/smp_tlb.c | 23 +-
arch/arm/kernel/smp_twd.c | 4 +-
arch/arm/mach-bcm/bcm_kona_smc.c | 2 +-
arch/arm/mach-mvebu/pmsu.c | 4 +-
arch/arm/mm/flush.c | 5 +-
arch/arm/vfp/vfpmodule.c | 2 +-
arch/arm64/kernel/armv8_deprecated.c | 4 +-
arch/arm64/kernel/perf_event.c | 16 +-
arch/arm64/kernel/topology.c | 2 +-
arch/arm64/kvm/arm.c | 6 +-
arch/csky/abiv2/cacheflush.c | 2 +-
arch/csky/kernel/cpu-probe.c | 2 +-
arch/csky/kernel/perf_event.c | 2 +-
arch/csky/kernel/smp.c | 2 +-
arch/csky/mm/cachev2.c | 2 +-
arch/ia64/kernel/mca.c | 4 +-
arch/ia64/kernel/palinfo.c | 3 +-
arch/ia64/kernel/smp.c | 12 +-
arch/ia64/kernel/smpboot.c | 2 +-
arch/ia64/kernel/uncached.c | 6 +-
arch/mips/cavium-octeon/octeon-irq.c | 4 +-
arch/mips/cavium-octeon/setup.c | 6 +-
arch/mips/kernel/crash.c | 3 +-
arch/mips/kernel/machine_kexec.c | 3 +-
arch/mips/kernel/perf_event_mipsxx.c | 7 +-
arch/mips/kernel/process.c | 2 +-
arch/mips/kernel/smp-bmips.c | 3 +-
arch/mips/kernel/smp-cps.c | 8 +-
arch/mips/kernel/smp.c | 11 +-
arch/mips/kernel/sysrq.c | 3 +-
arch/mips/mm/c-r4k.c | 4 +-
arch/mips/sibyte/common/cfe.c | 3 +-
arch/openrisc/kernel/smp.c | 13 +-
arch/parisc/kernel/cache.c | 4 +-
arch/parisc/mm/init.c | 2 +-
arch/powerpc/kernel/dawr.c | 3 +-
arch/powerpc/kernel/kvm.c | 2 +-
arch/powerpc/kernel/security.c | 6 +-
arch/powerpc/kernel/smp.c | 6 +-
arch/powerpc/kernel/sysfs.c | 28 +-
arch/powerpc/kernel/tau_6xx.c | 4 +-
arch/powerpc/kernel/watchdog.c | 4 +-
arch/powerpc/kexec/core_64.c | 3 +-
arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 +-
arch/powerpc/kvm/book3s_hv.c | 8 +-
arch/powerpc/mm/book3s64/pgtable.c | 2 +-
arch/powerpc/mm/book3s64/radix_tlb.c | 12 +-
arch/powerpc/mm/nohash/tlb.c | 11 +-
arch/powerpc/mm/slice.c | 4 +-
arch/powerpc/perf/core-book3s.c | 2 +-
arch/powerpc/perf/imc-pmu.c | 2 +-
arch/powerpc/platforms/85xx/smp.c | 9 +-
arch/powerpc/platforms/powernv/idle.c | 2 +-
arch/powerpc/platforms/pseries/lparcfg.c | 2 +-
arch/riscv/mm/cacheflush.c | 4 +-
arch/s390/hypfs/hypfs_diag0c.c | 2 +-
arch/s390/kernel/alternative.c | 2 +-
arch/s390/kernel/perf_cpum_cf.c | 10 +-
arch/s390/kernel/perf_cpum_cf_common.c | 4 +-
arch/s390/kernel/perf_cpum_sf.c | 4 +-
arch/s390/kernel/processor.c | 2 +-
arch/s390/kernel/smp.c | 2 +-
arch/s390/kernel/topology.c | 2 +-
arch/s390/mm/pgalloc.c | 2 +-
arch/s390/pci/pci_irq.c | 4 +-
arch/sh/kernel/smp.c | 19 +-
arch/sh/mm/cache.c | 3 +-
arch/sparc/include/asm/mman.h | 4 +-
arch/sparc/kernel/nmi.c | 17 +-
arch/sparc/kernel/perf_event.c | 4 +-
arch/sparc/kernel/smp_64.c | 9 +-
arch/sparc/mm/init_64.c | 2 +-
arch/x86/events/core.c | 6 +-
arch/x86/events/intel/core.c | 4 +-
arch/x86/kernel/alternative.c | 2 +-
arch/x86/kernel/amd_nb.c | 2 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/vector.c | 2 +-
arch/x86/kernel/cpu/aperfmperf.c | 5 +-
arch/x86/kernel/cpu/bugs.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 4 +-
arch/x86/kernel/cpu/mce/core.c | 12 +-
arch/x86/kernel/cpu/mce/inject.c | 12 +-
arch/x86/kernel/cpu/mce/intel.c | 2 +-
arch/x86/kernel/cpu/microcode/core.c | 4 +-
arch/x86/kernel/cpu/mtrr/mtrr.c | 2 +-
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 14 +-
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8 +-
arch/x86/kernel/cpu/sgx/main.c | 5 +-
arch/x86/kernel/cpu/umwait.c | 2 +-
arch/x86/kernel/cpu/vmware.c | 2 +-
arch/x86/kernel/cpuid.c | 2 +-
arch/x86/kernel/kvm.c | 6 +-
arch/x86/kernel/ldt.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 3 +-
arch/x86/kvm/x86.c | 11 +-
arch/x86/lib/cache-smp.c | 4 +-
arch/x86/lib/msr-smp.c | 20 +-
arch/x86/mm/pat/set_memory.c | 4 +-
arch/x86/mm/tlb.c | 12 +-
arch/x86/xen/mmu_pv.c | 4 +-
arch/x86/xen/smp_pv.c | 3 +-
arch/x86/xen/suspend.c | 4 +-
arch/xtensa/kernel/smp.c | 29 +-
block/blk-mq.c | 2 +-
drivers/acpi/processor_idle.c | 4 +-
drivers/char/agp/generic.c | 2 +-
drivers/clocksource/ingenic-timer.c | 2 +-
drivers/clocksource/mips-gic-timer.c | 2 +-
drivers/cpufreq/acpi-cpufreq.c | 15 +-
drivers/cpufreq/powernow-k8.c | 9 +-
drivers/cpufreq/powernv-cpufreq.c | 39 +-
drivers/cpufreq/sparc-us2e-cpufreq.c | 4 +-
drivers/cpufreq/sparc-us3-cpufreq.c | 4 +-
drivers/cpufreq/speedstep-ich.c | 7 +-
drivers/cpufreq/tegra194-cpufreq.c | 8 +-
drivers/cpuidle/coupled.c | 2 +-
drivers/cpuidle/driver.c | 8 +-
drivers/edac/amd64_edac.c | 4 +-
drivers/firmware/arm_sdei.c | 10 +-
drivers/gpu/drm/i915/vlv_sideband.c | 2 +-
drivers/hwmon/fam15h_power.c | 2 +-
.../hwtracing/coresight/coresight-cpu-debug.c | 3 +-
.../coresight/coresight-etm3x-core.c | 11 +-
.../coresight/coresight-etm4x-core.c | 12 +-
.../coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/hwtracing/coresight/coresight-trbe.c | 6 +-
drivers/irqchip/irq-mvebu-pic.c | 4 +-
.../net/ethernet/cavium/liquidio/lio_core.c | 2 +-
drivers/net/ethernet/marvell/mvneta.c | 34 +-
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 +-
drivers/perf/arm_spe_pmu.c | 14 +-
.../intel/speed_select_if/isst_if_mbox_msr.c | 4 +-
drivers/platform/x86/intel_ips.c | 4 +-
drivers/powercap/intel_rapl_common.c | 2 +-
drivers/powercap/intel_rapl_msr.c | 2 +-
drivers/regulator/qcom_spmi-regulator.c | 3 +-
drivers/soc/fsl/qbman/qman.c | 4 +-
drivers/soc/fsl/qbman/qman_test_stash.c | 9 +-
drivers/soc/xilinx/xlnx_event_manager.c | 2 +-
drivers/tty/sysrq.c | 3 +-
drivers/watchdog/booke_wdt.c | 8 +-
fs/buffer.c | 2 +-
include/linux/irq_work.h | 2 +-
include/linux/smp.h | 216 ++++--
include/linux/smp_types.h | 69 --
kernel/cpu.c | 4 +-
kernel/debug/debug_core.c | 2 +-
kernel/events/core.c | 10 +-
kernel/irq_work.c | 4 +-
kernel/profile.c | 4 +-
kernel/rcu/rcutorture.c | 3 +-
kernel/rcu/tasks.h | 4 +-
kernel/rcu/tree.c | 6 +-
kernel/rcu/tree_exp.h | 4 +-
kernel/relay.c | 5 +-
kernel/scftorture.c | 16 +-
kernel/sched/core.c | 4 +-
kernel/sched/fair.c | 2 +-
kernel/sched/membarrier.c | 10 +-
kernel/smp.c | 638 ++++++++----------
kernel/time/clockevents.c | 2 +-
kernel/time/clocksource.c | 2 +-
kernel/time/hrtimer.c | 5 +-
kernel/time/tick-common.c | 2 +-
kernel/trace/ftrace.c | 9 +-
kernel/trace/ring_buffer.c | 4 +-
kernel/trace/trace.c | 12 +-
kernel/trace/trace_events.c | 2 +-
kernel/up.c | 58 +-
mm/kasan/quarantine.c | 2 +-
mm/mmu_gather.c | 3 +-
mm/slab.c | 2 +-
net/bpf/test_run.c | 4 +-
net/core/dev.c | 2 +-
net/iucv/iucv.c | 19 +-
virt/kvm/kvm_main.c | 12 +-
186 files changed, 1070 insertions(+), 984 deletions(-)
delete mode 100644 include/linux/smp_types.h

--
2.27.0



2022-05-18 04:33:01

by Donghai Qiao

[permalink] [raw]
Subject: [PATCH v3 02/11] smp: the definitions of cross call interface

The functions of cross CPU call interface are defined below :

int smp_call(int cpu, smp_call_func_t func, void *info,
unsigned int flags)

int smp_call_cond(int cpu, smp_call_func_t func, void *info,
smp_cond_func_t condf, unsigned int flags)

void smp_call_mask(const struct cpumask *mask, smp_call_func_t func,
void *info, unsigned int flags)

void smp_call_mask_others(const struct cpumask *mask, smp_call_func_t func,
void *info, unsigned int flags)

void smp_call_mask_cond(const struct cpumask *mask, smp_call_func_t func,
void *info, smp_cond_func_t condf, unsigned int flags)

int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags)

Basically the set of functions above can cover the requirements for
synchronous and asynchronous type of cross calls. The target CPUs
can be specified as a unique one or all of the CPUs in a given cpumask
or all of the CPUs in cpumask except the local CPU. The CPUs in cpumask
can be as many as all the onlined CPUs or a set of selected CPUs.

Although there is a constrain that cross calls cannot be called from
context with disabled interrupts, the function smp_call_csd() is
allowed to do so, which requires the callers to provide and maintain
their own preallocated call_single_data_t structures.

Signed-off-by: Donghai Qiao <[email protected]>
---
v1 -> v2: Removed 'x' from the function names and change XCALL to
SMP_CALL from the new macros
v2 -> v3: In order to fix the issues that Peter pointed out previously:
Removed smp_call_any();
Changed smp_call_private to smp_call_csd;
Added smp_call_mask_others();
Modified the commit comments accordingly.
include/linux/smp.h | 30 ++++++++
kernel/smp.c | 172 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 202 insertions(+)

diff --git a/include/linux/smp.h b/include/linux/smp.h
index 94bd901b4e4c..06a20454fd53 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -148,6 +148,36 @@ do { \
*(_csd) = CSD_INIT((_func), (_info)); \
} while (0)

+
+/*
+ * smp_call Interface.
+ *
+ * Also see kernel/smp.c for the details.
+ */
+#define SMP_CALL_TYPE_SYNC CSD_TYPE_SYNC
+#define SMP_CALL_TYPE_ASYNC CSD_TYPE_ASYNC
+#define SMP_CALL_TYPE_IRQ_WORK CSD_TYPE_IRQ_WORK
+#define SMP_CALL_TYPE_TTWU CSD_TYPE_TTWU
+#define SMP_CALL_TYPE_MASK CSD_FLAG_TYPE_MASK
+
+#define SMP_CALL_ALL -1
+
+extern int smp_call(int cpu, smp_call_func_t func, void *info, unsigned int flags);
+
+extern int smp_call_cond(int cpu, smp_call_func_t func, void *info,
+ smp_cond_func_t condf, unsigned int flags);
+
+extern void smp_call_mask(const struct cpumask *mask, smp_call_func_t func,
+ void *info, unsigned int flags);
+
+void smp_call_mask_others(const struct cpumask *mask, smp_call_func_t func,
+ void *info, unsigned int flags);
+
+extern void smp_call_mask_cond(const struct cpumask *mask, smp_call_func_t func,
+ void *info, smp_cond_func_t condf, unsigned int flags);
+
+extern int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags);
+
/*
* Enqueue a llist_node on the call_single_queue; be very careful, read
* flush_smp_call_function_queue() in detail.
diff --git a/kernel/smp.c b/kernel/smp.c
index 4d192ac85a91..906be125068f 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -1185,3 +1185,175 @@ int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, bool phys)
return sscs.ret;
}
EXPORT_SYMBOL_GPL(smp_call_on_cpu);
+
+
+void __smp_call_mask_cond(const struct cpumask *mask,
+ smp_call_func_t func, void *info,
+ smp_cond_func_t cond_func, bool local_cpu,
+ unsigned int flags)
+{
+}
+
+/*
+ * smp_call Interface
+ *
+ * Consolidate the cross CPU call usage from the history below:
+ *
+ * Normally this interface cannot be used with interrupts disabled or
+ * from a hardware interrupt handler or from a bottom half handler.
+ * But there are two exceptions:
+ * 1) It can be used during early boot while early_boot_irqs_disabled
+ * is. In this scenario, you should use local_irq_save/restore()
+ * instead of local_irq_disable/enable()
+ * 2) Because smp_call_csd(cpu, csd, SMP_CALL_TYPE_ASYNC) is an asynchonous
+ * call with a preallocated csd structure, thus it can be called from
+ * the context where interrupts are disabled.
+ */
+
+/*
+ * Parameters:
+ *
+ * cpu: If cpu == SMP_CALL_ALL, the cross call is for all the online CPUs
+ * Otherwise, if 0 <= cpu < nr_cpu_ids, the cross call is for that cpu.
+ *
+ * func: It is the cross function that the destination CPUs need to execute.
+ * This function must be fast and non-blocking.
+ *
+ * info: It is the parameter to func().
+ *
+ * flags: The flags specify the manner the cross call is performaned in terms
+ * of synchronous or asynchronous.
+ *
+ * A synchronous cross call will not return immediately until all
+ * the destination CPUs have executed func() and responded the call.
+ *
+ * An asynchrouse cross call will return immediately as soon as it
+ * has fired all the cross calls and run func() locally if needed
+ * regardless the status of the target CPUs.
+ *
+ * Return: %0 on success or negative errno value on error.
+ */
+int smp_call(int cpu, smp_call_func_t func, void *info, unsigned int flags)
+{
+ return smp_call_cond(cpu, func, info, NULL, flags);
+}
+EXPORT_SYMBOL(smp_call);
+
+/*
+ * Parameters:
+ *
+ * cond_func: This is a condition function cond_func(cpu, info) invoked by
+ * the underlying cross call mechanism only. If the return value
+ * from cond_func(cpu, info) is true, the cross call will be sent
+ * to that cpu, otherwise not.
+ *
+ * Others: see smp_call().
+ *
+ * Return: %0 on success or negative errno value on error.
+ */
+int smp_call_cond(int cpu, smp_call_func_t func, void *info,
+ smp_cond_func_t cond_func, unsigned int flags)
+{
+ preempt_disable();
+ if (cpu == SMP_CALL_ALL) {
+ __smp_call_mask_cond(cpu_online_mask, func, info, cond_func, true, flags);
+ } else if ((unsigned int)cpu < nr_cpu_ids) {
+ __smp_call_mask_cond(cpumask_of(cpu), func, info, cond_func, true, flags);
+ } else {
+ preempt_enable();
+ pr_warn("Invalid cpu ID = %d\n", cpu);
+ return -ENXIO;
+ }
+ preempt_enable();
+ return 0;
+}
+EXPORT_SYMBOL(smp_call_cond);
+
+/*
+ * Parameters:
+ *
+ * mask: The cross call will be sent to all the CPUs in mask.
+ *
+ * Others: see smp_call().
+ */
+void smp_call_mask(const struct cpumask *mask, smp_call_func_t func,
+ void *info, unsigned int flags)
+{
+ if (mask == NULL) {
+ pr_warn("mask must not be NULL\n");
+ return;
+ }
+
+ preempt_disable();
+ __smp_call_mask_cond(mask, func, info, NULL, true, flags);
+ preempt_enable();
+}
+EXPORT_SYMBOL(smp_call_mask);
+
+/*
+ * Parameters:
+ *
+ * mask: The cross call will be sent to all the CPUs in mask except
+ * the local CPU.
+ *
+ * Others: see smp_call().
+ *
+ * Besides, its the callers' discrimination as to whether preemption
+ * needs to be disabled or not during the call.
+ */
+void smp_call_mask_others(const struct cpumask *mask, smp_call_func_t func,
+ void *info, unsigned int flags)
+{
+ if (mask == NULL) {
+ pr_warn("mask must not be NULL\n");
+ return;
+ }
+
+ __smp_call_mask_cond(mask, func, info, NULL, false, flags);
+}
+EXPORT_SYMBOL(smp_call_mask_others);
+
+/*
+ * The combination of smp_call_cond() and smp_call_mask()
+ */
+void smp_call_mask_cond(const struct cpumask *mask,
+ smp_call_func_t func, void *info,
+ smp_cond_func_t cond_func,
+ unsigned int flags)
+{
+ if (!mask) {
+ /*
+ * If mask is NULL meaning for all CPUs,
+ * then cond_func must be provided.
+ */
+ WARN_ON_ONCE(!cond_func);
+ mask = cpu_online_mask;
+ }
+
+ preempt_disable();
+ __smp_call_mask_cond(mask, func, info, cond_func, true, flags);
+ preempt_enable();
+}
+EXPORT_SYMBOL(smp_call_mask_cond);
+
+/*
+ * This function provides an alternative way of sending a cross call to
+ * only one destination CPU with a caller pre-allocated private csd instead
+ * of using the csd resource in the cross call mechanism. Thus it is the
+ * callers' responsibity to setup and maintain its own private csd.
+ *
+ * Because of that, this function can be used from the contexts with disabled
+ * interrupts.
+ *
+ * Parameters
+ *
+ * cpu: Must be a positive value less than nr_cpu_id.
+ * csd: The private csd provided by the callers.
+ *
+ * Others: see smp_call().
+ */
+int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags)
+{
+ return 0;
+}
+EXPORT_SYMBOL(smp_call_csd);
--
2.27.0


2022-05-18 04:39:28

by Donghai Qiao

[permalink] [raw]
Subject: [PATCH v3 03/11] smp: remove SCF_WAIT and SCF_RUN_LOCAL

Remove SCF_WAIT and SCF_RUN_LOCAL and change smp_call_function_many_cond
accordingly. In order to differentiate the cross calls that the local CPU
needs to be included from those the local CPU needs to be excluded, the
interface provides two different functions to deal with that - smp_call_mask()
and smp_call_mask_others().

As a result of these change, the set of on_each_cpu* functions will be
eliminated with a patch later on in this series.

Signed-off-by: Donghai Qiao <[email protected]>
---
v1 -> v2: Removed 'x' from the function names and change XCALL to SMP_CALL
from the new macros
v2 -> v3: Added a parameter 'local_cpu' to smp_call_function_many_cond
and the changes accordingly.
kernel/smp.c | 37 ++++++++++---------------------------
1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/kernel/smp.c b/kernel/smp.c
index 906be125068f..101a48d1d8af 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -802,23 +802,14 @@ int smp_call_function_any(const struct cpumask *mask,
}
EXPORT_SYMBOL_GPL(smp_call_function_any);

-/*
- * Flags to be used as scf_flags argument of smp_call_function_many_cond().
- *
- * %SCF_WAIT: Wait until function execution is completed
- * %SCF_RUN_LOCAL: Run also locally if local cpu is set in cpumask
- */
-#define SCF_WAIT (1U << 0)
-#define SCF_RUN_LOCAL (1U << 1)
-
static void smp_call_function_many_cond(const struct cpumask *mask,
smp_call_func_t func, void *info,
- unsigned int scf_flags,
+ bool local_cpu,
+ bool wait,
smp_cond_func_t cond_func)
{
int cpu, last_cpu, this_cpu = smp_processor_id();
struct call_function_data *cfd;
- bool wait = scf_flags & SCF_WAIT;
bool run_remote = false;
bool run_local = false;
int nr_cpus = 0;
@@ -844,14 +835,14 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
WARN_ON_ONCE(!in_task());

/* Check if we need local execution. */
- if ((scf_flags & SCF_RUN_LOCAL) && cpumask_test_cpu(this_cpu, mask))
+ if (local_cpu && cpumask_test_cpu(this_cpu, mask))
run_local = true;

/* Check if we need remote execution, i.e., any CPU excluding this one. */
cpu = cpumask_first_and(mask, cpu_online_mask);
if (cpu == this_cpu)
cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
- if (cpu < nr_cpu_ids)
+ if ((unsigned int)cpu < nr_cpu_ids)
run_remote = true;

if (run_remote) {
@@ -922,16 +913,12 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
}

/**
- * smp_call_function_many(): Run a function on a set of CPUs.
+ * smp_call_function_many(): Run a function on a set of CPUs except the local CPU.
* @mask: The set of cpus to run on (only runs on online subset).
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
- * @wait: Bitmask that controls the operation. If %SCF_WAIT is set, wait
- * (atomically) until function has completed on other CPUs. If
- * %SCF_RUN_LOCAL is set, the function will also be run locally
- * if the local CPU is set in the @cpumask.
- *
- * If @wait is true, then returns once @func has returned.
+ * @wait: If wait is true, the call will not return until func()
+ * has completed on other CPUs.
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler. Preemption
@@ -940,7 +927,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
void smp_call_function_many(const struct cpumask *mask,
smp_call_func_t func, void *info, bool wait)
{
- smp_call_function_many_cond(mask, func, info, wait * SCF_WAIT, NULL);
+ smp_call_function_many_cond(mask, func, info, false, wait, NULL);
}
EXPORT_SYMBOL(smp_call_function_many);

@@ -1052,7 +1039,7 @@ void __init smp_init(void)
}

/*
- * on_each_cpu_cond(): Call a function on each processor for which
+ * on_each_cpu_cond(): Call a function on each processor which
* the supplied function cond_func returns true, optionally waiting
* for all the required CPUs to finish. This may include the local
* processor.
@@ -1076,13 +1063,9 @@ void __init smp_init(void)
void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func,
void *info, bool wait, const struct cpumask *mask)
{
- unsigned int scf_flags = SCF_RUN_LOCAL;
-
- if (wait)
- scf_flags |= SCF_WAIT;

preempt_disable();
- smp_call_function_many_cond(mask, func, info, scf_flags, cond_func);
+ smp_call_function_many_cond(mask, func, info, true, wait, cond_func);
preempt_enable();
}
EXPORT_SYMBOL(on_each_cpu_cond_mask);
--
2.27.0


2022-05-18 04:47:01

by Donghai Qiao

[permalink] [raw]
Subject: [PATCH v3 07/11] smp: eliminate smp_call_function_any

When a caller needs to send a cross call to a preferred CPU,
the caller should provide the CPU rather than having the cross
call interface pick up one because an interface should do the
common job for the majority rather than cover every single
special cases.

In the scenario of smp_call_function_any(), a preferred CPU is
either the local CPU or any CPU in the same node or any online
CPU as long as it is present in cpumask. However, the way of
selecting a preferred CPU should be done by the caller rather
than by the interface. Thus, that particular code is moved
outside of smp_call_function_any() and formed a utility function
__smp_cpu_nearby() for this purpose. So, the function
smp_call_function_any() can be replaced with the combination of
__smp_cpu_nearby() and smp_call(). As a result, the function
smp_call_function_any() is eliminated.

Signed-off-by: Donghai Qiao <[email protected]>
---
v1 -> v2: Removed 'x' from the function names and change XCALL
to SMP_CALL from the new macros
v2 -> v3: Added a new utility function __smp_cpu_nearby() and
use the combination of __smp_cpu_nearby() and smp_call()
to replace smp_call_function_any() accordingly.
arch/arm/kernel/perf_event_v7.c | 18 +++++-
arch/arm64/kernel/perf_event.c | 14 ++++-
arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 12 +++-
drivers/cpufreq/acpi-cpufreq.c | 9 ++-
drivers/cpufreq/powernv-cpufreq.c | 37 +++++++++--
drivers/perf/arm_spe_pmu.c | 14 ++++-
include/linux/smp.h | 12 +---
kernel/smp.c | 77 ++++++++++-------------
8 files changed, 123 insertions(+), 70 deletions(-)

diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index eb2190477da1..64e9d62e9720 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1192,9 +1192,21 @@ static void armv7_read_num_pmnc_events(void *info)

static int armv7_probe_num_events(struct arm_pmu *arm_pmu)
{
- return smp_call_function_any(&arm_pmu->supported_cpus,
- armv7_read_num_pmnc_events,
- &arm_pmu->num_events, 1);
+ int cpu;
+ int ret;
+
+ preempt_disable();
+ cpu = __smp_cpu_nearby(&arm_pmu->supported_cpus);
+ if ((unsigned int)cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return -ENXIO;
+ }
+
+ ret = smp_call(cpu, armv7_read_num_pmnc_events,
+ &arm_pmu->num_events, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
+
+ return ret;
}

static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index cb69ff1e6138..be4ef28dc1d6 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1184,11 +1184,19 @@ static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
.pmu = cpu_pmu,
.present = false,
};
+ int cpu;
int ret;

- ret = smp_call_function_any(&cpu_pmu->supported_cpus,
- __armv8pmu_probe_pmu,
- &probe, 1);
+ preempt_disable();
+ cpu = __smp_cpu_nearby(&cpu_pmu->supported_cpus);
+ if ((unsigned int)cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return -ENXIO;
+ }
+
+ ret = smp_call(cpu, __armv8pmu_probe_pmu, &probe, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
+
if (ret)
return ret;

diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index 87666275eed9..f2dd4f29af27 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -502,6 +502,8 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
struct rdt_domain *d, struct rdtgroup *rdtgrp,
int evtid, int first)
{
+ int cpu;
+
/*
* setup the parameters to send to the IPI to read the data.
*/
@@ -512,7 +514,15 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
rr->val = 0;
rr->first = first;

- smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1);
+ preempt_disable();
+ cpu = __smp_cpu_nearby(&d->cpu_mask);
+ if ((unsigned int)cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return;
+ }
+
+ smp_call(cpu, mon_event_count, rr, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
}

int rdtgroup_mondata_show(struct seq_file *m, void *arg)
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 3d514b82d055..9bbb4b9391f8 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -310,10 +310,15 @@ static u32 drv_read(struct acpi_cpufreq_data *data, const struct cpumask *mask)
.reg = &perf->control_register,
.func.read = data->cpu_freq_read,
};
+ int cpu;
int err;

- err = smp_call_function_any(mask, do_drv_read, &cmd, 1);
- WARN_ON_ONCE(err); /* smp_call_function_any() was buggy? */
+ preempt_disable();
+ cpu = __smp_cpu_nearby(mask);
+ err = smp_call(cpu, do_drv_read, &cmd, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
+
+ WARN_ON_ONCE(err); /* smp_call was buggy? */
return cmd.val;
}

diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index fddbd1ea1635..078ab1c46f73 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -507,8 +507,15 @@ static unsigned int powernv_cpufreq_get(unsigned int cpu)
{
struct powernv_smp_call_data freq_data;

- smp_call_function_any(cpu_sibling_mask(cpu), powernv_read_cpu_freq,
- &freq_data, 1);
+ preempt_disable();
+ cpu = (unsigned int)__smp_cpu_nearby(cpu_sibling_mask(cpu));
+ if (cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return -ENXIO;
+ }
+
+ smp_call((int)cpu, powernv_read_cpu_freq, &freq_data, SMP_CALL_TYPE_SYNC);
+ preempt_enable();

return freq_data.freq;
}
@@ -744,6 +751,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
struct powernv_smp_call_data freq_data;
unsigned int cur_msec, gpstate_idx;
struct global_pstate_info *gpstates = policy->driver_data;
+ int cpu;

if (unlikely(rebooting) && new_index != get_nominal_index())
return 0;
@@ -817,11 +825,20 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,

no_gpstate:
/*
- * Use smp_call_function to send IPI and execute the
+ * Use smp_call to send IPI and execute the
* mtspr on target CPU. We could do that without IPI
* if current CPU is within policy->cpus (core)
*/
- smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
+ preempt_disable();
+ cpu = __smp_cpu_nearby(policy->cpus);
+ if ((unsigned int)cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return -ENXIO;
+ }
+
+ smp_call(cpu, set_pstate, &freq_data, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
+
return 0;
}

@@ -921,8 +938,16 @@ static void powernv_cpufreq_work_fn(struct work_struct *work)

cpus_read_lock();
cpumask_and(&mask, &chip->mask, cpu_online_mask);
- smp_call_function_any(&mask,
- powernv_cpufreq_throttle_check, NULL, 0);
+
+ preempt_disable();
+ cpu = (unsigned int)__smp_cpu_nearby(&mask);
+ if (cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return;
+ }
+
+ smp_call((int)cpu, powernv_cpufreq_throttle_check, NULL, SMP_CALL_TYPE_ASYNC);
+ preempt_enable();

if (!chip->restore)
goto out;
diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index d44bcc29d99c..92fa8e00086f 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -1104,11 +1104,21 @@ static int arm_spe_pmu_cpu_teardown(unsigned int cpu, struct hlist_node *node)

static int arm_spe_pmu_dev_init(struct arm_spe_pmu *spe_pmu)
{
- int ret;
cpumask_t *mask = &spe_pmu->supported_cpus;
+ int cpu;
+ int ret;

/* Make sure we probe the hardware on a relevant CPU */
- ret = smp_call_function_any(mask, __arm_spe_pmu_dev_probe, spe_pmu, 1);
+ preempt_disable();
+ cpu = __smp_cpu_nearby(mask);
+ if ((unsigned int)cpu >= nr_cpu_ids) {
+ preempt_enable();
+ return -ENXIO;
+ }
+
+ ret = smp_call(cpu, __arm_spe_pmu_dev_probe, spe_pmu, SMP_CALL_TYPE_SYNC);
+ preempt_enable();
+
if (ret || !(spe_pmu->features & SPE_PMU_FEAT_DEV_PROBED))
return -ENXIO;

diff --git a/include/linux/smp.h b/include/linux/smp.h
index b4885e45690b..1fb0951ca16b 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -178,6 +178,8 @@ extern void smp_call_mask_cond(const struct cpumask *mask, smp_call_func_t func,

extern int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags);

+extern int __smp_cpu_nearby(const struct cpumask *mask);
+
/*
* Enqueue a llist_node on the call_single_queue; be very careful, read
* flush_smp_call_function_queue() in detail.
@@ -291,9 +293,6 @@ void smp_call_function(smp_call_func_t func, void *info, int wait);
void smp_call_function_many(const struct cpumask *mask,
smp_call_func_t func, void *info, bool wait);

-int smp_call_function_any(const struct cpumask *mask,
- smp_call_func_t func, void *info, int wait);
-
void kick_all_cpus_sync(void);
void wake_up_all_idle_cpus(void);

@@ -342,13 +341,6 @@ static inline void smp_send_reschedule(int cpu) { }
(up_smp_call_function(func, info))
static inline void call_function_init(void) { }

-static inline int
-smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
- void *info, int wait)
-{
- return smp_call_function_single(0, func, info, wait);
-}
-
static inline void kick_all_cpus_sync(void) { }
static inline void wake_up_all_idle_cpus(void) { }

diff --git a/kernel/smp.c b/kernel/smp.c
index f08135ad70e3..df343b1368eb 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -641,49 +641,6 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
}
EXPORT_SYMBOL(smp_call_function_single);

-/*
- * smp_call_function_any - Run a function on any of the given cpus
- * @mask: The mask of cpus it can run on.
- * @func: The function to run. This must be fast and non-blocking.
- * @info: An arbitrary pointer to pass to the function.
- * @wait: If true, wait until function has completed.
- *
- * Returns 0 on success, else a negative status code (if no cpus were online).
- *
- * Selection preference:
- * 1) current cpu if in @mask
- * 2) any cpu of current node if in @mask
- * 3) any other online cpu in @mask
- */
-int smp_call_function_any(const struct cpumask *mask,
- smp_call_func_t func, void *info, int wait)
-{
- unsigned int cpu;
- const struct cpumask *nodemask;
- int ret;
-
- /* Try for same CPU (cheapest) */
- cpu = get_cpu();
- if (cpumask_test_cpu(cpu, mask))
- goto call;
-
- /* Try for same node. */
- nodemask = cpumask_of_node(cpu_to_node(cpu));
- for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids;
- cpu = cpumask_next_and(cpu, nodemask, mask)) {
- if (cpu_online(cpu))
- goto call;
- }
-
- /* Any online will do: smp_call_function_single handles nr_cpu_ids. */
- cpu = cpumask_any_and(mask, cpu_online_mask);
-call:
- ret = smp_call_function_single(cpu, func, info, wait);
- put_cpu();
- return ret;
-}
-EXPORT_SYMBOL_GPL(smp_call_function_any);
-
static void smp_call_function_many_cond(const struct cpumask *mask,
smp_call_func_t func, void *info,
bool local_cpu,
@@ -1072,6 +1029,40 @@ void __smp_call_mask_cond(const struct cpumask *mask,
preempt_enable();
}

+/**
+ * Given cpumask, find an online CPU as close to the local CPU as
+ * possible in the order below:
+ *
+ * - The first pick is the local CPU if it is present in cpumask.
+ * - The second pick is a CPU located in the same node of the
+ * local CPU and it is also present in cpumask.
+ * - The Third pick is any online CPU which is also in cpumask.
+ *
+ * The callers should disable preemption when using this function.
+ */
+int __smp_cpu_nearby(const struct cpumask *mask)
+{
+ int cpu;
+ const struct cpumask *nodemask;
+
+ cpu = smp_processor_id();
+ if (cpumask_test_cpu(cpu, mask))
+ return cpu;
+
+ /* Any CPU in the same node */
+ nodemask = cpumask_of_node(cpu_to_node(cpu));
+ for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids;
+ cpu = cpumask_next_and(cpu, nodemask, mask)) {
+ if (cpu_online(cpu))
+ return cpu;
+ }
+
+ /* Any online CPU will do */
+ cpu = cpumask_any_and(mask, cpu_online_mask);
+ return cpu;
+}
+EXPORT_SYMBOL(__smp_cpu_nearby);
+
/*
* smp_call Interface
*
--
2.27.0


2022-05-18 06:25:39

by Sven Schnelle

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] smp: cross CPU call interface

Donghai Qiao <[email protected]> writes:

> The motivation of this patch set is intended to make the existing
> cross CPU call mechanism become a formal interface, more friendly
> to the kernel developers.
>
> For the simplicity self-explanatory less code redundancy and no
> ambiguity, the set of functions below can satisfy any existing
> demand for cross call, at the meantime they still carry over the
> same semantics and the similar parameter lists.
> [..]

With this patchset applied i see the following splat on s390 when the
ftrace selftests are run:

[ 1.007231] Running postponed tracer tests:
[ 1.007398] Testing tracer function:
[ 1.036267] Callback from call_rcu_tasks() invoked.
[ 1.117709] BUG: using smp_processor_id() in preemptible [00000000] code: swapper/0/1
[ 1.117737] caller is __smp_call_mask_cond+0x42/0x5f8
[ 1.117751] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.18.0-rc7-00017-g9cc3e6b66c62 #789
[ 1.117760] Hardware name: IBM 3906 M04 704 (z/VM 7.1.0)
[ 1.117769] Call Trace:
[ 1.117777] [<000000000f571e54>] dump_stack_lvl+0xac/0x100
[ 1.117788] [<000000000f576eec>] check_preemption_disabled+0xf4/0xf8
[ 1.117798] [<000000000e94eb72>] __smp_call_mask_cond+0x42/0x5f8
[ 1.117808] [<000000000e94f35c>] smp_call_mask_others+0x54/0x70
[ 1.117818] [<000000000e9a8d5e>] ftrace_modify_all_code+0x146/0x170
[ 1.117831] [<000000000e9a8e70>] ftrace_run_update_code+0x30/0x88
[ 1.117842] [<000000000e9ad3a2>] ftrace_startup+0xea/0x1a0
[ 1.117852] [<000000000e9ad498>] register_ftrace_function+0x40/0x88
[ 1.117863] [<000000000e9ccaa8>] function_trace_init+0x90/0x108
[ 1.117897] [<00000000102957aa>] trace_selftest_startup_function+0x6a/0x338
[ 1.117910] [<000000000f56149a>] run_tracer_selftest+0x11a/0x1b0
[ 1.117934] [<0000000010294fe8>] init_trace_selftests+0x90/0x140
[ 1.117965] [<000000000e808aa8>] do_one_initcall+0x78/0x390
[ 1.117996] [<0000000010280804>] do_initcalls+0x12c/0x150
[ 1.118009] [<0000000010280af8>] kernel_init_freeable+0x250/0x290
[ 1.118018] [<000000000f5770de>] kernel_init+0x2e/0x170
[ 1.118028] [<000000000e80b924>] __ret_from_fork+0x3c/0x58
[ 1.118038] [<000000000f5881ea>] ret_from_fork+0xa/0x40
[ 1.118049] 2 locks held by swapper/0/1:
[ 1.118058] #0: 000000001012bae0 (trace_types_lock){+.+.}-{3:3}, at: init_trace_selftests+0x30/0x140
[ 1.118085] #1: 000000001012b698 (ftrace_lock){+.+.}-{3:3}, at: register_ftrace_function+0x32/0x88

2022-05-18 09:05:21

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] smp: cross CPU call interface

I still haven't seen any good rationale for this. It causes massive
churn just to have more complicated interface (and thus more code)
than before. What is the benefit?

I'm also not sure what is formal about this interface, or why it
should be formal. IPIs should be rare, and we'd better off looking
for instances we can remove entirely.

2022-05-18 19:40:26

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] smp: eliminate smp_call_function_any

Hi Donghai,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on rafael-pm/linux-next]
[also build test WARNING on linus/master v5.18-rc7]
[cannot apply to tip/x86/core powerpc/next next-20220518]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Donghai-Qiao/smp-cross-CPU-call-interface/20220518-020728
base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20220519/[email protected]/config)
compiler: arceb-elf-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/9ccc00bf617be7b23dca37d3a7d845165c365725
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Donghai-Qiao/smp-cross-CPU-call-interface/20220518-020728
git checkout 9ccc00bf617be7b23dca37d3a7d845165c365725
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

>> kernel/smp.c:1033: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst
* Given cpumask, find an online CPU as close to the local CPU as


vim +1033 kernel/smp.c

1031
1032 /**
> 1033 * Given cpumask, find an online CPU as close to the local CPU as
1034 * possible in the order below:
1035 *
1036 * - The first pick is the local CPU if it is present in cpumask.
1037 * - The second pick is a CPU located in the same node of the
1038 * local CPU and it is also present in cpumask.
1039 * - The Third pick is any online CPU which is also in cpumask.
1040 *
1041 * The callers should disable preemption when using this function.
1042 */
1043 int __smp_cpu_nearby(const struct cpumask *mask)
1044 {
1045 int cpu;
1046 const struct cpumask *nodemask;
1047
1048 cpu = smp_processor_id();
1049 if (cpumask_test_cpu(cpu, mask))
1050 return cpu;
1051
1052 /* Any CPU in the same node */
1053 nodemask = cpumask_of_node(cpu_to_node(cpu));
1054 for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids;
1055 cpu = cpumask_next_and(cpu, nodemask, mask)) {
1056 if (cpu_online(cpu))
1057 return cpu;
1058 }
1059
1060 /* Any online CPU will do */
1061 cpu = cpumask_any_and(mask, cpu_online_mask);
1062 return cpu;
1063 }
1064 EXPORT_SYMBOL(__smp_cpu_nearby);
1065

--
0-DAY CI Kernel Test Service
https://01.org/lkp