From 1ed0f6a3ef94996341f3c5a2d4034ba1a2532b0a Mon Sep 17 00:00:00 2001 From: Anil Veerabhadrappa Date: Tue, 23 Jun 2009 13:56:29 -0700 Subject: [SCSI] bnx2i: remove global variable bnx2i_reg_devices Removed bnx2i_reg_devices as this counter is not really used in a meaningful way Signed-off-by: Michael Chan Signed-off-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers/scsi/bnx2i/bnx2i_init.c') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index ae4b2d588fd..269192d7437 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -15,7 +15,6 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; -static int bnx2i_reg_device; #define DRV_MODULE_NAME "bnx2i" #define DRV_MODULE_VERSION "2.0.1d" @@ -193,10 +192,6 @@ void bnx2i_register_device(struct bnx2i_hba *hba) hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); - spin_lock(&hba->lock); - bnx2i_reg_device++; - spin_unlock(&hba->lock); - set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); } @@ -234,10 +229,6 @@ static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); - spin_lock(&hba->lock); - bnx2i_reg_device--; - spin_unlock(&hba->lock); - /* ep_disconnect could come before NETDEV_DOWN, driver won't * see NETDEV_DOWN as it already unregistered itself. */ @@ -276,16 +267,12 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) int rc; read_lock(&bnx2i_dev_lock); - if (bnx2i_reg_device && - !test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { + if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); if (rc) /* duplicate registration */ printk(KERN_ERR "bnx2i- dev reg failed\n"); - spin_lock(&hba->lock); - bnx2i_reg_device++; hba->age++; - spin_unlock(&hba->lock); set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); } @@ -350,10 +337,6 @@ void bnx2i_ulp_exit(struct cnic_dev *dev) if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); - - spin_lock(&hba->lock); - bnx2i_reg_device--; - spin_unlock(&hba->lock); } write_unlock(&bnx2i_dev_lock); @@ -421,7 +404,6 @@ static void __exit bnx2i_mod_exit(void) if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); - bnx2i_reg_device--; } write_unlock(&bnx2i_dev_lock); -- cgit v1.2.3-70-g09d2 From 4e85f15166a6a9da8317ddb8600b604b27e58aa3 Mon Sep 17 00:00:00 2001 From: Anil Veerabhadrappa Date: Tue, 23 Jun 2009 14:04:23 -0700 Subject: [SCSI] bnx2i: bug fixes in bnx2i_init_one to handle error conditions Fixed bnx2i_init_one() to properly handle return code of cnic->register_device() and propagate it back to the caller. No need to check for BNX2I_CNIC_REGISTERED, because unless the adapter is added to adapter_list it will not be registered in ep_connect context Signed-off-by: Michael Chan Signed-off-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers/scsi/bnx2i/bnx2i_init.c') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 269192d7437..2aeeeee3372 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -267,22 +267,29 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) int rc; read_lock(&bnx2i_dev_lock); - if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { - rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); - if (rc) /* duplicate registration */ - printk(KERN_ERR "bnx2i- dev reg failed\n"); - + rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); + if (!rc) { hba->age++; - set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); - } + } else if (rc == -EBUSY) /* duplicate registration */ + printk(KERN_ALERT "bnx2i, duplicate registration" + "hba=%p, cnic=%p\n", hba, cnic); + else if (rc == -EAGAIN) + printk(KERN_ERR "bnx2i, driver not registered\n"); + else if (rc == -EINVAL) + printk(KERN_ERR "bnx2i, invalid type %d\n", CNIC_ULP_ISCSI); + else + printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc); read_unlock(&bnx2i_dev_lock); - write_lock(&bnx2i_dev_lock); - list_add_tail(&hba->link, &adapter_list); - adapter_count++; - write_unlock(&bnx2i_dev_lock); - return 0; + if (!rc) { + write_lock(&bnx2i_dev_lock); + list_add_tail(&hba->link, &adapter_list); + adapter_count++; + write_unlock(&bnx2i_dev_lock); + } + + return rc; } -- cgit v1.2.3-70-g09d2 From 3be924fb1d7be90c3ae6aa30ca42e9aa5d75efaf Mon Sep 17 00:00:00 2001 From: Anil Veerabhadrappa Date: Tue, 23 Jun 2009 14:07:40 -0700 Subject: [SCSI] bnx2i: convert bnx2i_dev_lock to mutex convert bnx2i_dev_lock to type mutex from rwlock_t because cnic->register_device() can sleep for various reasons including memory allocation, waiting for ISCSI_INIT completion and while acquiring mutex lock, cnic_lock. Signed-off-by: Michael Chan Signed-off-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 54 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'drivers/scsi/bnx2i/bnx2i_init.c') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 2aeeeee3372..fd78540ffc9 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -17,8 +17,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; #define DRV_MODULE_NAME "bnx2i" -#define DRV_MODULE_VERSION "2.0.1d" -#define DRV_MODULE_RELDATE "Mar 25, 2009" +#define DRV_MODULE_VERSION "2.0.1e" +#define DRV_MODULE_RELDATE "June 22, 2009" static char version[] __devinitdata = "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ @@ -30,7 +30,7 @@ MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 iSCSI Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -static DEFINE_RWLOCK(bnx2i_dev_lock); +static DEFINE_MUTEX(bnx2i_dev_lock); unsigned int event_coal_div = 1; module_param(event_coal_div, int, 0664); @@ -99,14 +99,14 @@ struct bnx2i_hba *get_adapter_list_head(void) if (!adapter_count) goto hba_not_found; - read_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); list_for_each_entry(tmp_hba, &adapter_list, link) { if (tmp_hba->cnic && tmp_hba->cnic->cm_select_dev) { hba = tmp_hba; break; } } - read_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); hba_not_found: return hba; } @@ -121,14 +121,14 @@ struct bnx2i_hba *bnx2i_find_hba_for_cnic(struct cnic_dev *cnic) { struct bnx2i_hba *hba, *temp; - read_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); list_for_each_entry_safe(hba, temp, &adapter_list, link) { if (hba->cnic == cnic) { - read_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); return hba; } } - read_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); return NULL; } @@ -206,10 +206,10 @@ void bnx2i_reg_dev_all(void) { struct bnx2i_hba *hba, *temp; - read_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); list_for_each_entry_safe(hba, temp, &adapter_list, link) bnx2i_register_device(hba); - read_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); } @@ -246,10 +246,10 @@ void bnx2i_unreg_dev_all(void) { struct bnx2i_hba *hba, *temp; - read_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); list_for_each_entry_safe(hba, temp, &adapter_list, link) bnx2i_unreg_one_device(hba); - read_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); } @@ -258,19 +258,21 @@ void bnx2i_unreg_dev_all(void) * @hba: bnx2i adapter instance * @cnic: cnic device handle * - * Global resource lock and host adapter lock is held during critical sections - * below. This routine is called from cnic_register_driver() context and - * work horse thread which does majority of device specific initialization + * Global resource lock is held during critical sections below. This routine is + * called from either cnic_register_driver() or device hot plug context and + * and does majority of device specific initialization */ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) { int rc; - read_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); if (!rc) { hba->age++; set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); + list_add_tail(&hba->link, &adapter_list); + adapter_count++; } else if (rc == -EBUSY) /* duplicate registration */ printk(KERN_ALERT "bnx2i, duplicate registration" "hba=%p, cnic=%p\n", hba, cnic); @@ -280,14 +282,8 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) printk(KERN_ERR "bnx2i, invalid type %d\n", CNIC_ULP_ISCSI); else printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc); - read_unlock(&bnx2i_dev_lock); - if (!rc) { - write_lock(&bnx2i_dev_lock); - list_add_tail(&hba->link, &adapter_list); - adapter_count++; - write_unlock(&bnx2i_dev_lock); - } + mutex_unlock(&bnx2i_dev_lock); return rc; } @@ -337,7 +333,7 @@ void bnx2i_ulp_exit(struct cnic_dev *dev) "found, dev 0x%p\n", dev); return; } - write_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); list_del_init(&hba->link); adapter_count--; @@ -345,7 +341,7 @@ void bnx2i_ulp_exit(struct cnic_dev *dev) hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); } - write_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); bnx2i_free_hba(hba); } @@ -367,6 +363,8 @@ static int __init bnx2i_mod_init(void) if (!is_power_of_2(sq_size)) sq_size = roundup_pow_of_two(sq_size); + mutex_init(&bnx2i_dev_lock); + bnx2i_scsi_xport_template = iscsi_register_transport(&bnx2i_iscsi_transport); if (!bnx2i_scsi_xport_template) { @@ -402,7 +400,7 @@ static void __exit bnx2i_mod_exit(void) { struct bnx2i_hba *hba; - write_lock(&bnx2i_dev_lock); + mutex_lock(&bnx2i_dev_lock); while (!list_empty(&adapter_list)) { hba = list_entry(adapter_list.next, struct bnx2i_hba, link); list_del(&hba->link); @@ -413,11 +411,9 @@ static void __exit bnx2i_mod_exit(void) clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); } - write_unlock(&bnx2i_dev_lock); bnx2i_free_hba(hba); - write_lock(&bnx2i_dev_lock); } - write_unlock(&bnx2i_dev_lock); + mutex_unlock(&bnx2i_dev_lock); iscsi_unregister_transport(&bnx2i_iscsi_transport); cnic_unregister_driver(CNIC_ULP_ISCSI); -- cgit v1.2.3-70-g09d2 From fac3cc458fc2f8272bcc1ff1903474ff41715723 Mon Sep 17 00:00:00 2001 From: Anil Veerabhadrappa Date: Wed, 8 Jul 2009 18:21:01 -0700 Subject: [SCSI] bnx2i: register given device with cnic if shost != NULL in ep_connect() When using iface, bnx2i was unable to offload further connections after all active sessions are logged out. bnx2i will unregister the device from cnic when the last connection is torn down. Next call to ep_connect() will fail because the device is not registered. This issue is not seen if shost == NULL is passed to ep_connect() call because in that case bnx2i will registers all known devices with cnic before doing a route look-up. When shost != NULL, bnx2i knows the device on which to offload the connection and has to register this device before attempting to offload the connection Signed-off-by: Anil Veerabhadrappa Reviewed-by: Michael Chan Reviewed-by Mike Christie Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 7 +++++-- drivers/scsi/bnx2i/bnx2i_iscsi.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/bnx2i/bnx2i_init.c') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index fd78540ffc9..0c4210d48ee 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -185,14 +185,17 @@ void bnx2i_stop(void *handle) */ void bnx2i_register_device(struct bnx2i_hba *hba) { + int rc; + if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) || test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { return; } - hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); + rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); - set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); + if (!rc) + set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); } diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index f7412196f2f..98148f3f3c6 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1653,15 +1653,18 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, struct iscsi_endpoint *ep; int rc = 0; - if (shost) + if (shost) { /* driver is given scsi host to work with */ hba = iscsi_host_priv(shost); - else + /* Register the device with cnic if not already done so */ + bnx2i_register_device(hba); + } else /* * check if the given destination can be reached through * a iscsi capable NetXtreme2 device */ hba = bnx2i_check_route(dst_addr); + if (!hba) { rc = -ENOMEM; goto check_busy; -- cgit v1.2.3-70-g09d2