mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 00:21:32 +00:00
[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>
This commit is contained in:
parent
725dd399ae
commit
53151bbb83
@ -2629,7 +2629,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
|
||||
rspiocbq,
|
||||
(phba->fc_ratov * 2)
|
||||
+ LPFC_DRVR_TIMEOUT);
|
||||
if (iocb_stat) {
|
||||
if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) {
|
||||
ret_val = -EIO;
|
||||
goto err_get_xri_exit;
|
||||
}
|
||||
@ -3204,8 +3204,9 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
|
||||
rspiocbq, (phba->fc_ratov * 2) +
|
||||
LPFC_DRVR_TIMEOUT);
|
||||
|
||||
if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) &&
|
||||
(rsp->ulpStatus != IOCB_SUCCESS))) {
|
||||
if ((iocb_stat != IOCB_SUCCESS) ||
|
||||
((phba->sli_rev < LPFC_SLI_REV4) &&
|
||||
(rsp->ulpStatus != IOSTAT_SUCCESS))) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
|
||||
"3126 Failed loopback test issue iocb: "
|
||||
"iocb_stat:x%x\n", iocb_stat);
|
||||
|
@ -4490,9 +4490,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
|
||||
piocb->ulpContext =
|
||||
vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
|
||||
}
|
||||
if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
|
||||
piocb->ulpFCP2Rcvy = 1;
|
||||
}
|
||||
piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0;
|
||||
piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f);
|
||||
|
||||
/* ulpTimeout is only one byte */
|
||||
@ -4986,6 +4984,73 @@ lpfc_taskmgmt_name(uint8_t task_mgmt_cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_check_fcp_rsp - check the returned fcp_rsp to see if task failed
|
||||
* @vport: The virtual port for which this call is being executed.
|
||||
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
|
||||
*
|
||||
* This routine checks the FCP RSP INFO to see if the tsk mgmt command succeded
|
||||
*
|
||||
* Return code :
|
||||
* 0x2003 - Error
|
||||
* 0x2002 - Success
|
||||
**/
|
||||
static int
|
||||
lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd)
|
||||
{
|
||||
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
|
||||
uint32_t rsp_info;
|
||||
uint32_t rsp_len;
|
||||
uint8_t rsp_info_code;
|
||||
int ret = FAILED;
|
||||
|
||||
|
||||
if (fcprsp == NULL)
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"0703 fcp_rsp is missing\n");
|
||||
else {
|
||||
rsp_info = fcprsp->rspStatus2;
|
||||
rsp_len = be32_to_cpu(fcprsp->rspRspLen);
|
||||
rsp_info_code = fcprsp->rspInfo3;
|
||||
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
LOG_FCP,
|
||||
"0706 fcp_rsp valid 0x%x,"
|
||||
" rsp len=%d code 0x%x\n",
|
||||
rsp_info,
|
||||
rsp_len, rsp_info_code);
|
||||
|
||||
if ((fcprsp->rspStatus2&RSP_LEN_VALID) && (rsp_len == 8)) {
|
||||
switch (rsp_info_code) {
|
||||
case RSP_NO_FAILURE:
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"0715 Task Mgmt No Failure\n");
|
||||
ret = SUCCESS;
|
||||
break;
|
||||
case RSP_TM_NOT_SUPPORTED: /* TM rejected */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"0716 Task Mgmt Target "
|
||||
"reject\n");
|
||||
break;
|
||||
case RSP_TM_NOT_COMPLETED: /* TM failed */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"0717 Task Mgmt Target "
|
||||
"failed TM\n");
|
||||
break;
|
||||
case RSP_TM_INVALID_LU: /* TM to invalid LU! */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"0718 Task Mgmt to invalid "
|
||||
"LUN\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler
|
||||
* @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,
|
||||
|
||||
status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
|
||||
iocbq, iocbqrsp, lpfc_cmd->timeout);
|
||||
if (status != IOCB_SUCCESS) {
|
||||
if (status == IOCB_TIMEDOUT) {
|
||||
ret = TIMEOUT_ERROR;
|
||||
} else
|
||||
ret = FAILED;
|
||||
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
||||
if ((status != IOCB_SUCCESS) ||
|
||||
(iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
|
||||
"0727 TMF %s to TGT %d LUN %d failed (%d, %d) "
|
||||
"iocb_flag x%x\n",
|
||||
@ -5060,9 +5121,21 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
|
||||
tgt_id, lun_id, iocbqrsp->iocb.ulpStatus,
|
||||
iocbqrsp->iocb.un.ulpWord[4],
|
||||
iocbq->iocb_flag);
|
||||
} else if (status == IOCB_BUSY)
|
||||
ret = FAILED;
|
||||
else
|
||||
/* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
|
||||
if (status == IOCB_SUCCESS) {
|
||||
if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
|
||||
/* Something in the FCP_RSP was invalid.
|
||||
* Check conditions */
|
||||
ret = lpfc_check_fcp_rsp(vport, lpfc_cmd);
|
||||
else
|
||||
ret = FAILED;
|
||||
} else if (status == IOCB_TIMEDOUT) {
|
||||
ret = TIMEOUT_ERROR;
|
||||
} else {
|
||||
ret = FAILED;
|
||||
}
|
||||
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
||||
} else
|
||||
ret = SUCCESS;
|
||||
|
||||
lpfc_sli_release_iocbq(phba, iocbqrsp);
|
||||
@ -5186,7 +5259,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
|
||||
unsigned tgt_id = cmnd->device->id;
|
||||
unsigned int lun_id = cmnd->device->lun;
|
||||
struct lpfc_scsi_event_header scsi_event;
|
||||
int status, ret = SUCCESS;
|
||||
int status;
|
||||
|
||||
if (!rdata) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
|
||||
@ -5227,9 +5300,11 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
|
||||
* So, continue on.
|
||||
* We will report success if all the i/o aborts successfully.
|
||||
*/
|
||||
ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
if (status == SUCCESS)
|
||||
status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
LPFC_CTX_LUN);
|
||||
return ret;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5253,7 +5328,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
|
||||
unsigned tgt_id = cmnd->device->id;
|
||||
unsigned int lun_id = cmnd->device->lun;
|
||||
struct lpfc_scsi_event_header scsi_event;
|
||||
int status, ret = SUCCESS;
|
||||
int status;
|
||||
|
||||
if (!rdata) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
|
||||
@ -5294,9 +5369,10 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
|
||||
* So, continue on.
|
||||
* We will report success if all the i/o aborts successfully.
|
||||
*/
|
||||
ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
if (status == SUCCESS)
|
||||
status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
|
||||
LPFC_CTX_TGT);
|
||||
return ret;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +73,7 @@ struct fcp_rsp {
|
||||
#define RSP_RO_MISMATCH_ERR 0x03
|
||||
#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */
|
||||
#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */
|
||||
#define RSP_TM_INVALID_LU 0x09 /* Task mgmt function to invalid LU */
|
||||
|
||||
uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */
|
||||
|
||||
|
@ -10196,6 +10196,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
|
||||
if (iocb_completed) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"0331 IOCB wake signaled\n");
|
||||
/* Note: we are not indicating if the IOCB has a success
|
||||
* status or not - that's for the caller to check.
|
||||
* IOCB_SUCCESS means just that the command was sent and
|
||||
* completed. Not that it completed successfully.
|
||||
* */
|
||||
} else if (timeleft == 0) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"0338 IOCB wait timeout error - no "
|
||||
|
Loading…
Reference in New Issue
Block a user