aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/padata.c61
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. */
528static 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,
531int padata_set_cpumask(struct padata_instance *pinst, 546int 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
569out_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
551out: 577out:
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
598static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) 627static 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
646out:
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
770err_free_pd: 809err_free_mask:
771 padata_free_pd(pd); 810 free_cpumask_var(pinst->cpumask);
772err_free_inst: 811err_free_inst:
773 kfree(pinst); 812 kfree(pinst);
774 put_online_cpus(); 813 put_online_cpus();