Commit 3512ac09 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: SLI path split: Refactor SCSI paths

This patch refactors the SCSI paths to use SLI-4 as the primary interface.

 - Conversion away from using SLI-3 iocb structures to set/access fields in
   common routines. Use the new generic get/set routines that were added.
   This move changes code from indirect structure references to using local
   variables with the generic routines.

 - Refactor routines when setting non-generic fields, to have both SLI3 and
   SLI4 specific sections. This replaces the set-as-SLI3 then translate to
   SLI4 behavior of the past.

Link: https://lore.kernel.org/r/20220225022308.16486-14-jsmart2021@gmail.comCo-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 61910d6a
...@@ -916,6 +916,10 @@ struct lpfc_hba { ...@@ -916,6 +916,10 @@ struct lpfc_hba {
(struct lpfc_vport *vport, (struct lpfc_vport *vport,
struct lpfc_io_buf *lpfc_cmd, struct lpfc_io_buf *lpfc_cmd,
uint8_t tmo); uint8_t tmo);
int (*lpfc_scsi_prep_task_mgmt_cmd)
(struct lpfc_vport *vport,
struct lpfc_io_buf *lpfc_cmd,
u64 lun, u8 task_mgmt_cmd);
/* IOCB interface function jump table entries */ /* IOCB interface function jump table entries */
int (*__lpfc_sli_issue_iocb) int (*__lpfc_sli_issue_iocb)
......
...@@ -2942,25 +2942,38 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) ...@@ -2942,25 +2942,38 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
* -1 - Internal error (bad profile, ...etc) * -1 - Internal error (bad profile, ...etc)
*/ */
static int static int
lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
struct lpfc_wcqe_complete *wcqe) struct lpfc_iocbq *pIocbOut)
{ {
struct scsi_cmnd *cmd = lpfc_cmd->pCmd; struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
struct sli3_bg_fields *bgf;
int ret = 0; int ret = 0;
u32 status = bf_get(lpfc_wcqe_c_status, wcqe); struct lpfc_wcqe_complete *wcqe;
u32 status;
u32 bghm = 0; u32 bghm = 0;
u32 bgstat = 0; u32 bgstat = 0;
u64 failing_sector = 0; u64 failing_sector = 0;
if (phba->sli_rev == LPFC_SLI_REV4) {
wcqe = &pIocbOut->wcqe_cmpl;
status = bf_get(lpfc_wcqe_c_status, wcqe);
if (status == CQE_STATUS_DI_ERROR) { if (status == CQE_STATUS_DI_ERROR) {
if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ /* Guard Check failed */
if (bf_get(lpfc_wcqe_c_bg_ge, wcqe))
bgstat |= BGS_GUARD_ERR_MASK; bgstat |= BGS_GUARD_ERR_MASK;
if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */
/* AppTag Check failed */
if (bf_get(lpfc_wcqe_c_bg_ae, wcqe))
bgstat |= BGS_APPTAG_ERR_MASK; bgstat |= BGS_APPTAG_ERR_MASK;
if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */
/* RefTag Check failed */
if (bf_get(lpfc_wcqe_c_bg_re, wcqe))
bgstat |= BGS_REFTAG_ERR_MASK; bgstat |= BGS_REFTAG_ERR_MASK;
/* Check to see if there was any good data before the error */ /* Check to see if there was any good data before the
* error
*/
if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK;
bghm = wcqe->total_data_placed; bghm = wcqe->total_data_placed;
...@@ -2971,125 +2984,16 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, ...@@ -2971,125 +2984,16 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
* type of error it is. * type of error it is.
*/ */
if (!bgstat) if (!bgstat)
bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | bgstat |= (BGS_REFTAG_ERR_MASK |
BGS_APPTAG_ERR_MASK |
BGS_GUARD_ERR_MASK); BGS_GUARD_ERR_MASK);
} }
if (lpfc_bgs_get_guard_err(bgstat)) { } else {
ret = 1; bgf = &pIocbOut->iocb.unsli3.sli3_bg;
bghm = bgf->bghm;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); bgstat = bgf->bgstat;
set_host_byte(cmd, DID_ABORT);
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),
scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_reftag_err(bgstat)) {
ret = 1;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
set_host_byte(cmd, DID_ABORT);
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),
scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_apptag_err(bgstat)) {
ret = 1;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
set_host_byte(cmd, DID_ABORT);
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),
scsi_logical_block_count(cmd), 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),
scsi_logical_block_count(cmd), bgstat, bghm);
/* Calculate what type of error it was */
lpfc_calc_bg_err(phba, lpfc_cmd);
} }
return ret;
}
/*
* 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_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
struct lpfc_iocbq *pIocbOut)
{
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg;
int ret = 0;
uint32_t bghm = bgf->bghm;
uint32_t bgstat = bgf->bgstat;
uint64_t failing_sector = 0;
if (lpfc_bgs_get_invalid_prof(bgstat)) { if (lpfc_bgs_get_invalid_prof(bgstat)) {
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
...@@ -3117,7 +3021,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, ...@@ -3117,7 +3021,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
if (lpfc_bgs_get_guard_err(bgstat)) { if (lpfc_bgs_get_guard_err(bgstat)) {
ret = 1; ret = 1;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
set_host_byte(cmd, DID_ABORT); set_host_byte(cmd, DID_ABORT);
phba->bg_guard_err_cnt++; phba->bg_guard_err_cnt++;
...@@ -3131,10 +3034,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, ...@@ -3131,10 +3034,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
if (lpfc_bgs_get_reftag_err(bgstat)) { if (lpfc_bgs_get_reftag_err(bgstat)) {
ret = 1; ret = 1;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
set_host_byte(cmd, DID_ABORT); set_host_byte(cmd, DID_ABORT);
phba->bg_reftag_err_cnt++; phba->bg_reftag_err_cnt++;
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
"9056 BLKGRD: Ref Tag error in cmd " "9056 BLKGRD: Ref Tag error in cmd "
...@@ -3146,10 +3047,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, ...@@ -3146,10 +3047,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
if (lpfc_bgs_get_apptag_err(bgstat)) { if (lpfc_bgs_get_apptag_err(bgstat)) {
ret = 1; ret = 1;
scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
set_host_byte(cmd, DID_ABORT); set_host_byte(cmd, DID_ABORT);
phba->bg_apptag_err_cnt++; phba->bg_apptag_err_cnt++;
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
"9061 BLKGRD: App Tag error in cmd " "9061 BLKGRD: App Tag error in cmd "
...@@ -4195,7 +4094,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, ...@@ -4195,7 +4094,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
struct Scsi_Host *shost; struct Scsi_Host *shost;
u32 logit = LOG_FCP; u32 logit = LOG_FCP;
u32 status, idx; u32 status, idx;
unsigned long iflags = 0;
u32 lat; u32 lat;
u8 wait_xb_clr = 0; u8 wait_xb_clr = 0;
...@@ -4210,30 +4108,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, ...@@ -4210,30 +4108,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
rdata = lpfc_cmd->rdata; rdata = lpfc_cmd->rdata;
ndlp = rdata->pnode; ndlp = rdata->pnode;
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.cmd_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 */ /* Sanity check on return of outstanding command */
cmd = lpfc_cmd->pCmd; cmd = lpfc_cmd->pCmd;
if (!cmd) { if (!cmd) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"9042 I/O completion: Not an active IO\n"); "9042 I/O completion: Not an active IO\n");
spin_unlock(&lpfc_cmd->buf_lock);
lpfc_release_scsi_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd);
return; return;
} }
/* Guard against abort handler being called at same time */
spin_lock(&lpfc_cmd->buf_lock);
idx = lpfc_cmd->cur_iocbq.hba_wqidx; idx = lpfc_cmd->cur_iocbq.hba_wqidx;
if (phba->sli4_hba.hdwq) if (phba->sli4_hba.hdwq)
phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
...@@ -4408,12 +4292,14 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, ...@@ -4408,12 +4292,14 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
* This is a response for a BG enabled * This is a response for a BG enabled
* cmd. Parse BG error * cmd. Parse BG error
*/ */
lpfc_sli4_parse_bg_err(phba, lpfc_cmd, lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut);
wcqe);
break; break;
} else {
lpfc_printf_vlog(vport, KERN_WARNING,
LOG_BG,
"9040 non-zero BGSTAT "
"on unprotected cmd\n");
} }
lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG,
"9040 non-zero BGSTAT on unprotected cmd\n");
} }
lpfc_printf_vlog(vport, KERN_WARNING, logit, lpfc_printf_vlog(vport, KERN_WARNING, logit,
"9036 Local Reject FCP cmd x%x failed" "9036 Local Reject FCP cmd x%x failed"
...@@ -5019,7 +4905,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, ...@@ -5019,7 +4905,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
} }
/** /**
* lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit
* @vport: The virtual port for which this call is being executed. * @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_io_buf data structure. * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
* @lun: Logical unit number. * @lun: Logical unit number.
...@@ -5033,10 +4919,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, ...@@ -5033,10 +4919,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
* 1 - Success * 1 - Success
**/ **/
static int static int
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
struct lpfc_io_buf *lpfc_cmd, struct lpfc_io_buf *lpfc_cmd,
uint64_t lun, u64 lun, u8 task_mgmt_cmd)
uint8_t task_mgmt_cmd)
{ {
struct lpfc_iocbq *piocbq; struct lpfc_iocbq *piocbq;
IOCB_t *piocb; IOCB_t *piocb;
...@@ -5057,15 +4942,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, ...@@ -5057,15 +4942,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
int_to_scsilun(lun, &fcp_cmnd->fcp_lun); int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl2 = task_mgmt_cmd; fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
if (vport->phba->sli_rev == 3 && if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED))
!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED))
lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd);
piocb->ulpCommand = CMD_FCP_ICMND64_CR; piocb->ulpCommand = CMD_FCP_ICMND64_CR;
piocb->ulpContext = ndlp->nlp_rpi; piocb->ulpContext = ndlp->nlp_rpi;
if (vport->phba->sli_rev == LPFC_SLI_REV4) {
piocb->ulpContext =
vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
}
piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0; piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0;
piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f);
piocb->ulpPU = 0; piocb->ulpPU = 0;
...@@ -5081,7 +4961,78 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, ...@@ -5081,7 +4961,78 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
} else } else
piocb->ulpTimeout = lpfc_cmd->timeout; piocb->ulpTimeout = lpfc_cmd->timeout;
if (vport->phba->sli_rev == LPFC_SLI_REV4) return 1;
}
/**
* lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_io_buf data structure.
* @lun: Logical unit number.
* @task_mgmt_cmd: SCSI task management command.
*
* This routine creates FCP information unit corresponding to @task_mgmt_cmd
* for device with SLI-4 interface spec.
*
* Return codes:
* 0 - Error
* 1 - Success
**/
static int
lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport,
struct lpfc_io_buf *lpfc_cmd,
u64 lun, u8 task_mgmt_cmd)
{
struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
union lpfc_wqe128 *wqe = &pwqeq->wqe;
struct fcp_cmnd *fcp_cmnd;
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE)
return 0;
pwqeq->vport = vport;
/* Initialize 64 bytes only */
memset(wqe, 0, sizeof(union lpfc_wqe128));
/* From the icmnd template, initialize words 4 - 11 */
memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
sizeof(uint32_t) * 8);
fcp_cmnd = lpfc_cmd->fcp_cmnd;
/* Clear out any old data in the FCP command area */
memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl3 = 0;
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
bf_set(payload_offset_len, &wqe->fcp_icmd,
sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
bf_set(cmd_buff_len, &wqe->fcp_icmd, 0);
bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, /* ulpContext */
vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com,
((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0));
bf_set(wqe_class, &wqe->fcp_icmd.wqe_com,
(ndlp->nlp_fcp_info & 0x0f));
/* ulpTimeout is only one byte */
if (lpfc_cmd->timeout > 0xff) {
/*
* Do not timeout the command at the firmware level.
* The driver will provide the timeout mechanism.
*/
bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0);
} else {
bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout);
}
lpfc_prep_embed_io(vport->phba, lpfc_cmd);
bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag);
wqe->generic.wqe_com.abort_tag = pwqeq->iotag;
bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
return 1; return 1;
...@@ -5109,6 +5060,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) ...@@ -5109,6 +5060,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3;
phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3;
phba->lpfc_scsi_prep_task_mgmt_cmd =
lpfc_scsi_prep_task_mgmt_cmd_s3;
break; break;
case LPFC_PCI_DEV_OC: case LPFC_PCI_DEV_OC:
phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
...@@ -5116,6 +5069,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) ...@@ -5116,6 +5069,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4;
phba->lpfc_scsi_prep_task_mgmt_cmd =
lpfc_scsi_prep_task_mgmt_cmd_s4;
break; break;
default: default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
...@@ -5594,6 +5549,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5594,6 +5549,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
{ {
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cur_iocbq = NULL;
struct lpfc_rport_data *rdata; struct lpfc_rport_data *rdata;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
struct lpfc_io_buf *lpfc_cmd; struct lpfc_io_buf *lpfc_cmd;
...@@ -5687,6 +5643,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5687,6 +5643,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
} }
lpfc_cmd->rx_cmd_start = start; lpfc_cmd->rx_cmd_start = start;
cur_iocbq = &lpfc_cmd->cur_iocbq;
/* /*
* Store the midlayer's command structure for the completion phase * Store the midlayer's command structure for the completion phase
* and complete the command initialization. * and complete the command initialization.
...@@ -5694,7 +5651,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5694,7 +5651,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
lpfc_cmd->pCmd = cmnd; lpfc_cmd->pCmd = cmnd;
lpfc_cmd->rdata = rdata; lpfc_cmd->rdata = rdata;
lpfc_cmd->ndlp = ndlp; lpfc_cmd->ndlp = ndlp;
lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; cur_iocbq->cmd_cmpl = NULL;
cmnd->host_scribble = (unsigned char *)lpfc_cmd; cmnd->host_scribble = (unsigned char *)lpfc_cmd;
err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
...@@ -5736,7 +5693,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5736,7 +5693,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
goto out_host_busy_free_buf; goto out_host_busy_free_buf;
} }
/* check the necessary and sufficient condition to support VMID */ /* check the necessary and sufficient condition to support VMID */
if (lpfc_is_vmid_enabled(phba) && if (lpfc_is_vmid_enabled(phba) &&
(ndlp->vmid_support || (ndlp->vmid_support ||
...@@ -5749,20 +5705,19 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5749,20 +5705,19 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
if (uuid) { if (uuid) {
err = lpfc_vmid_get_appid(vport, uuid, cmnd, err = lpfc_vmid_get_appid(vport, uuid, cmnd,
(union lpfc_vmid_io_tag *) (union lpfc_vmid_io_tag *)
&lpfc_cmd->cur_iocbq.vmid_tag); &cur_iocbq->vmid_tag);
if (!err) if (!err)
lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID; cur_iocbq->cmd_flag |= LPFC_IO_VMID;
} }
} }
atomic_inc(&ndlp->cmd_pending); atomic_inc(&ndlp->cmd_pending);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
#endif #endif
/* Issue I/O to adapter */ /* Issue I/O to adapter */
err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq,
&lpfc_cmd->cur_iocbq,
SLI_IOCB_RET_IOCB); SLI_IOCB_RET_IOCB);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (start) { if (start) {
...@@ -5775,7 +5730,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5775,7 +5730,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
#endif #endif
if (err) { if (err) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
"3376 FCP could not issue IOCB err %x " "3376 FCP could not issue iocb err %x "
"FCP cmd x%x <%d/%llu> " "FCP cmd x%x <%d/%llu> "
"sid: x%x did: x%x oxid: x%x " "sid: x%x did: x%x oxid: x%x "
"Data: x%x x%x x%x x%x\n", "Data: x%x x%x x%x x%x\n",
...@@ -5784,15 +5739,15 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) ...@@ -5784,15 +5739,15 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
cmnd->device ? cmnd->device->lun : (u64)-1, cmnd->device ? cmnd->device->lun : (u64)-1,
vport->fc_myDID, ndlp->nlp_DID, vport->fc_myDID, ndlp->nlp_DID,
phba->sli_rev == LPFC_SLI_REV4 ? phba->sli_rev == LPFC_SLI_REV4 ?
lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, cur_iocbq->sli4_xritag : 0xffff,
phba->sli_rev == LPFC_SLI_REV4 ? phba->sli_rev == LPFC_SLI_REV4 ?
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] :
lpfc_cmd->cur_iocbq.iocb.ulpContext, cur_iocbq->iocb.ulpContext,
lpfc_cmd->cur_iocbq.iotag, cur_iocbq->iotag,
phba->sli_rev == LPFC_SLI_REV4 ? phba->sli_rev == LPFC_SLI_REV4 ?
bf_get(wqe_tmo, bf_get(wqe_tmo,
&lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) : &cur_iocbq->wqe.generic.wqe_com) :
lpfc_cmd->cur_iocbq.iocb.ulpTimeout, cur_iocbq->iocb.ulpTimeout,
(uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
goto out_host_busy_free_buf; goto out_host_busy_free_buf;
...@@ -6174,7 +6129,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, ...@@ -6174,7 +6129,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
return FAILED; return FAILED;
pnode = rdata->pnode; pnode = rdata->pnode;
lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL); lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL);
if (lpfc_cmd == NULL) if (lpfc_cmd == NULL)
return FAILED; return FAILED;
lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
...@@ -6182,7 +6137,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, ...@@ -6182,7 +6137,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
lpfc_cmd->pCmd = NULL; lpfc_cmd->pCmd = NULL;
lpfc_cmd->ndlp = pnode; lpfc_cmd->ndlp = pnode;
status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
task_mgmt_cmd); task_mgmt_cmd);
if (!status) { if (!status) {
lpfc_release_scsi_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd);
...@@ -6196,6 +6151,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, ...@@ -6196,6 +6151,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
return FAILED; return FAILED;
} }
iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl; iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl;
iocbq->vport = vport;
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
"0702 Issue %s to TGT %d LUN %llu " "0702 Issue %s to TGT %d LUN %llu "
...@@ -6207,26 +6163,28 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, ...@@ -6207,26 +6163,28 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
iocbq, iocbqrsp, lpfc_cmd->timeout); iocbq, iocbqrsp, lpfc_cmd->timeout);
if ((status != IOCB_SUCCESS) || if ((status != IOCB_SUCCESS) ||
(iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) {
if (status != IOCB_SUCCESS || if (status != IOCB_SUCCESS ||
iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR)
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0727 TMF %s to TGT %d LUN %llu " "0727 TMF %s to TGT %d LUN %llu "
"failed (%d, %d) cmd_flag x%x\n", "failed (%d, %d) cmd_flag x%x\n",
lpfc_taskmgmt_name(task_mgmt_cmd), lpfc_taskmgmt_name(task_mgmt_cmd),
tgt_id, lun_id, tgt_id, lun_id,
iocbqrsp->iocb.ulpStatus, get_job_ulpstatus(phba, iocbqrsp),
iocbqrsp->iocb.un.ulpWord[4], get_job_word4(phba, iocbqrsp),
iocbq->cmd_flag); iocbq->cmd_flag);
/* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
if (status == IOCB_SUCCESS) { if (status == IOCB_SUCCESS) {
if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) if (get_job_ulpstatus(phba, iocbqrsp) ==
IOSTAT_FCP_RSP_ERROR)
/* Something in the FCP_RSP was invalid. /* Something in the FCP_RSP was invalid.
* Check conditions */ * Check conditions */
ret = lpfc_check_fcp_rsp(vport, lpfc_cmd); ret = lpfc_check_fcp_rsp(vport, lpfc_cmd);
else else
ret = FAILED; ret = FAILED;
} else if (status == IOCB_TIMEDOUT) { } else if ((status == IOCB_TIMEDOUT) ||
(status == IOCB_ABORTED)) {
ret = TIMEOUT_ERROR; ret = TIMEOUT_ERROR;
} else { } else {
ret = FAILED; ret = FAILED;
...@@ -6236,7 +6194,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport, ...@@ -6236,7 +6194,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
lpfc_sli_release_iocbq(phba, iocbqrsp); lpfc_sli_release_iocbq(phba, iocbqrsp);
if (ret != TIMEOUT_ERROR) if (status != IOCB_TIMEDOUT)
lpfc_release_scsi_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd);
return ret; return ret;
......
...@@ -12648,6 +12648,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, ...@@ -12648,6 +12648,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
wait_queue_head_t *pdone_q; wait_queue_head_t *pdone_q;
unsigned long iflags; unsigned long iflags;
struct lpfc_io_buf *lpfc_cmd; struct lpfc_io_buf *lpfc_cmd;
size_t offset = offsetof(struct lpfc_iocbq, wqe);
spin_lock_irqsave(&phba->hbalock, iflags); spin_lock_irqsave(&phba->hbalock, iflags);
if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) { if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) {
...@@ -12668,10 +12669,11 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, ...@@ -12668,10 +12669,11 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
return; return;
} }
/* Copy the contents of the local rspiocb into the caller's buffer. */
cmdiocbq->cmd_flag |= LPFC_IO_WAKE; cmdiocbq->cmd_flag |= LPFC_IO_WAKE;
if (cmdiocbq->context2 && rspiocbq) if (cmdiocbq->context2 && rspiocbq)
memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, memcpy((char *)cmdiocbq->context2 + offset,
&rspiocbq->iocb, sizeof(IOCB_t)); (char *)rspiocbq + offset, sizeof(*rspiocbq) - offset);
/* Set the exchange busy flag for task management commands */ /* Set the exchange busy flag for task management commands */
if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment