aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:39:52 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:45 -0400
commitcd45ae38035d1b7f98dd92429b59bbc8ba9443e9 (patch)
tree5f8eb5706b2f4814882116ead755f0842b1fa38f /drivers/scsi/fcoe
parent7229b6d0b2a9e62d5eb4886dcd0137664c735718 (diff)
scsi, fcoe: Fix CPU hotplug callback registration
Subsystems that want to register CPU hotplug callbacks, as well as perform initialization for the CPUs that are already online, often do it as shown below: get_online_cpus(); for_each_online_cpu(cpu) init_cpu(cpu); register_cpu_notifier(&foobar_cpu_notifier); put_online_cpus(); This is wrong, since it is prone to ABBA deadlocks involving the cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently with CPU hotplug operations). Instead, the correct and race-free way of performing the callback registration is: cpu_notifier_register_begin(); for_each_online_cpu(cpu) init_cpu(cpu); /* Note the use of the double underscored version of the API */ __register_cpu_notifier(&foobar_cpu_notifier); cpu_notifier_register_done(); Fix the fcoe code in scsi by using this latter form of callback registration. Cc: Robert Love <robert.w.love@intel.com> Cc: "James E.J. Bottomley" <JBottomley@parallels.com> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r--drivers/scsi/fcoe/fcoe.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index f3170008ae71..d5e105b173f0 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -2633,14 +2633,18 @@ static int __init fcoe_init(void)
2633 skb_queue_head_init(&p->fcoe_rx_list); 2633 skb_queue_head_init(&p->fcoe_rx_list);
2634 } 2634 }
2635 2635
2636 cpu_notifier_register_begin();
2637
2636 for_each_online_cpu(cpu) 2638 for_each_online_cpu(cpu)
2637 fcoe_percpu_thread_create(cpu); 2639 fcoe_percpu_thread_create(cpu);
2638 2640
2639 /* Initialize per CPU interrupt thread */ 2641 /* Initialize per CPU interrupt thread */
2640 rc = register_hotcpu_notifier(&fcoe_cpu_notifier); 2642 rc = __register_hotcpu_notifier(&fcoe_cpu_notifier);
2641 if (rc) 2643 if (rc)
2642 goto out_free; 2644 goto out_free;
2643 2645
2646 cpu_notifier_register_done();
2647
2644 /* Setup link change notification */ 2648 /* Setup link change notification */
2645 fcoe_dev_setup(); 2649 fcoe_dev_setup();
2646 2650
@@ -2655,6 +2659,9 @@ out_free:
2655 for_each_online_cpu(cpu) { 2659 for_each_online_cpu(cpu) {
2656 fcoe_percpu_thread_destroy(cpu); 2660 fcoe_percpu_thread_destroy(cpu);
2657 } 2661 }
2662
2663 cpu_notifier_register_done();
2664
2658 mutex_unlock(&fcoe_config_mutex); 2665 mutex_unlock(&fcoe_config_mutex);
2659 destroy_workqueue(fcoe_wq); 2666 destroy_workqueue(fcoe_wq);
2660 return rc; 2667 return rc;
@@ -2687,11 +2694,15 @@ static void __exit fcoe_exit(void)
2687 } 2694 }
2688 rtnl_unlock(); 2695 rtnl_unlock();
2689 2696
2690 unregister_hotcpu_notifier(&fcoe_cpu_notifier); 2697 cpu_notifier_register_begin();
2691 2698
2692 for_each_online_cpu(cpu) 2699 for_each_online_cpu(cpu)
2693 fcoe_percpu_thread_destroy(cpu); 2700 fcoe_percpu_thread_destroy(cpu);
2694 2701
2702 __unregister_hotcpu_notifier(&fcoe_cpu_notifier);
2703
2704 cpu_notifier_register_done();
2705
2695 mutex_unlock(&fcoe_config_mutex); 2706 mutex_unlock(&fcoe_config_mutex);
2696 2707
2697 /* 2708 /*