summaryrefslogtreecommitdiffstats
path: root/kernel/padata.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/padata.c')
-rw-r--r--kernel/padata.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/kernel/padata.c b/kernel/padata.c
index 1b9b4bac4a9b..b4066147bce4 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -275,11 +275,51 @@ static void padata_reorder(struct parallel_data *pd)
275 return; 275 return;
276} 276}
277 277
278static void invoke_padata_reorder(struct work_struct *work)
279{
280 struct padata_parallel_queue *pqueue;
281 struct parallel_data *pd;
282
283 local_bh_disable();
284 pqueue = container_of(work, struct padata_parallel_queue, reorder_work);
285 pd = pqueue->pd;
286 padata_reorder(pd);
287 local_bh_enable();
288}
289
278static void padata_reorder_timer(unsigned long arg) 290static void padata_reorder_timer(unsigned long arg)
279{ 291{
280 struct parallel_data *pd = (struct parallel_data *)arg; 292 struct parallel_data *pd = (struct parallel_data *)arg;
293 unsigned int weight;
294 int target_cpu, cpu;
281 295
282 padata_reorder(pd); 296 cpu = get_cpu();
297
298 /* We don't lock pd here to not interfere with parallel processing
299 * padata_reorder() calls on other CPUs. We just need any CPU out of
300 * the cpumask.pcpu set. It would be nice if it's the right one but
301 * it doesn't matter if we're off to the next one by using an outdated
302 * pd->processed value.
303 */
304 weight = cpumask_weight(pd->cpumask.pcpu);
305 target_cpu = padata_index_to_cpu(pd, pd->processed % weight);
306
307 /* ensure to call the reorder callback on the correct CPU */
308 if (cpu != target_cpu) {
309 struct padata_parallel_queue *pqueue;
310 struct padata_instance *pinst;
311
312 /* The timer function is serialized wrt itself -- no locking
313 * needed.
314 */
315 pinst = pd->pinst;
316 pqueue = per_cpu_ptr(pd->pqueue, target_cpu);
317 queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work);
318 } else {
319 padata_reorder(pd);
320 }
321
322 put_cpu();
283} 323}
284 324
285static void padata_serial_worker(struct work_struct *serial_work) 325static void padata_serial_worker(struct work_struct *serial_work)
@@ -399,6 +439,7 @@ static void padata_init_pqueues(struct parallel_data *pd)
399 __padata_list_init(&pqueue->reorder); 439 __padata_list_init(&pqueue->reorder);
400 __padata_list_init(&pqueue->parallel); 440 __padata_list_init(&pqueue->parallel);
401 INIT_WORK(&pqueue->work, padata_parallel_worker); 441 INIT_WORK(&pqueue->work, padata_parallel_worker);
442 INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder);
402 atomic_set(&pqueue->num_obj, 0); 443 atomic_set(&pqueue->num_obj, 0);
403 } 444 }
404} 445}