diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/padata.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/kernel/padata.c b/kernel/padata.c index 9e18dfa372a9..57ec4eb5f2e3 100644 --- a/kernel/padata.c +++ b/kernel/padata.c | |||
@@ -516,12 +516,27 @@ static void padata_replace(struct padata_instance *pinst, | |||
516 | 516 | ||
517 | synchronize_rcu(); | 517 | synchronize_rcu(); |
518 | 518 | ||
519 | padata_flush_queues(pd_old); | 519 | if (pd_old) { |
520 | padata_free_pd(pd_old); | 520 | padata_flush_queues(pd_old); |
521 | padata_free_pd(pd_old); | ||
522 | } | ||
521 | 523 | ||
522 | pinst->flags &= ~PADATA_RESET; | 524 | pinst->flags &= ~PADATA_RESET; |
523 | } | 525 | } |
524 | 526 | ||
527 | /* If cpumask contains no active cpu, we mark the instance as invalid. */ | ||
528 | static bool padata_validate_cpumask(struct padata_instance *pinst, | ||
529 | const struct cpumask *cpumask) | ||
530 | { | ||
531 | if (!cpumask_intersects(cpumask, cpu_active_mask)) { | ||
532 | pinst->flags |= PADATA_INVALID; | ||
533 | return false; | ||
534 | } | ||
535 | |||
536 | pinst->flags &= ~PADATA_INVALID; | ||
537 | return true; | ||
538 | } | ||
539 | |||
525 | /** | 540 | /** |
526 | * padata_set_cpumask - set the cpumask that padata should use | 541 | * padata_set_cpumask - set the cpumask that padata should use |
527 | * | 542 | * |
@@ -531,11 +546,18 @@ static void padata_replace(struct padata_instance *pinst, | |||
531 | int padata_set_cpumask(struct padata_instance *pinst, | 546 | int padata_set_cpumask(struct padata_instance *pinst, |
532 | cpumask_var_t cpumask) | 547 | cpumask_var_t cpumask) |
533 | { | 548 | { |
534 | struct parallel_data *pd; | 549 | int valid; |
535 | int err = 0; | 550 | int err = 0; |
551 | struct parallel_data *pd = NULL; | ||
536 | 552 | ||
537 | mutex_lock(&pinst->lock); | 553 | mutex_lock(&pinst->lock); |
538 | 554 | ||
555 | valid = padata_validate_cpumask(pinst, cpumask); | ||
556 | if (!valid) { | ||
557 | __padata_stop(pinst); | ||
558 | goto out_replace; | ||
559 | } | ||
560 | |||
539 | get_online_cpus(); | 561 | get_online_cpus(); |
540 | 562 | ||
541 | pd = padata_alloc_pd(pinst, cpumask); | 563 | pd = padata_alloc_pd(pinst, cpumask); |
@@ -544,10 +566,14 @@ int padata_set_cpumask(struct padata_instance *pinst, | |||
544 | goto out; | 566 | goto out; |
545 | } | 567 | } |
546 | 568 | ||
569 | out_replace: | ||
547 | cpumask_copy(pinst->cpumask, cpumask); | 570 | cpumask_copy(pinst->cpumask, cpumask); |
548 | 571 | ||
549 | padata_replace(pinst, pd); | 572 | padata_replace(pinst, pd); |
550 | 573 | ||
574 | if (valid) | ||
575 | __padata_start(pinst); | ||
576 | |||
551 | out: | 577 | out: |
552 | put_online_cpus(); | 578 | put_online_cpus(); |
553 | 579 | ||
@@ -567,6 +593,9 @@ static int __padata_add_cpu(struct padata_instance *pinst, int cpu) | |||
567 | return -ENOMEM; | 593 | return -ENOMEM; |
568 | 594 | ||
569 | padata_replace(pinst, pd); | 595 | padata_replace(pinst, pd); |
596 | |||
597 | if (padata_validate_cpumask(pinst, pinst->cpumask)) | ||
598 | __padata_start(pinst); | ||
570 | } | 599 | } |
571 | 600 | ||
572 | return 0; | 601 | return 0; |
@@ -597,9 +626,16 @@ EXPORT_SYMBOL(padata_add_cpu); | |||
597 | 626 | ||
598 | static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) | 627 | static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) |
599 | { | 628 | { |
600 | struct parallel_data *pd; | 629 | struct parallel_data *pd = NULL; |
601 | 630 | ||
602 | if (cpumask_test_cpu(cpu, cpu_online_mask)) { | 631 | if (cpumask_test_cpu(cpu, cpu_online_mask)) { |
632 | |||
633 | if (!padata_validate_cpumask(pinst, pinst->cpumask)) { | ||
634 | __padata_stop(pinst); | ||
635 | padata_replace(pinst, pd); | ||
636 | goto out; | ||
637 | } | ||
638 | |||
603 | pd = padata_alloc_pd(pinst, pinst->cpumask); | 639 | pd = padata_alloc_pd(pinst, pinst->cpumask); |
604 | if (!pd) | 640 | if (!pd) |
605 | return -ENOMEM; | 641 | return -ENOMEM; |
@@ -607,6 +643,7 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) | |||
607 | padata_replace(pinst, pd); | 643 | padata_replace(pinst, pd); |
608 | } | 644 | } |
609 | 645 | ||
646 | out: | ||
610 | return 0; | 647 | return 0; |
611 | } | 648 | } |
612 | 649 | ||
@@ -732,7 +769,7 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
732 | struct workqueue_struct *wq) | 769 | struct workqueue_struct *wq) |
733 | { | 770 | { |
734 | struct padata_instance *pinst; | 771 | struct padata_instance *pinst; |
735 | struct parallel_data *pd; | 772 | struct parallel_data *pd = NULL; |
736 | 773 | ||
737 | pinst = kzalloc(sizeof(struct padata_instance), GFP_KERNEL); | 774 | pinst = kzalloc(sizeof(struct padata_instance), GFP_KERNEL); |
738 | if (!pinst) | 775 | if (!pinst) |
@@ -740,12 +777,14 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
740 | 777 | ||
741 | get_online_cpus(); | 778 | get_online_cpus(); |
742 | 779 | ||
743 | pd = padata_alloc_pd(pinst, cpumask); | 780 | if (!alloc_cpumask_var(&pinst->cpumask, GFP_KERNEL)) |
744 | if (!pd) | ||
745 | goto err_free_inst; | 781 | goto err_free_inst; |
746 | 782 | ||
747 | if (!alloc_cpumask_var(&pinst->cpumask, GFP_KERNEL)) | 783 | if (padata_validate_cpumask(pinst, cpumask)) { |
748 | goto err_free_pd; | 784 | pd = padata_alloc_pd(pinst, cpumask); |
785 | if (!pd) | ||
786 | goto err_free_mask; | ||
787 | } | ||
749 | 788 | ||
750 | rcu_assign_pointer(pinst->pd, pd); | 789 | rcu_assign_pointer(pinst->pd, pd); |
751 | 790 | ||
@@ -767,8 +806,8 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
767 | 806 | ||
768 | return pinst; | 807 | return pinst; |
769 | 808 | ||
770 | err_free_pd: | 809 | err_free_mask: |
771 | padata_free_pd(pd); | 810 | free_cpumask_var(pinst->cpumask); |
772 | err_free_inst: | 811 | err_free_inst: |
773 | kfree(pinst); | 812 | kfree(pinst); |
774 | put_online_cpus(); | 813 | put_online_cpus(); |