aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_fcp.c
diff options
context:
space:
mode:
authorjohn fastabend <john.r.fastabend@intel.com>2010-11-30 19:18:39 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:21 -0500
commitac17ea8d7d45d0495316edff13faa0dfd6bb2225 (patch)
tree6c8d0935d8b59ed3205fdfe9d074ab0b0a978fa2 /drivers/scsi/libfc/fc_fcp.c
parente90ff5ef0aab1d40f0e92a44d66f8d45a20d8c95 (diff)
[SCSI] libfc: incorrect scsi host byte codes returned to scsi-ml
The fcp packet recovery handler fc_fcp_recover() is called when errors occurr in a fcp session. Currently it is generically setting the status code to FC_CMD_RECOVERY for all error types. This results in DID_BUS_BUSY errors being returned to the scsi-ml. DID_BUS_BUSY errors indicate "BUS stayed busy through time out period" according to scsi.h. Many of the error reported by fc_rcp_recovery() are pkt errors. Here we update fc_fcp_recovery to use better host byte codes. With certain FAST FAIL flags set DID_BUS_BUSY and DID_ERROR will have different behaviors this was causing dm multipath to fail quickly in some cases where a retry would be a better action. Signed-off-by: John Fastabend <john.r.fastabend@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/fc_fcp.c')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 0e985dbaedc4..8eb67676d0dd 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -96,7 +96,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *);
96static void fc_fcp_complete_locked(struct fc_fcp_pkt *); 96static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
97static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); 97static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
98static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); 98static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
99static void fc_fcp_recovery(struct fc_fcp_pkt *); 99static void fc_fcp_recovery(struct fc_fcp_pkt *, u8 code);
100static void fc_fcp_timeout(unsigned long); 100static void fc_fcp_timeout(unsigned long);
101static void fc_fcp_rec(struct fc_fcp_pkt *); 101static void fc_fcp_rec(struct fc_fcp_pkt *);
102static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); 102static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
@@ -120,7 +120,8 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
120#define FC_DATA_UNDRUN 7 120#define FC_DATA_UNDRUN 7
121#define FC_ERROR 8 121#define FC_ERROR 8
122#define FC_HRD_ERROR 9 122#define FC_HRD_ERROR 9
123#define FC_CMD_RECOVERY 10 123#define FC_CRC_ERROR 10
124#define FC_TIMED_OUT 11
124 125
125/* 126/*
126 * Error recovery timeout values. 127 * Error recovery timeout values.
@@ -438,6 +439,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
438 void *buf; 439 void *buf;
439 struct scatterlist *sg; 440 struct scatterlist *sg;
440 u32 nents; 441 u32 nents;
442 u8 host_bcode = FC_COMPLETE;
441 443
442 fh = fc_frame_header_get(fp); 444 fh = fc_frame_header_get(fp);
443 offset = ntohl(fh->fh_parm_offset); 445 offset = ntohl(fh->fh_parm_offset);
@@ -446,13 +448,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
446 buf = fc_frame_payload_get(fp, 0); 448 buf = fc_frame_payload_get(fp, 0);
447 449
448 /* 450 /*
449 * if this I/O is ddped then clear it 451 * if this I/O is ddped then clear it and initiate recovery since data
450 * and initiate recovery since data 452 * frames are expected to be placed directly in that case.
451 * frames are expected to be placed 453 *
452 * directly in that case. 454 * Indicate error to scsi-ml because something went wrong with the
455 * ddp handling to get us here.
453 */ 456 */
454 if (fsp->xfer_ddp != FC_XID_UNKNOWN) { 457 if (fsp->xfer_ddp != FC_XID_UNKNOWN) {
455 fc_fcp_ddp_done(fsp); 458 fc_fcp_ddp_done(fsp);
459 FC_FCP_DBG(fsp, "DDP I/O in fc_fcp_recv_data set ERROR\n");
460 host_bcode = FC_ERROR;
456 goto err; 461 goto err;
457 } 462 }
458 if (offset + len > fsp->data_len) { 463 if (offset + len > fsp->data_len) {
@@ -462,6 +467,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
462 goto crc_err; 467 goto crc_err;
463 FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx " 468 FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx "
464 "data_len %x\n", len, offset, fsp->data_len); 469 "data_len %x\n", len, offset, fsp->data_len);
470
471 /* Data is corrupted indicate scsi-ml should retry */
472 host_bcode = FC_DATA_OVRRUN;
465 goto err; 473 goto err;
466 } 474 }
467 if (offset != fsp->xfer_len) 475 if (offset != fsp->xfer_len)
@@ -498,8 +506,10 @@ crc_err:
498 * If so, we need to retry the entire operation. 506 * If so, we need to retry the entire operation.
499 * Otherwise, ignore it. 507 * Otherwise, ignore it.
500 */ 508 */
501 if (fsp->state & FC_SRB_DISCONTIG) 509 if (fsp->state & FC_SRB_DISCONTIG) {
510 host_bcode = FC_CRC_ERROR;
502 goto err; 511 goto err;
512 }
503 return; 513 return;
504 } 514 }
505 } 515 }
@@ -517,7 +527,7 @@ crc_err:
517 fc_fcp_complete_locked(fsp); 527 fc_fcp_complete_locked(fsp);
518 return; 528 return;
519err: 529err:
520 fc_fcp_recovery(fsp); 530 fc_fcp_recovery(fsp, host_bcode);
521} 531}
522 532
523/** 533/**
@@ -1347,7 +1357,7 @@ static void fc_fcp_timeout(unsigned long data)
1347 else if (fsp->state & FC_SRB_RCV_STATUS) 1357 else if (fsp->state & FC_SRB_RCV_STATUS)
1348 fc_fcp_complete_locked(fsp); 1358 fc_fcp_complete_locked(fsp);
1349 else 1359 else
1350 fc_fcp_recovery(fsp); 1360 fc_fcp_recovery(fsp, FC_TIMED_OUT);
1351 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; 1361 fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
1352unlock: 1362unlock:
1353 fc_fcp_unlock_pkt(fsp); 1363 fc_fcp_unlock_pkt(fsp);
@@ -1391,7 +1401,7 @@ retry:
1391 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1401 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1392 fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); 1402 fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
1393 else 1403 else
1394 fc_fcp_recovery(fsp); 1404 fc_fcp_recovery(fsp, FC_TIMED_OUT);
1395} 1405}
1396 1406
1397/** 1407/**
@@ -1460,7 +1470,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1460 fc_fcp_retry_cmd(fsp); 1470 fc_fcp_retry_cmd(fsp);
1461 break; 1471 break;
1462 } 1472 }
1463 fc_fcp_recovery(fsp); 1473 fc_fcp_recovery(fsp, FC_ERROR);
1464 break; 1474 break;
1465 } 1475 }
1466 } else if (opcode == ELS_LS_ACC) { 1476 } else if (opcode == ELS_LS_ACC) {
@@ -1575,7 +1585,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1575 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1585 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1576 fc_fcp_rec(fsp); 1586 fc_fcp_rec(fsp);
1577 else 1587 else
1578 fc_fcp_recovery(fsp); 1588 fc_fcp_recovery(fsp, FC_ERROR);
1579 break; 1589 break;
1580 } 1590 }
1581 fc_fcp_unlock_pkt(fsp); 1591 fc_fcp_unlock_pkt(fsp);
@@ -1587,9 +1597,9 @@ out:
1587 * fc_fcp_recovery() - Handler for fcp_pkt recovery 1597 * fc_fcp_recovery() - Handler for fcp_pkt recovery
1588 * @fsp: The FCP pkt that needs to be aborted 1598 * @fsp: The FCP pkt that needs to be aborted
1589 */ 1599 */
1590static void fc_fcp_recovery(struct fc_fcp_pkt *fsp) 1600static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
1591{ 1601{
1592 fsp->status_code = FC_CMD_RECOVERY; 1602 fsp->status_code = code;
1593 fsp->cdb_status = 0; 1603 fsp->cdb_status = 0;
1594 fsp->io_status = 0; 1604 fsp->io_status = 0;
1595 /* 1605 /*
@@ -1695,7 +1705,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1695 break; 1705 break;
1696 case ELS_LS_RJT: 1706 case ELS_LS_RJT:
1697 default: 1707 default:
1698 fc_fcp_recovery(fsp); 1708 fc_fcp_recovery(fsp, FC_ERROR);
1699 break; 1709 break;
1700 } 1710 }
1701 fc_fcp_unlock_pkt(fsp); 1711 fc_fcp_unlock_pkt(fsp);
@@ -1721,7 +1731,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1721 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1731 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
1722 fc_fcp_rec(fsp); 1732 fc_fcp_rec(fsp);
1723 else 1733 else
1724 fc_fcp_recovery(fsp); 1734 fc_fcp_recovery(fsp, FC_TIMED_OUT);
1725 break; 1735 break;
1726 case -FC_EX_CLOSED: /* e.g., link failure */ 1736 case -FC_EX_CLOSED: /* e.g., link failure */
1727 /* fall through */ 1737 /* fall through */
@@ -1946,18 +1956,29 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1946 break; 1956 break;
1947 case FC_CMD_ABORTED: 1957 case FC_CMD_ABORTED:
1948 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " 1958 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
1949 "due to FC_CMD_ABORTED\n"); 1959 "due to FC_CMD_ABORTED\n");
1950 sc_cmd->result = (DID_ERROR << 16) | fsp->io_status; 1960 sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
1951 break; 1961 break;
1952 case FC_CMD_RECOVERY:
1953 sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
1954 break;
1955 case FC_CMD_RESET: 1962 case FC_CMD_RESET:
1963 FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
1964 "due to FC_CMD_RESET\n");
1956 sc_cmd->result = (DID_RESET << 16); 1965 sc_cmd->result = (DID_RESET << 16);
1957 break; 1966 break;
1958 case FC_HRD_ERROR: 1967 case FC_HRD_ERROR:
1968 FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
1969 "due to FC_HRD_ERROR\n");
1959 sc_cmd->result = (DID_NO_CONNECT << 16); 1970 sc_cmd->result = (DID_NO_CONNECT << 16);
1960 break; 1971 break;
1972 case FC_CRC_ERROR:
1973 FC_FCP_DBG(fsp, "Returning DID_PARITY to scsi-ml "
1974 "due to FC_CRC_ERROR\n");
1975 sc_cmd->result = (DID_PARITY << 16);
1976 break;
1977 case FC_TIMED_OUT:
1978 FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml "
1979 "due to FC_TIMED_OUT\n");
1980 sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
1981 break;
1961 default: 1982 default:
1962 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " 1983 FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
1963 "due to unknown error\n"); 1984 "due to unknown error\n");