aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2011-08-04 20:38:42 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:35:35 -0400
commitabc49a937b23adc7d9748709ca82ee32464ae089 (patch)
tree5b7dc010edc07e25406d64ba2742a36a92b58c97 /drivers/scsi
parent9be17fc43e0121e966049a323ad38a35626525c1 (diff)
[SCSI] bnx2fc: Handle NETDEV_UNREGISTER for vlan devices
Since the driver holds the reference for vlan netdev, the reference has to be released by the driver when the vlan device is removed. Driver handles this in NETDEV_UNREGISTER event. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c92
1 files changed, 57 insertions, 35 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 673c97c31b9b..dccabafc3bb5 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -56,6 +56,7 @@ static struct scsi_host_template bnx2fc_shost_template;
56static struct fc_function_template bnx2fc_transport_function; 56static struct fc_function_template bnx2fc_transport_function;
57static struct fc_function_template bnx2fc_vport_xport_function; 57static struct fc_function_template bnx2fc_vport_xport_function;
58static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); 58static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
59static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule);
59static int bnx2fc_destroy(struct net_device *net_device); 60static int bnx2fc_destroy(struct net_device *net_device);
60static int bnx2fc_enable(struct net_device *netdev); 61static int bnx2fc_enable(struct net_device *netdev);
61static int bnx2fc_disable(struct net_device *netdev); 62static int bnx2fc_disable(struct net_device *netdev);
@@ -78,6 +79,7 @@ static void bnx2fc_destroy_work(struct work_struct *work);
78static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev); 79static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
79static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device 80static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
80 *phys_dev); 81 *phys_dev);
82static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface);
81static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic); 83static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
82 84
83static int bnx2fc_fw_init(struct bnx2fc_hba *hba); 85static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
@@ -783,7 +785,7 @@ static void bnx2fc_destroy_timer(unsigned long data)
783 * @vlan_id: vlan id - associated vlan id with this event 785 * @vlan_id: vlan id - associated vlan id with this event
784 * 786 *
785 * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and 787 * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
786 * NETDEV_CHANGE_MTU events 788 * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans.
787 */ 789 */
788static void bnx2fc_indicate_netevent(void *context, unsigned long event, 790static void bnx2fc_indicate_netevent(void *context, unsigned long event,
789 u16 vlan_id) 791 u16 vlan_id)
@@ -791,12 +793,11 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
791 struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context; 793 struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
792 struct fc_lport *lport; 794 struct fc_lport *lport;
793 struct fc_lport *vport; 795 struct fc_lport *vport;
794 struct bnx2fc_interface *interface; 796 struct bnx2fc_interface *interface, *tmp;
795 int wait_for_upload = 0; 797 int wait_for_upload = 0;
796 u32 link_possible = 1; 798 u32 link_possible = 1;
797 799
798 /* Ignore vlans for now */ 800 if (vlan_id != 0 && event != NETDEV_UNREGISTER)
799 if (vlan_id != 0)
800 return; 801 return;
801 802
802 switch (event) { 803 switch (event) {
@@ -820,6 +821,18 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
820 case NETDEV_CHANGE: 821 case NETDEV_CHANGE:
821 break; 822 break;
822 823
824 case NETDEV_UNREGISTER:
825 if (!vlan_id)
826 return;
827 mutex_lock(&bnx2fc_dev_lock);
828 list_for_each_entry_safe(interface, tmp, &if_list, list) {
829 if (interface->hba != hba)
830 continue;
831 __bnx2fc_destroy(interface, true);
832 }
833 mutex_unlock(&bnx2fc_dev_lock);
834 return;
835
823 default: 836 default:
824 printk(KERN_ERR PFX "Unkonwn netevent %ld", event); 837 printk(KERN_ERR PFX "Unkonwn netevent %ld", event);
825 return; 838 return;
@@ -1022,12 +1035,27 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
1022 return 0; 1035 return 0;
1023} 1036}
1024 1037
1038static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport)
1039{
1040 struct bnx2fc_lport *blport, *tmp;
1041
1042 spin_lock_bh(&hba->hba_lock);
1043 list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
1044 if (blport->lport == lport) {
1045 list_del(&blport->list);
1046 kfree(blport);
1047 }
1048 }
1049 spin_unlock_bh(&hba->hba_lock);
1050}
1051
1025static int bnx2fc_vport_destroy(struct fc_vport *vport) 1052static int bnx2fc_vport_destroy(struct fc_vport *vport)
1026{ 1053{
1027 struct Scsi_Host *shost = vport_to_shost(vport); 1054 struct Scsi_Host *shost = vport_to_shost(vport);
1028 struct fc_lport *n_port = shost_priv(shost); 1055 struct fc_lport *n_port = shost_priv(shost);
1029 struct fc_lport *vn_port = vport->dd_data; 1056 struct fc_lport *vn_port = vport->dd_data;
1030 struct fcoe_port *port = lport_priv(vn_port); 1057 struct fcoe_port *port = lport_priv(vn_port);
1058 struct bnx2fc_interface *interface = port->priv;
1031 struct fc_lport *v_port; 1059 struct fc_lport *v_port;
1032 bool found = false; 1060 bool found = false;
1033 1061
@@ -1044,6 +1072,9 @@ static int bnx2fc_vport_destroy(struct fc_vport *vport)
1044 } 1072 }
1045 list_del(&vn_port->list); 1073 list_del(&vn_port->list);
1046 mutex_unlock(&n_port->lp_mutex); 1074 mutex_unlock(&n_port->lp_mutex);
1075 bnx2fc_free_vport(interface->hba, port->lport);
1076 bnx2fc_port_shutdown(port->lport);
1077 bnx2fc_interface_put(interface);
1047 queue_work(bnx2fc_wq, &port->destroy_work); 1078 queue_work(bnx2fc_wq, &port->destroy_work);
1048 return 0; 1079 return 0;
1049} 1080}
@@ -1386,7 +1417,6 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface)
1386{ 1417{
1387 struct fc_lport *lport = interface->ctlr.lp; 1418 struct fc_lport *lport = interface->ctlr.lp;
1388 struct fcoe_port *port = lport_priv(lport); 1419 struct fcoe_port *port = lport_priv(lport);
1389 struct bnx2fc_lport *blport, *tmp;
1390 struct bnx2fc_hba *hba = interface->hba; 1420 struct bnx2fc_hba *hba = interface->hba;
1391 1421
1392 /* Stop the transmit retry timer */ 1422 /* Stop the transmit retry timer */
@@ -1400,14 +1430,7 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface)
1400 __dev_remove_pack(&interface->fip_packet_type); 1430 __dev_remove_pack(&interface->fip_packet_type);
1401 synchronize_net(); 1431 synchronize_net();
1402 1432
1403 spin_lock_bh(&hba->hba_lock); 1433 bnx2fc_free_vport(hba, lport);
1404 list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
1405 if (blport->lport == lport) {
1406 list_del(&blport->list);
1407 kfree(blport);
1408 }
1409 }
1410 spin_unlock_bh(&hba->hba_lock);
1411} 1434}
1412 1435
1413static void bnx2fc_if_destroy(struct fc_lport *lport) 1436static void bnx2fc_if_destroy(struct fc_lport *lport)
@@ -1433,6 +1456,23 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
1433 scsi_host_put(lport->host); 1456 scsi_host_put(lport->host);
1434} 1457}
1435 1458
1459static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule)
1460{
1461 struct fc_lport *lport = interface->ctlr.lp;
1462 struct fcoe_port *port = lport_priv(lport);
1463
1464 bnx2fc_interface_cleanup(interface);
1465 bnx2fc_stop(interface);
1466
1467 list_del(&interface->list);
1468 lport = interface->ctlr.lp;
1469 bnx2fc_interface_put(interface);
1470 if (schedule)
1471 queue_work(bnx2fc_wq, &port->destroy_work);
1472 else
1473 bnx2fc_if_destroy(lport);
1474}
1475
1436/** 1476/**
1437 * bnx2fc_destroy - Destroy a bnx2fc FCoE interface 1477 * bnx2fc_destroy - Destroy a bnx2fc FCoE interface
1438 * 1478 *
@@ -1446,7 +1486,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
1446static int bnx2fc_destroy(struct net_device *netdev) 1486static int bnx2fc_destroy(struct net_device *netdev)
1447{ 1487{
1448 struct bnx2fc_interface *interface = NULL; 1488 struct bnx2fc_interface *interface = NULL;
1449 struct fc_lport *lport;
1450 int rc = 0; 1489 int rc = 0;
1451 1490
1452 rtnl_lock(); 1491 rtnl_lock();
@@ -1460,13 +1499,8 @@ static int bnx2fc_destroy(struct net_device *netdev)
1460 } 1499 }
1461 1500
1462 1501
1463 bnx2fc_interface_cleanup(interface);
1464 lport = interface->ctlr.lp;
1465 bnx2fc_stop(interface);
1466 list_del(&interface->list);
1467 destroy_workqueue(interface->timer_work_queue); 1502 destroy_workqueue(interface->timer_work_queue);
1468 bnx2fc_interface_put(interface); 1503 __bnx2fc_destroy(interface, false);
1469 bnx2fc_if_destroy(lport);
1470 1504
1471netdev_err: 1505netdev_err:
1472 mutex_unlock(&bnx2fc_dev_lock); 1506 mutex_unlock(&bnx2fc_dev_lock);
@@ -1478,15 +1512,12 @@ static void bnx2fc_destroy_work(struct work_struct *work)
1478{ 1512{
1479 struct fcoe_port *port; 1513 struct fcoe_port *port;
1480 struct fc_lport *lport; 1514 struct fc_lport *lport;
1481 struct bnx2fc_interface *interface;
1482 1515
1483 port = container_of(work, struct fcoe_port, destroy_work); 1516 port = container_of(work, struct fcoe_port, destroy_work);
1484 lport = port->lport; 1517 lport = port->lport;
1485 interface = port->priv;
1486 1518
1487 BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n"); 1519 BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
1488 1520
1489 bnx2fc_port_shutdown(lport);
1490 rtnl_lock(); 1521 rtnl_lock();
1491 mutex_lock(&bnx2fc_dev_lock); 1522 mutex_lock(&bnx2fc_dev_lock);
1492 bnx2fc_if_destroy(lport); 1523 bnx2fc_if_destroy(lport);
@@ -2031,7 +2062,6 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
2031{ 2062{
2032 struct bnx2fc_hba *hba; 2063 struct bnx2fc_hba *hba;
2033 struct bnx2fc_interface *interface, *tmp; 2064 struct bnx2fc_interface *interface, *tmp;
2034 struct fc_lport *lport;
2035 2065
2036 BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n"); 2066 BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
2037 2067
@@ -2053,18 +2083,10 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
2053 list_del_init(&hba->list); 2083 list_del_init(&hba->list);
2054 adapter_count--; 2084 adapter_count--;
2055 2085
2056 list_for_each_entry_safe(interface, tmp, &if_list, list) { 2086 list_for_each_entry_safe(interface, tmp, &if_list, list)
2057 /* destroy not called yet, move to quiesced list */ 2087 /* destroy not called yet, move to quiesced list */
2058 if (interface->hba == hba) { 2088 if (interface->hba == hba)
2059 bnx2fc_interface_cleanup(interface); 2089 __bnx2fc_destroy(interface, false);
2060 bnx2fc_stop(interface);
2061
2062 list_del(&interface->list);
2063 lport = interface->ctlr.lp;
2064 bnx2fc_interface_put(interface);
2065 bnx2fc_if_destroy(lport);
2066 }
2067 }
2068 mutex_unlock(&bnx2fc_dev_lock); 2090 mutex_unlock(&bnx2fc_dev_lock);
2069 2091
2070 bnx2fc_ulp_stop(hba); 2092 bnx2fc_ulp_stop(hba);