diff options
Diffstat (limited to 'kernel/padata.c')
-rw-r--r-- | kernel/padata.c | 43 |
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 | ||
278 | static 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 | |||
278 | static void padata_reorder_timer(unsigned long arg) | 290 | static 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 | ||
285 | static void padata_serial_worker(struct work_struct *serial_work) | 325 | static 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 | } |