diff options
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 47 |
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 *); | |||
97 | static void fc_fcp_complete_locked(struct fc_fcp_pkt *); | 97 | static void fc_fcp_complete_locked(struct fc_fcp_pkt *); |
98 | static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); | 98 | static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); |
99 | static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); | 99 | static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); |
100 | static void fc_timeout_error(struct fc_fcp_pkt *); | 100 | static void fc_fcp_recovery(struct fc_fcp_pkt *); |
101 | static void fc_fcp_timeout(unsigned long); | 101 | static void fc_fcp_timeout(unsigned long); |
102 | static void fc_fcp_rec(struct fc_fcp_pkt *); | 102 | static void fc_fcp_rec(struct fc_fcp_pkt *); |
103 | static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); | 103 | static 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; | ||
519 | err: | ||
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; |
1346 | unlock: | 1355 | unlock: |
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 | */ |
1584 | static void fc_timeout_error(struct fc_fcp_pkt *fsp) | 1593 | static 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: |