All of lore.kernel.org
 help / color / mirror / Atom feed
From: Donghai Qiao <dqiao@redhat.com>
To: akpm@linux-foundation.org, sfr@canb.auug.org.au, arnd@arndb.de,
	peterz@infradead.org, heying24@huawei.com,
	andriy.shevchenko@linux.intel.com, axboe@kernel.dk,
	rdunlap@infradead.org, tglx@linutronix.de, gor@linux.ibm.com
Cc: donghai.w.qiao@gmail.com, linux-kernel@vger.kernel.org,
	Donghai Qiao <dqiao@redhat.com>
Subject: [PATCH v4 05/11] smp: replace smp_call_function_single_async with smp_call_csd
Date: Thu, 19 May 2022 16:49:37 -0400	[thread overview]
Message-ID: <20220519204943.1079578-6-dqiao@redhat.com> (raw)
In-Reply-To: <20220519204943.1079578-1-dqiao@redhat.com>

Replaced smp_call_function_single_async with smp_call_csd and extended
it to support one CPU synchronous call with preallocated csd structure.

Signed-off-by: Donghai Qiao <dqiao@redhat.com>
---
v1 -> v2: removed 'x' from the function names and change XCALL to
          SMP_CALL from the new macros
v2 -> v3: Changed the call of smp_call_private() to smp_call_csd()

 include/linux/smp.h |   3 +-
 kernel/smp.c        | 157 ++++++++++++++++++++------------------------
 2 files changed, 75 insertions(+), 85 deletions(-)

diff --git a/include/linux/smp.h b/include/linux/smp.h
index 06a20454fd53..b4885e45690b 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -193,7 +193,8 @@ int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
 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);
 
