diff options
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 4834d3c130d6..0c825c0944f7 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -801,6 +801,12 @@ skip_oem: | |||
801 | /** | 801 | /** |
802 | * fcoe_if_destroy() - Tear down a SW FCoE instance | 802 | * fcoe_if_destroy() - Tear down a SW FCoE instance |
803 | * @lport: The local port to be destroyed | 803 | * @lport: The local port to be destroyed |
804 | * | ||
805 | * Locking: must be called with the RTNL mutex held and RTNL mutex | ||
806 | * needed to be dropped by this function since not dropping RTNL | ||
807 | * would cause circular locking warning on synchronous fip worker | ||
808 | * cancelling thru fcoe_interface_put invoked by this function. | ||
809 | * | ||
804 | */ | 810 | */ |
805 | static void fcoe_if_destroy(struct fc_lport *lport) | 811 | static void fcoe_if_destroy(struct fc_lport *lport) |
806 | { | 812 | { |
@@ -823,7 +829,6 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
823 | /* Free existing transmit skbs */ | 829 | /* Free existing transmit skbs */ |
824 | fcoe_clean_pending_queue(lport); | 830 | fcoe_clean_pending_queue(lport); |
825 | 831 | ||
826 | rtnl_lock(); | ||
827 | if (!is_zero_ether_addr(port->data_src_addr)) | 832 | if (!is_zero_ether_addr(port->data_src_addr)) |
828 | dev_unicast_delete(netdev, port->data_src_addr); | 833 | dev_unicast_delete(netdev, port->data_src_addr); |
829 | rtnl_unlock(); | 834 | rtnl_unlock(); |
@@ -1902,7 +1907,12 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp) | |||
1902 | goto out_nodev; | 1907 | goto out_nodev; |
1903 | } | 1908 | } |
1904 | 1909 | ||
1905 | rtnl_lock(); | 1910 | if (!rtnl_trylock()) { |
1911 | dev_put(netdev); | ||
1912 | mutex_unlock(&fcoe_config_mutex); | ||
1913 | return restart_syscall(); | ||
1914 | } | ||
1915 | |||
1906 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1916 | fcoe = fcoe_hostlist_lookup_port(netdev); |
1907 | rtnl_unlock(); | 1917 | rtnl_unlock(); |
1908 | 1918 | ||
@@ -1952,7 +1962,12 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp) | |||
1952 | goto out_nodev; | 1962 | goto out_nodev; |
1953 | } | 1963 | } |
1954 | 1964 | ||
1955 | rtnl_lock(); | 1965 | if (!rtnl_trylock()) { |
1966 | dev_put(netdev); | ||
1967 | mutex_unlock(&fcoe_config_mutex); | ||
1968 | return restart_syscall(); | ||
1969 | } | ||
1970 | |||
1956 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1971 | fcoe = fcoe_hostlist_lookup_port(netdev); |
1957 | rtnl_unlock(); | 1972 | rtnl_unlock(); |
1958 | 1973 | ||
@@ -2003,7 +2018,12 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
2003 | goto out_nodev; | 2018 | goto out_nodev; |
2004 | } | 2019 | } |
2005 | 2020 | ||
2006 | rtnl_lock(); | 2021 | if (!rtnl_trylock()) { |
2022 | dev_put(netdev); | ||
2023 | mutex_unlock(&fcoe_config_mutex); | ||
2024 | return restart_syscall(); | ||
2025 | } | ||
2026 | |||
2007 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2027 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2008 | if (!fcoe) { | 2028 | if (!fcoe) { |
2009 | rtnl_unlock(); | 2029 | rtnl_unlock(); |
@@ -2012,7 +2032,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
2012 | } | 2032 | } |
2013 | list_del(&fcoe->list); | 2033 | list_del(&fcoe->list); |
2014 | fcoe_interface_cleanup(fcoe); | 2034 | fcoe_interface_cleanup(fcoe); |
2015 | rtnl_unlock(); | 2035 | /* RTNL mutex is dropped by fcoe_if_destroy */ |
2016 | fcoe_if_destroy(fcoe->ctlr.lp); | 2036 | fcoe_if_destroy(fcoe->ctlr.lp); |
2017 | module_put(THIS_MODULE); | 2037 | module_put(THIS_MODULE); |
2018 | 2038 | ||
@@ -2033,6 +2053,8 @@ static void fcoe_destroy_work(struct work_struct *work) | |||
2033 | 2053 | ||
2034 | port = container_of(work, struct fcoe_port, destroy_work); | 2054 | port = container_of(work, struct fcoe_port, destroy_work); |
2035 | mutex_lock(&fcoe_config_mutex); | 2055 | mutex_lock(&fcoe_config_mutex); |
2056 | rtnl_lock(); | ||
2057 | /* RTNL mutex is dropped by fcoe_if_destroy */ | ||
2036 | fcoe_if_destroy(port->lport); | 2058 | fcoe_if_destroy(port->lport); |
2037 | mutex_unlock(&fcoe_config_mutex); | 2059 | mutex_unlock(&fcoe_config_mutex); |
2038 | } | 2060 | } |
@@ -2054,6 +2076,12 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2054 | struct net_device *netdev; | 2076 | struct net_device *netdev; |
2055 | 2077 | ||
2056 | mutex_lock(&fcoe_config_mutex); | 2078 | mutex_lock(&fcoe_config_mutex); |
2079 | |||
2080 | if (!rtnl_trylock()) { | ||
2081 | mutex_unlock(&fcoe_config_mutex); | ||
2082 | return restart_syscall(); | ||
2083 | } | ||
2084 | |||
2057 | #ifdef CONFIG_FCOE_MODULE | 2085 | #ifdef CONFIG_FCOE_MODULE |
2058 | /* | 2086 | /* |
2059 | * Make sure the module has been initialized, and is not about to be | 2087 | * Make sure the module has been initialized, and is not about to be |
@@ -2071,7 +2099,6 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2071 | goto out_nomod; | 2099 | goto out_nomod; |
2072 | } | 2100 | } |
2073 | 2101 | ||
2074 | rtnl_lock(); | ||
2075 | netdev = fcoe_if_to_netdev(buffer); | 2102 | netdev = fcoe_if_to_netdev(buffer); |
2076 | if (!netdev) { | 2103 | if (!netdev) { |
2077 | rc = -ENODEV; | 2104 | rc = -ENODEV; |
@@ -2126,9 +2153,9 @@ out_free: | |||
2126 | out_putdev: | 2153 | out_putdev: |
2127 | dev_put(netdev); | 2154 | dev_put(netdev); |
2128 | out_nodev: | 2155 | out_nodev: |
2129 | rtnl_unlock(); | ||
2130 | module_put(THIS_MODULE); | 2156 | module_put(THIS_MODULE); |
2131 | out_nomod: | 2157 | out_nomod: |
2158 | rtnl_unlock(); | ||
2132 | mutex_unlock(&fcoe_config_mutex); | 2159 | mutex_unlock(&fcoe_config_mutex); |
2133 | return rc; | 2160 | return rc; |
2134 | } | 2161 | } |