summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-10-10 12:24:07 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 04:58:18 -0400
commit53151bbb83f11b358ac94eddd81347c581dc51ea (patch)
treeffce8c5717d448789f1be3ac78c261b6d2d5a681 /drivers/scsi/lpfc
parent725dd399ae69d0703c0417f9ce0ce065d2a914d1 (diff)
[SCSI] lpfc 8.3.43: Fixed not processing task management IOCB response status
This patch implements the changes requested by Jeremy Linton: http://marc.info/?l=linux-scsi&m=136242124409687&w=2 The patch revises the command issuing behavior, detecting cases where the Task Mgmt command may have completed but with a non-successful status, which it previously treated as a successful TMF. The patch also corrects a flushing of I/O that was done which should only be done on successful TMF completion. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c112
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c5
4 files changed, 104 insertions, 21 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index b92aec989d60..82134d20e2d8 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2629,7 +2629,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
2629 rspiocbq, 2629 rspiocbq,
2630 (phba->fc_ratov * 2) 2630 (phba->fc_ratov * 2)
2631 + LPFC_DRVR_TIMEOUT); 2631 + LPFC_DRVR_TIMEOUT);
2632 if (iocb_stat) { 2632 if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) {
2633 ret_val = -EIO; 2633 ret_val = -EIO;
2634 goto err_get_xri_exit; 2634 goto err_get_xri_exit;
2635 } 2635 }
@@ -3204,8 +3204,9 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
3204 rspiocbq, (phba->fc_ratov * 2) + 3204 rspiocbq, (phba->fc_ratov * 2) +
3205 LPFC_DRVR_TIMEOUT); 3205 LPFC_DRVR_TIMEOUT);
3206 3206
3207 if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) && 3207 if ((iocb_stat != IOCB_SUCCESS) ||
3208 (rsp->ulpStatus != IOCB_SUCCESS))) { 3208 ((phba->sli_rev < LPFC_SLI_REV4) &&
3209 (rsp->ulpStatus != IOSTAT_SUCCESS))) {
3209 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, 3210 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3210 "3126 Failed loopback test issue iocb: " 3211 "3126 Failed loopback test issue iocb: "
3211 "iocb_stat:x%x\n", iocb_stat); 3212 "iocb_stat:x%x\n", iocb_stat);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 443bbca9694c..b2ede05a5f0a 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4490,9 +4490,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
4490 piocb->ulpContext = 4490 piocb->ulpContext =
4491 vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; 4491 vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
4492 } 4492 }
4493 if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 4493 piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0;
4494 piocb->ulpFCP2Rcvy = 1;
4495 }
4496 piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); 4494 piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f);
4497 4495
4498 /* ulpTimeout is only one byte */ 4496 /* ulpTimeout is only one byte */
@@ -4986,6 +4984,73 @@ lpfc_taskmgmt_name(uint8_t task_mgmt_cmd)
4986 } 4984 }
4987} 4985}
4988 4986
4987
4988/**
4989 * lpfc_check_fcp_rsp - check the returned fcp_rsp to see if task failed
4990 * @vport: The virtual port for which this call is being executed.
4991 * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
4992 *
4993 * This routine checks the FCP RSP INFO to see if the tsk mgmt command succeded
4994 *
4995 * Return code :
4996 * 0x2003 - Error
4997 * 0x2002 - Success
4998 **/
4999static int
5000lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd)
5001{
5002 struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
5003 uint32_t rsp_info;
5004 uint32_t rsp_len;
5005 uint8_t rsp_info_code;
5006 int ret = FAILED;
5007
5008
5009 if (fcprsp == NULL)
5010 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
5011 "0703 fcp_rsp is missing\n");
5012 else {
5013 rsp_info = fcprsp->rspStatus2;
5014 rsp_len = be32_to_cpu(fcprsp->rspRspLen);
5015 rsp_info_code = fcprsp->rspInfo3;
5016
5017
5018 lpfc_printf_vlog(vport, KERN_INFO,
5019 LOG_FCP,
5020 "0706 fcp_rsp valid 0x%x,"
5021 " rsp len=%d code 0x%x\n",
5022 rsp_info,
5023 rsp_len, rsp_info_code);
5024
5025 if ((fcprsp->rspStatus2&RSP_LEN_VALID) && (rsp_len == 8)) {
5026 switch (rsp_info_code) {
5027 case RSP_NO_FAILURE:
5028 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
5029 "0715 Task Mgmt No Failure\n");
5030 ret = SUCCESS;
5031 break;
5032 case RSP_TM_NOT_SUPPORTED: /* TM rejected */
5033 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
5034 "0716 Task Mgmt Target "
5035 "reject\n");
5036 break;
5037 case RSP_TM_NOT_COMPLETED: /* TM failed */
5038 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
5039 "0717 Task Mgmt Target "
5040 "failed TM\n");
5041 break;
5042 case RSP_TM_INVALID_LU: /* TM to invalid LU! */
5043 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
5044 "0718 Task Mgmt to invalid "
5045 "LUN\n");
5046 break;
5047 }
5048 }
5049 }
5050 return ret;
5051}
5052
5053
4989/** 5054/**
4990 * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler 5055 * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler
4991 * @vport: The virtual port for which this call is being executed. 5056 * @vport: The virtual port for which this call is being executed.
@@ -5047,12 +5112,8 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
5047 5112
5048 status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, 5113 status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
5049 iocbq, iocbqrsp, lpfc_cmd->timeout); 5114 iocbq, iocbqrsp, lpfc_cmd->timeout);
5050 if (status != IOCB_SUCCESS) { 5115 if ((status != IOCB_SUCCESS) ||
5051 if (status == IOCB_TIMEDOUT) { 5116 (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) {
5052 ret = TIMEOUT_ERROR;
5053 } else
5054 ret = FAILED;
5055 lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
5056 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 5117 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
5057 "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " 5118 "0727 TMF %s to TGT %d LUN %d failed (%d, %d) "
5058 "iocb_flag x%x\n", 5119 "iocb_flag x%x\n",
@@ -5060,9 +5121,21 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
5060 tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, 5121 tgt_id, lun_id, iocbqrsp->iocb.ulpStatus,
5061 iocbqrsp->iocb.un.ulpWord[4], 5122 iocbqrsp->iocb.un.ulpWord[4],
5062 iocbq->iocb_flag); 5123 iocbq->iocb_flag);
5063 } else if (status == IOCB_BUSY) 5124 /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
5064 ret = FAILED; 5125 if (status == IOCB_SUCCESS) {
5065 else 5126 if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
5127 /* Something in the FCP_RSP was invalid.
5128 * Check conditions */
5129 ret = lpfc_check_fcp_rsp(vport, lpfc_cmd);
5130 else
5131 ret = FAILED;
5132 } else if (status == IOCB_TIMEDOUT) {
5133 ret = TIMEOUT_ERROR;
5134 } else {
5135 ret = FAILED;
5136 }
5137 lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
5138 } else
5066 ret = SUCCESS; 5139 ret = SUCCESS;
5067 5140
5068 lpfc_sli_release_iocbq(phba, iocbqrsp); 5141 lpfc_sli_release_iocbq(phba, iocbqrsp);
@@ -5186,7 +5259,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
5186 unsigned tgt_id = cmnd->device->id; 5259 unsigned tgt_id = cmnd->device->id;
5187 unsigned int lun_id = cmnd->device->lun; 5260 unsigned int lun_id = cmnd->device->lun;
5188 struct lpfc_scsi_event_header scsi_event; 5261 struct lpfc_scsi_event_header scsi_event;
5189 int status, ret = SUCCESS; 5262 int status;
5190 5263
5191 if (!rdata) { 5264 if (!rdata) {
5192 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 5265 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5227,9 +5300,11 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
5227 * So, continue on. 5300 * So, continue on.
5228 * We will report success if all the i/o aborts successfully. 5301 * We will report success if all the i/o aborts successfully.
5229 */ 5302 */
5230 ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, 5303 if (status == SUCCESS)
5304 status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
5231 LPFC_CTX_LUN); 5305 LPFC_CTX_LUN);
5232 return ret; 5306
5307 return status;
5233} 5308}
5234 5309
5235/** 5310/**
@@ -5253,7 +5328,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
5253 unsigned tgt_id = cmnd->device->id; 5328 unsigned tgt_id = cmnd->device->id;
5254 unsigned int lun_id = cmnd->device->lun; 5329 unsigned int lun_id = cmnd->device->lun;
5255 struct lpfc_scsi_event_header scsi_event; 5330 struct lpfc_scsi_event_header scsi_event;
5256 int status, ret = SUCCESS; 5331 int status;
5257 5332
5258 if (!rdata) { 5333 if (!rdata) {
5259 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 5334 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5294,9 +5369,10 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
5294 * So, continue on. 5369 * So, continue on.
5295 * We will report success if all the i/o aborts successfully. 5370 * We will report success if all the i/o aborts successfully.
5296 */ 5371 */
5297 ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, 5372 if (status == SUCCESS)
5373 status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
5298 LPFC_CTX_TGT); 5374 LPFC_CTX_TGT);
5299 return ret; 5375 return status;
5300} 5376}
5301 5377
5302/** 5378/**
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index b1d9f7fcb911..852ff7def493 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -73,6 +73,7 @@ struct fcp_rsp {
73#define RSP_RO_MISMATCH_ERR 0x03 73#define RSP_RO_MISMATCH_ERR 0x03
74#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */ 74#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */
75#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */ 75#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */
76#define RSP_TM_INVALID_LU 0x09 /* Task mgmt function to invalid LU */
76 77
77 uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */ 78 uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */
78 79
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a262d22bca44..8f580fda443f 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -10196,6 +10196,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
10196 if (iocb_completed) { 10196 if (iocb_completed) {
10197 lpfc_printf_log(phba, KERN_INFO, LOG_SLI, 10197 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
10198 "0331 IOCB wake signaled\n"); 10198 "0331 IOCB wake signaled\n");
10199 /* Note: we are not indicating if the IOCB has a success
10200 * status or not - that's for the caller to check.
10201 * IOCB_SUCCESS means just that the command was sent and
10202 * completed. Not that it completed successfully.
10203 * */
10199 } else if (timeleft == 0) { 10204 } else if (timeleft == 0) {
10200 lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 10205 lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
10201 "0338 IOCB wait timeout error - no " 10206 "0338 IOCB wait timeout error - no "