aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:39:39 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:44 -0400
commitbc0003c93f0e68b5383fb36579f7efa267b7dc16 (patch)
tree8f8434edd45a45109d4a2d7c8b9ca0c775895f3b
parent009f225ef050d231ebb7b87264a21a7daac0f175 (diff)
scsi, bnx2i: 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 bnx2i code in scsi by using this latter form of callback registration. Cc: Eddie Wai <eddie.wai@broadcom.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>
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 34c294b42c84..80c03b452d61 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -537,11 +537,15 @@ static int __init bnx2i_mod_init(void)
537 p->iothread = NULL; 537 p->iothread = NULL;
538 } 538 }
539 539
540 cpu_notifier_register_begin();
541
540 for_each_online_cpu(cpu) 542 for_each_online_cpu(cpu)
541 bnx2i_percpu_thread_create(cpu); 543 bnx2i_percpu_thread_create(cpu);
542 544
543 /* Initialize per CPU interrupt thread */ 545 /* Initialize per CPU interrupt thread */
544 register_hotcpu_notifier(&bnx2i_cpu_notifier); 546 __register_hotcpu_notifier(&bnx2i_cpu_notifier);
547
548 cpu_notifier_register_done();
545 549
546 return 0; 550 return 0;
547 551
@@ -581,11 +585,15 @@ static void __exit bnx2i_mod_exit(void)
581 } 585 }
582 mutex_unlock(&bnx2i_dev_lock); 586 mutex_unlock(&bnx2i_dev_lock);
583 587
584 unregister_hotcpu_notifier(&bnx2i_cpu_notifier); 588 cpu_notifier_register_begin();
585 589
586 for_each_online_cpu(cpu) 590 for_each_online_cpu(cpu)
587 bnx2i_percpu_thread_destroy(cpu); 591 bnx2i_percpu_thread_destroy(cpu);
588 592
593 __unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
594
595 cpu_notifier_register_done();
596
589 iscsi_unregister_transport(&bnx2i_iscsi_transport); 597 iscsi_unregister_transport(&bnx2i_iscsi_transport);
590 cnic_unregister_driver(CNIC_ULP_ISCSI); 598 cnic_unregister_driver(CNIC_ULP_ISCSI);
591} 599}