aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2i
diff options
context:
space:
mode:
authorEddie Wai <eddie.wai@broadcom.com>2010-08-12 16:44:30 -0700
committerJames Bottomley <James.Bottomley@suse.de>2010-09-05 14:51:16 -0300
commit250ae982e2864aa0e06a09137382f44e58b51683 (patch)
treefde480c10f393bbd4c6ea1d2af3e189d2d6f415e /drivers/scsi/bnx2i
parent2c2255e08dee510c68d641195f83d40899897c65 (diff)
downloadkernel_samsung_smdk4412-250ae982e2864aa0e06a09137382f44e58b51683.tar.gz
kernel_samsung_smdk4412-250ae982e2864aa0e06a09137382f44e58b51683.tar.bz2
kernel_samsung_smdk4412-250ae982e2864aa0e06a09137382f44e58b51683.zip
[SCSI] bnx2i: Added chip cleanup for the remove module path
In the case when an ep_connect request is interrupted due to route request stall, if the iSCSI daemon is terminated by the user, the chip will be left in a state which will not get cleaned up upon module removal. Upon module reload, when the same context id is used for a new connection, chip panic would occur. This patch adds chip cleanup in the module removal path. Signed-off-by: Eddie Wai <eddie.wai@broadcom.com> Acked-by: Benjamin Li <benli@broadcom.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/bnx2i')
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c54
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c3
2 files changed, 37 insertions, 20 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index a796f565f38..1294936f4fa 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -167,6 +167,38 @@ void bnx2i_start(void *handle)
/**
+ * bnx2i_chip_cleanup - local routine to handle chip cleanup
+ * @hba: Adapter instance to register
+ *
+ * Driver checks if adapter still has any active connections before
+ * executing the cleanup process
+ */
+static void bnx2i_chip_cleanup(struct bnx2i_hba *hba)
+{
+ struct bnx2i_endpoint *bnx2i_ep;
+ struct list_head *pos, *tmp;
+
+ if (hba->ofld_conns_active) {
+ /* Stage to force the disconnection
+ * This is the case where the daemon is either slow or
+ * not present
+ */
+ printk(KERN_ALERT "bnx2i: (%s) chip cleanup for %d active "
+ "connections\n", hba->netdev->name,
+ hba->ofld_conns_active);
+ mutex_lock(&hba->net_dev_lock);
+ list_for_each_safe(pos, tmp, &hba->ep_active_list) {
+ bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
+ /* Clean up the chip only */
+ bnx2i_hw_ep_disconnect(bnx2i_ep);
+ bnx2i_ep->cm_sk = NULL;
+ }
+ mutex_unlock(&hba->net_dev_lock);
+ }
+}
+
+
+/**
* bnx2i_stop - cnic callback to shutdown adapter instance
* @handle: transparent handle pointing to adapter structure
*
@@ -176,8 +208,6 @@ void bnx2i_start(void *handle)
void bnx2i_stop(void *handle)
{
struct bnx2i_hba *hba = handle;
- struct list_head *pos, *tmp;
- struct bnx2i_endpoint *bnx2i_ep;
int conns_active;
/* check if cleanup happened in GOING_DOWN context */
@@ -198,24 +228,7 @@ void bnx2i_stop(void *handle)
if (hba->ofld_conns_active == conns_active)
break;
}
- if (hba->ofld_conns_active) {
- /* Stage to force the disconnection
- * This is the case where the daemon is either slow or
- * not present
- */
- printk(KERN_ALERT "bnx2i: Wait timeout, force all eps "
- "to disconnect (%d)\n", hba->ofld_conns_active);
- mutex_lock(&hba->net_dev_lock);
- list_for_each_safe(pos, tmp, &hba->ep_active_list) {
- bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
- /* Clean up the chip only */
- bnx2i_hw_ep_disconnect(bnx2i_ep);
- }
- mutex_unlock(&hba->net_dev_lock);
- if (hba->ofld_conns_active)
- printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n",
- hba->ofld_conns_active);
- }
+ bnx2i_chip_cleanup(hba);
/* This flag should be cleared last so that ep_disconnect() gracefully
* cleans up connection context
@@ -457,6 +470,7 @@ static void __exit bnx2i_mod_exit(void)
adapter_count--;
if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+ bnx2i_chip_cleanup(hba);
hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
clear_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 0425540d481..fb50efbce08 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1953,6 +1953,9 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
if (!cnic)
return 0;
+ if (bnx2i_ep->state == EP_STATE_IDLE)
+ return 0;
+
if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
goto destroy_conn;