aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2fc
diff options
context:
space:
mode:
authorEddie Wai <eddie.wai@broadcom.com>2013-09-26 01:01:20 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 04:58:02 -0400
commit0680810c11fe16e7f8797908c8cb94e6a4933cbd (patch)
tree41c5651218dc96ca33926a157e50d25f35746c9d /drivers/scsi/bnx2fc
parent21837896097a6d141c7ac581500ee648c5b4bb89 (diff)
[SCSI] BNX2FC: hung task timeout warning observed when rmmod bnx2x with active FCoE targets
[v2] - removed the interface->enabled flag setting which prevented the fcoe ctlr link from being brought back up after a MTU change A rtnl_lock deadlock was observed from the rmmod thread where it tries to unregister the fcoe_ctlr device. This unregistration triggered a flush of the sysfs queue of the associated ctlr and led to a call to the set_fcoe_ctlr_enabled routine. This will eventually propagate down to call the bnx2fc_disable routine and contented for the rtnl_lock in the same context. This patch creates a subset of the bnx2fc_enable/disable routine which removes the unnecesary rtnl_lock and the bnx2fc_dev_lock acquisition from the set_fcoe_ctlr_enabled path. kernel: INFO: task rmmod:7874 blocked for more than 120 seconds. kernel: Tainted: G W --------------- 2.6.32-415.0.1.el6.x86_64 #1 kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. kernel: rmmod D 000000000000000f 0 7874 6518 0x00000080 kernel: ffff88022158f7d8 0000000000000086 0000000000000000 0000000000000000 kernel: ffff88023fe72600 ffff88043c74d410 ffff88043c74d400 ffff88043c74d000 kernel: ffff88021ecbe5f8 ffff88022158ffd8 000000000000fbc8 ffff88021ecbe5f8 kernel: Call Trace: kernel: [<ffffffff81525985>] schedule_timeout+0x215/0x2e0 kernel: [<ffffffff810680c0>] ? pick_next_task_fair+0xd0/0x130 kernel: [<ffffffff81524858>] ? schedule+0x178/0x3b2 kernel: [<ffffffff81525603>] wait_for_common+0x123/0x180 kernel: [<ffffffff81066b40>] ? default_wake_function+0x0/0x20 kernel: [<ffffffff811a486e>] ? ifind_fast+0x5e/0xb0 kernel: [<ffffffff8152571d>] wait_for_completion+0x1d/0x20 kernel: [<ffffffff81203868>] sysfs_addrm_finish+0x228/0x270 kernel: [<ffffffff812014ab>] sysfs_hash_and_remove+0x5b/0x90 kernel: [<ffffffff812056af>] sysfs_remove_group+0x5f/0x100 kernel: [<ffffffff81367e8b>] device_remove_groups+0x3b/0x60 kernel: [<ffffffff8136811d>] device_remove_attrs+0x3d/0x90 kernel: [<ffffffff81368295>] device_del+0x125/0x1e0 kernel: [<ffffffff81368372>] device_unregister+0x22/0x60 kernel: [<ffffffffa038ead2>] fcoe_ctlr_device_delete+0xe2/0xf4 [libfcoe] kernel: [<ffffffffa03c43cb>] bnx2fc_interface_release+0x5b/0x90 [bnx2fc] kernel: [<ffffffffa03c4370>] ? bnx2fc_interface_release+0x0/0x90 [bnx2fc] kernel: [<ffffffff812835e7>] kref_put+0x37/0x70 kernel: [<ffffffffa03c4192>] __bnx2fc_destroy+0x72/0xa0 [bnx2fc] kernel: [<ffffffffa03c5265>] bnx2fc_ulp_exit+0xf5/0x160 [bnx2fc] <- got bnx2fc_dev_lock mutex_lock kernel: [<ffffffffa03b03c6>] cnic_ulp_exit+0xb6/0xc0 [cnic] kernel: [<ffffffffa03b5418>] cnic_netdev_event+0x368/0x370 [cnic] kernel: [<ffffffffa038c56c>] ? fcoe_del_netdev_mapping+0x8c/0xa0 [libfcoe] kernel: [<ffffffff8152a6e5>] notifier_call_chain+0x55/0x80 kernel: [<ffffffff810a0a46>] raw_notifier_call_chain+0x16/0x20 kernel: [<ffffffff81459beb>] call_netdevice_notifiers+0x1b/0x20 kernel: [<ffffffff8145ab34>] rollback_registered_many+0x154/0x280 kernel: [<ffffffff8145ad08>] rollback_registered+0x38/0x50 kernel: [<ffffffff8145ad78>] unregister_netdevice_queue+0x58/0xa0 kernel: [<ffffffff8145add0>] unregister_netdevice+0x10/0x20 kernel: [<ffffffff8145adfe>] unregister_netdev+0x1e/0x30 <- got rtnl_lock!!!!!!!!! kernel: [<ffffffffa0122278>] __bnx2x_remove+0x48/0x270 [bnx2x] <- got & rel rtnl_lock kernel: [<ffffffffa0122554>] bnx2x_remove_one+0x44/0x80 [bnx2x] kernel: [<ffffffff812a3af7>] pci_device_remove+0x37/0x70 kernel: [<ffffffff8136b2ef>] __device_release_driver+0x6f/0xe0 kernel: [<ffffffff8136b428>] driver_detach+0xc8/0xd0 kernel: [<ffffffff8136a22e>] bus_remove_driver+0x8e/0x110 kernel: [<ffffffff8136bc12>] driver_unregister+0x62/0xa0 kernel: [<ffffffff812a3e04>] pci_unregister_driver+0x44/0xb0 kernel: [<ffffffffa0191954>] bnx2x_cleanup+0x18/0x73 [bnx2x] kernel: [<ffffffff810b8be4>] sys_delete_module+0x194/0x260 kernel: [<ffffffff810e1347>] ? audit_syscall_entry+0x1d7/0x200 kernel: [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b Signed-off-by: Eddie Wai <eddie.wai@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bnx2fc')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 69ac55495c1d..7a25766b0fcd 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -2004,6 +2004,24 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
2004 set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic); 2004 set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
2005} 2005}
2006 2006
2007/* Assumes rtnl_lock and the bnx2fc_dev_lock are already taken */
2008static int __bnx2fc_disable(struct fcoe_ctlr *ctlr)
2009{
2010 struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
2011
2012 if (interface->enabled == true) {
2013 if (!ctlr->lp) {
2014 pr_err(PFX "__bnx2fc_disable: lport not found\n");
2015 return -ENODEV;
2016 } else {
2017 interface->enabled = false;
2018 fcoe_ctlr_link_down(ctlr);
2019 fcoe_clean_pending_queue(ctlr->lp);
2020 }
2021 }
2022 return 0;
2023}
2024
2007/** 2025/**
2008 * Deperecated: Use bnx2fc_enabled() 2026 * Deperecated: Use bnx2fc_enabled()
2009 */ 2027 */
@@ -2018,20 +2036,34 @@ static int bnx2fc_disable(struct net_device *netdev)
2018 2036
2019 interface = bnx2fc_interface_lookup(netdev); 2037 interface = bnx2fc_interface_lookup(netdev);
2020 ctlr = bnx2fc_to_ctlr(interface); 2038 ctlr = bnx2fc_to_ctlr(interface);
2021 if (!interface || !ctlr->lp) { 2039
2040 if (!interface) {
2022 rc = -ENODEV; 2041 rc = -ENODEV;
2023 printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); 2042 pr_err(PFX "bnx2fc_disable: interface not found\n");
2024 } else { 2043 } else {
2025 interface->enabled = false; 2044 rc = __bnx2fc_disable(ctlr);
2026 fcoe_ctlr_link_down(ctlr);
2027 fcoe_clean_pending_queue(ctlr->lp);
2028 } 2045 }
2029
2030 mutex_unlock(&bnx2fc_dev_lock); 2046 mutex_unlock(&bnx2fc_dev_lock);
2031 rtnl_unlock(); 2047 rtnl_unlock();
2032 return rc; 2048 return rc;
2033} 2049}
2034 2050
2051static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
2052{
2053 struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
2054
2055 if (interface->enabled == false) {
2056 if (!ctlr->lp) {
2057 pr_err(PFX "__bnx2fc_enable: lport not found\n");
2058 return -ENODEV;
2059 } else if (!bnx2fc_link_ok(ctlr->lp)) {
2060 fcoe_ctlr_link_up(ctlr);
2061 interface->enabled = true;
2062 }
2063 }
2064 return 0;
2065}
2066
2035/** 2067/**
2036 * Deprecated: Use bnx2fc_enabled() 2068 * Deprecated: Use bnx2fc_enabled()
2037 */ 2069 */
@@ -2046,12 +2078,11 @@ static int bnx2fc_enable(struct net_device *netdev)
2046 2078
2047 interface = bnx2fc_interface_lookup(netdev); 2079 interface = bnx2fc_interface_lookup(netdev);
2048 ctlr = bnx2fc_to_ctlr(interface); 2080 ctlr = bnx2fc_to_ctlr(interface);
2049 if (!interface || !ctlr->lp) { 2081 if (!interface) {
2050 rc = -ENODEV; 2082 rc = -ENODEV;
2051 printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); 2083 pr_err(PFX "bnx2fc_enable: interface not found\n");
2052 } else if (!bnx2fc_link_ok(ctlr->lp)) { 2084 } else {
2053 fcoe_ctlr_link_up(ctlr); 2085 rc = __bnx2fc_enable(ctlr);
2054 interface->enabled = true;
2055 } 2086 }
2056 2087
2057 mutex_unlock(&bnx2fc_dev_lock); 2088 mutex_unlock(&bnx2fc_dev_lock);
@@ -2072,14 +2103,12 @@ static int bnx2fc_enable(struct net_device *netdev)
2072static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) 2103static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev)
2073{ 2104{
2074 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev); 2105 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
2075 struct fc_lport *lport = ctlr->lp;
2076 struct net_device *netdev = bnx2fc_netdev(lport);
2077 2106
2078 switch (cdev->enabled) { 2107 switch (cdev->enabled) {
2079 case FCOE_CTLR_ENABLED: 2108 case FCOE_CTLR_ENABLED:
2080 return bnx2fc_enable(netdev); 2109 return __bnx2fc_enable(ctlr);
2081 case FCOE_CTLR_DISABLED: 2110 case FCOE_CTLR_DISABLED:
2082 return bnx2fc_disable(netdev); 2111 return __bnx2fc_disable(ctlr);
2083 case FCOE_CTLR_UNUSED: 2112 case FCOE_CTLR_UNUSED:
2084 default: 2113 default:
2085 return -ENOTSUPP; 2114 return -ENOTSUPP;