From 627e628f6662550455e57466148d03f354ecdd3b Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:35 -0700 Subject: [SCSI] bnx2fc: Reset the max receive frame size Reset max receive frame size every time before attempting FLOGI. Without this, the stale MFS value will be used. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7cb2cd48b17b..ea1e6cccd435 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1735,6 +1735,11 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface) if (++wait_cnt > 12) break; } + + /* Reset max receive frame size to default */ + if (fc_set_mfs(lport, BNX2FC_MFS)) + return; + fc_lport_init(lport); fc_fabric_login(lport); } -- cgit v1.2.3 From 3224876358a37f6e531dd5c7f7f002106ef328fc Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:36 -0700 Subject: [SCSI] bnx2fc: Bug fixes in percpu_thread_create/destroy Look up p->work_list to process cq completions, and correct the error check for thread creation. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index ea1e6cccd435..a4770d9fc80e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2122,7 +2122,7 @@ static void bnx2fc_percpu_thread_create(unsigned int cpu) (void *)p, "bnx2fc_thread/%d", cpu); /* bind thread to the cpu */ - if (likely(!IS_ERR(p->iothread))) { + if (likely(!IS_ERR(thread))) { kthread_bind(thread, cpu); p->iothread = thread; wake_up_process(thread); @@ -2134,7 +2134,6 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu) struct bnx2fc_percpu_s *p; struct task_struct *thread; struct bnx2fc_work *work, *tmp; - LIST_HEAD(work_list); BNX2FC_MISC_DBG("destroying io thread for CPU %d\n", cpu); @@ -2146,7 +2145,7 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu) /* Free all work in the list */ - list_for_each_entry_safe(work, tmp, &work_list, list) { + list_for_each_entry_safe(work, tmp, &p->work_list, list) { list_del_init(&work->list); bnx2fc_process_cq_compl(work->tgt, work->wqe); kfree(work); -- cgit v1.2.3 From e9a5289ca3bb2d3e2a8f9e464eeb97b076dcb0d1 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:37 -0700 Subject: [SCSI] bnx2fc: Enable bsg_request support for bnx2fc Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index a4770d9fc80e..9e2bf398ff91 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2378,6 +2378,7 @@ static struct fc_function_template bnx2fc_transport_function = { .vport_create = bnx2fc_vport_create, .vport_delete = bnx2fc_vport_destroy, .vport_disable = bnx2fc_vport_disable, + .bsg_request = fc_lport_bsg_request, }; static struct fc_function_template bnx2fc_vport_xport_function = { @@ -2411,6 +2412,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = { .get_fc_host_stats = fc_get_host_stats, .issue_fc_host_lip = bnx2fc_fcoe_reset, .terminate_rport_io = fc_rport_terminate_io, + .bsg_request = fc_lport_bsg_request, }; /** -- cgit v1.2.3 From cdf54668bc48193e43adc8f75ce419ce0ce50fc0 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:39 -0700 Subject: [SCSI] bnx2fc: Do not attempt destroying NPIV port twice When NPIV ports are created/deleted rapidly there is a race condition between bnx2fc_vport_destroy() from sysfs and bnx2fc_flogi_resp(), which could try to delete the NPIV port from the list twice. Fix is to loop through the list of NPIV ports to find a match, and only when it exists remove it. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 9e2bf398ff91..21792e7eaeb2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1028,8 +1028,20 @@ static int bnx2fc_vport_destroy(struct fc_vport *vport) struct fc_lport *n_port = shost_priv(shost); struct fc_lport *vn_port = vport->dd_data; struct fcoe_port *port = lport_priv(vn_port); + struct fc_lport *v_port; + bool found = false; mutex_lock(&n_port->lp_mutex); + list_for_each_entry(v_port, &n_port->vports, list) + if (v_port->vport == vport) { + found = true; + break; + } + + if (!found) { + mutex_unlock(&n_port->lp_mutex); + return -ENOENT; + } list_del(&vn_port->list); mutex_unlock(&n_port->lp_mutex); queue_work(bnx2fc_wq, &port->destroy_work); -- cgit v1.2.3 From 776cebcac6fad2f638c0ab16e2111a84c1c85d84 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:40 -0700 Subject: [SCSI] bnx2fc: Change function names of bnx2fc_netdev_setup/bnx2fc_netdev_cleanup Change them to bnx2fc_interface_setup/bnx2fc_interface_cleanup in preperation for the patches to follow. Interface specific cleanup functionality will be moved to bnx2fc_interface_cleanup. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 21792e7eaeb2..407a9b841d4a 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1064,7 +1064,7 @@ static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable) } -static int bnx2fc_netdev_setup(struct bnx2fc_interface *interface) +static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) { struct net_device *netdev = interface->netdev; struct net_device *physdev = interface->hba->phys_dev; @@ -1262,7 +1262,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, interface->ctlr.get_src_addr = bnx2fc_get_src_mac; set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags); - rc = bnx2fc_netdev_setup(interface); + rc = bnx2fc_interface_setup(interface); if (!rc) return interface; @@ -1382,7 +1382,7 @@ free_blport: return NULL; } -static void bnx2fc_netdev_cleanup(struct bnx2fc_interface *interface) +static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) { /* Dont listen for Ethernet packets anymore */ __dev_remove_pack(&interface->fcoe_packet_type); @@ -1459,7 +1459,7 @@ static int bnx2fc_destroy(struct net_device *netdev) hba = interface->hba; - bnx2fc_netdev_cleanup(interface); + bnx2fc_interface_cleanup(interface); lport = interface->ctlr.lp; bnx2fc_stop(interface); list_del(&interface->list); @@ -1938,7 +1938,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) if (!lport) { printk(KERN_ERR PFX "Failed to create interface (%s)\n", netdev->name); - bnx2fc_netdev_cleanup(interface); + bnx2fc_interface_cleanup(interface); rc = -EINVAL; goto if_create_err; } @@ -2057,7 +2057,7 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) list_for_each_entry_safe(interface, tmp, &if_list, list) { /* destroy not called yet, move to quiesced list */ if (interface->hba == hba) { - bnx2fc_netdev_cleanup(interface); + bnx2fc_interface_cleanup(interface); bnx2fc_stop(interface); list_del(&interface->list); -- cgit v1.2.3 From 9be17fc43e0121e966049a323ad38a35626525c1 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:41 -0700 Subject: [SCSI] bnx2fc: Reorganize cleanup code between interface_cleanup and if_destory Move interface specific cleanup functionality to from bnx2fc_if_destroy to bnx2fc_interface_cleanup. Do not access interface/hba in bnx2fc_if_destroy as by the time this function is called interface may already be destroyed. This patch is in preparation to handle NETDEV_UNREGISTER on a vlan device. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 47 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 407a9b841d4a..673c97c31b9b 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1384,16 +1384,10 @@ free_blport: static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) { - /* Dont listen for Ethernet packets anymore */ - __dev_remove_pack(&interface->fcoe_packet_type); - __dev_remove_pack(&interface->fip_packet_type); - synchronize_net(); -} - -static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba) -{ + struct fc_lport *lport = interface->ctlr.lp; struct fcoe_port *port = lport_priv(lport); struct bnx2fc_lport *blport, *tmp; + struct bnx2fc_hba *hba = interface->hba; /* Stop the transmit retry timer */ del_timer_sync(&port->timer); @@ -1401,6 +1395,24 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba) /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); + /* Dont listen for Ethernet packets anymore */ + __dev_remove_pack(&interface->fcoe_packet_type); + __dev_remove_pack(&interface->fip_packet_type); + synchronize_net(); + + spin_lock_bh(&hba->hba_lock); + list_for_each_entry_safe(blport, tmp, &hba->vports, list) { + if (blport->lport == lport) { + list_del(&blport->list); + kfree(blport); + } + } + spin_unlock_bh(&hba->hba_lock); +} + +static void bnx2fc_if_destroy(struct fc_lport *lport) +{ + /* Free queued packets for the receive thread */ bnx2fc_clean_rx_queue(lport); @@ -1417,15 +1429,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba) /* Free memory used by statistical counters */ fc_lport_free_stats(lport); - spin_lock_bh(&hba->hba_lock); - list_for_each_entry_safe(blport, tmp, &hba->vports, list) { - if (blport->lport == lport) { - list_del(&blport->list); - kfree(blport); - } - } - spin_unlock_bh(&hba->hba_lock); - /* Release Scsi_Host */ scsi_host_put(lport->host); } @@ -1443,7 +1446,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba) static int bnx2fc_destroy(struct net_device *netdev) { struct bnx2fc_interface *interface = NULL; - struct bnx2fc_hba *hba; struct fc_lport *lport; int rc = 0; @@ -1457,7 +1459,6 @@ static int bnx2fc_destroy(struct net_device *netdev) goto netdev_err; } - hba = interface->hba; bnx2fc_interface_cleanup(interface); lport = interface->ctlr.lp; @@ -1465,7 +1466,7 @@ static int bnx2fc_destroy(struct net_device *netdev) list_del(&interface->list); destroy_workqueue(interface->timer_work_queue); bnx2fc_interface_put(interface); - bnx2fc_if_destroy(lport, hba); + bnx2fc_if_destroy(lport); netdev_err: mutex_unlock(&bnx2fc_dev_lock); @@ -1478,19 +1479,17 @@ static void bnx2fc_destroy_work(struct work_struct *work) struct fcoe_port *port; struct fc_lport *lport; struct bnx2fc_interface *interface; - struct bnx2fc_hba *hba; port = container_of(work, struct fcoe_port, destroy_work); lport = port->lport; interface = port->priv; - hba = interface->hba; BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n"); bnx2fc_port_shutdown(lport); rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); - bnx2fc_if_destroy(lport, hba); + bnx2fc_if_destroy(lport); mutex_unlock(&bnx2fc_dev_lock); rtnl_unlock(); } @@ -2063,7 +2062,7 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) list_del(&interface->list); lport = interface->ctlr.lp; bnx2fc_interface_put(interface); - bnx2fc_if_destroy(lport, hba); + bnx2fc_if_destroy(lport); } } mutex_unlock(&bnx2fc_dev_lock); -- cgit v1.2.3 From abc49a937b23adc7d9748709ca82ee32464ae089 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:42 -0700 Subject: [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 Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 92 ++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 35 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') 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; static struct fc_function_template bnx2fc_transport_function; static struct fc_function_template bnx2fc_vport_xport_function; static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); +static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule); static int bnx2fc_destroy(struct net_device *net_device); static int bnx2fc_enable(struct net_device *netdev); static int bnx2fc_disable(struct net_device *netdev); @@ -78,6 +79,7 @@ static void bnx2fc_destroy_work(struct work_struct *work); static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev); static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device *phys_dev); +static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface); static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic); static int bnx2fc_fw_init(struct bnx2fc_hba *hba); @@ -783,7 +785,7 @@ static void bnx2fc_destroy_timer(unsigned long data) * @vlan_id: vlan id - associated vlan id with this event * * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and - * NETDEV_CHANGE_MTU events + * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans. */ static void bnx2fc_indicate_netevent(void *context, unsigned long event, u16 vlan_id) @@ -791,12 +793,11 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context; struct fc_lport *lport; struct fc_lport *vport; - struct bnx2fc_interface *interface; + struct bnx2fc_interface *interface, *tmp; int wait_for_upload = 0; u32 link_possible = 1; - /* Ignore vlans for now */ - if (vlan_id != 0) + if (vlan_id != 0 && event != NETDEV_UNREGISTER) return; switch (event) { @@ -820,6 +821,18 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, case NETDEV_CHANGE: break; + case NETDEV_UNREGISTER: + if (!vlan_id) + return; + mutex_lock(&bnx2fc_dev_lock); + list_for_each_entry_safe(interface, tmp, &if_list, list) { + if (interface->hba != hba) + continue; + __bnx2fc_destroy(interface, true); + } + mutex_unlock(&bnx2fc_dev_lock); + return; + default: printk(KERN_ERR PFX "Unkonwn netevent %ld", event); return; @@ -1022,12 +1035,27 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) return 0; } +static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport) +{ + struct bnx2fc_lport *blport, *tmp; + + spin_lock_bh(&hba->hba_lock); + list_for_each_entry_safe(blport, tmp, &hba->vports, list) { + if (blport->lport == lport) { + list_del(&blport->list); + kfree(blport); + } + } + spin_unlock_bh(&hba->hba_lock); +} + static int bnx2fc_vport_destroy(struct fc_vport *vport) { struct Scsi_Host *shost = vport_to_shost(vport); struct fc_lport *n_port = shost_priv(shost); struct fc_lport *vn_port = vport->dd_data; struct fcoe_port *port = lport_priv(vn_port); + struct bnx2fc_interface *interface = port->priv; struct fc_lport *v_port; bool found = false; @@ -1044,6 +1072,9 @@ static int bnx2fc_vport_destroy(struct fc_vport *vport) } list_del(&vn_port->list); mutex_unlock(&n_port->lp_mutex); + bnx2fc_free_vport(interface->hba, port->lport); + bnx2fc_port_shutdown(port->lport); + bnx2fc_interface_put(interface); queue_work(bnx2fc_wq, &port->destroy_work); return 0; } @@ -1386,7 +1417,6 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) { struct fc_lport *lport = interface->ctlr.lp; struct fcoe_port *port = lport_priv(lport); - struct bnx2fc_lport *blport, *tmp; struct bnx2fc_hba *hba = interface->hba; /* Stop the transmit retry timer */ @@ -1400,14 +1430,7 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) __dev_remove_pack(&interface->fip_packet_type); synchronize_net(); - spin_lock_bh(&hba->hba_lock); - list_for_each_entry_safe(blport, tmp, &hba->vports, list) { - if (blport->lport == lport) { - list_del(&blport->list); - kfree(blport); - } - } - spin_unlock_bh(&hba->hba_lock); + bnx2fc_free_vport(hba, lport); } static void bnx2fc_if_destroy(struct fc_lport *lport) @@ -1433,6 +1456,23 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) scsi_host_put(lport->host); } +static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule) +{ + struct fc_lport *lport = interface->ctlr.lp; + struct fcoe_port *port = lport_priv(lport); + + bnx2fc_interface_cleanup(interface); + bnx2fc_stop(interface); + + list_del(&interface->list); + lport = interface->ctlr.lp; + bnx2fc_interface_put(interface); + if (schedule) + queue_work(bnx2fc_wq, &port->destroy_work); + else + bnx2fc_if_destroy(lport); +} + /** * bnx2fc_destroy - Destroy a bnx2fc FCoE interface * @@ -1446,7 +1486,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) static int bnx2fc_destroy(struct net_device *netdev) { struct bnx2fc_interface *interface = NULL; - struct fc_lport *lport; int rc = 0; rtnl_lock(); @@ -1460,13 +1499,8 @@ static int bnx2fc_destroy(struct net_device *netdev) } - bnx2fc_interface_cleanup(interface); - lport = interface->ctlr.lp; - bnx2fc_stop(interface); - list_del(&interface->list); destroy_workqueue(interface->timer_work_queue); - bnx2fc_interface_put(interface); - bnx2fc_if_destroy(lport); + __bnx2fc_destroy(interface, false); netdev_err: mutex_unlock(&bnx2fc_dev_lock); @@ -1478,15 +1512,12 @@ static void bnx2fc_destroy_work(struct work_struct *work) { struct fcoe_port *port; struct fc_lport *lport; - struct bnx2fc_interface *interface; port = container_of(work, struct fcoe_port, destroy_work); lport = port->lport; - interface = port->priv; BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n"); - bnx2fc_port_shutdown(lport); rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); bnx2fc_if_destroy(lport); @@ -2031,7 +2062,6 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) { struct bnx2fc_hba *hba; struct bnx2fc_interface *interface, *tmp; - struct fc_lport *lport; BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n"); @@ -2053,18 +2083,10 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) list_del_init(&hba->list); adapter_count--; - list_for_each_entry_safe(interface, tmp, &if_list, list) { + list_for_each_entry_safe(interface, tmp, &if_list, list) /* destroy not called yet, move to quiesced list */ - if (interface->hba == hba) { - bnx2fc_interface_cleanup(interface); - bnx2fc_stop(interface); - - list_del(&interface->list); - lport = interface->ctlr.lp; - bnx2fc_interface_put(interface); - bnx2fc_if_destroy(lport); - } - } + if (interface->hba == hba) + __bnx2fc_destroy(interface, false); mutex_unlock(&bnx2fc_dev_lock); bnx2fc_ulp_stop(hba); -- cgit v1.2.3 From cd703ae790a07ece30e51a8583ea2490d14efb7c Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:43 -0700 Subject: [SCSI] bnx2fc: Clear DESTROY_CMPL flag after firmware destroy Since this flag was never cleared, the driver does not wait for firmware destroy completions, causing missed KCQEs. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index dccabafc3bb5..ca2e20690b93 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -771,8 +771,8 @@ static void bnx2fc_destroy_timer(unsigned long data) { struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data; - BNX2FC_MISC_DBG("ERROR:bnx2fc_destroy_timer - " - "Destroy compl not received!!\n"); + printk(KERN_ERR PFX "ERROR:bnx2fc_destroy_timer - " + "Destroy compl not received!!\n"); set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags); wake_up_interruptible(&hba->destroy_wait); } @@ -1701,6 +1701,7 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba) wait_event_interruptible(hba->destroy_wait, test_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags)); + clear_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags); /* This should never happen */ if (signal_pending(current)) flush_signals(current); -- cgit v1.2.3 From 3f8744d147375aca902de7a9f2632a89872565f4 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:48 -0700 Subject: [SCSI] bnx2fc: Drop incoming ABTS As an initiator, driver need not handle incoming ABTS. It initiates an ABTS if any IO requests time out. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index ca2e20690b93..62c0e94a916f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -547,6 +547,14 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) break; } } + + if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) { + /* Drop incoming ABTS */ + put_cpu(); + kfree_skb(skb); + return; + } + if (le32_to_cpu(fr_crc(fp)) != ~crc32(~0, skb->data, fr_len)) { if (stats->InvalidCRCCount < 5) -- cgit v1.2.3 From 5243960777a8d5f0dfabd0e67035d13ac6eaf304 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:50 -0700 Subject: [SCSI] bnx2fc: Obtain WWNN/WWPN from the shared memory bnx2x driver would obtain the WWNN/WWPN from the shared memory and can be obtained by the bnx2fc driver via ndo_fcoe_get_wwn. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 62c0e94a916f..25d3bcd179b1 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -65,7 +65,6 @@ static void bnx2fc_recv_frame(struct sk_buff *skb); static void bnx2fc_start_disc(struct bnx2fc_interface *interface); static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev); -static int bnx2fc_net_config(struct fc_lport *lp); static int bnx2fc_lport_config(struct fc_lport *lport); static int bnx2fc_em_config(struct fc_lport *lport); static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba); @@ -737,7 +736,7 @@ void bnx2fc_get_link_state(struct bnx2fc_hba *hba) clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state); } -static int bnx2fc_net_config(struct fc_lport *lport) +static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) { struct bnx2fc_hba *hba; struct bnx2fc_interface *interface; @@ -763,11 +762,16 @@ static int bnx2fc_net_config(struct fc_lport *lport) bnx2fc_link_speed_update(lport); if (!lport->vport) { - wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 1, 0); + if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) + wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, + 1, 0); BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn); fc_set_wwnn(lport, wwnn); - wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 2, 0); + if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) + wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, + 2, 0); + BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn); fc_set_wwpn(lport, wwpn); } @@ -1367,7 +1371,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, fc_set_wwpn(lport, vport->port_name); } /* Configure netdev and networking properties of the lport */ - rc = bnx2fc_net_config(lport); + rc = bnx2fc_net_config(lport, interface->netdev); if (rc) { printk(KERN_ERR PFX "Error on bnx2fc_net_config\n"); goto lp_config_err; -- cgit v1.2.3 From 861efc547ce517e3d75a507ebc2268e6a0dfa767 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:51 -0700 Subject: [SCSI] bnx2fc: Prevent creating of NPIV port with duplicate WWN This patch adds a validation step before allowing creation of a new NPIV port. It checks whether the WWPN passed for the new NPIV port to be created is unique for the given physical port. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 25d3bcd179b1..351ca4cb403f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1020,6 +1020,17 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) struct bnx2fc_interface *interface = port->priv; struct net_device *netdev = interface->netdev; struct fc_lport *vn_port; + int rc; + char buf[32]; + + rc = fcoe_validate_vport_create(vport); + if (rc) { + fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf)); + printk(KERN_ERR PFX "Failed to create vport, " + "WWPN (0x%s) already exists\n", + buf); + return rc; + } if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) { printk(KERN_ERR PFX "vn ports cannot be created on" -- cgit v1.2.3 From 55a3a35dd4fe616301450c85a77e2d5b5f4bb7bf Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Thu, 4 Aug 2011 17:38:52 -0700 Subject: [SCSI] bnx2fc: Bump version to 1.0.5 Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 42228ca5a9d2..903e8f64980e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -62,7 +62,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "1.0.4" +#define BNX2FC_VERSION "1.0.5" #define PFX "bnx2fc: " diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 351ca4cb403f..e6c987946b69 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); #define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_VERSION BNX2FC_VERSION -#define DRV_MODULE_RELDATE "Jun 23, 2011" +#define DRV_MODULE_RELDATE "Aug 03, 2011" static char version[] __devinitdata = -- cgit v1.2.3 From eccdcd026ae7359e22b70444b8a45f712f05cc37 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Wed, 24 Aug 2011 18:56:42 -0700 Subject: [SCSI] bnx2fc: Need not schedule destroy_work from __bnx2fc_destroy Since it is already called in the right context with rtnl_lock and dev_mutex held. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index e6c987946b69..24e707151d3e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -56,7 +56,7 @@ static struct scsi_host_template bnx2fc_shost_template; static struct fc_function_template bnx2fc_transport_function; static struct fc_function_template bnx2fc_vport_xport_function; static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); -static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule); +static void __bnx2fc_destroy(struct bnx2fc_interface *interface); static int bnx2fc_destroy(struct net_device *net_device); static int bnx2fc_enable(struct net_device *netdev); static int bnx2fc_disable(struct net_device *netdev); @@ -840,7 +840,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, list_for_each_entry_safe(interface, tmp, &if_list, list) { if (interface->hba != hba) continue; - __bnx2fc_destroy(interface, true); + __bnx2fc_destroy(interface); } mutex_unlock(&bnx2fc_dev_lock); return; @@ -1479,21 +1479,16 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) scsi_host_put(lport->host); } -static void __bnx2fc_destroy(struct bnx2fc_interface *interface, bool schedule) +static void __bnx2fc_destroy(struct bnx2fc_interface *interface) { struct fc_lport *lport = interface->ctlr.lp; - struct fcoe_port *port = lport_priv(lport); bnx2fc_interface_cleanup(interface); bnx2fc_stop(interface); - list_del(&interface->list); lport = interface->ctlr.lp; bnx2fc_interface_put(interface); - if (schedule) - queue_work(bnx2fc_wq, &port->destroy_work); - else - bnx2fc_if_destroy(lport); + bnx2fc_if_destroy(lport); } /** @@ -1523,7 +1518,7 @@ static int bnx2fc_destroy(struct net_device *netdev) destroy_workqueue(interface->timer_work_queue); - __bnx2fc_destroy(interface, false); + __bnx2fc_destroy(interface); netdev_err: mutex_unlock(&bnx2fc_dev_lock); @@ -2110,7 +2105,7 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) list_for_each_entry_safe(interface, tmp, &if_list, list) /* destroy not called yet, move to quiesced list */ if (interface->hba == hba) - __bnx2fc_destroy(interface, false); + __bnx2fc_destroy(interface); mutex_unlock(&bnx2fc_dev_lock); bnx2fc_ulp_stop(hba); -- cgit v1.2.3 From c780673cfb1e3d16d23f9808738539625d3b9363 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 30 Aug 2011 15:54:47 -0700 Subject: [SCSI] bnx2fc: Reset max receive frame size during link up If the max receive frame size is changed during link down, the driver uses the same value after linkup unless it is reset to default. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 24e707151d3e..6387067b91a6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -863,6 +863,8 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, bnx2fc_link_speed_update(lport); if (link_possible && !bnx2fc_link_ok(lport)) { + /* Reset max recv frame size to default */ + fc_set_mfs(lport, BNX2FC_MFS); printk(KERN_ERR "indicate_netevent: ctlr_link_up\n"); fcoe_ctlr_link_up(&interface->ctlr); } else if (fcoe_ctlr_link_down(&interface->ctlr)) { -- cgit v1.2.3 From 8a5badf1ea10c726b9cc04e52f91395b1248e034 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 30 Aug 2011 15:54:48 -0700 Subject: [SCSI] bnx2fc: Send solicitation only after vlan discovery is complete Link up event is generated to the driver even before vlan discovery has started. Because of this driver can send discovery solicitation on a stale vlan. Call fcoe_ctlr_link_up() only when the driver is in enabled state, which implies the vlan discovery is complete before sending solicitation. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc.h | 1 + drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 903e8f64980e..02535e8d9e00 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -224,6 +224,7 @@ struct bnx2fc_interface { struct fcoe_ctlr ctlr; u8 vlan_enabled; int vlan_id; + bool enabled; }; #define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 6387067b91a6..ba88ddb4580b 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -865,8 +865,11 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, if (link_possible && !bnx2fc_link_ok(lport)) { /* Reset max recv frame size to default */ fc_set_mfs(lport, BNX2FC_MFS); - printk(KERN_ERR "indicate_netevent: ctlr_link_up\n"); - fcoe_ctlr_link_up(&interface->ctlr); + /* + * ctlr link up will only be handled during + * enable to avoid sending discovery solicitation + * on a stale vlan + */ } else if (fcoe_ctlr_link_down(&interface->ctlr)) { mutex_lock(&lport->lp_mutex); list_for_each_entry(vport, &lport->vports, list) @@ -1784,7 +1787,7 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface) lport = interface->ctlr.lp; BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n"); - if (!bnx2fc_link_ok(lport)) { + if (!bnx2fc_link_ok(lport) && interface->enabled) { BNX2FC_HBA_DBG(lport, "ctlr_link_up\n"); fcoe_ctlr_link_up(&interface->ctlr); fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; @@ -1866,6 +1869,7 @@ static int bnx2fc_disable(struct net_device *netdev) rc = -ENODEV; printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); } else { + interface->enabled = false; fcoe_ctlr_link_down(&interface->ctlr); fcoe_clean_pending_queue(interface->ctlr.lp); } @@ -1888,8 +1892,10 @@ static int bnx2fc_enable(struct net_device *netdev) if (!interface || !interface->ctlr.lp) { rc = -ENODEV; printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); - } else if (!bnx2fc_link_ok(interface->ctlr.lp)) + } else if (!bnx2fc_link_ok(interface->ctlr.lp)) { fcoe_ctlr_link_up(&interface->ctlr); + interface->enabled = true; + } mutex_unlock(&bnx2fc_dev_lock); rtnl_unlock(); @@ -2002,8 +2008,15 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) /* Make this master N_port */ interface->ctlr.lp = lport; + if (!bnx2fc_link_ok(lport)) { + fcoe_ctlr_link_up(&interface->ctlr); + fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; + set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); + } + BNX2FC_HBA_DBG(lport, "create: START DISC\n"); bnx2fc_start_disc(interface); + interface->enabled = true; /* * Release from kref_init in bnx2fc_interface_setup, on success * lport should be holding a reference taken in bnx2fc_if_create -- cgit v1.2.3 From 26b2982f78c1fc6f486a67271b1d0a0d305dd54b Mon Sep 17 00:00:00 2001 From: Nithin Nayak Sujir Date: Tue, 30 Aug 2011 15:54:50 -0700 Subject: [SCSI] bnx2fc: Validate vlan id in NETDEV_UNREGISTER handler When bnx2fc receives an UNREGISTER event on a vlan interface it calls destroy on all interfaces that matches the physical interface. Add vlan_id check to destroy only the vlan interface that generated the event. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index ba88ddb4580b..886938d025cd 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -838,9 +838,9 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, return; mutex_lock(&bnx2fc_dev_lock); list_for_each_entry_safe(interface, tmp, &if_list, list) { - if (interface->hba != hba) - continue; - __bnx2fc_destroy(interface); + if (interface->hba == hba && + interface->vlan_id == (vlan_id & VLAN_VID_MASK)) + __bnx2fc_destroy(interface); } mutex_unlock(&bnx2fc_dev_lock); return; -- cgit v1.2.3 From 0cbf32e1681d870632a1772601cbaadd996dc978 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 30 Aug 2011 15:54:51 -0700 Subject: [SCSI] bnx2fc: Avoid calling bnx2fc_if_destroy with unnecessary locks It is not required to hold rtnl_lock and bnx2fc_dev_lock when calling bnx2fc_if_destroy, as the locking is only required to serialize creation and deletion of fcoe instances. More importantly, this unnecessary locking causes deadlock as bnx2fc_if_destroy calls fc_remove_host holding rtnl_lock. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 886938d025cd..a5111f365f69 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1487,13 +1487,13 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) static void __bnx2fc_destroy(struct bnx2fc_interface *interface) { struct fc_lport *lport = interface->ctlr.lp; + struct fcoe_port *port = lport_priv(lport); bnx2fc_interface_cleanup(interface); bnx2fc_stop(interface); list_del(&interface->list); - lport = interface->ctlr.lp; bnx2fc_interface_put(interface); - bnx2fc_if_destroy(lport); + queue_work(bnx2fc_wq, &port->destroy_work); } /** @@ -1541,11 +1541,7 @@ static void bnx2fc_destroy_work(struct work_struct *work) BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n"); - rtnl_lock(); - mutex_lock(&bnx2fc_dev_lock); bnx2fc_if_destroy(lport); - mutex_unlock(&bnx2fc_dev_lock); - rtnl_unlock(); } static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba) -- cgit v1.2.3 From 013068fa6f65f7037adedc141fbd27afc99ab1bb Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 30 Aug 2011 15:54:52 -0700 Subject: [SCSI] bnx2fc: Fix panic caused because of incorrect errror handling in create(). Driver incorrectly calls bnx2fc_interface_cleanup() when bnx2fc_if_create fails which accesses bad pointer. Handle bnx2fc_if_create failure by directly calling bnx2fc_net_cleanup. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index a5111f365f69..330f9f0e1937 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1441,6 +1441,14 @@ free_blport: return NULL; } +static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface) +{ + /* Dont listen for Ethernet packets anymore */ + __dev_remove_pack(&interface->fcoe_packet_type); + __dev_remove_pack(&interface->fip_packet_type); + synchronize_net(); +} + static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) { struct fc_lport *lport = interface->ctlr.lp; @@ -1453,10 +1461,7 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); - /* Dont listen for Ethernet packets anymore */ - __dev_remove_pack(&interface->fcoe_packet_type); - __dev_remove_pack(&interface->fip_packet_type); - synchronize_net(); + bnx2fc_net_cleanup(interface); bnx2fc_free_vport(hba, lport); } @@ -1991,7 +1996,6 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) if (!lport) { printk(KERN_ERR PFX "Failed to create interface (%s)\n", netdev->name); - bnx2fc_interface_cleanup(interface); rc = -EINVAL; goto if_create_err; } @@ -2026,6 +2030,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) if_create_err: destroy_workqueue(interface->timer_work_queue); ifput_err: + bnx2fc_net_cleanup(interface); bnx2fc_interface_put(interface); netdev_err: module_put(THIS_MODULE); -- cgit v1.2.3 From cf00025d1d04cef76ef979d39e54122c3b9233e9 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 30 Aug 2011 15:54:54 -0700 Subject: [SCSI] bnx2fc: Bumped version to 1.0.6 Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 02535e8d9e00..8dd5d4a41d39 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -62,7 +62,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "1.0.5" +#define BNX2FC_VERSION "1.0.6" #define PFX "bnx2fc: " diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 330f9f0e1937..eb28446aeeb0 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); #define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_VERSION BNX2FC_VERSION -#define DRV_MODULE_RELDATE "Aug 03, 2011" +#define DRV_MODULE_RELDATE "Aug 30, 2011" static char version[] __devinitdata = -- cgit v1.2.3 From 0a336d6f1b9e2419c2fa724a5463b63fa9df7ee5 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Mon, 19 Sep 2011 16:52:14 -0700 Subject: [SCSI] bnx2fc: Bumped version to 1.0.7 Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 8dd5d4a41d39..038b36ac3134 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -62,7 +62,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "1.0.6" +#define BNX2FC_VERSION "1.0.7" #define PFX "bnx2fc: " diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index eb28446aeeb0..7e6ce7bd0fb6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); #define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_VERSION BNX2FC_VERSION -#define DRV_MODULE_RELDATE "Aug 30, 2011" +#define DRV_MODULE_RELDATE "Sep 19, 2011" static char version[] __devinitdata = -- cgit v1.2.3 From fd8fa9071e49a56cc91f739813ea88f16b7c1240 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Mon, 3 Oct 2011 16:45:00 -0700 Subject: [SCSI] bnx2fc: call ctlr_link_up only when the interface is enabled Link may not be up when the driver receives ulp_start event, and hence fcoe_ctlr_link_up is not called. Call fcoe_ctlr_link_up during indicate_netevent only when the interface is enabled. (It has to be called when enabled because that is an indication that the vlan discovery is completed). Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7e6ce7bd0fb6..d2bbb8030f7e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -870,6 +870,8 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, * enable to avoid sending discovery solicitation * on a stale vlan */ + if (interface->enabled) + fcoe_ctlr_link_up(&interface->ctlr); } else if (fcoe_ctlr_link_down(&interface->ctlr)) { mutex_lock(&lport->lp_mutex); list_for_each_entry(vport, &lport->vports, list) -- cgit v1.2.3 From f72f6979c924af1c33dac9aff5a8004e89ada667 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Mon, 3 Oct 2011 16:45:02 -0700 Subject: [SCSI] bnx2fc: Return error statistics of remote peer Add support for get_lesb so that the valid statistics are returned by the remote peer when RLS command is issued. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index d2bbb8030f7e..0f1ca86aff9f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -99,6 +99,25 @@ static struct notifier_block bnx2fc_cpu_notifier = { .notifier_call = bnx2fc_cpu_callback, }; +static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport) +{ + return ((struct bnx2fc_interface *) + ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; +} + +/** + * bnx2fc_get_lesb() - Fill the FCoE Link Error Status Block + * @lport: the local port + * @fc_lesb: the link error status block + */ +static void bnx2fc_get_lesb(struct fc_lport *lport, + struct fc_els_lesb *fc_lesb) +{ + struct net_device *netdev = bnx2fc_netdev(lport); + + __fcoe_get_lesb(lport, fc_lesb, netdev); +} + static void bnx2fc_clean_rx_queue(struct fc_lport *lp) { struct fcoe_percpu_s *bg; @@ -2512,6 +2531,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = { .elsct_send = bnx2fc_elsct_send, .fcp_abort_io = bnx2fc_abort_io, .fcp_cleanup = bnx2fc_cleanup, + .get_lesb = bnx2fc_get_lesb, .rport_event_callback = bnx2fc_rport_event_handler, }; -- cgit v1.2.3 From 29f366e8a99fdced4c0b5417a478d7539adc66d3 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Mon, 3 Oct 2011 16:45:03 -0700 Subject: [SCSI] bnx2fc: Bumped version to 1.0.8 Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: James Bottomley --- drivers/scsi/bnx2fc/bnx2fc.h | 2 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 038b36ac3134..d882a2d1aac0 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -62,7 +62,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "1.0.7" +#define BNX2FC_VERSION "1.0.8" #define PFX "bnx2fc: " diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 0f1ca86aff9f..ba7ecb152a32 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); #define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_VERSION BNX2FC_VERSION -#define DRV_MODULE_RELDATE "Sep 19, 2011" +#define DRV_MODULE_RELDATE "Oct 02, 2011" static char version[] __devinitdata = -- cgit v1.2.3