|
Oliver Neukum |
de7401 |
From cf5868c8a22dc2854b96e9569064bb92365549ca Mon Sep 17 00:00:00 2001
|
|
Oliver Neukum |
de7401 |
From: Mathias Krause <minipli@googlemail.com>
|
|
Oliver Neukum |
de7401 |
Date: Fri, 8 Sep 2017 20:57:10 +0200
|
|
Oliver Neukum |
de7401 |
Subject: [PATCH] padata: ensure the reorder timer callback runs on the correct
|
|
Oliver Neukum |
de7401 |
CPU
|
|
Oliver Neukum |
de7401 |
Git-commit: cf5868c8a22dc2854b96e9569064bb92365549ca
|
|
Oliver Neukum |
de7401 |
References: git-fixes
|
|
Oliver Neukum |
de7401 |
Patch-mainline: v4.15-rc1
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
The reorder timer function runs on the CPU where the timer interrupt was
|
|
Oliver Neukum |
de7401 |
handled which is not necessarily one of the CPUs of the 'pcpu' CPU mask
|
|
Oliver Neukum |
de7401 |
set.
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
Ensure the padata_reorder() callback runs on the correct CPU, which is
|
|
Oliver Neukum |
de7401 |
one in the 'pcpu' CPU mask set and, preferrably, the next expected one.
|
|
Oliver Neukum |
de7401 |
Do so by comparing the current CPU with the expected target CPU. If they
|
|
Oliver Neukum |
de7401 |
match, call padata_reorder() right away. If they differ, schedule a work
|
|
Oliver Neukum |
de7401 |
item on the target CPU that does the padata_reorder() call for us.
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
Signed-off-by: Mathias Krause <minipli@googlemail.com>
|
|
Oliver Neukum |
de7401 |
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
|
Oliver Neukum |
de7401 |
Signed-off-by: Oliver Neukum <oneukum@suse.com>
|
|
Oliver Neukum |
de7401 |
---
|
|
Oliver Neukum |
de7401 |
include/linux/padata.h | 2 ++
|
|
Oliver Neukum |
de7401 |
kernel/padata.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
|
|
Oliver Neukum |
de7401 |
2 files changed, 44 insertions(+), 1 deletion(-)
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
diff --git a/include/linux/padata.h b/include/linux/padata.h
|
|
Oliver Neukum |
de7401 |
index 2f9c1f93b1ce..5c0175bbc179 100644
|
|
Oliver Neukum |
de7401 |
--- a/include/linux/padata.h
|
|
Oliver Neukum |
de7401 |
+++ b/include/linux/padata.h
|
|
Oliver Neukum |
de7401 |
@@ -85,6 +85,7 @@ struct padata_serial_queue {
|
|
Oliver Neukum |
de7401 |
* @swork: work struct for serialization.
|
|
Oliver Neukum |
de7401 |
* @pd: Backpointer to the internal control structure.
|
|
Oliver Neukum |
de7401 |
* @work: work struct for parallelization.
|
|
Oliver Neukum |
de7401 |
+ * @reorder_work: work struct for reordering.
|
|
Oliver Neukum |
de7401 |
* @num_obj: Number of objects that are processed by this cpu.
|
|
Oliver Neukum |
de7401 |
* @cpu_index: Index of the cpu.
|
|
Oliver Neukum |
de7401 |
*/
|
|
Oliver Neukum |
de7401 |
@@ -93,6 +94,7 @@ struct padata_parallel_queue {
|
|
Oliver Neukum |
de7401 |
struct padata_list reorder;
|
|
Oliver Neukum |
de7401 |
struct parallel_data *pd;
|
|
Oliver Neukum |
de7401 |
struct work_struct work;
|
|
Oliver Neukum |
de7401 |
+ struct work_struct reorder_work;
|
|
Oliver Neukum |
de7401 |
atomic_t num_obj;
|
|
Oliver Neukum |
de7401 |
int cpu_index;
|
|
Oliver Neukum |
de7401 |
};
|
|
Oliver Neukum |
de7401 |
diff --git a/kernel/padata.c b/kernel/padata.c
|
|
Oliver Neukum |
de7401 |
index 1b9b4bac4a9b..b4066147bce4 100644
|
|
Oliver Neukum |
de7401 |
--- a/kernel/padata.c
|
|
Oliver Neukum |
de7401 |
+++ b/kernel/padata.c
|
|
Oliver Neukum |
de7401 |
@@ -275,11 +275,51 @@ static void padata_reorder(struct parallel_data *pd)
|
|
Oliver Neukum |
de7401 |
return;
|
|
Oliver Neukum |
de7401 |
}
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
+static void invoke_padata_reorder(struct work_struct *work)
|
|
Oliver Neukum |
de7401 |
+{
|
|
Oliver Neukum |
de7401 |
+ struct padata_parallel_queue *pqueue;
|
|
Oliver Neukum |
de7401 |
+ struct parallel_data *pd;
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
+ local_bh_disable();
|
|
Oliver Neukum |
de7401 |
+ pqueue = container_of(work, struct padata_parallel_queue, reorder_work);
|
|
Oliver Neukum |
de7401 |
+ pd = pqueue->pd;
|
|
Oliver Neukum |
de7401 |
+ padata_reorder(pd);
|
|
Oliver Neukum |
de7401 |
+ local_bh_enable();
|
|
Oliver Neukum |
de7401 |
+}
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
static void padata_reorder_timer(unsigned long arg)
|
|
Oliver Neukum |
de7401 |
{
|
|
Oliver Neukum |
de7401 |
struct parallel_data *pd = (struct parallel_data *)arg;
|
|
Oliver Neukum |
de7401 |
+ unsigned int weight;
|
|
Oliver Neukum |
de7401 |
+ int target_cpu, cpu;
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
- padata_reorder(pd);
|
|
Oliver Neukum |
de7401 |
+ cpu = get_cpu();
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
+ /* We don't lock pd here to not interfere with parallel processing
|
|
Oliver Neukum |
de7401 |
+ * padata_reorder() calls on other CPUs. We just need any CPU out of
|
|
Oliver Neukum |
de7401 |
+ * the cpumask.pcpu set. It would be nice if it's the right one but
|
|
Oliver Neukum |
de7401 |
+ * it doesn't matter if we're off to the next one by using an outdated
|
|
Oliver Neukum |
de7401 |
+ * pd->processed value.
|
|
Oliver Neukum |
de7401 |
+ */
|
|
Oliver Neukum |
de7401 |
+ weight = cpumask_weight(pd->cpumask.pcpu);
|
|
Oliver Neukum |
de7401 |
+ target_cpu = padata_index_to_cpu(pd, pd->processed % weight);
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
+ /* ensure to call the reorder callback on the correct CPU */
|
|
Oliver Neukum |
de7401 |
+ if (cpu != target_cpu) {
|
|
Oliver Neukum |
de7401 |
+ struct padata_parallel_queue *pqueue;
|
|
Oliver Neukum |
de7401 |
+ struct padata_instance *pinst;
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
+ /* The timer function is serialized wrt itself -- no locking
|
|
Oliver Neukum |
de7401 |
+ * needed.
|
|
Oliver Neukum |
de7401 |
+ */
|
|
Oliver Neukum |
de7401 |
+ pinst = pd->pinst;
|
|
Oliver Neukum |
de7401 |
+ pqueue = per_cpu_ptr(pd->pqueue, target_cpu);
|
|
Oliver Neukum |
de7401 |
+ queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work);
|
|
Oliver Neukum |
de7401 |
+ } else {
|
|
Oliver Neukum |
de7401 |
+ padata_reorder(pd);
|
|
Oliver Neukum |
de7401 |
+ }
|
|
Oliver Neukum |
de7401 |
+
|
|
Oliver Neukum |
de7401 |
+ put_cpu();
|
|
Oliver Neukum |
de7401 |
}
|
|
Oliver Neukum |
de7401 |
|
|
Oliver Neukum |
de7401 |
static void padata_serial_worker(struct work_struct *serial_work)
|
|
Oliver Neukum |
de7401 |
@@ -399,6 +439,7 @@ static void padata_init_pqueues(struct parallel_data *pd)
|
|
Oliver Neukum |
de7401 |
__padata_list_init(&pqueue->reorder);
|
|
Oliver Neukum |
de7401 |
__padata_list_init(&pqueue->parallel);
|
|
Oliver Neukum |
de7401 |
INIT_WORK(&pqueue->work, padata_parallel_worker);
|
|
Oliver Neukum |
de7401 |
+ INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder);
|
|
Oliver Neukum |
de7401 |
atomic_set(&pqueue->num_obj, 0);
|
|
Oliver Neukum |
de7401 |
}
|
|
Oliver Neukum |
de7401 |
}
|
|
Oliver Neukum |
de7401 |
--
|
|
Oliver Neukum |
de7401 |
2.16.4
|
|
Oliver Neukum |
de7401 |
|