[SCSI] lpfc 8.3.8: BugFixes: SLI relates changes
Fix hardware/SLI relates issues: - Handle XB bit so that ELS XRIs are not prematurely released. - Handle XB bit so that FCP XRIs are not prematurely released. - Define new security SLI Commands. - Remove unused security SLI commands - Skip receive data size parameter check on received FLOGI. - Added LPFC_USE_FCPWQIDX flag to iocb to force SLI layer to submit abort WQE on same WQ as the command WQE. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Родитель
2cec802980
Коммит
341af10239
|
@ -99,7 +99,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
|
|||
|
||||
void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
|
||||
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
|
||||
struct serv_parm *, uint32_t);
|
||||
struct serv_parm *, uint32_t, int);
|
||||
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
void lpfc_more_plogi(struct lpfc_vport *);
|
||||
void lpfc_more_adisc(struct lpfc_vport *);
|
||||
|
|
|
@ -4385,7 +4385,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|||
|
||||
did = Fabric_DID;
|
||||
|
||||
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
|
||||
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
|
||||
/* For a FLOGI we accept, then if our portname is greater
|
||||
* then the remote portname we initiate Nport login.
|
||||
*/
|
||||
|
|
|
@ -1465,17 +1465,13 @@ typedef struct { /* FireFly BIU registers */
|
|||
#define CMD_IOCB_LOGENTRY_CN 0x94
|
||||
#define CMD_IOCB_LOGENTRY_ASYNC_CN 0x96
|
||||
|
||||
/* Unhandled Data Security SLI Commands */
|
||||
#define DSSCMD_IWRITE64_CR 0xD8
|
||||
#define DSSCMD_IWRITE64_CX 0xD9
|
||||
#define DSSCMD_IREAD64_CR 0xDA
|
||||
#define DSSCMD_IREAD64_CX 0xDB
|
||||
#define DSSCMD_INVALIDATE_DEK 0xDC
|
||||
#define DSSCMD_SET_KEK 0xDD
|
||||
#define DSSCMD_GET_KEK_ID 0xDE
|
||||
#define DSSCMD_GEN_XFER 0xDF
|
||||
/* Data Security SLI Commands */
|
||||
#define DSSCMD_IWRITE64_CR 0xF8
|
||||
#define DSSCMD_IWRITE64_CX 0xF9
|
||||
#define DSSCMD_IREAD64_CR 0xFA
|
||||
#define DSSCMD_IREAD64_CX 0xFB
|
||||
|
||||
#define CMD_MAX_IOCB_CMD 0xE6
|
||||
#define CMD_MAX_IOCB_CMD 0xFB
|
||||
#define CMD_IOCB_MASK 0xff
|
||||
|
||||
#define MAX_MSG_DATA 28 /* max msg data in CMD_ADAPTER_MSG
|
||||
|
|
|
@ -62,7 +62,7 @@ lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
|
||||
int
|
||||
lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||
struct serv_parm * sp, uint32_t class)
|
||||
struct serv_parm *sp, uint32_t class, int flogi)
|
||||
{
|
||||
volatile struct serv_parm *hsp = &vport->fc_sparam;
|
||||
uint16_t hsp_value, ssp_value = 0;
|
||||
|
@ -75,49 +75,56 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
* correcting the byte values.
|
||||
*/
|
||||
if (sp->cls1.classValid) {
|
||||
hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
|
||||
hsp->cls1.rcvDataSizeLsb;
|
||||
ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
|
||||
sp->cls1.rcvDataSizeLsb;
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
|
||||
sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
|
||||
if (!flogi) {
|
||||
hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
|
||||
hsp->cls1.rcvDataSizeLsb);
|
||||
ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
|
||||
sp->cls1.rcvDataSizeLsb);
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls1.rcvDataSizeLsb =
|
||||
hsp->cls1.rcvDataSizeLsb;
|
||||
sp->cls1.rcvDataSizeMsb =
|
||||
hsp->cls1.rcvDataSizeMsb;
|
||||
}
|
||||
}
|
||||
} else if (class == CLASS1) {
|
||||
} else if (class == CLASS1)
|
||||
goto bad_service_param;
|
||||
}
|
||||
|
||||
if (sp->cls2.classValid) {
|
||||
hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
|
||||
hsp->cls2.rcvDataSizeLsb;
|
||||
ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
|
||||
sp->cls2.rcvDataSizeLsb;
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
|
||||
sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
|
||||
if (!flogi) {
|
||||
hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
|
||||
hsp->cls2.rcvDataSizeLsb);
|
||||
ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
|
||||
sp->cls2.rcvDataSizeLsb);
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls2.rcvDataSizeLsb =
|
||||
hsp->cls2.rcvDataSizeLsb;
|
||||
sp->cls2.rcvDataSizeMsb =
|
||||
hsp->cls2.rcvDataSizeMsb;
|
||||
}
|
||||
}
|
||||
} else if (class == CLASS2) {
|
||||
} else if (class == CLASS2)
|
||||
goto bad_service_param;
|
||||
}
|
||||
|
||||
if (sp->cls3.classValid) {
|
||||
hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
|
||||
hsp->cls3.rcvDataSizeLsb;
|
||||
ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
|
||||
sp->cls3.rcvDataSizeLsb;
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
|
||||
sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
|
||||
if (!flogi) {
|
||||
hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
|
||||
hsp->cls3.rcvDataSizeLsb);
|
||||
ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
|
||||
sp->cls3.rcvDataSizeLsb);
|
||||
if (!ssp_value)
|
||||
goto bad_service_param;
|
||||
if (ssp_value > hsp_value) {
|
||||
sp->cls3.rcvDataSizeLsb =
|
||||
hsp->cls3.rcvDataSizeLsb;
|
||||
sp->cls3.rcvDataSizeMsb =
|
||||
hsp->cls3.rcvDataSizeMsb;
|
||||
}
|
||||
}
|
||||
} else if (class == CLASS3) {
|
||||
} else if (class == CLASS3)
|
||||
goto bad_service_param;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preserve the upper four bits of the MSB from the PLOGI response.
|
||||
|
@ -295,7 +302,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
NULL);
|
||||
return 0;
|
||||
}
|
||||
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
|
||||
if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
|
||||
/* Reject this request because invalid parameters */
|
||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
||||
|
@ -831,7 +838,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
|
|||
"0142 PLOGI RSP: Invalid WWN.\n");
|
||||
goto out;
|
||||
}
|
||||
if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
|
||||
if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
|
||||
goto out;
|
||||
/* PLOGI chkparm OK */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
|
|
|
@ -626,6 +626,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
|
|||
&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
|
||||
if (psb->cur_iocbq.sli4_xritag == xri) {
|
||||
list_del(&psb->list);
|
||||
psb->exch_busy = 0;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
spin_unlock_irqrestore(
|
||||
&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
|
@ -688,11 +689,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
|
|||
list);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
psb->exch_busy = 1;
|
||||
rc++;
|
||||
} else
|
||||
} else {
|
||||
psb->exch_busy = 0;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
}
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
}
|
||||
|
@ -839,11 +841,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
|
|||
psb->cur_iocbq.sli4_xritag);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
psb->exch_busy = 1;
|
||||
rc++;
|
||||
} else
|
||||
} else {
|
||||
psb->exch_busy = 0;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
}
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
break;
|
||||
|
@ -857,11 +860,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
|
|||
list);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
psb->exch_busy = 1;
|
||||
rc++;
|
||||
} else
|
||||
} else {
|
||||
psb->exch_busy = 0;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
}
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
}
|
||||
|
@ -951,8 +955,7 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
|
|||
{
|
||||
unsigned long iflag = 0;
|
||||
|
||||
if (psb->status == IOSTAT_LOCAL_REJECT
|
||||
&& psb->result == IOERR_ABORT_REQUESTED) {
|
||||
if (psb->exch_busy) {
|
||||
spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
iflag);
|
||||
psb->pCmd = NULL;
|
||||
|
@ -2221,6 +2224,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
|
||||
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
|
||||
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
|
||||
/* pick up SLI4 exhange busy status from HBA */
|
||||
lpfc_cmd->exch_busy = pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY;
|
||||
|
||||
if (pnode && NLP_CHK_NODE_ACT(pnode))
|
||||
atomic_dec(&pnode->cmd_pending);
|
||||
|
||||
|
@ -2990,6 +2996,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|||
|
||||
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
|
||||
abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
|
||||
abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
|
||||
|
||||
if (lpfc_is_link_up(phba))
|
||||
icmd->ulpCommand = CMD_ABORT_XRI_CN;
|
||||
|
|
|
@ -118,6 +118,7 @@ struct lpfc_scsi_buf {
|
|||
|
||||
uint32_t timeout;
|
||||
|
||||
uint16_t exch_busy; /* SLI4 hba reported XB on complete WCQE */
|
||||
uint16_t status; /* From IOCB Word 7- ulpStatus */
|
||||
uint32_t result; /* From IOCB Word 4. */
|
||||
|
||||
|
|
|
@ -580,10 +580,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
|
|||
else
|
||||
sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag);
|
||||
if (sglq) {
|
||||
if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED
|
||||
&& ((iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
|
||||
&& (iocbq->iocb.un.ulpWord[4]
|
||||
== IOERR_ABORT_REQUESTED))) {
|
||||
if (iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) {
|
||||
spin_lock_irqsave(&phba->sli4_hba.abts_sgl_list_lock,
|
||||
iflag);
|
||||
list_add(&sglq->list,
|
||||
|
@ -764,10 +761,6 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
|
|||
case DSSCMD_IWRITE64_CX:
|
||||
case DSSCMD_IREAD64_CR:
|
||||
case DSSCMD_IREAD64_CX:
|
||||
case DSSCMD_INVALIDATE_DEK:
|
||||
case DSSCMD_SET_KEK:
|
||||
case DSSCMD_GET_KEK_ID:
|
||||
case DSSCMD_GEN_XFER:
|
||||
type = LPFC_SOL_IOCB;
|
||||
break;
|
||||
case CMD_ABORT_XRI_CN:
|
||||
|
@ -2228,9 +2221,15 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
* All other are passed to the completion callback.
|
||||
*/
|
||||
if (pring->ringno == LPFC_ELS_RING) {
|
||||
if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) {
|
||||
if ((phba->sli_rev < LPFC_SLI_REV4) &&
|
||||
(cmdiocbp->iocb_flag &
|
||||
LPFC_DRIVER_ABORTED)) {
|
||||
spin_lock_irqsave(&phba->hbalock,
|
||||
iflag);
|
||||
cmdiocbp->iocb_flag &=
|
||||
~LPFC_DRIVER_ABORTED;
|
||||
spin_unlock_irqrestore(&phba->hbalock,
|
||||
iflag);
|
||||
saveq->iocb.ulpStatus =
|
||||
IOSTAT_LOCAL_REJECT;
|
||||
saveq->iocb.un.ulpWord[4] =
|
||||
|
@ -2240,7 +2239,47 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
* of DMAing payload, so don't free data
|
||||
* buffer till after a hbeat.
|
||||
*/
|
||||
spin_lock_irqsave(&phba->hbalock,
|
||||
iflag);
|
||||
saveq->iocb_flag |= LPFC_DELAY_MEM_FREE;
|
||||
spin_unlock_irqrestore(&phba->hbalock,
|
||||
iflag);
|
||||
}
|
||||
if ((phba->sli_rev == LPFC_SLI_REV4) &&
|
||||
(saveq->iocb_flag & LPFC_EXCHANGE_BUSY)) {
|
||||
/* Set cmdiocb flag for the exchange
|
||||
* busy so sgl (xri) will not be
|
||||
* released until the abort xri is
|
||||
* received from hba, clear the
|
||||
* LPFC_DRIVER_ABORTED bit in case
|
||||
* it was driver initiated abort.
|
||||
*/
|
||||
spin_lock_irqsave(&phba->hbalock,
|
||||
iflag);
|
||||
cmdiocbp->iocb_flag &=
|
||||
~LPFC_DRIVER_ABORTED;
|
||||
cmdiocbp->iocb_flag |=
|
||||
LPFC_EXCHANGE_BUSY;
|
||||
spin_unlock_irqrestore(&phba->hbalock,
|
||||
iflag);
|
||||
cmdiocbp->iocb.ulpStatus =
|
||||
IOSTAT_LOCAL_REJECT;
|
||||
cmdiocbp->iocb.un.ulpWord[4] =
|
||||
IOERR_ABORT_REQUESTED;
|
||||
/*
|
||||
* For SLI4, irsiocb contains NO_XRI
|
||||
* in sli_xritag, it shall not affect
|
||||
* releasing sgl (xri) process.
|
||||
*/
|
||||
saveq->iocb.ulpStatus =
|
||||
IOSTAT_LOCAL_REJECT;
|
||||
saveq->iocb.un.ulpWord[4] =
|
||||
IOERR_SLI_ABORTED;
|
||||
spin_lock_irqsave(&phba->hbalock,
|
||||
iflag);
|
||||
saveq->iocb_flag |= LPFC_DELAY_MEM_FREE;
|
||||
spin_unlock_irqrestore(&phba->hbalock,
|
||||
iflag);
|
||||
}
|
||||
}
|
||||
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
|
||||
|
@ -5987,12 +6026,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||
else
|
||||
bf_set(abort_cmd_ia, &wqe->abort_cmd, 0);
|
||||
bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG);
|
||||
abort_tag = iocbq->iocb.un.acxri.abortIoTag;
|
||||
wqe->words[5] = 0;
|
||||
bf_set(lpfc_wqe_gen_ct, &wqe->generic,
|
||||
((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l));
|
||||
abort_tag = iocbq->iocb.un.acxri.abortIoTag;
|
||||
wqe->generic.abort_tag = abort_tag;
|
||||
/*
|
||||
* The abort handler will send us CMD_ABORT_XRI_CN or
|
||||
* CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX
|
||||
|
@ -6121,15 +6158,15 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|||
if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe))
|
||||
return IOCB_ERROR;
|
||||
|
||||
if (piocb->iocb_flag & LPFC_IO_FCP) {
|
||||
if ((piocb->iocb_flag & LPFC_IO_FCP) ||
|
||||
(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
|
||||
/*
|
||||
* For FCP command IOCB, get a new WQ index to distribute
|
||||
* WQE across the WQsr. On the other hand, for abort IOCB,
|
||||
* it carries the same WQ index to the original command
|
||||
* IOCB.
|
||||
*/
|
||||
if ((piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
|
||||
(piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN))
|
||||
if (piocb->iocb_flag & LPFC_IO_FCP)
|
||||
piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba);
|
||||
if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
|
||||
&wqe))
|
||||
|
@ -7004,7 +7041,14 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
abort_iocb->iocb.ulpContext != abort_context ||
|
||||
(abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
else {
|
||||
else if (phba->sli_rev < LPFC_SLI_REV4) {
|
||||
/*
|
||||
* leave the SLI4 aborted command on the txcmplq
|
||||
* list and the command complete WCQE's XB bit
|
||||
* will tell whether the SGL (XRI) can be released
|
||||
* immediately or to the aborted SGL list for the
|
||||
* following abort XRI from the HBA.
|
||||
*/
|
||||
list_del_init(&abort_iocb->list);
|
||||
pring->txcmplq_cnt--;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
@ -7013,11 +7057,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
* payload, so don't free data buffer till after
|
||||
* a hbeat.
|
||||
*/
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE;
|
||||
|
||||
abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
abort_iocb->iocb.un.ulpWord[4] = IOERR_ABORT_REQUESTED;
|
||||
(abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
|
||||
}
|
||||
}
|
||||
|
@ -7106,7 +7152,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
return 0;
|
||||
|
||||
/* This signals the response to set the correct status
|
||||
* before calling the completion handler.
|
||||
* before calling the completion handler
|
||||
*/
|
||||
cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
|
||||
|
||||
|
@ -7124,6 +7170,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
|
||||
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
|
||||
abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx;
|
||||
if (cmdiocb->iocb_flag & LPFC_IO_FCP)
|
||||
abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX;
|
||||
|
||||
if (phba->link_state >= LPFC_LINK_UP)
|
||||
iabt->ulpCommand = CMD_ABORT_XRI_CN;
|
||||
|
@ -7330,6 +7378,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
|
|||
|
||||
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
|
||||
abtsiocb->fcp_wqidx = iocbq->fcp_wqidx;
|
||||
if (iocbq->iocb_flag & LPFC_IO_FCP)
|
||||
abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
|
||||
|
||||
if (lpfc_is_link_up(phba))
|
||||
abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
|
||||
|
@ -8359,11 +8409,24 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn
|
||||
* @phba: pointer to lpfc hba data structure
|
||||
* @pIocbIn: pointer to the rspiocbq
|
||||
* @pIocbOut: pointer to the cmdiocbq
|
||||
* @wcqe: pointer to the complete wcqe
|
||||
*
|
||||
* This routine transfers the fields of a command iocbq to a response iocbq
|
||||
* by copying all the IOCB fields from command iocbq and transferring the
|
||||
* completion status information from the complete wcqe.
|
||||
**/
|
||||
static void
|
||||
lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn,
|
||||
lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *pIocbIn,
|
||||
struct lpfc_iocbq *pIocbOut,
|
||||
struct lpfc_wcqe_complete *wcqe)
|
||||
{
|
||||
unsigned long iflags;
|
||||
size_t offset = offsetof(struct lpfc_iocbq, iocb);
|
||||
|
||||
memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset,
|
||||
|
@ -8379,6 +8442,13 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn,
|
|||
pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
|
||||
else
|
||||
pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
|
||||
|
||||
/* Pick up HBA exchange busy condition */
|
||||
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY;
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8419,7 +8489,7 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
|
|||
}
|
||||
|
||||
/* Fake the irspiocbq and copy necessary response information */
|
||||
lpfc_sli4_iocb_param_transfer(irspiocbq, cmdiocbq, wcqe);
|
||||
lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
|
||||
|
||||
return irspiocbq;
|
||||
}
|
||||
|
@ -8976,7 +9046,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba,
|
|||
}
|
||||
|
||||
/* Fake the irspiocb and copy necessary response information */
|
||||
lpfc_sli4_iocb_param_transfer(&irspiocbq, cmdiocbq, wcqe);
|
||||
lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe);
|
||||
|
||||
/* Pass the cmd_iocb and the rsp state to the upper layer */
|
||||
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq);
|
||||
|
|
|
@ -53,17 +53,19 @@ struct lpfc_iocbq {
|
|||
|
||||
IOCB_t iocb; /* IOCB cmd */
|
||||
uint8_t retry; /* retry counter for IOCB cmd - if needed */
|
||||
uint8_t iocb_flag;
|
||||
uint16_t iocb_flag;
|
||||
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
|
||||
#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
|
||||
#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
|
||||
#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
|
||||
#define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */
|
||||
#define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */
|
||||
#define LPFC_FIP_ELS_ID_MASK 0xc0 /* ELS_ID range 0-3 */
|
||||
#define LPFC_FIP_ELS_ID_SHIFT 6
|
||||
#define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */
|
||||
#define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */
|
||||
|
||||
#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
|
||||
#define LPFC_FIP_ELS_ID_SHIFT 14
|
||||
|
||||
uint8_t abort_count;
|
||||
uint8_t rsvd2;
|
||||
uint32_t drvrTimeout; /* driver timeout in seconds */
|
||||
uint32_t fcp_wqidx; /* index to FCP work queue */
|
||||
|
|
Загрузка…
Ссылка в новой задаче