-int smp_call_function_single_async(int cpu, struct __call_single_data *csd);
+#define	smp_call_function_single_async(cpu, csd) \
+	smp_call_csd(cpu, csd, SMP_CALL_TYPE_ASYNC)
 
 /*
  * Cpus stopping functions in panic. All have default weak definitions.
diff --git a/kernel/smp.c b/kernel/smp.c
index 8fdea9547502..f08135ad70e3 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -444,41 +444,6 @@ void __smp_call_single_queue(int cpu, struct llist_node *node)
 		send_call_function_single_ipi(cpu);
 }
 
-/*
- * Insert a previously allocated call_single_data_t element
- * for execution on the given CPU. data must already have
- * ->func, ->info, and ->flags set.
- */
-static int generic_exec_single(int cpu, struct __call_single_data *csd)
-{
-	if (cpu == smp_processor_id()) {
-		smp_call_func_t func = csd->func;
-		void *info = csd->info;
-		unsigned long flags;
-
-		/*
-		 * We can unlock early even for the synchronous on-stack case,
-		 * since we're doing this from the same CPU..
-		 */
-		csd_lock_record(csd);
-		csd_unlock(csd);
-		local_irq_save(flags);
-		func(info);
-		csd_lock_record(NULL);
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	if ((unsigned)cpu >= nr_cpu_ids || !cpu_online(cpu)) {
-		csd_unlock(csd);
-		return -ENXIO;
-	}
-
-	__smp_call_single_queue(cpu, &csd->node.llist);
-
-	return 0;
-}
-
 /**
  * generic_smp_call_function_single_interrupt - Execute SMP IPI callbacks
  *
@@ -676,52 +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_single_async() - Run an asynchronous function on a
- * 			         specific CPU.
- * @cpu: The CPU to run on.
- * @csd: Pre-allocated and setup data structure
- *
- * Like smp_call_function_single(), but the call is asynchonous and
- * can thus be done from contexts with disabled interrupts.
- *
- * The caller passes his own pre-allocated data structure
- * (ie: embedded in an object) and is responsible for synchronizing it
- * such that the IPIs performed on the @csd are strictly serialized.
- *
- * If the function is called with one csd which has not yet been
- * processed by previous call to smp_call_function_single_async(), the
- * function will return immediately with -EBUSY showing that the csd
- * object is still in progress.
- *
- * NOTE: Be careful, there is unfortunately no current debugging facility to
- * validate the correctness of this serialization.
- *
- * Return: %0 on success or negative errno value on error
- */
-int smp_call_function_single_async(int cpu, struct __call_single_data *csd)
-{
-	int err = 0;
-
-	preempt_disable();
-
-	if (csd->node.u_flags & CSD_FLAG_LOCK) {
-		err = -EBUSY;
-		goto out;
-	}
-
-	csd->node.u_flags = CSD_FLAG_LOCK;
-	smp_wmb();
-
-	err = generic_exec_single(cpu, csd);
-
-out:
-	preempt_enable();
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(smp_call_function_single_async);
-
 /*
  * smp_call_function_any - Run a function on any of the given cpus
  * @mask: The mask of cpus it can run on.
@@ -1304,15 +1223,85 @@ EXPORT_SYMBOL(smp_call_mask_cond);
  * Because of that, this function can be used from the contexts with disabled
  * interrupts.
  *
- * Parameters
+ * The bit CSD_FLAG_LOCK will be set to csd->node.u_flags only if the call
+ * is made as type CSD_TYPE_SYNC or CSD_TYPE_ASYNC.
  *
+ * Parameters
  * cpu:   Must be a positive value less than nr_cpu_id.
  * csd:   The private csd provided by the callers.
- *
  * Others: see smp_call().
+ *
+ * Return: %0 on success or negative errno value on error.
+ *
+ * The following comments are from smp_call_function_single_async():
+ *
+ *   The call is asynchronous and can thus be done from contexts with
+ *   disabled interrupts. If the function is called with one csd which
+ *   has not yet been processed by previous call, the function will
+ *   return immediately with -EBUSY showing that the csd object is
+ *   still in progress.
+ *
+ *   NOTE: Be careful, there is unfortunately no current debugging
+ *   facility to validate the correctness of this serialization.
  */
 int smp_call_csd(int cpu, call_single_data_t *csd, unsigned int flags)
 {
-	return 0;
+	int err = 0;
+
+	if ((unsigned int)cpu >= nr_cpu_ids || !cpu_online(cpu)) {
+		pr_warn("cpu ID must be a positive number < nr_cpu_ids and must be currently online\n");
+		return -EINVAL;
+	}
+
+	if (csd == NULL) {
+		pr_warn("csd must not be NULL\n");
+		return -EINVAL;
+	}
+
+	preempt_disable();
+	if (csd->node.u_flags & CSD_FLAG_LOCK) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * CSD_FLAG_LOCK is set for CSD_TYPE_SYNC or CSD_TYPE_ASYNC only.
+	 */
+	if ((flags & ~(CSD_TYPE_SYNC | CSD_TYPE_ASYNC)) == 0)
+		csd->node.u_flags = CSD_FLAG_LOCK | flags;
+	else
+		csd->node.u_flags = flags;
+
+	if (cpu == smp_processor_id()) {
+		smp_call_func_t func = csd->func;
+		void *info = csd->info;
+		unsigned long flags;
+
+		/*
+		 * We can unlock early even for the synchronous on-stack case,
+		 * since we're doing this from the same CPU..
+		 */
+		csd_lock_record(csd);
+		csd_unlock(csd);
+		local_irq_save(flags);
+		func(info);
+		csd_lock_record(NULL);
+		local_irq_restore(flags);
+		goto out;
+	}
+
+	/*
+	 * Ensure the flags are visible before the csd
+	 * goes to the queue.
+	 */
+	smp_wmb();
+
+	__smp_call_single_queue(cpu, &csd->node.llist);
+
+	if (flags & CSD_TYPE_SYNC)
+		csd_lock_wait(csd);
+out:
+	preempt_enable();
+	return err;
 }
 EXPORT_SYMBOL(smp_call_csd);
-- 
2.27.0


  parent reply	other threads:[~2022-05-19 20:50 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-19 20:49 [PATCH v4 00/11] smp: cross CPU call interface Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 01/11] smp: consolidate the structure definitions to smp.h Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 02/11] smp: the definitions of cross call interface Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 03/11] smp: remove SCF_WAIT and SCF_RUN_LOCAL Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 04/11] smp: replace smp_call_function_single() with smp_call() Donghai Qiao
2022-05-19 20:49 ` Donghai Qiao [this message]
2022-05-19 20:49 ` [PATCH v4 06/11] smp: use smp_call_csd() from irq_work.c and core.c Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 07/11] smp: eliminate smp_call_function_any Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 08/11] smp: replace smp_call_function_many_cond with __smp_call_mask_cond Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 09/11] smp: replace smp_call_function_single_async with smp_call_csd Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 10/11] smp: replace smp_call_function_single() with smp_call Donghai Qiao
2022-05-19 20:49 ` [PATCH v4 11/11] smp: up.c to adopt the same format of cross CPU call Donghai Qiao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220519204943.1079578-6-dqiao@redhat.com \
    --to=dqiao@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=arnd@arndb.de \
    --cc=axboe@kernel.dk \
    --cc=donghai.w.qiao@gmail.com \
    --cc=gor@linux.ibm.com \
    --cc=heying24@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=rdunlap@infradead.org \
    --cc=sfr@canb.auug.org.au \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.