mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
scsi: lpfc: Convert SCSI I/O completions to SLI-3 and SLI-4 handlers
The current driver implementation uses SLI-4 WQE to iocb conversion before calling the cmpl callback function. Rework the FCP I/O completion path to utilize the SLI-4 WQE. This patch converts the SCSI I/O completion paths from the iocb-centric interfaces to the routines are native for whether I/Os are iocb-based (SLI-3) or WQE-based (SLI-4). Most existing routines were iocb-based, so this creates a lot of SLI-4 specific routines to provide the functionality. Link: https://lore.kernel.org/r/20201115192646.12977-15-james.smart@broadcom.com Co-developed-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <james.smart@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
da255e2e7c
commit
96e209be6e
@ -2891,6 +2891,150 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks for BlockGuard errors detected by
|
||||
* the HBA. In case of errors, the ASC/ASCQ fields in the
|
||||
* sense buffer will be set accordingly, paired with
|
||||
* ILLEGAL_REQUEST to signal to the kernel that the HBA
|
||||
* detected corruption.
|
||||
*
|
||||
* Returns:
|
||||
* 0 - No error found
|
||||
* 1 - BlockGuard error found
|
||||
* -1 - Internal error (bad profile, ...etc)
|
||||
*/
|
||||
static int
|
||||
lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
|
||||
struct lpfc_wcqe_complete *wcqe)
|
||||
{
|
||||
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
|
||||
int ret = 0;
|
||||
u32 status = bf_get(lpfc_wcqe_c_status, wcqe);
|
||||
u32 bghm = 0;
|
||||
u32 bgstat = 0;
|
||||
u64 failing_sector = 0;
|
||||
|
||||
if (status == CQE_STATUS_DI_ERROR) {
|
||||
if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */
|
||||
bgstat |= BGS_GUARD_ERR_MASK;
|
||||
if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */
|
||||
bgstat |= BGS_APPTAG_ERR_MASK;
|
||||
if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */
|
||||
bgstat |= BGS_REFTAG_ERR_MASK;
|
||||
|
||||
/* Check to see if there was any good data before the error */
|
||||
if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
|
||||
bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK;
|
||||
bghm = wcqe->total_data_placed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set ALL the error bits to indicate we don't know what
|
||||
* type of error it is.
|
||||
*/
|
||||
if (!bgstat)
|
||||
bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK |
|
||||
BGS_GUARD_ERR_MASK);
|
||||
}
|
||||
|
||||
if (lpfc_bgs_get_guard_err(bgstat)) {
|
||||
ret = 1;
|
||||
|
||||
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
|
||||
0x10, 0x1);
|
||||
cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 |
|
||||
SAM_STAT_CHECK_CONDITION;
|
||||
phba->bg_guard_err_cnt++;
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
|
||||
"9059 BLKGRD: Guard Tag error in cmd"
|
||||
" 0x%x lba 0x%llx blk cnt 0x%x "
|
||||
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
|
||||
(unsigned long long)scsi_get_lba(cmd),
|
||||
blk_rq_sectors(cmd->request), bgstat, bghm);
|
||||
}
|
||||
|
||||
if (lpfc_bgs_get_reftag_err(bgstat)) {
|
||||
ret = 1;
|
||||
|
||||
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
|
||||
0x10, 0x3);
|
||||
cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 |
|
||||
SAM_STAT_CHECK_CONDITION;
|
||||
|
||||
phba->bg_reftag_err_cnt++;
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
|
||||
"9060 BLKGRD: Ref Tag error in cmd"
|
||||
" 0x%x lba 0x%llx blk cnt 0x%x "
|
||||
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
|
||||
(unsigned long long)scsi_get_lba(cmd),
|
||||
blk_rq_sectors(cmd->request), bgstat, bghm);
|
||||
}
|
||||
|
||||
if (lpfc_bgs_get_apptag_err(bgstat)) {
|
||||
ret = 1;
|
||||
|
||||
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
|
||||
0x10, 0x2);
|
||||
cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 |
|
||||
SAM_STAT_CHECK_CONDITION;
|
||||
|
||||
phba->bg_apptag_err_cnt++;
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
|
||||
"9062 BLKGRD: App Tag error in cmd"
|
||||
" 0x%x lba 0x%llx blk cnt 0x%x "
|
||||
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
|
||||
(unsigned long long)scsi_get_lba(cmd),
|
||||
blk_rq_sectors(cmd->request), bgstat, bghm);
|
||||
}
|
||||
|
||||
if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
|
||||
/*
|
||||
* setup sense data descriptor 0 per SPC-4 as an information
|
||||
* field, and put the failing LBA in it.
|
||||
* This code assumes there was also a guard/app/ref tag error
|
||||
* indication.
|
||||
*/
|
||||
cmd->sense_buffer[7] = 0xc; /* Additional sense length */
|
||||
cmd->sense_buffer[8] = 0; /* Information descriptor type */
|
||||
cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */
|
||||
cmd->sense_buffer[10] = 0x80; /* Validity bit */
|
||||
|
||||
/* bghm is a "on the wire" FC frame based count */
|
||||
switch (scsi_get_prot_op(cmd)) {
|
||||
case SCSI_PROT_READ_INSERT:
|
||||
case SCSI_PROT_WRITE_STRIP:
|
||||
bghm /= cmd->device->sector_size;
|
||||
break;
|
||||
case SCSI_PROT_READ_STRIP:
|
||||
case SCSI_PROT_WRITE_INSERT:
|
||||
case SCSI_PROT_READ_PASS:
|
||||
case SCSI_PROT_WRITE_PASS:
|
||||
bghm /= (cmd->device->sector_size +
|
||||
sizeof(struct scsi_dif_tuple));
|
||||
break;
|
||||
}
|
||||
|
||||
failing_sector = scsi_get_lba(cmd);
|
||||
failing_sector += bghm;
|
||||
|
||||
/* Descriptor Information */
|
||||
put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
/* No error was reported - problem in FW? */
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
|
||||
"9068 BLKGRD: Unknown error in cmd"
|
||||
" 0x%x lba 0x%llx blk cnt 0x%x "
|
||||
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
|
||||
(unsigned long long)scsi_get_lba(cmd),
|
||||
blk_rq_sectors(cmd->request), bgstat, bghm);
|
||||
|
||||
/* Calcuate what type of error it was */
|
||||
lpfc_calc_bg_err(phba, lpfc_cmd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks for BlockGuard errors detected by
|
||||
@ -3570,12 +3714,11 @@ lpfc_scsi_prep_cmnd_buf(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
**/
|
||||
static void
|
||||
lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
|
||||
struct lpfc_io_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) {
|
||||
struct lpfc_io_buf *lpfc_cmd, uint32_t fcpi_parm) {
|
||||
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
|
||||
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
|
||||
uint32_t resp_info = fcprsp->rspStatus2;
|
||||
uint32_t scsi_status = fcprsp->rspStatus3;
|
||||
uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
|
||||
struct lpfc_fast_path_event *fast_path_evt = NULL;
|
||||
struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode;
|
||||
unsigned long flags;
|
||||
@ -3690,13 +3833,11 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
|
||||
**/
|
||||
static void
|
||||
lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
struct lpfc_iocbq *rsp_iocb)
|
||||
uint32_t fcpi_parm)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
|
||||
struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
|
||||
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
|
||||
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;
|
||||
@ -3831,13 +3972,10 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
*/
|
||||
} else if (fcpi_parm) {
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
|
||||
"9029 FCP %s Check Error xri x%x Data: "
|
||||
"9029 FCP %s Check Error Data: "
|
||||
"x%x x%x x%x x%x x%x\n",
|
||||
((cmnd->sc_data_direction == DMA_FROM_DEVICE) ?
|
||||
"Read" : "Write"),
|
||||
((phba->sli_rev == LPFC_SLI_REV4) ?
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag :
|
||||
rsp_iocb->iocb.ulpContext),
|
||||
fcpDl, be32_to_cpu(fcprsp->rspResId),
|
||||
fcpi_parm, cmnd->cmnd[0], scsi_status);
|
||||
|
||||
@ -3864,7 +4002,333 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
|
||||
out:
|
||||
cmnd->result = host_status << 16 | scsi_status;
|
||||
lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, rsp_iocb);
|
||||
lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, fcpi_parm);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO
|
||||
* @phba: The hba for which this call is being executed.
|
||||
* @pwqeIn: The command WQE for the scsi cmnd.
|
||||
* @pwqeOut: The response WQE for the scsi cmnd.
|
||||
*
|
||||
* This routine assigns scsi command result by looking into response WQE
|
||||
* status field appropriately. This routine handles QUEUE FULL condition as
|
||||
* well by ramping down device queue depth.
|
||||
**/
|
||||
static void
|
||||
lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
|
||||
struct lpfc_wcqe_complete *wcqe)
|
||||
{
|
||||
struct lpfc_io_buf *lpfc_cmd =
|
||||
(struct lpfc_io_buf *)pwqeIn->context1;
|
||||
struct lpfc_vport *vport = pwqeIn->vport;
|
||||
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
|
||||
struct lpfc_nodelist *ndlp = rdata->pnode;
|
||||
struct scsi_cmnd *cmd;
|
||||
unsigned long flags;
|
||||
struct lpfc_fast_path_event *fast_path_evt;
|
||||
struct Scsi_Host *shost;
|
||||
u32 logit = LOG_FCP;
|
||||
u32 status, idx;
|
||||
unsigned long iflags = 0;
|
||||
|
||||
/* Sanity check on return of outstanding command */
|
||||
if (!lpfc_cmd) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"9032 Null lpfc_cmd pointer. No "
|
||||
"release, skip completion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
||||
/* TOREMOVE - currently this flag is checked during
|
||||
* the release of lpfc_iocbq. Remove once we move
|
||||
* to lpfc_wqe_job construct.
|
||||
*
|
||||
* This needs to be done outside buf_lock
|
||||
*/
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY;
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
}
|
||||
|
||||
/* Guard against abort handler being called at same time */
|
||||
spin_lock(&lpfc_cmd->buf_lock);
|
||||
|
||||
/* Sanity check on return of outstanding command */
|
||||
cmd = lpfc_cmd->pCmd;
|
||||
if (!cmd || !phba) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"9042 I/O completion: Not an active IO\n");
|
||||
spin_unlock(&lpfc_cmd->buf_lock);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
return;
|
||||
}
|
||||
idx = lpfc_cmd->cur_iocbq.hba_wqidx;
|
||||
if (phba->sli4_hba.hdwq)
|
||||
phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
|
||||
this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
|
||||
#endif
|
||||
shost = cmd->device->host;
|
||||
|
||||
status = bf_get(lpfc_wcqe_c_status, wcqe);
|
||||
lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK);
|
||||
lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
|
||||
|
||||
lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
|
||||
if (bf_get(lpfc_wcqe_c_xb, wcqe))
|
||||
lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
if (lpfc_cmd->prot_data_type) {
|
||||
struct scsi_dif_tuple *src = NULL;
|
||||
|
||||
src = (struct scsi_dif_tuple *)lpfc_cmd->prot_data_segment;
|
||||
/*
|
||||
* Used to restore any changes to protection
|
||||
* data for error injection.
|
||||
*/
|
||||
switch (lpfc_cmd->prot_data_type) {
|
||||
case LPFC_INJERR_REFTAG:
|
||||
src->ref_tag =
|
||||
lpfc_cmd->prot_data;
|
||||
break;
|
||||
case LPFC_INJERR_APPTAG:
|
||||
src->app_tag =
|
||||
(uint16_t)lpfc_cmd->prot_data;
|
||||
break;
|
||||
case LPFC_INJERR_GUARD:
|
||||
src->guard_tag =
|
||||
(uint16_t)lpfc_cmd->prot_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lpfc_cmd->prot_data = 0;
|
||||
lpfc_cmd->prot_data_type = 0;
|
||||
lpfc_cmd->prot_data_segment = NULL;
|
||||
}
|
||||
#endif
|
||||
if (unlikely(lpfc_cmd->status)) {
|
||||
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
|
||||
(lpfc_cmd->result & IOERR_DRVR_MASK))
|
||||
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
||||
else if (lpfc_cmd->status >= IOSTAT_CNT)
|
||||
lpfc_cmd->status = IOSTAT_DEFAULT;
|
||||
if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR &&
|
||||
!lpfc_cmd->fcp_rsp->rspStatus3 &&
|
||||
(lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) &&
|
||||
!(vport->cfg_log_verbose & LOG_FCP_UNDER))
|
||||
logit = 0;
|
||||
else
|
||||
logit = LOG_FCP | LOG_FCP_UNDER;
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, logit,
|
||||
"9034 FCP cmd x%x failed <%d/%lld> "
|
||||
"status: x%x result: x%x "
|
||||
"sid: x%x did: x%x oxid: x%x "
|
||||
"Data: x%x x%x x%x\n",
|
||||
cmd->cmnd[0],
|
||||
cmd->device ? cmd->device->id : 0xffff,
|
||||
cmd->device ? cmd->device->lun : 0xffff,
|
||||
lpfc_cmd->status, lpfc_cmd->result,
|
||||
vport->fc_myDID,
|
||||
(ndlp) ? ndlp->nlp_DID : 0,
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag,
|
||||
wcqe->parameter, wcqe->total_data_placed,
|
||||
lpfc_cmd->cur_iocbq.iotag);
|
||||
}
|
||||
|
||||
switch (lpfc_cmd->status) {
|
||||
case IOSTAT_SUCCESS:
|
||||
cmd->result = DID_OK << 16;
|
||||
break;
|
||||
case IOSTAT_FCP_RSP_ERROR:
|
||||
lpfc_handle_fcp_err(vport, lpfc_cmd,
|
||||
pwqeIn->wqe.fcp_iread.total_xfer_len -
|
||||
wcqe->total_data_placed);
|
||||
break;
|
||||
case IOSTAT_NPORT_BSY:
|
||||
case IOSTAT_FABRIC_BSY:
|
||||
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
|
||||
fast_path_evt = lpfc_alloc_fast_evt(phba);
|
||||
if (!fast_path_evt)
|
||||
break;
|
||||
fast_path_evt->un.fabric_evt.event_type =
|
||||
FC_REG_FABRIC_EVENT;
|
||||
fast_path_evt->un.fabric_evt.subcategory =
|
||||
(lpfc_cmd->status == IOSTAT_NPORT_BSY) ?
|
||||
LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY;
|
||||
if (ndlp) {
|
||||
memcpy(&fast_path_evt->un.fabric_evt.wwpn,
|
||||
&ndlp->nlp_portname,
|
||||
sizeof(struct lpfc_name));
|
||||
memcpy(&fast_path_evt->un.fabric_evt.wwnn,
|
||||
&ndlp->nlp_nodename,
|
||||
sizeof(struct lpfc_name));
|
||||
}
|
||||
fast_path_evt->vport = vport;
|
||||
fast_path_evt->work_evt.evt =
|
||||
LPFC_EVT_FASTPATH_MGMT_EVT;
|
||||
spin_lock_irqsave(&phba->hbalock, flags);
|
||||
list_add_tail(&fast_path_evt->work_evt.evt_listp,
|
||||
&phba->work_list);
|
||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||
lpfc_worker_wake_up(phba);
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, logit,
|
||||
"9035 Fabric/Node busy FCP cmd x%x failed"
|
||||
" <%d/%lld> "
|
||||
"status: x%x result: x%x "
|
||||
"sid: x%x did: x%x oxid: x%x "
|
||||
"Data: x%x x%x x%x\n",
|
||||
cmd->cmnd[0],
|
||||
cmd->device ? cmd->device->id : 0xffff,
|
||||
cmd->device ? cmd->device->lun : 0xffff,
|
||||
lpfc_cmd->status, lpfc_cmd->result,
|
||||
vport->fc_myDID,
|
||||
(ndlp) ? ndlp->nlp_DID : 0,
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag,
|
||||
wcqe->parameter,
|
||||
wcqe->total_data_placed,
|
||||
lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
|
||||
break;
|
||||
case IOSTAT_REMOTE_STOP:
|
||||
if (ndlp) {
|
||||
/* This I/O was aborted by the target, we don't
|
||||
* know the rxid and because we did not send the
|
||||
* ABTS we cannot generate and RRQ.
|
||||
*/
|
||||
lpfc_set_rrq_active(phba, ndlp,
|
||||
lpfc_cmd->cur_iocbq.sli4_lxritag,
|
||||
0, 0);
|
||||
}
|
||||
fallthrough;
|
||||
case IOSTAT_LOCAL_REJECT:
|
||||
if (lpfc_cmd->result & IOERR_DRVR_MASK)
|
||||
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
||||
if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
|
||||
lpfc_cmd->result ==
|
||||
IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR ||
|
||||
lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR ||
|
||||
lpfc_cmd->result ==
|
||||
IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) {
|
||||
cmd->result = DID_NO_CONNECT << 16;
|
||||
break;
|
||||
}
|
||||
if (lpfc_cmd->result == IOERR_INVALID_RPI ||
|
||||
lpfc_cmd->result == IOERR_NO_RESOURCES ||
|
||||
lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
|
||||
lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
|
||||
cmd->result = DID_REQUEUE << 16;
|
||||
break;
|
||||
}
|
||||
if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
|
||||
lpfc_cmd->result == IOERR_TX_DMA_FAILED) &&
|
||||
status == CQE_STATUS_DI_ERROR) {
|
||||
if (scsi_get_prot_op(cmd) !=
|
||||
SCSI_PROT_NORMAL) {
|
||||
/*
|
||||
* This is a response for a BG enabled
|
||||
* cmd. Parse BG error
|
||||
*/
|
||||
lpfc_sli4_parse_bg_err(phba, lpfc_cmd,
|
||||
wcqe);
|
||||
break;
|
||||
}
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG,
|
||||
"9040 non-zero BGSTAT on unprotected cmd\n");
|
||||
}
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, logit,
|
||||
"9036 Local Reject FCP cmd x%x failed"
|
||||
" <%d/%lld> "
|
||||
"status: x%x result: x%x "
|
||||
"sid: x%x did: x%x oxid: x%x "
|
||||
"Data: x%x x%x x%x\n",
|
||||
cmd->cmnd[0],
|
||||
cmd->device ? cmd->device->id : 0xffff,
|
||||
cmd->device ? cmd->device->lun : 0xffff,
|
||||
lpfc_cmd->status, lpfc_cmd->result,
|
||||
vport->fc_myDID,
|
||||
(ndlp) ? ndlp->nlp_DID : 0,
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag,
|
||||
wcqe->parameter,
|
||||
wcqe->total_data_placed,
|
||||
lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
|
||||
fallthrough;
|
||||
default:
|
||||
if (lpfc_cmd->status >= IOSTAT_CNT)
|
||||
lpfc_cmd->status = IOSTAT_DEFAULT;
|
||||
cmd->result = DID_ERROR << 16;
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
|
||||
"9037 FCP Completion Error: xri %x "
|
||||
"status x%x result x%x [x%x] "
|
||||
"placed x%x\n",
|
||||
lpfc_cmd->cur_iocbq.sli4_xritag,
|
||||
lpfc_cmd->status, lpfc_cmd->result,
|
||||
wcqe->parameter,
|
||||
wcqe->total_data_placed);
|
||||
}
|
||||
if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) {
|
||||
u32 *lp = (u32 *)cmd->sense_buffer;
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
|
||||
"9039 Iodone <%d/%llu> cmd x%p, error "
|
||||
"x%x SNS x%x x%x Data: x%x x%x\n",
|
||||
cmd->device->id, cmd->device->lun, cmd,
|
||||
cmd->result, *lp, *(lp + 3), cmd->retries,
|
||||
scsi_get_resid(cmd));
|
||||
}
|
||||
|
||||
lpfc_update_stats(vport, lpfc_cmd);
|
||||
|
||||
if (vport->cfg_max_scsicmpl_time &&
|
||||
time_after(jiffies, lpfc_cmd->start_time +
|
||||
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (ndlp) {
|
||||
if (ndlp->cmd_qdepth >
|
||||
atomic_read(&ndlp->cmd_pending) &&
|
||||
(atomic_read(&ndlp->cmd_pending) >
|
||||
LPFC_MIN_TGT_QDEPTH) &&
|
||||
(cmd->cmnd[0] == READ_10 ||
|
||||
cmd->cmnd[0] == WRITE_10))
|
||||
ndlp->cmd_qdepth =
|
||||
atomic_read(&ndlp->cmd_pending);
|
||||
|
||||
ndlp->last_change_time = jiffies;
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
if (lpfc_cmd->ts_cmd_start) {
|
||||
lpfc_cmd->ts_isr_cmpl = lpfc_cmd->cur_iocbq.isr_timestamp;
|
||||
lpfc_cmd->ts_data_io = ktime_get_ns();
|
||||
phba->ktime_last_cmd = lpfc_cmd->ts_data_io;
|
||||
lpfc_io_ktime(phba, lpfc_cmd);
|
||||
}
|
||||
#endif
|
||||
lpfc_cmd->pCmd = NULL;
|
||||
spin_unlock(&lpfc_cmd->buf_lock);
|
||||
|
||||
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
|
||||
cmd->scsi_done(cmd);
|
||||
|
||||
/*
|
||||
* If there is an abort thread waiting for command completion
|
||||
* wake up the thread.
|
||||
*/
|
||||
spin_lock(&lpfc_cmd->buf_lock);
|
||||
lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED;
|
||||
if (lpfc_cmd->waitq)
|
||||
wake_up(lpfc_cmd->waitq);
|
||||
spin_unlock(&lpfc_cmd->buf_lock);
|
||||
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3987,7 +4451,8 @@ 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(vport, lpfc_cmd, pIocbOut);
|
||||
lpfc_handle_fcp_err(vport, lpfc_cmd,
|
||||
pIocbOut->iocb.un.fcpi.fcpi_parm);
|
||||
break;
|
||||
case IOSTAT_NPORT_BSY:
|
||||
case IOSTAT_FABRIC_BSY:
|
||||
@ -4314,8 +4779,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
|
||||
pwqeq->vport = vport;
|
||||
pwqeq->context1 = lpfc_cmd;
|
||||
pwqeq->hba_wqidx = lpfc_cmd->hdwq_no;
|
||||
if (!pwqeq->iocb_cmpl)
|
||||
pwqeq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
|
||||
pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14339,7 +14339,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
||||
#endif
|
||||
if (cmdiocbq->iocb_cmpl == NULL) {
|
||||
if (cmdiocbq->wqe_cmpl) {
|
||||
if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
|
||||
/* For FCP the flag is cleared in wqe_cmpl */
|
||||
if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) &&
|
||||
cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED;
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
@ -14356,6 +14358,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only SLI4 non-IO commands stil use IOCB */
|
||||
/* Fake the irspiocb and copy necessary response information */
|
||||
lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user