[PATCH v3 04/11] smp: replace smp_call_function_single() with smp_call()

From: Donghai Qiao
Date: Tue May 17 2022 - 14:04:05 EST


Eliminated the percpu global csd_data and temporarily hooked up
smp_call_function_single() to smp_call().

Signed-off-by: Donghai Qiao <dqiao@xxxxxxxxxx>
---
v1 -> v2: Removed 'x' from the function names and change XCALL to
SMP_CALL from the new macros
kernel/smp.c | 74 ++++++++++++++++++----------------------------------
1 file changed, 25 insertions(+), 49 deletions(-)

diff --git a/kernel/smp.c b/kernel/smp.c
index 101a48d1d8af..8fdea9547502 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -414,8 +414,6 @@ static __always_inline void csd_unlock(struct __call_single_data *csd)
smp_store_release(&csd->node.u_flags, 0);
}

-static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);
-
void __smp_call_single_queue(int cpu, struct llist_node *node)
{
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
@@ -649,6 +647,9 @@ void flush_smp_call_function_from_idle(void)
}

/*
+ * This is a temporarily hook up. This function will be eliminated
+ * with a later patch in this series.
+ *
* smp_call_function_single - Run a function on a specific CPU
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
@@ -657,59 +658,21 @@ void flush_smp_call_function_from_idle(void)
* Returns 0 on success, else a negative status code.
*/
int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
- int wait)
+ int wait)
{
- call_single_data_t *csd;
- call_single_data_t csd_stack = {
- .node = { .u_flags = CSD_FLAG_LOCK | CSD_TYPE_SYNC, },
- };
- int this_cpu;
- int err;
-
- /*
- * prevent preemption and reschedule on another processor,
- * as well as CPU removal
- */
- this_cpu = get_cpu();
-
- /*
- * Can deadlock when called with interrupts disabled.
- * We allow cpu's that are not yet online though, as no one else can
- * send smp call function interrupt to this cpu and as such deadlocks
- * can't happen.
- */
- WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
- && !oops_in_progress);
+ unsigned int flags = 0;

- /*
- * When @wait we can deadlock when we interrupt between llist_add() and
- * arch_send_call_function_ipi*(); when !@wait we can deadlock due to
- * csd_lock() on because the interrupt context uses the same csd
- * storage.
- */
- WARN_ON_ONCE(!in_task());
-
- csd = &csd_stack;
- if (!wait) {
- csd = this_cpu_ptr(&csd_data);
- csd_lock(csd);
- }
-
- csd->func = func;
- csd->info = info;
-#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
- csd->node.src = smp_processor_id();
- csd->node.dst = cpu;
-#endif
-
- err = generic_exec_single(cpu, csd);
+ if ((unsigned int)cpu >= nr_cpu_ids || !cpu_online(cpu))
+ return -ENXIO;

if (wait)
- csd_lock_wait(csd);
+ flags = SMP_CALL_TYPE_SYNC;
+ else
+ flags = SMP_CALL_TYPE_ASYNC;

- put_cpu();
+ smp_call(cpu, func, info, flags);

- return err;
+ return 0;
}
EXPORT_SYMBOL(smp_call_function_single);

@@ -1175,6 +1138,19 @@ void __smp_call_mask_cond(const struct cpumask *mask,
smp_cond_func_t cond_func, bool local_cpu,
unsigned int flags)
{
+ bool wait = false;
+
+ if (flags == SMP_CALL_TYPE_SYNC)
+ wait = true;
+
+ preempt_disable();
+
+ /*
+ * This is temporarily hook. The function smp_call_function_many_cond()
+ * will be inlined here with a later patch in this series.
+ */
+ smp_call_function_many_cond(mask, func, info, local_cpu, wait, cond_func);
+ preempt_enable();
}

/*
--
2.27.0