diff options
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 202 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 6 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_transport.c | 56 |
3 files changed, 94 insertions, 170 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index bde6ee5333e..5d3700dc6f8 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -381,6 +381,42 @@ out: } /** + * fcoe_interface_release() - fcoe_port kref release function + * @kref: Embedded reference count in an fcoe_interface struct + */ +static void fcoe_interface_release(struct kref *kref) +{ + struct fcoe_interface *fcoe; + struct net_device *netdev; + + fcoe = container_of(kref, struct fcoe_interface, kref); + netdev = fcoe->netdev; + /* tear-down the FCoE controller */ + fcoe_ctlr_destroy(&fcoe->ctlr); + kfree(fcoe); + dev_put(netdev); + module_put(THIS_MODULE); +} + +/** + * fcoe_interface_get() - Get a reference to a FCoE interface + * @fcoe: The FCoE interface to be held + */ +static inline void fcoe_interface_get(struct fcoe_interface *fcoe) +{ + kref_get(&fcoe->kref); +} + +/** + * fcoe_interface_put() - Put a reference to a FCoE interface + * @fcoe: The FCoE interface to be released + */ +static inline void fcoe_interface_put(struct fcoe_interface *fcoe) +{ + kref_put(&fcoe->kref, fcoe_interface_release); +} + +/** * fcoe_interface_cleanup() - Clean up a FCoE interface * @fcoe: The FCoE interface to be cleaned up * @@ -392,6 +428,21 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) struct fcoe_ctlr *fip = &fcoe->ctlr; u8 flogi_maddr[ETH_ALEN]; const struct net_device_ops *ops; + struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); + + FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); + + /* Logout of the fabric */ + fc_fabric_logoff(fcoe->ctlr.lp); + + /* Cleanup the fc_lport */ + fc_lport_destroy(fcoe->ctlr.lp); + + /* Stop the transmit retry timer */ + del_timer_sync(&port->timer); + + /* Free existing transmit skbs */ + fcoe_clean_pending_queue(fcoe->ctlr.lp); /* * Don't listen for Ethernet packets anymore. @@ -414,6 +465,9 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) } else dev_mc_del(netdev, FIP_ALL_ENODE_MACS); + if (!is_zero_ether_addr(port->data_src_addr)) + dev_uc_del(netdev, port->data_src_addr); + /* Tell the LLD we are done w/ FCoE */ ops = netdev->netdev_ops; if (ops->ndo_fcoe_disable) { @@ -421,42 +475,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" " specific feature for LLD.\n"); } -} - -/** - * fcoe_interface_release() - fcoe_port kref release function - * @kref: Embedded reference count in an fcoe_interface struct - */ -static void fcoe_interface_release(struct kref *kref) -{ - struct fcoe_interface *fcoe; - struct net_device *netdev; - - fcoe = container_of(kref, struct fcoe_interface, kref); - netdev = fcoe->netdev; - /* tear-down the FCoE controller */ - fcoe_ctlr_destroy(&fcoe->ctlr); - kfree(fcoe); - dev_put(netdev); - module_put(THIS_MODULE); -} - -/** - * fcoe_interface_get() - Get a reference to a FCoE interface - * @fcoe: The FCoE interface to be held - */ -static inline void fcoe_interface_get(struct fcoe_interface *fcoe) -{ - kref_get(&fcoe->kref); -} - -/** - * fcoe_interface_put() - Put a reference to a FCoE interface - * @fcoe: The FCoE interface to be released - */ -static inline void fcoe_interface_put(struct fcoe_interface *fcoe) -{ - kref_put(&fcoe->kref, fcoe_interface_release); + fcoe_interface_put(fcoe); } /** @@ -821,39 +840,9 @@ skip_oem: * fcoe_if_destroy() - Tear down a SW FCoE instance * @lport: The local port to be destroyed * - * Locking: must be called with the RTNL mutex held and RTNL mutex - * needed to be dropped by this function since not dropping RTNL - * would cause circular locking warning on synchronous fip worker - * cancelling thru fcoe_interface_put invoked by this function. - * */ static void fcoe_if_destroy(struct fc_lport *lport) { - struct fcoe_port *port = lport_priv(lport); - struct fcoe_interface *fcoe = port->priv; - struct net_device *netdev = fcoe->netdev; - - FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); - - /* Logout of the fabric */ - fc_fabric_logoff(lport); - - /* Cleanup the fc_lport */ - fc_lport_destroy(lport); - - /* Stop the transmit retry timer */ - del_timer_sync(&port->timer); - - /* Free existing transmit skbs */ - fcoe_clean_pending_queue(lport); - - if (!is_zero_ether_addr(port->data_src_addr)) - dev_uc_del(netdev, port->data_src_addr); - rtnl_unlock(); - - /* receives may not be stopped until after this */ - fcoe_interface_put(fcoe); - /* Free queued packets for the per-CPU receive threads */ fcoe_percpu_clean(lport); @@ -1783,23 +1772,8 @@ static int fcoe_disable(struct net_device *netdev) int rc = 0; mutex_lock(&fcoe_config_mutex); -#ifdef CONFIG_FCOE_MODULE - /* - * Make sure the module has been initialized, and is not about to be - * removed. Module paramter sysfs files are writable before the - * module_init function is called and after module_exit. - */ - if (THIS_MODULE->state != MODULE_STATE_LIVE) { - rc = -ENODEV; - goto out_nodev; - } -#endif - - if (!rtnl_trylock()) { - mutex_unlock(&fcoe_config_mutex); - return -ERESTARTSYS; - } + rtnl_lock(); fcoe = fcoe_hostlist_lookup_port(netdev); rtnl_unlock(); @@ -1809,7 +1783,6 @@ static int fcoe_disable(struct net_device *netdev) } else rc = -ENODEV; -out_nodev: mutex_unlock(&fcoe_config_mutex); return rc; } @@ -1828,22 +1801,7 @@ static int fcoe_enable(struct net_device *netdev) int rc = 0; mutex_lock(&fcoe_config_mutex); -#ifdef CONFIG_FCOE_MODULE - /* - * Make sure the module has been initialized, and is not about to be - * removed. Module paramter sysfs files are writable before the - * module_init function is called and after module_exit. - */ - if (THIS_MODULE->state != MODULE_STATE_LIVE) { - rc = -ENODEV; - goto out_nodev; - } -#endif - if (!rtnl_trylock()) { - mutex_unlock(&fcoe_config_mutex); - return -ERESTARTSYS; - } - + rtnl_lock(); fcoe = fcoe_hostlist_lookup_port(netdev); rtnl_unlock(); @@ -1852,7 +1810,6 @@ static int fcoe_enable(struct net_device *netdev) else if (!fcoe_link_ok(fcoe->ctlr.lp)) fcoe_ctlr_link_up(&fcoe->ctlr); -out_nodev: mutex_unlock(&fcoe_config_mutex); return rc; } @@ -1868,35 +1825,22 @@ out_nodev: static int fcoe_destroy(struct net_device *netdev) { struct fcoe_interface *fcoe; + struct fc_lport *lport; int rc = 0; mutex_lock(&fcoe_config_mutex); -#ifdef CONFIG_FCOE_MODULE - /* - * Make sure the module has been initialized, and is not about to be - * removed. Module paramter sysfs files are writable before the - * module_init function is called and after module_exit. - */ - if (THIS_MODULE->state != MODULE_STATE_LIVE) { - rc = -ENODEV; - goto out_nodev; - } -#endif - if (!rtnl_trylock()) { - mutex_unlock(&fcoe_config_mutex); - return -ERESTARTSYS; - } - + rtnl_lock(); fcoe = fcoe_hostlist_lookup_port(netdev); if (!fcoe) { rtnl_unlock(); rc = -ENODEV; goto out_nodev; } - fcoe_interface_cleanup(fcoe); + lport = fcoe->ctlr.lp; list_del(&fcoe->list); - /* RTNL mutex is dropped by fcoe_if_destroy */ - fcoe_if_destroy(fcoe->ctlr.lp); + fcoe_interface_cleanup(fcoe); + rtnl_unlock(); + fcoe_if_destroy(lport); out_nodev: mutex_unlock(&fcoe_config_mutex); return rc; @@ -1912,8 +1856,6 @@ static void fcoe_destroy_work(struct work_struct *work) port = container_of(work, struct fcoe_port, destroy_work); mutex_lock(&fcoe_config_mutex); - rtnl_lock(); - /* RTNL mutex is dropped by fcoe_if_destroy */ fcoe_if_destroy(port->lport); mutex_unlock(&fcoe_config_mutex); } @@ -1948,23 +1890,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) struct fc_lport *lport; mutex_lock(&fcoe_config_mutex); - - if (!rtnl_trylock()) { - mutex_unlock(&fcoe_config_mutex); - return -ERESTARTSYS; - } - -#ifdef CONFIG_FCOE_MODULE - /* - * Make sure the module has been initialized, and is not about to be - * removed. Module paramter sysfs files are writable before the - * module_init function is called and after module_exit. - */ - if (THIS_MODULE->state != MODULE_STATE_LIVE) { - rc = -ENODEV; - goto out_nodev; - } -#endif + rtnl_lock(); /* look for existing lport */ if (fcoe_hostlist_lookup(netdev)) { diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 9d38be2a41f..229e4af5508 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -978,10 +978,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) * the FCF that answers multicast solicitations, not the others that * are sending periodic multicast advertisements. */ - if (mtu_valid) { - list_del(&fcf->list); - list_add(&fcf->list, &fip->fcfs); - } + if (mtu_valid) + list_move(&fcf->list, &fip->fcfs); /* * If this is the first validated FCF, note the time and diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 258684101bf..f81f77c8569 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -335,7 +335,7 @@ out_attach: EXPORT_SYMBOL(fcoe_transport_attach); /** - * fcoe_transport_attach - Detaches an FCoE transport + * fcoe_transport_detach - Detaches an FCoE transport * @ft: The fcoe transport to be attached * * Returns : 0 for success @@ -343,6 +343,7 @@ EXPORT_SYMBOL(fcoe_transport_attach); int fcoe_transport_detach(struct fcoe_transport *ft) { int rc = 0; + struct fcoe_netdev_mapping *nm = NULL, *tmp; mutex_lock(&ft_mutex); if (!ft->attached) { @@ -352,6 +353,19 @@ int fcoe_transport_detach(struct fcoe_transport *ft) goto out_attach; } + /* remove netdev mapping for this transport as it is going away */ + mutex_lock(&fn_mutex); + list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { + if (nm->ft == ft) { + LIBFCOE_TRANSPORT_DBG("transport %s going away, " + "remove its netdev mapping for %s\n", + ft->name, nm->netdev->name); + list_del(&nm->list); + kfree(nm); + } + } + mutex_unlock(&fn_mutex); + list_del(&ft->list); ft->attached = false; LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name); @@ -371,9 +385,9 @@ static int fcoe_transport_show(char *buffer, const struct kernel_param *kp) i = j = sprintf(buffer, "Attached FCoE transports:"); mutex_lock(&ft_mutex); list_for_each_entry(ft, &fcoe_transports, list) { - i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); - if (i >= PAGE_SIZE) + if (i >= PAGE_SIZE - IFNAMSIZ) break; + i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); } mutex_unlock(&ft_mutex); if (i == j) @@ -530,9 +544,6 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) struct fcoe_transport *ft = NULL; enum fip_state fip_mode = (enum fip_state)(long)kp->arg; - if (!mutex_trylock(&ft_mutex)) - return restart_syscall(); - #ifdef CONFIG_LIBFCOE_MODULE /* * Make sure the module has been initialized, and is not about to be @@ -543,6 +554,8 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) goto out_nodev; #endif + mutex_lock(&ft_mutex); + netdev = fcoe_if_to_netdev(buffer); if (!netdev) { LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer); @@ -586,10 +599,7 @@ out_putdev: dev_put(netdev); out_nodev: mutex_unlock(&ft_mutex); - if (rc == -ERESTARTSYS) - return restart_syscall(); - else - return rc; + return rc; } /** @@ -608,9 +618,6 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) struct net_device *netdev = NULL; struct fcoe_transport *ft = NULL; - if (!mutex_trylock(&ft_mutex)) - return restart_syscall(); - #ifdef CONFIG_LIBFCOE_MODULE /* * Make sure the module has been initialized, and is not about to be @@ -621,6 +628,8 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) goto out_nodev; #endif + mutex_lock(&ft_mutex); + netdev = fcoe_if_to_netdev(buffer); if (!netdev) { LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer); @@ -645,11 +654,7 @@ out_putdev: dev_put(netdev); out_nodev: mutex_unlock(&ft_mutex); - - if (rc == -ERESTARTSYS) - return restart_syscall(); - else - return rc; + return rc; } /** @@ -667,9 +672,6 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) struct net_device *netdev = NULL; struct fcoe_transport *ft = NULL; - if (!mutex_trylock(&ft_mutex)) - return restart_syscall(); - #ifdef CONFIG_LIBFCOE_MODULE /* * Make sure the module has been initialized, and is not about to be @@ -680,6 +682,8 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) goto out_nodev; #endif + mutex_lock(&ft_mutex); + netdev = fcoe_if_to_netdev(buffer); if (!netdev) goto out_nodev; @@ -716,9 +720,6 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) struct net_device *netdev = NULL; struct fcoe_transport *ft = NULL; - if (!mutex_trylock(&ft_mutex)) - return restart_syscall(); - #ifdef CONFIG_LIBFCOE_MODULE /* * Make sure the module has been initialized, and is not about to be @@ -729,6 +730,8 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) goto out_nodev; #endif + mutex_lock(&ft_mutex); + netdev = fcoe_if_to_netdev(buffer); if (!netdev) goto out_nodev; @@ -743,10 +746,7 @@ out_putdev: dev_put(netdev); out_nodev: mutex_unlock(&ft_mutex); - if (rc == -ERESTARTSYS) - return restart_syscall(); - else - return rc; + return rc; } /** |