aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2012-06-07 05:19:35 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:23 -0400
commit5c17ae217ad13463f821c3bab774335777da9c33 (patch)
tree681652b5df7088693a49d697b17d84fd261425c4
parentd075498c987623107f7bface4dad72fe9260a0d3 (diff)
[SCSI] bnx2fc: Improve error recovery by handling parity errors
During parity errors, the ramrods are not issued to FW. bnx2fc waits for the timeout value, and proceeds with cleaning up the IOs. Since we are already out-of-sync with FW, cleanup commands timeout too, and do not get the completion. This operation takes 36 secs for each session to upload causing huge delays. To fix this, bnx2fc now gets a PARITY_ERROR from cnic driver, and upon failure, the driver does not issue any commands to the FW and finishes the upload process sooner. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h1
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c4
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c25
3 files changed, 24 insertions, 6 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 2f1bea42336f..baac6e968095 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -275,6 +275,7 @@ struct bnx2fc_rport {
275#define BNX2FC_FLAG_CTX_ALLOC_FAILURE 0x6 275#define BNX2FC_FLAG_CTX_ALLOC_FAILURE 0x6
276#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x7 276#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x7
277#define BNX2FC_FLAG_EXPL_LOGO 0x8 277#define BNX2FC_FLAG_EXPL_LOGO 0x8
278#define BNX2FC_FLAG_DISABLE_FAILED 0x9
278 279
279 u8 src_addr[ETH_ALEN]; 280 u8 src_addr[ETH_ALEN];
280 u32 max_sqes; 281 u32 max_sqes;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 2ca6bfe4ce5e..6d6eee42ac7d 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1244,7 +1244,9 @@ static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
1244 if (disable_kcqe->completion_status) { 1244 if (disable_kcqe->completion_status) {
1245 printk(KERN_ERR PFX "Disable failed with cmpl status %d\n", 1245 printk(KERN_ERR PFX "Disable failed with cmpl status %d\n",
1246 disable_kcqe->completion_status); 1246 disable_kcqe->completion_status);
1247 return; 1247 set_bit(BNX2FC_FLAG_DISABLE_FAILED, &tgt->flags);
1248 set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
1249 wake_up_interruptible(&tgt->upld_wait);
1248 } else { 1250 } else {
1249 /* disable successful */ 1251 /* disable successful */
1250 BNX2FC_TGT_DBG(tgt, "disable successful\n"); 1252 BNX2FC_TGT_DBG(tgt, "disable successful\n");
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 082a25c3117e..85ffdeaa3b85 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -181,8 +181,14 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
181 181
182 set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags); 182 set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags);
183 set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags); 183 set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags);
184 rc = bnx2fc_initiate_cleanup(io_req); 184
185 BUG_ON(rc); 185 /* Do not issue cleanup when disable request failed */
186 if (test_bit(BNX2FC_FLAG_DISABLE_FAILED, &tgt->flags))
187 bnx2fc_process_cleanup_compl(io_req, io_req->task, 0);
188 else {
189 rc = bnx2fc_initiate_cleanup(io_req);
190 BUG_ON(rc);
191 }
186 } 192 }
187 193
188 list_for_each_safe(list, tmp, &tgt->active_tm_queue) { 194 list_for_each_safe(list, tmp, &tgt->active_tm_queue) {
@@ -212,8 +218,13 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
212 io_req->cb_arg = NULL; 218 io_req->cb_arg = NULL;
213 } 219 }
214 220
215 rc = bnx2fc_initiate_cleanup(io_req); 221 /* Do not issue cleanup when disable request failed */
216 BUG_ON(rc); 222 if (test_bit(BNX2FC_FLAG_DISABLE_FAILED, &tgt->flags))
223 bnx2fc_process_cleanup_compl(io_req, io_req->task, 0);
224 else {
225 rc = bnx2fc_initiate_cleanup(io_req);
226 BUG_ON(rc);
227 }
217 } 228 }
218 229
219 list_for_each_safe(list, tmp, &tgt->io_retire_queue) { 230 list_for_each_safe(list, tmp, &tgt->io_retire_queue) {
@@ -321,9 +332,13 @@ static void bnx2fc_upload_session(struct fcoe_port *port,
321 332
322 del_timer_sync(&tgt->upld_timer); 333 del_timer_sync(&tgt->upld_timer);
323 334
324 } else 335 } else if (test_bit(BNX2FC_FLAG_DISABLE_FAILED, &tgt->flags)) {
336 printk(KERN_ERR PFX "ERROR!! DISABLE req failed, destroy"
337 " not sent to FW\n");
338 } else {
325 printk(KERN_ERR PFX "ERROR!! DISABLE req timed out, destroy" 339 printk(KERN_ERR PFX "ERROR!! DISABLE req timed out, destroy"
326 " not sent to FW\n"); 340 " not sent to FW\n");
341 }
327 342
328 /* Free session resources */ 343 /* Free session resources */
329 bnx2fc_free_session_resc(hba, tgt); 344 bnx2fc_free_session_resc(hba, tgt);