|
@@ -292,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
|
|
+lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
|
|
|
{
|
|
|
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
|
|
|
struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
|
|
|
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
|
|
|
struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
|
|
|
- uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
|
|
|
+ uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
|
|
|
uint32_t resp_info = fcprsp->rspStatus2;
|
|
|
uint32_t scsi_status = fcprsp->rspStatus3;
|
|
|
uint32_t *lp;
|
|
@@ -359,6 +359,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
|
|
be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
|
|
|
fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
|
|
|
|
|
|
+ /*
|
|
|
+ * If there is an under run check if under run reported by
|
|
|
+ * storage array is same as the under run reported by HBA.
|
|
|
+ * If this is not same, there is a dropped frame.
|
|
|
+ */
|
|
|
+ if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
|
|
|
+ fcpi_parm &&
|
|
|
+ (cmnd->resid != fcpi_parm)) {
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING,
|
|
|
+ LOG_FCP | LOG_FCP_ERROR,
|
|
|
+ "%d:0735 FCP Read Check Error and Underrun "
|
|
|
+ "Data: x%x x%x x%x x%x\n", phba->brd_no,
|
|
|
+ be32_to_cpu(fcpcmd->fcpDl),
|
|
|
+ cmnd->resid,
|
|
|
+ fcpi_parm, cmnd->cmnd[0]);
|
|
|
+ cmnd->resid = cmnd->request_bufflen;
|
|
|
+ host_status = DID_ERROR;
|
|
|
+ }
|
|
|
/*
|
|
|
* The cmnd->underflow is the minimum number of bytes that must
|
|
|
* be transfered for this command. Provided a sense condition
|
|
@@ -439,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|
|
switch (lpfc_cmd->status) {
|
|
|
case IOSTAT_FCP_RSP_ERROR:
|
|
|
/* Call FCP RSP handler to determine result */
|
|
|
- lpfc_handle_fcp_err(lpfc_cmd);
|
|
|
+ lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
|
|
|
break;
|
|
|
case IOSTAT_NPORT_BSY:
|
|
|
case IOSTAT_FABRIC_BSY:
|
|
@@ -673,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|
|
return (1);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
|
|
|
+ struct lpfc_iocbq *cmdiocbq,
|
|
|
+ struct lpfc_iocbq *rspiocbq)
|
|
|
+{
|
|
|
+ struct lpfc_scsi_buf *lpfc_cmd =
|
|
|
+ (struct lpfc_scsi_buf *) cmdiocbq->context1;
|
|
|
+ if (lpfc_cmd)
|
|
|
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
|
|
unsigned tgt_id, unsigned int lun,
|
|
@@ -709,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
|
|
&phba->sli.ring[phba->sli.fcp_ring],
|
|
|
iocbq, iocbqrsp, lpfc_cmd->timeout);
|
|
|
if (ret != IOCB_SUCCESS) {
|
|
|
+ if (ret == IOCB_TIMEDOUT)
|
|
|
+ iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
|
|
|
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
|
|
- ret = FAILED;
|
|
|
} else {
|
|
|
ret = SUCCESS;
|
|
|
lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
|
|
@@ -977,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
+lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
|
|
|
{
|
|
|
struct Scsi_Host *shost = cmnd->device->host;
|
|
|
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
|
@@ -987,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
struct lpfc_nodelist *pnode = rdata->pnode;
|
|
|
uint32_t cmd_result = 0, cmd_status = 0;
|
|
|
int ret = FAILED;
|
|
|
+ int iocb_status = IOCB_SUCCESS;
|
|
|
int cnt, loopcnt;
|
|
|
|
|
|
lpfc_block_error_handler(cmnd);
|
|
@@ -998,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
*/
|
|
|
while ( 1 ) {
|
|
|
if (!pnode)
|
|
|
- return FAILED;
|
|
|
+ goto out;
|
|
|
|
|
|
if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
|
|
|
spin_unlock_irq(phba->host->host_lock);
|
|
@@ -1016,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
}
|
|
|
pnode = rdata->pnode;
|
|
|
if (!pnode)
|
|
|
- return FAILED;
|
|
|
+ goto out;
|
|
|
}
|
|
|
if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
|
|
|
break;
|
|
@@ -1031,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
lpfc_cmd->rdata = rdata;
|
|
|
|
|
|
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
|
|
|
- FCP_LUN_RESET);
|
|
|
+ FCP_TARGET_RESET);
|
|
|
if (!ret)
|
|
|
goto out_free_scsi_buf;
|
|
|
|
|
@@ -1043,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
goto out_free_scsi_buf;
|
|
|
|
|
|
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
|
|
|
- "%d:0703 Issue LUN Reset to TGT %d LUN %d "
|
|
|
- "Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
|
|
|
+ "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
|
|
|
+ "nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
|
|
|
cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
|
|
|
|
|
|
- ret = lpfc_sli_issue_iocb_wait(phba,
|
|
|
+ iocb_status = lpfc_sli_issue_iocb_wait(phba,
|
|
|
&phba->sli.ring[phba->sli.fcp_ring],
|
|
|
iocbq, iocbqrsp, lpfc_cmd->timeout);
|
|
|
- if (ret == IOCB_SUCCESS)
|
|
|
- ret = SUCCESS;
|
|
|
|
|
|
+ if (iocb_status == IOCB_TIMEDOUT)
|
|
|
+ iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
|
|
|
+
|
|
|
+ if (iocb_status == IOCB_SUCCESS)
|
|
|
+ ret = SUCCESS;
|
|
|
+ else
|
|
|
+ ret = iocb_status;
|
|
|
|
|
|
cmd_result = iocbqrsp->iocb.un.ulpWord[4];
|
|
|
cmd_status = iocbqrsp->iocb.ulpStatus;
|
|
@@ -1090,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|
|
|
|
|
if (cnt) {
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
|
|
- "%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
|
|
|
+ "%d:0719 device reset I/O flush failure: cnt x%x\n",
|
|
|
phba->brd_no, cnt);
|
|
|
ret = FAILED;
|
|
|
}
|
|
|
|
|
|
out_free_scsi_buf:
|
|
|
- lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
|
-
|
|
|
+ if (iocb_status != IOCB_TIMEDOUT) {
|
|
|
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
|
+ }
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
|
|
- "%d:0713 SCSI layer issued LUN reset (%d, %d) "
|
|
|
- "Data: x%x x%x x%x\n",
|
|
|
- phba->brd_no, cmnd->device->id,cmnd->device->lun,
|
|
|
+ "%d:0713 SCSI layer issued device reset (%d, %d) "
|
|
|
+ "return x%x status x%x result x%x\n",
|
|
|
+ phba->brd_no, cmnd->device->id, cmnd->device->lun,
|
|
|
ret, cmd_status, cmd_result);
|
|
|
|
|
|
out:
|
|
@@ -1110,7 +1148,7 @@ out:
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|
|
+lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
|
|
|
{
|
|
|
struct Scsi_Host *shost = cmnd->device->host;
|
|
|
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
|
@@ -1155,13 +1193,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|
|
"%d:0700 Bus Reset on target %d failed\n",
|
|
|
phba->brd_no, i);
|
|
|
err_count++;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (ret != IOCB_TIMEDOUT)
|
|
|
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
|
+
|
|
|
if (err_count == 0)
|
|
|
ret = SUCCESS;
|
|
|
-
|
|
|
- lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
|
+ else
|
|
|
+ ret = FAILED;
|
|
|
|
|
|
/*
|
|
|
* All outstanding txcmplq I/Os should have been aborted by
|
|
@@ -1302,8 +1344,8 @@ struct scsi_host_template lpfc_template = {
|
|
|
.info = lpfc_info,
|
|
|
.queuecommand = lpfc_queuecommand,
|
|
|
.eh_abort_handler = lpfc_abort_handler,
|
|
|
- .eh_device_reset_handler= lpfc_reset_lun_handler,
|
|
|
- .eh_bus_reset_handler = lpfc_reset_bus_handler,
|
|
|
+ .eh_device_reset_handler= lpfc_device_reset_handler,
|
|
|
+ .eh_bus_reset_handler = lpfc_bus_reset_handler,
|
|
|
.slave_alloc = lpfc_slave_alloc,
|
|
|
.slave_configure = lpfc_slave_configure,
|
|
|
.slave_destroy = lpfc_slave_destroy,
|