diff options
author | Vasu Dev <vasu.dev@intel.com> | 2012-04-20 23:16:27 +0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-05-10 11:59:24 +0400 |
commit | 433eba04c2cb53e0bbd2fb6da22d18f725bbf33f (patch) | |
tree | e97c20c561dff813324df87b1bbc5e61ff6d91c3 /drivers/scsi/fcoe/fcoe.c | |
parent | 9941fa6e9725c8d27b60c4839ccebe93bda60231 (diff) | |
download | linux-433eba04c2cb53e0bbd2fb6da22d18f725bbf33f.tar.xz |
[SCSI] fcoe: remove lport from net device before doing per cpu rx thread cleanup
Remove lport from net device and then do synchronize net device to flush
inflight rx frames for the lport before doing fcoe_percpu_clean.
In case of master lport, remove all rx packet handlers completely and
then only do fcoe_percpu_clean. This required splitting fcoe_interface_cleanup
to do remove part separately and for that added func fcoe_interface_remove
and then call it from fcoe_if_destory before doing fcoe_percpu_clean.
However if fcoe_interface_remove() is already called then
don't call again from fcoe_interface_cleanup() to preserve its
existing flows.
This patch along with Neil's other patch to avoid soft irq context
on ingress will avoid passing up frames on disabled lport as
discussed in this mail thread:-
http://lists.open-fcoe.org/pipermail/devel/2012-February/011947.html
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 335e85192807..09a6a26282ac 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -411,20 +411,18 @@ out: } /** - * fcoe_interface_cleanup() - Clean up a FCoE interface + * fcoe_interface_remove() - remove FCoE interface from netdev * @fcoe: The FCoE interface to be cleaned up * * Caller must be holding the RTNL mutex */ -static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) +static void fcoe_interface_remove(struct fcoe_interface *fcoe) { struct net_device *netdev = fcoe->netdev; struct fcoe_ctlr *fip = &fcoe->ctlr; u8 flogi_maddr[ETH_ALEN]; const struct net_device_ops *ops; - rtnl_lock(); - /* * Don't listen for Ethernet packets anymore. * synchronize_net() ensures that the packet handlers are not running @@ -453,7 +451,22 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" " specific feature for LLD.\n"); } + fcoe->removed = 1; +} + + +/** + * fcoe_interface_cleanup() - Clean up a FCoE interface + * @fcoe: The FCoE interface to be cleaned up + */ +static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) +{ + struct net_device *netdev = fcoe->netdev; + struct fcoe_ctlr *fip = &fcoe->ctlr; + rtnl_lock(); + if (!fcoe->removed) + fcoe_interface_remove(fcoe); rtnl_unlock(); /* Release the self-reference taken during fcoe_interface_create() */ @@ -941,6 +954,10 @@ static void fcoe_if_destroy(struct fc_lport *lport) rtnl_lock(); if (!is_zero_ether_addr(port->data_src_addr)) dev_uc_del(netdev, port->data_src_addr); + if (lport->vport) + synchronize_net(); + else + fcoe_interface_remove(fcoe); rtnl_unlock(); /* Free queued packets for the per-CPU receive threads */ |