aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2010-03-12 19:08:44 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-04-11 10:23:42 -0400
commit5c12c418e905aac2826bb70f947648944c079ed9 (patch)
tree802e2e53f57361a6d3899bee226354813c94597f /drivers/scsi/libfc
parent3e22760d4db6fd89e0be46c3d132390a251da9c6 (diff)
[SCSI] libfc: fix fcp pkt recovery in fc_fcp_recv_data
Currently fc_fcp_recv_data calls fc_fcp_retry_cmd to retry failed IO but in this case tgt is still sending data frames, therefore exchange needs to be aborted first before initiating retry. So this patch fixes this by aborting exchange first then have retry. Renames fc_timeout_error to fc_fcp_recovery since fc_timeout_error is already called from several other places beside from fcp timeout handler and then used fc_fcp_recovery for abort & retry from fc_fcp_recv_data, this rename also required renaming FC_CMD_TIME_OUT status to FC_CMD_RECOVERY to be consistent with new fc_fcp_recovery. Data frames are not expected for an DDPed exchange and potentially it could be tampered data frame, so does recovery in this case by calling fc_fcp_recovery. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 17396c708b08..39f18e39125c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -97,7 +97,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *);
97static void fc_fcp_complete_locked(struct fc_fcp_pkt *); 97static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
98static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); 98static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
99static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); 99static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
100static void fc_timeout_error(struct fc_fcp_pkt *); 100static void fc_fcp_recovery(struct fc_fcp_pkt *);
101static void fc_fcp_timeout(unsigned long); 101static void fc_fcp_timeout(unsigned long);
102static void fc_fcp_rec(struct fc_fcp_pkt *); 102static void fc_fcp_rec(struct fc_fcp_pkt *);
103static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); 103static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
@@ -121,7 +121,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
121#define FC_DATA_UNDRUN 7 121#define FC_DATA_UNDRUN 7
122#define FC_ERROR 8 122#define FC_ERROR 8
123#define FC_HRD_ERROR 9 123#define FC_HRD_ERROR 9
124#define FC_CMD_TIME_OUT 10 124#define FC_CMD_RECOVERY 10
125 125
126/* 126/*
127 * Error recovery timeout values. 127 * Error recovery timeout values.
@@ -446,9 +446,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
446 len = fr_len(fp) - sizeof(*fh); 446 len = fr_len(fp) - sizeof(*fh);
447 buf = fc_frame_payload_get(fp, 0); 447 buf = fc_frame_payload_get(fp, 0);
448 448
449 /* if this I/O is ddped, update xfer len */ 449 /*
450 fc_fcp_ddp_done(fsp); 450 * if this I/O is ddped then clear it
451 451 * and initiate recovery since data
452 * frames are expected to be placed
453 * directly in that case.
454 */
455 if (fsp->xfer_ddp != FC_XID_UNKNOWN) {
456 fc_fcp_ddp_done(fsp);
457 goto err;
458 }
452 if (offset + len > fsp->data_len) { 459 if (offset + len > fsp->data_len) {
453 /* this should never happen */ 460 /* this should never happen */
454 if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && 461 if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
@@ -456,8 +463,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
456 goto crc_err; 463 goto crc_err;
457 FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx " 464 FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx "
458 "data_len %x\n", len, offset, fsp->data_len); 465 "data_len %x\n", len, offset, fsp->data_len);
459 fc_fcp_retry_cmd(fsp); 466 goto err;
460 return;
461 } 467 }
462 if (offset != fsp->xfer_len) 468 if (offset != fsp->xfer_len)
463 fsp->state |= FC_SRB_DISCONTIG; 469 fsp->state |= FC_SRB_DISCONTIG;
@@ -493,7 +499,7 @@ crc_err:
493 * Otherwise, ignore it. 499 * Otherwise, ignore it.
494 */ 500 */
495 if (fsp->state & FC_SRB_DISCONTIG) 501 if (fsp->state & FC_SRB_DISCONTIG)
496 fc_fcp_retry_cmd(fsp); 502 goto err;
497 return; 503 return;
498 } 504 }
499 } 505 }
@@ -509,6 +515,9 @@ crc_err:
509 if (unlikely(fsp->state & FC_SRB_RCV_STATUS) && 515 if (unlikely(fsp->state & FC_SRB_RCV_STATUS) &&
510 fsp->xfer_len == fsp->data_len - fsp->scsi_resid) 516 fsp->xfer_len == fsp->data_len - fsp->scsi_resid)
511 fc_fcp_complete_locked(fsp); 517 fc_fcp_complete_locked(fsp);
518 return;
519err:
520 fc_fcp_recovery(fsp);
512} 521}
513 522
514/** 523/**
@@ -1341,7 +1350,7 @@ static void fc_fcp_timeout(unsigned long data)
1341 else if (fsp->state & FC_SRB_RCV_STATUS) 1350 else if (fsp->state & FC_SRB_RCV_STATUS)
1342 fc_fcp_complete_locked(fsp); 1351 fc_fcp_complete_locked(fsp);
1343 else 1352 else
1344 fc_timeout_error(fsp); 1353 fc_fcp_recovery(fsp);
1345 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; 1354 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
1346unlock: 1355unlock:
1347 fc_fcp_unlock_pkt(fsp); 1356 fc_fcp_unlock_pkt(fsp);
@@ -1385,7 +1394,7 @@ retry:
1385 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1394 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1386 fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); 1395 fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
1387 else 1396 else
1388 fc_timeout_error(fsp); 1397 fc_fcp_recovery(fsp);
1389} 1398}
1390 1399
1391/** 1400/**
@@ -1454,7 +1463,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1454 fc_fcp_retry_cmd(fsp); 1463 fc_fcp_retry_cmd(fsp);
1455 break; 1464 break;
1456 } 1465 }
1457 fc_timeout_error(fsp); 1466 fc_fcp_recovery(fsp);
1458 break; 1467 break;
1459 } 1468 }
1460 } else if (opcode == ELS_LS_ACC) { 1469 } else if (opcode == ELS_LS_ACC) {
@@ -1569,7 +1578,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1569 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1578 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1570 fc_fcp_rec(fsp); 1579 fc_fcp_rec(fsp);
1571 else 1580 else
1572 fc_timeout_error(fsp); 1581 fc_fcp_recovery(fsp);
1573 break; 1582 break;
1574 } 1583 }
1575 fc_fcp_unlock_pkt(fsp); 1584 fc_fcp_unlock_pkt(fsp);
@@ -1578,12 +1587,12 @@ out:
1578} 1587}
1579 1588
1580/** 1589/**
1581 * fc_timeout_error() - Handler for fcp_pkt timeouts 1590 * fc_fcp_recovery() - Handler for fcp_pkt recovery
1582 * @fsp: The FCP packt that has timed out 1591 * @fsp: The FCP pkt that needs to be aborted
1583 */ 1592 */
1584static void fc_timeout_error(struct fc_fcp_pkt *fsp) 1593static void fc_fcp_recovery(struct fc_fcp_pkt *fsp)
1585{ 1594{
1586 fsp->status_code = FC_CMD_TIME_OUT; 1595 fsp->status_code = FC_CMD_RECOVERY;
1587 fsp->cdb_status = 0; 1596 fsp->cdb_status = 0;
1588 fsp->io_status = 0; 1597 fsp->io_status = 0;
1589 /* 1598 /*
@@ -1689,7 +1698,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1689 break; 1698 break;
1690 case ELS_LS_RJT: 1699 case ELS_LS_RJT:
1691 default: 1700 default:
1692 fc_timeout_error(fsp); 1701 fc_fcp_recovery(fsp);
1693 break; 1702 break;
1694 } 1703 }
1695 fc_fcp_unlock_pkt(fsp); 1704 fc_fcp_unlock_pkt(fsp);
@@ -1715,7 +1724,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1715 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1724 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1716 fc_fcp_rec(fsp); 1725 fc_fcp_rec(fsp);
1717 else 1726 else
1718 fc_timeout_error(fsp); 1727 fc_fcp_recovery(fsp);
1719 break; 1728 break;
1720 case -FC_EX_CLOSED: /* e.g., link failure */ 1729 case -FC_EX_CLOSED: /* e.g., link failure */
1721 /* fall through */ 1730 /* fall through */
@@ -1934,7 +1943,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1934 case FC_CMD_ABORTED: 1943 case FC_CMD_ABORTED:
1935 sc_cmd->result = (DID_ERROR << 16) | fsp->io_status; 1944 sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
1936 break; 1945 break;
1937 case FC_CMD_TIME_OUT: 1946 case FC_CMD_RECOVERY:
1938 sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status; 1947 sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
1939 break; 1948 break;
1940 case FC_CMD_RESET: 1949 case FC_CMD_RESET: