aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2012-04-20 15:16:27 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-05-10 03:59:24 -0400
commit433eba04c2cb53e0bbd2fb6da22d18f725bbf33f (patch)
treee97c20c561dff813324df87b1bbc5e61ff6d91c3 /drivers/scsi/fcoe
parent9941fa6e9725c8d27b60c4839ccebe93bda60231 (diff)
[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')
-rw-r--r--drivers/scsi/fcoe/fcoe.c25
-rw-r--r--drivers/scsi/fcoe/fcoe.h4
2 files changed, 24 insertions, 5 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:
411} 411}
412 412
413/** 413/**
414 * fcoe_interface_cleanup() - Clean up a FCoE interface 414 * fcoe_interface_remove() - remove FCoE interface from netdev
415 * @fcoe: The FCoE interface to be cleaned up 415 * @fcoe: The FCoE interface to be cleaned up
416 * 416 *
417 * Caller must be holding the RTNL mutex 417 * Caller must be holding the RTNL mutex
418 */ 418 */
419static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) 419static void fcoe_interface_remove(struct fcoe_interface *fcoe)
420{ 420{
421 struct net_device *netdev = fcoe->netdev; 421 struct net_device *netdev = fcoe->netdev;
422 struct fcoe_ctlr *fip = &fcoe->ctlr; 422 struct fcoe_ctlr *fip = &fcoe->ctlr;
423 u8 flogi_maddr[ETH_ALEN]; 423 u8 flogi_maddr[ETH_ALEN];
424 const struct net_device_ops *ops; 424 const struct net_device_ops *ops;
425 425
426 rtnl_lock();
427
428 /* 426 /*
429 * Don't listen for Ethernet packets anymore. 427 * Don't listen for Ethernet packets anymore.
430 * synchronize_net() ensures that the packet handlers are not running 428 * synchronize_net() ensures that the packet handlers are not running
@@ -453,7 +451,22 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
453 FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" 451 FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
454 " specific feature for LLD.\n"); 452 " specific feature for LLD.\n");
455 } 453 }
454 fcoe->removed = 1;
455}
456
457
458/**
459 * fcoe_interface_cleanup() - Clean up a FCoE interface
460 * @fcoe: The FCoE interface to be cleaned up
461 */
462static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
463{
464 struct net_device *netdev = fcoe->netdev;
465 struct fcoe_ctlr *fip = &fcoe->ctlr;
456 466
467 rtnl_lock();
468 if (!fcoe->removed)
469 fcoe_interface_remove(fcoe);
457 rtnl_unlock(); 470 rtnl_unlock();
458 471
459 /* Release the self-reference taken during fcoe_interface_create() */ 472 /* Release the self-reference taken during fcoe_interface_create() */
@@ -941,6 +954,10 @@ static void fcoe_if_destroy(struct fc_lport *lport)
941 rtnl_lock(); 954 rtnl_lock();
942 if (!is_zero_ether_addr(port->data_src_addr)) 955 if (!is_zero_ether_addr(port->data_src_addr))
943 dev_uc_del(netdev, port->data_src_addr); 956 dev_uc_del(netdev, port->data_src_addr);
957 if (lport->vport)
958 synchronize_net();
959 else
960 fcoe_interface_remove(fcoe);
944 rtnl_unlock(); 961 rtnl_unlock();
945 962
946 /* Free queued packets for the per-CPU receive threads */ 963 /* Free queued packets for the per-CPU receive threads */
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 3c2733a12aa1..96ac938d39cc 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -71,7 +71,8 @@ do { \
71 * @ctlr: The FCoE controller (for FIP) 71 * @ctlr: The FCoE controller (for FIP)
72 * @oem: The offload exchange manager for all local port 72 * @oem: The offload exchange manager for all local port
73 * instances associated with this port 73 * instances associated with this port
74 * This structure is 1:1 with a net devive. 74 * @removed: Indicates fcoe interface removed from net device
75 * This structure is 1:1 with a net device.
75 */ 76 */
76struct fcoe_interface { 77struct fcoe_interface {
77 struct list_head list; 78 struct list_head list;
@@ -81,6 +82,7 @@ struct fcoe_interface {
81 struct packet_type fip_packet_type; 82 struct packet_type fip_packet_type;
82 struct fcoe_ctlr ctlr; 83 struct fcoe_ctlr ctlr;
83 struct fc_exch_mgr *oem; 84 struct fc_exch_mgr *oem;
85 u8 removed;
84}; 86};
85 87
86#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) 88#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)