[SCSI] bnx2fc: cleanup task management IO when it times out.
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>
Tue, 24 Apr 2012 22:26:03 +0000 (15:26 -0700)
committerJames Bottomley <JBottomley@Parallels.com>
Tue, 22 May 2012 09:01:26 +0000 (10:01 +0100)
When the task management IO times out, or a flush operation is performed while
task management IO is pending, driver is not cleaning up the IO. This patch
cleans up the IO for the above cases.

Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c

index 43258c3c90aef0248b9f745a17f98b71f60e0530..4f7453b9e41e2486b662d7fc3d8f55b1762fe154 100644 (file)
@@ -810,8 +810,22 @@ retry_tmf:
        spin_lock_bh(&tgt->tgt_lock);
 
        io_req->wait_for_comp = 0;
-       if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags)))
+       if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) {
                set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags);
+               if (io_req->on_tmf_queue) {
+                       list_del_init(&io_req->link);
+                       io_req->on_tmf_queue = 0;
+               }
+               io_req->wait_for_comp = 1;
+               bnx2fc_initiate_cleanup(io_req);
+               spin_unlock_bh(&tgt->tgt_lock);
+               rc = wait_for_completion_timeout(&io_req->tm_done,
+                                                BNX2FC_FW_TIMEOUT);
+               spin_lock_bh(&tgt->tgt_lock);
+               io_req->wait_for_comp = 0;
+               if (!rc)
+                       kref_put(&io_req->refcount, bnx2fc_cmd_release);
+       }
 
        spin_unlock_bh(&tgt->tgt_lock);
 
index d3ee231a5680653d931f10a7b31645272e3d4907..082a25c3117e58cf961c383803e743ac92b7da24 100644 (file)
@@ -185,6 +185,16 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
                BUG_ON(rc);
        }
 
+       list_for_each_safe(list, tmp, &tgt->active_tm_queue) {
+               i++;
+               io_req = (struct bnx2fc_cmd *)list;
+               list_del_init(&io_req->link);
+               io_req->on_tmf_queue = 0;
+               BNX2FC_IO_DBG(io_req, "tm_queue cleanup\n");
+               if (io_req->wait_for_comp)
+                       complete(&io_req->tm_done);
+       }
+
        list_for_each_safe(list, tmp, &tgt->els_queue) {
                i++;
                io_req = (struct bnx2fc_cmd *)list;