|
|
|
@ -70,8 +70,9 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *,
|
|
|
|
uint32_t);
|
|
|
|
uint32_t);
|
|
|
|
static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *,
|
|
|
|
static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *,
|
|
|
|
uint8_t *, uint32_t *);
|
|
|
|
uint8_t *, uint32_t *);
|
|
|
|
static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *,
|
|
|
|
static struct lpfc_iocbq *
|
|
|
|
struct lpfc_iocbq *);
|
|
|
|
lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba,
|
|
|
|
|
|
|
|
struct lpfc_iocbq *rspiocbq);
|
|
|
|
static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
|
|
|
|
static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
|
|
|
|
struct hbq_dmabuf *);
|
|
|
|
struct hbq_dmabuf *);
|
|
|
|
static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
|
|
|
|
static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
|
|
|
|
@ -89,6 +90,9 @@ static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q);
|
|
|
|
static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba,
|
|
|
|
static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba,
|
|
|
|
struct lpfc_queue *cq,
|
|
|
|
struct lpfc_queue *cq,
|
|
|
|
struct lpfc_cqe *cqe);
|
|
|
|
struct lpfc_cqe *cqe);
|
|
|
|
|
|
|
|
static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba,
|
|
|
|
|
|
|
|
struct lpfc_iocbq *pwqeq,
|
|
|
|
|
|
|
|
struct lpfc_sglq *sglq);
|
|
|
|
|
|
|
|
|
|
|
|
union lpfc_wqe128 lpfc_iread_cmd_template;
|
|
|
|
union lpfc_wqe128 lpfc_iread_cmd_template;
|
|
|
|
union lpfc_wqe128 lpfc_iwrite_cmd_template;
|
|
|
|
union lpfc_wqe128 lpfc_iwrite_cmd_template;
|
|
|
|
@ -3550,16 +3554,11 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
|
|
|
|
struct lpfc_iocbq *prspiocb)
|
|
|
|
struct lpfc_iocbq *prspiocb)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct lpfc_iocbq *cmd_iocb = NULL;
|
|
|
|
struct lpfc_iocbq *cmd_iocb = NULL;
|
|
|
|
uint16_t iotag;
|
|
|
|
u16 iotag;
|
|
|
|
spinlock_t *temp_lock = NULL;
|
|
|
|
|
|
|
|
unsigned long iflag = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
|
temp_lock = &pring->ring_lock;
|
|
|
|
iotag = get_wqe_reqtag(prspiocb);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
temp_lock = &phba->hbalock;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(temp_lock, iflag);
|
|
|
|
|
|
|
|
iotag = prspiocb->iocb.ulpIoTag;
|
|
|
|
iotag = prspiocb->iocb.ulpIoTag;
|
|
|
|
|
|
|
|
|
|
|
|
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
|
|
|
|
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
|
|
|
|
@ -3569,17 +3568,14 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
|
|
|
|
list_del_init(&cmd_iocb->list);
|
|
|
|
list_del_init(&cmd_iocb->list);
|
|
|
|
cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
|
|
|
|
cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
|
|
|
|
pring->txcmplq_cnt--;
|
|
|
|
pring->txcmplq_cnt--;
|
|
|
|
spin_unlock_irqrestore(temp_lock, iflag);
|
|
|
|
|
|
|
|
return cmd_iocb;
|
|
|
|
return cmd_iocb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(temp_lock, iflag);
|
|
|
|
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
"0317 iotag x%x is out of "
|
|
|
|
"0317 iotag x%x is out of "
|
|
|
|
"range: max iotag x%x wd0 x%x\n",
|
|
|
|
"range: max iotag x%x\n",
|
|
|
|
iotag, phba->sli.last_iotag,
|
|
|
|
iotag, phba->sli.last_iotag);
|
|
|
|
*(((uint32_t *) &prspiocb->iocb) + 7));
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -3600,15 +3596,7 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
|
|
|
|
struct lpfc_sli_ring *pring, uint16_t iotag)
|
|
|
|
struct lpfc_sli_ring *pring, uint16_t iotag)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct lpfc_iocbq *cmd_iocb = NULL;
|
|
|
|
struct lpfc_iocbq *cmd_iocb = NULL;
|
|
|
|
spinlock_t *temp_lock = NULL;
|
|
|
|
|
|
|
|
unsigned long iflag = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
|
|
|
|
|
temp_lock = &pring->ring_lock;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
temp_lock = &phba->hbalock;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(temp_lock, iflag);
|
|
|
|
|
|
|
|
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
|
|
|
|
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
|
|
|
|
cmd_iocb = phba->sli.iocbq_lookup[iotag];
|
|
|
|
cmd_iocb = phba->sli.iocbq_lookup[iotag];
|
|
|
|
if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) {
|
|
|
|
if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) {
|
|
|
|
@ -3616,12 +3604,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
|
|
|
|
list_del_init(&cmd_iocb->list);
|
|
|
|
list_del_init(&cmd_iocb->list);
|
|
|
|
cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
|
|
|
|
cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
|
|
|
|
pring->txcmplq_cnt--;
|
|
|
|
pring->txcmplq_cnt--;
|
|
|
|
spin_unlock_irqrestore(temp_lock, iflag);
|
|
|
|
|
|
|
|
return cmd_iocb;
|
|
|
|
return cmd_iocb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(temp_lock, iflag);
|
|
|
|
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
"0372 iotag x%x lookup error: max iotag (x%x) "
|
|
|
|
"0372 iotag x%x lookup error: max iotag (x%x) "
|
|
|
|
"cmd_flag x%x\n",
|
|
|
|
"cmd_flag x%x\n",
|
|
|
|
@ -3654,18 +3640,29 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
struct lpfc_iocbq *cmdiocbp;
|
|
|
|
struct lpfc_iocbq *cmdiocbp;
|
|
|
|
int rc = 1;
|
|
|
|
int rc = 1;
|
|
|
|
unsigned long iflag;
|
|
|
|
unsigned long iflag;
|
|
|
|
|
|
|
|
u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag;
|
|
|
|
|
|
|
|
|
|
|
|
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
|
|
|
|
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ulp_command = get_job_cmnd(phba, saveq);
|
|
|
|
|
|
|
|
ulp_status = get_job_ulpstatus(phba, saveq);
|
|
|
|
|
|
|
|
ulp_word4 = get_job_word4(phba, saveq);
|
|
|
|
|
|
|
|
ulp_context = get_job_ulpcontext(phba, saveq);
|
|
|
|
|
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
|
|
|
|
|
iotag = get_wqe_reqtag(saveq);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
iotag = saveq->iocb.ulpIoTag;
|
|
|
|
|
|
|
|
|
|
|
|
if (cmdiocbp) {
|
|
|
|
if (cmdiocbp) {
|
|
|
|
|
|
|
|
ulp_command = get_job_cmnd(phba, cmdiocbp);
|
|
|
|
if (cmdiocbp->cmd_cmpl) {
|
|
|
|
if (cmdiocbp->cmd_cmpl) {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* If an ELS command failed send an event to mgmt
|
|
|
|
* If an ELS command failed send an event to mgmt
|
|
|
|
* application.
|
|
|
|
* application.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if (saveq->iocb.ulpStatus &&
|
|
|
|
if (ulp_status &&
|
|
|
|
(pring->ringno == LPFC_ELS_RING) &&
|
|
|
|
(pring->ringno == LPFC_ELS_RING) &&
|
|
|
|
(cmdiocbp->iocb.ulpCommand ==
|
|
|
|
(ulp_command == CMD_ELS_REQUEST64_CR))
|
|
|
|
CMD_ELS_REQUEST64_CR))
|
|
|
|
|
|
|
|
lpfc_send_els_failure_event(phba,
|
|
|
|
lpfc_send_els_failure_event(phba,
|
|
|
|
cmdiocbp, saveq);
|
|
|
|
cmdiocbp, saveq);
|
|
|
|
|
|
|
|
|
|
|
|
@ -3727,20 +3724,20 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
~LPFC_DRIVER_ABORTED;
|
|
|
|
~LPFC_DRIVER_ABORTED;
|
|
|
|
spin_unlock_irqrestore(
|
|
|
|
spin_unlock_irqrestore(
|
|
|
|
&phba->hbalock, iflag);
|
|
|
|
&phba->hbalock, iflag);
|
|
|
|
cmdiocbp->iocb.ulpStatus =
|
|
|
|
set_job_ulpstatus(cmdiocbp,
|
|
|
|
IOSTAT_LOCAL_REJECT;
|
|
|
|
IOSTAT_LOCAL_REJECT);
|
|
|
|
cmdiocbp->iocb.un.ulpWord[4] =
|
|
|
|
set_job_ulpword4(cmdiocbp,
|
|
|
|
IOERR_ABORT_REQUESTED;
|
|
|
|
IOERR_ABORT_REQUESTED);
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* For SLI4, irsiocb contains
|
|
|
|
* For SLI4, irsiocb contains
|
|
|
|
* NO_XRI in sli_xritag, it
|
|
|
|
* NO_XRI in sli_xritag, it
|
|
|
|
* shall not affect releasing
|
|
|
|
* shall not affect releasing
|
|
|
|
* sgl (xri) process.
|
|
|
|
* sgl (xri) process.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
saveq->iocb.ulpStatus =
|
|
|
|
set_job_ulpstatus(saveq,
|
|
|
|
IOSTAT_LOCAL_REJECT;
|
|
|
|
IOSTAT_LOCAL_REJECT);
|
|
|
|
saveq->iocb.un.ulpWord[4] =
|
|
|
|
set_job_ulpword4(saveq,
|
|
|
|
IOERR_SLI_ABORTED;
|
|
|
|
IOERR_SLI_ABORTED);
|
|
|
|
spin_lock_irqsave(
|
|
|
|
spin_lock_irqsave(
|
|
|
|
&phba->hbalock, iflag);
|
|
|
|
&phba->hbalock, iflag);
|
|
|
|
saveq->cmd_flag |=
|
|
|
|
saveq->cmd_flag |=
|
|
|
|
@ -3768,12 +3765,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
"0322 Ring %d handler: "
|
|
|
|
"0322 Ring %d handler: "
|
|
|
|
"unexpected completion IoTag x%x "
|
|
|
|
"unexpected completion IoTag x%x "
|
|
|
|
"Data: x%x x%x x%x x%x\n",
|
|
|
|
"Data: x%x x%x x%x x%x\n",
|
|
|
|
pring->ringno,
|
|
|
|
pring->ringno, iotag, ulp_status,
|
|
|
|
saveq->iocb.ulpIoTag,
|
|
|
|
ulp_word4, ulp_command, ulp_context);
|
|
|
|
saveq->iocb.ulpStatus,
|
|
|
|
|
|
|
|
saveq->iocb.un.ulpWord[4],
|
|
|
|
|
|
|
|
saveq->iocb.ulpCommand,
|
|
|
|
|
|
|
|
saveq->iocb.ulpContext);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -4088,23 +4081,23 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
struct lpfc_iocbq *rspiocbp)
|
|
|
|
struct lpfc_iocbq *rspiocbp)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct lpfc_iocbq *saveq;
|
|
|
|
struct lpfc_iocbq *saveq;
|
|
|
|
struct lpfc_iocbq *cmdiocbp;
|
|
|
|
struct lpfc_iocbq *cmdiocb;
|
|
|
|
struct lpfc_iocbq *next_iocb;
|
|
|
|
struct lpfc_iocbq *next_iocb;
|
|
|
|
IOCB_t *irsp = NULL;
|
|
|
|
IOCB_t *irsp;
|
|
|
|
uint32_t free_saveq;
|
|
|
|
uint32_t free_saveq;
|
|
|
|
uint8_t iocb_cmd_type;
|
|
|
|
u8 cmd_type;
|
|
|
|
lpfc_iocb_type type;
|
|
|
|
lpfc_iocb_type type;
|
|
|
|
unsigned long iflag;
|
|
|
|
unsigned long iflag;
|
|
|
|
|
|
|
|
u32 ulp_status = get_job_ulpstatus(phba, rspiocbp);
|
|
|
|
|
|
|
|
u32 ulp_word4 = get_job_word4(phba, rspiocbp);
|
|
|
|
|
|
|
|
u32 ulp_command = get_job_cmnd(phba, rspiocbp);
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
/* First add the response iocb to the countinueq list */
|
|
|
|
/* First add the response iocb to the countinueq list */
|
|
|
|
list_add_tail(&rspiocbp->list, &(pring->iocb_continueq));
|
|
|
|
list_add_tail(&rspiocbp->list, &pring->iocb_continueq);
|
|
|
|
pring->iocb_continueq_cnt++;
|
|
|
|
pring->iocb_continueq_cnt++;
|
|
|
|
|
|
|
|
|
|
|
|
/* Now, determine whether the list is completed for processing */
|
|
|
|
|
|
|
|
irsp = &rspiocbp->iocb;
|
|
|
|
|
|
|
|
if (irsp->ulpLe) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* By default, the driver expects to free all resources
|
|
|
|
* By default, the driver expects to free all resources
|
|
|
|
* associated with this iocb completion.
|
|
|
|
* associated with this iocb completion.
|
|
|
|
@ -4112,7 +4105,6 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
free_saveq = 1;
|
|
|
|
free_saveq = 1;
|
|
|
|
saveq = list_get_first(&pring->iocb_continueq,
|
|
|
|
saveq = list_get_first(&pring->iocb_continueq,
|
|
|
|
struct lpfc_iocbq, list);
|
|
|
|
struct lpfc_iocbq, list);
|
|
|
|
irsp = &(saveq->iocb);
|
|
|
|
|
|
|
|
list_del_init(&pring->iocb_continueq);
|
|
|
|
list_del_init(&pring->iocb_continueq);
|
|
|
|
pring->iocb_continueq_cnt = 0;
|
|
|
|
pring->iocb_continueq_cnt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
@ -4122,30 +4114,32 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
* If resource errors reported from HBA, reduce
|
|
|
|
* If resource errors reported from HBA, reduce
|
|
|
|
* queuedepths of the SCSI device.
|
|
|
|
* queuedepths of the SCSI device.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
|
|
|
if (ulp_status == IOSTAT_LOCAL_REJECT &&
|
|
|
|
((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
|
|
|
|
((ulp_word4 & IOERR_PARAM_MASK) ==
|
|
|
|
IOERR_NO_RESOURCES)) {
|
|
|
|
IOERR_NO_RESOURCES)) {
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
phba->lpfc_rampdown_queue_depth(phba);
|
|
|
|
phba->lpfc_rampdown_queue_depth(phba);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (irsp->ulpStatus) {
|
|
|
|
if (ulp_status) {
|
|
|
|
/* Rsp ring <ringno> error: IOCB */
|
|
|
|
/* Rsp ring <ringno> error: IOCB */
|
|
|
|
|
|
|
|
if (phba->sli_rev < LPFC_SLI_REV4) {
|
|
|
|
|
|
|
|
irsp = &rspiocbp->iocb;
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
"0328 Rsp Ring %d error: "
|
|
|
|
"0328 Rsp Ring %d error: ulp_status x%x "
|
|
|
|
"IOCB Data: "
|
|
|
|
"IOCB Data: "
|
|
|
|
"x%x x%x x%x x%x "
|
|
|
|
"x%08x x%08x x%08x x%08x "
|
|
|
|
"x%x x%x x%x x%x "
|
|
|
|
"x%08x x%08x x%08x x%08x "
|
|
|
|
"x%x x%x x%x x%x "
|
|
|
|
"x%08x x%08x x%08x x%08x "
|
|
|
|
"x%x x%x x%x x%x\n",
|
|
|
|
"x%08x x%08x x%08x x%08x\n",
|
|
|
|
pring->ringno,
|
|
|
|
pring->ringno, ulp_status,
|
|
|
|
irsp->un.ulpWord[0],
|
|
|
|
get_job_ulpword(rspiocbp, 0),
|
|
|
|
irsp->un.ulpWord[1],
|
|
|
|
get_job_ulpword(rspiocbp, 1),
|
|
|
|
irsp->un.ulpWord[2],
|
|
|
|
get_job_ulpword(rspiocbp, 2),
|
|
|
|
irsp->un.ulpWord[3],
|
|
|
|
get_job_ulpword(rspiocbp, 3),
|
|
|
|
irsp->un.ulpWord[4],
|
|
|
|
get_job_ulpword(rspiocbp, 4),
|
|
|
|
irsp->un.ulpWord[5],
|
|
|
|
get_job_ulpword(rspiocbp, 5),
|
|
|
|
*(((uint32_t *)irsp) + 6),
|
|
|
|
*(((uint32_t *)irsp) + 6),
|
|
|
|
*(((uint32_t *)irsp) + 7),
|
|
|
|
*(((uint32_t *)irsp) + 7),
|
|
|
|
*(((uint32_t *)irsp) + 8),
|
|
|
|
*(((uint32_t *)irsp) + 8),
|
|
|
|
@ -4156,23 +4150,34 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
*(((uint32_t *)irsp) + 13),
|
|
|
|
*(((uint32_t *)irsp) + 13),
|
|
|
|
*(((uint32_t *)irsp) + 14),
|
|
|
|
*(((uint32_t *)irsp) + 14),
|
|
|
|
*(((uint32_t *)irsp) + 15));
|
|
|
|
*(((uint32_t *)irsp) + 15));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
|
|
|
|
"0321 Rsp Ring %d error: "
|
|
|
|
|
|
|
|
"IOCB Data: "
|
|
|
|
|
|
|
|
"x%x x%x x%x x%x\n",
|
|
|
|
|
|
|
|
pring->ringno,
|
|
|
|
|
|
|
|
rspiocbp->wcqe_cmpl.word0,
|
|
|
|
|
|
|
|
rspiocbp->wcqe_cmpl.total_data_placed,
|
|
|
|
|
|
|
|
rspiocbp->wcqe_cmpl.parameter,
|
|
|
|
|
|
|
|
rspiocbp->wcqe_cmpl.word3);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Fetch the IOCB command type and call the correct completion
|
|
|
|
* Fetch the iocb command type and call the correct completion
|
|
|
|
* routine. Solicited and Unsolicited IOCBs on the ELS ring
|
|
|
|
* routine. Solicited and Unsolicited IOCBs on the ELS ring
|
|
|
|
* get freed back to the lpfc_iocb_list by the discovery
|
|
|
|
* get freed back to the lpfc_iocb_list by the discovery
|
|
|
|
* kernel thread.
|
|
|
|
* kernel thread.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
|
|
|
|
cmd_type = ulp_command & CMD_IOCB_MASK;
|
|
|
|
type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
|
|
|
|
type = lpfc_sli_iocb_cmd_type(cmd_type);
|
|
|
|
switch (type) {
|
|
|
|
switch (type) {
|
|
|
|
case LPFC_SOL_IOCB:
|
|
|
|
case LPFC_SOL_IOCB:
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
rc = lpfc_sli_process_sol_iocb(phba, pring, saveq);
|
|
|
|
rc = lpfc_sli_process_sol_iocb(phba, pring, saveq);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case LPFC_UNSOL_IOCB:
|
|
|
|
case LPFC_UNSOL_IOCB:
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq);
|
|
|
|
rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq);
|
|
|
|
@ -4180,49 +4185,42 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
if (!rc)
|
|
|
|
if (!rc)
|
|
|
|
free_saveq = 0;
|
|
|
|
free_saveq = 0;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case LPFC_ABORT_IOCB:
|
|
|
|
case LPFC_ABORT_IOCB:
|
|
|
|
cmdiocbp = NULL;
|
|
|
|
cmdiocb = NULL;
|
|
|
|
if (irsp->ulpCommand != CMD_XRI_ABORTED_CX) {
|
|
|
|
if (ulp_command != CMD_XRI_ABORTED_CX)
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
cmdiocb = lpfc_sli_iocbq_lookup(phba, pring,
|
|
|
|
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring,
|
|
|
|
|
|
|
|
saveq);
|
|
|
|
saveq);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
if (cmdiocb) {
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmdiocbp) {
|
|
|
|
|
|
|
|
/* Call the specified completion routine */
|
|
|
|
/* Call the specified completion routine */
|
|
|
|
if (cmdiocbp->cmd_cmpl) {
|
|
|
|
if (cmdiocb->cmd_cmpl) {
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock,
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
iflag);
|
|
|
|
cmdiocb->cmd_cmpl(phba, cmdiocb, saveq);
|
|
|
|
(cmdiocbp->cmd_cmpl)(phba, cmdiocbp,
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
|
|
|
saveq);
|
|
|
|
} else {
|
|
|
|
spin_lock_irqsave(&phba->hbalock,
|
|
|
|
__lpfc_sli_release_iocbq(phba, cmdiocb);
|
|
|
|
iflag);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
|
|
|
|
__lpfc_sli_release_iocbq(phba,
|
|
|
|
|
|
|
|
cmdiocbp);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case LPFC_UNKNOWN_IOCB:
|
|
|
|
case LPFC_UNKNOWN_IOCB:
|
|
|
|
if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
|
|
|
|
if (ulp_command == CMD_ADAPTER_MSG) {
|
|
|
|
char adaptermsg[LPFC_MAX_ADPTMSG];
|
|
|
|
char adaptermsg[LPFC_MAX_ADPTMSG];
|
|
|
|
|
|
|
|
|
|
|
|
memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
|
|
|
|
memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
|
|
|
|
memcpy(&adaptermsg[0], (uint8_t *)irsp,
|
|
|
|
memcpy(&adaptermsg[0], (uint8_t *)&rspiocbp->wqe,
|
|
|
|
MAX_MSG_DATA);
|
|
|
|
MAX_MSG_DATA);
|
|
|
|
dev_warn(&((phba->pcidev)->dev),
|
|
|
|
dev_warn(&((phba->pcidev)->dev),
|
|
|
|
"lpfc%d: %s\n",
|
|
|
|
"lpfc%d: %s\n",
|
|
|
|
phba->brd_no, adaptermsg);
|
|
|
|
phba->brd_no, adaptermsg);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
/* Unknown IOCB command */
|
|
|
|
/* Unknown command */
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
|
|
|
"0335 Unknown IOCB "
|
|
|
|
"0335 Unknown IOCB "
|
|
|
|
"command Data: x%x "
|
|
|
|
"command Data: x%x "
|
|
|
|
"x%x x%x x%x\n",
|
|
|
|
"x%x x%x x%x\n",
|
|
|
|
irsp->ulpCommand,
|
|
|
|
ulp_command,
|
|
|
|
irsp->ulpStatus,
|
|
|
|
ulp_status,
|
|
|
|
irsp->ulpIoTag,
|
|
|
|
get_wqe_reqtag(rspiocbp),
|
|
|
|
irsp->ulpContext);
|
|
|
|
get_job_ulpcontext(phba, rspiocbp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -4236,7 +4234,6 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
|
__lpfc_sli_release_iocbq(phba, saveq);
|
|
|
|
__lpfc_sli_release_iocbq(phba, saveq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rspiocbp = NULL;
|
|
|
|
rspiocbp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
|
|
|
return rspiocbp;
|
|
|
|
return rspiocbp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -4429,7 +4426,7 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
|
|
|
|
irspiocbq = container_of(cq_event, struct lpfc_iocbq,
|
|
|
|
irspiocbq = container_of(cq_event, struct lpfc_iocbq,
|
|
|
|
cq_event);
|
|
|
|
cq_event);
|
|
|
|
/* Translate ELS WCQE to response IOCBQ */
|
|
|
|
/* Translate ELS WCQE to response IOCBQ */
|
|
|
|
irspiocbq = lpfc_sli4_els_wcqe_to_rspiocbq(phba,
|
|
|
|
irspiocbq = lpfc_sli4_els_preprocess_rspiocbq(phba,
|
|
|
|
irspiocbq);
|
|
|
|
irspiocbq);
|
|
|
|
if (irspiocbq)
|
|
|
|
if (irspiocbq)
|
|
|
|
lpfc_sli_sp_handle_rspiocb(phba, pring,
|
|
|
|
lpfc_sli_sp_handle_rspiocb(phba, pring,
|
|
|
|
@ -10957,7 +10954,17 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
struct lpfc_io_buf *lpfc_cmd =
|
|
|
|
struct lpfc_io_buf *lpfc_cmd =
|
|
|
|
(struct lpfc_io_buf *)piocb->context1;
|
|
|
|
(struct lpfc_io_buf *)piocb->context1;
|
|
|
|
union lpfc_wqe128 *wqe = &piocb->wqe;
|
|
|
|
|
|
|
|
|
|
|
|
lpfc_prep_embed_io(phba, lpfc_cmd);
|
|
|
|
|
|
|
|
rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
|
|
lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct lpfc_iocbq *piocb = &lpfc_cmd->cur_iocbq;
|
|
|
|
|
|
|
|
union lpfc_wqe128 *wqe = &lpfc_cmd->cur_iocbq.wqe;
|
|
|
|
struct sli4_sge *sgl;
|
|
|
|
struct sli4_sge *sgl;
|
|
|
|
|
|
|
|
|
|
|
|
/* 128 byte wqe support here */
|
|
|
|
/* 128 byte wqe support here */
|
|
|
|
@ -11006,8 +11013,6 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|
|
|
wqe->words[31] = piocb->vmid_tag.app_id;
|
|
|
|
wqe->words[31] = piocb->vmid_tag.app_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@ -11029,9 +11034,10 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|
|
|
struct lpfc_iocbq *piocb, uint32_t flag)
|
|
|
|
struct lpfc_iocbq *piocb, uint32_t flag)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct lpfc_sglq *sglq;
|
|
|
|
struct lpfc_sglq *sglq;
|
|
|
|
union lpfc_wqe128 wqe;
|
|
|
|
union lpfc_wqe128 *wqe;
|
|
|
|
struct lpfc_queue *wq;
|
|
|
|
struct lpfc_queue *wq;
|
|
|
|
struct lpfc_sli_ring *pring;
|
|
|
|
struct lpfc_sli_ring *pring;
|
|
|
|
|
|
|
|
u32 ulp_command = get_job_cmnd(phba, piocb);
|
|
|
|
|
|
|
|
|
|
|
|
/* Get the WQ */
|
|
|
|
/* Get the WQ */
|
|
|
|
if ((piocb->cmd_flag & LPFC_IO_FCP) ||
|
|
|
|
if ((piocb->cmd_flag & LPFC_IO_FCP) ||
|
|
|
|
@ -11049,10 +11055,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
lockdep_assert_held(&pring->ring_lock);
|
|
|
|
lockdep_assert_held(&pring->ring_lock);
|
|
|
|
|
|
|
|
wqe = &piocb->wqe;
|
|
|
|
if (piocb->sli4_xritag == NO_XRI) {
|
|
|
|
if (piocb->sli4_xritag == NO_XRI) {
|
|
|
|
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
|
|
|
|
if (ulp_command == CMD_ABORT_XRI_WQE)
|
|
|
|
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
|
|
|
|
|
|
|
|
sglq = NULL;
|
|
|
|
sglq = NULL;
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
if (!list_empty(&pring->txq)) {
|
|
|
|
if (!list_empty(&pring->txq)) {
|
|
|
|
@ -11093,14 +11098,24 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|
|
|
if (sglq) {
|
|
|
|
if (sglq) {
|
|
|
|
piocb->sli4_lxritag = sglq->sli4_lxritag;
|
|
|
|
piocb->sli4_lxritag = sglq->sli4_lxritag;
|
|
|
|
piocb->sli4_xritag = sglq->sli4_xritag;
|
|
|
|
piocb->sli4_xritag = sglq->sli4_xritag;
|
|
|
|
if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq))
|
|
|
|
|
|
|
|
|
|
|
|
/* ABTS sent by initiator to CT exchange, the
|
|
|
|
|
|
|
|
* RX_ID field will be filled with the newly
|
|
|
|
|
|
|
|
* allocated responder XRI.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (ulp_command == CMD_XMIT_BLS_RSP64_CX &&
|
|
|
|
|
|
|
|
piocb->abort_bls == LPFC_ABTS_UNSOL_INT)
|
|
|
|
|
|
|
|
bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
|
|
|
|
|
|
|
|
piocb->sli4_xritag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bf_set(wqe_xri_tag, &wqe->generic.wqe_com,
|
|
|
|
|
|
|
|
piocb->sli4_xritag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lpfc_wqe_bpl2sgl(phba, piocb, sglq) == NO_XRI)
|
|
|
|
return IOCB_ERROR;
|
|
|
|
return IOCB_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe))
|
|
|
|
if (lpfc_sli4_wq_put(wq, wqe))
|
|
|
|
return IOCB_ERROR;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lpfc_sli4_wq_put(wq, &wqe))
|
|
|
|
|
|
|
|
return IOCB_ERROR;
|
|
|
|
return IOCB_ERROR;
|
|
|
|
lpfc_sli_ringtxcmpl_put(phba, pring, piocb);
|
|
|
|
lpfc_sli_ringtxcmpl_put(phba, pring, piocb);
|
|
|
|
|
|
|
|
|
|
|
|
@ -14098,123 +14113,7 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn
|
|
|
|
* lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe
|
|
|
|
* @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_hba *phba,
|
|
|
|
|
|
|
|
struct lpfc_iocbq *pIocbIn,
|
|
|
|
|
|
|
|
struct lpfc_iocbq *pIocbOut,
|
|
|
|
|
|
|
|
struct lpfc_wcqe_complete *wcqe)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int numBdes, i;
|
|
|
|
|
|
|
|
unsigned long iflags;
|
|
|
|
|
|
|
|
uint32_t status, max_response;
|
|
|
|
|
|
|
|
struct lpfc_dmabuf *dmabuf;
|
|
|
|
|
|
|
|
struct ulp_bde64 *bpl, bde;
|
|
|
|
|
|
|
|
size_t offset = offsetof(struct lpfc_iocbq, iocb);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset,
|
|
|
|
|
|
|
|
sizeof(struct lpfc_iocbq) - offset);
|
|
|
|
|
|
|
|
/* Map WCQE parameters into irspiocb parameters */
|
|
|
|
|
|
|
|
status = bf_get(lpfc_wcqe_c_status, wcqe);
|
|
|
|
|
|
|
|
pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK);
|
|
|
|
|
|
|
|
if (pIocbOut->cmd_flag & LPFC_IO_FCP)
|
|
|
|
|
|
|
|
if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.fcpi.fcpi_parm =
|
|
|
|
|
|
|
|
pIocbOut->iocb.un.fcpi.fcpi_parm -
|
|
|
|
|
|
|
|
wcqe->total_data_placed;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
|
|
|
|
|
|
|
|
switch (pIocbOut->iocb.ulpCommand) {
|
|
|
|
|
|
|
|
case CMD_ELS_REQUEST64_CR:
|
|
|
|
|
|
|
|
dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3;
|
|
|
|
|
|
|
|
bpl = (struct ulp_bde64 *)dmabuf->virt;
|
|
|
|
|
|
|
|
bde.tus.w = le32_to_cpu(bpl[1].tus.w);
|
|
|
|
|
|
|
|
max_response = bde.tus.f.bdeSize;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CMD_GEN_REQUEST64_CR:
|
|
|
|
|
|
|
|
max_response = 0;
|
|
|
|
|
|
|
|
if (!pIocbOut->context3)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/
|
|
|
|
|
|
|
|
sizeof(struct ulp_bde64);
|
|
|
|
|
|
|
|
dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3;
|
|
|
|
|
|
|
|
bpl = (struct ulp_bde64 *)dmabuf->virt;
|
|
|
|
|
|
|
|
for (i = 0; i < numBdes; i++) {
|
|
|
|
|
|
|
|
bde.tus.w = le32_to_cpu(bpl[i].tus.w);
|
|
|
|
|
|
|
|
if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64)
|
|
|
|
|
|
|
|
max_response += bde.tus.f.bdeSize;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
max_response = wcqe->total_data_placed;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_response < wcqe->total_data_placed)
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.genreq64.bdl.bdeSize =
|
|
|
|
|
|
|
|
wcqe->total_data_placed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Convert BG errors for completion status */
|
|
|
|
|
|
|
|
if (status == CQE_STATUS_DI_ERROR) {
|
|
|
|
|
|
|
|
pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bf_get(lpfc_wcqe_c_bg_edir, wcqe))
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0;
|
|
|
|
|
|
|
|
if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
|
|
|
|
|
|
|
BGS_GUARD_ERR_MASK;
|
|
|
|
|
|
|
|
if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
|
|
|
|
|
|
|
BGS_APPTAG_ERR_MASK;
|
|
|
|
|
|
|
|
if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.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)) {
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
|
|
|
|
|
|
|
BGS_HI_WATER_MARK_PRESENT_MASK;
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bghm =
|
|
|
|
|
|
|
|
wcqe->total_data_placed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Set ALL the error bits to indicate we don't know what
|
|
|
|
|
|
|
|
* type of error it is.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat)
|
|
|
|
|
|
|
|
pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
|
|
|
|
|
|
|
|
(BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK |
|
|
|
|
|
|
|
|
BGS_GUARD_ERR_MASK);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Pick up HBA exchange busy condition */
|
|
|
|
|
|
|
|
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
|
|
|
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflags);
|
|
|
|
|
|
|
|
pIocbIn->cmd_flag |= LPFC_EXCHANGE_BUSY;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe
|
|
|
|
|
|
|
|
* @phba: Pointer to HBA context object.
|
|
|
|
* @phba: Pointer to HBA context object.
|
|
|
|
* @irspiocbq: Pointer to work-queue completion queue entry.
|
|
|
|
* @irspiocbq: Pointer to work-queue completion queue entry.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
@ -14225,7 +14124,7 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
|
|
|
|
* Return: Pointer to the receive IOCBQ, NULL otherwise.
|
|
|
|
* Return: Pointer to the receive IOCBQ, NULL otherwise.
|
|
|
|
**/
|
|
|
|
**/
|
|
|
|
static struct lpfc_iocbq *
|
|
|
|
static struct lpfc_iocbq *
|
|
|
|
lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
|
|
|
|
lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba,
|
|
|
|
struct lpfc_iocbq *irspiocbq)
|
|
|
|
struct lpfc_iocbq *irspiocbq)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct lpfc_sli_ring *pring;
|
|
|
|
struct lpfc_sli_ring *pring;
|
|
|
|
@ -14238,11 +14137,13 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
|
|
|
|
wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&pring->ring_lock, iflags);
|
|
|
|
pring->stats.iocb_event++;
|
|
|
|
pring->stats.iocb_event++;
|
|
|
|
/* Look up the ELS command IOCB and create pseudo response IOCB */
|
|
|
|
/* Look up the ELS command IOCB and create pseudo response IOCB */
|
|
|
|
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
|
|
|
|
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
|
|
|
|
bf_get(lpfc_wcqe_c_request_tag, wcqe));
|
|
|
|
bf_get(lpfc_wcqe_c_request_tag, wcqe));
|
|
|
|
if (unlikely(!cmdiocbq)) {
|
|
|
|
if (unlikely(!cmdiocbq)) {
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
"0386 ELS complete with no corresponding "
|
|
|
|
"0386 ELS complete with no corresponding "
|
|
|
|
"cmdiocb: 0x%x 0x%x 0x%x 0x%x\n",
|
|
|
|
"cmdiocb: 0x%x 0x%x 0x%x 0x%x\n",
|
|
|
|
@ -14252,13 +14153,18 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(&pring->ring_lock, iflags);
|
|
|
|
memcpy(&irspiocbq->wqe, &cmdiocbq->wqe, sizeof(union lpfc_wqe128));
|
|
|
|
|
|
|
|
memcpy(&irspiocbq->wcqe_cmpl, wcqe, sizeof(*wcqe));
|
|
|
|
|
|
|
|
|
|
|
|
/* Put the iocb back on the txcmplq */
|
|
|
|
/* Put the iocb back on the txcmplq */
|
|
|
|
lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
|
|
|
|
lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
|
|
|
|
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
|
|
|
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
|
|
|
|
|
|
|
|
|
|
|
/* Fake the irspiocbq and copy necessary response information */
|
|
|
|
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
|
|
|
lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
|
|
|
|
spin_lock_irqsave(&phba->hbalock, iflags);
|
|
|
|
|
|
|
|
cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return irspiocbq;
|
|
|
|
return irspiocbq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -15084,9 +14990,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
|
|
|
/* Look up the FCP command IOCB and create pseudo response IOCB */
|
|
|
|
/* Look up the FCP command IOCB and create pseudo response IOCB */
|
|
|
|
spin_lock_irqsave(&pring->ring_lock, iflags);
|
|
|
|
spin_lock_irqsave(&pring->ring_lock, iflags);
|
|
|
|
pring->stats.iocb_event++;
|
|
|
|
pring->stats.iocb_event++;
|
|
|
|
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
|
|
|
|
|
|
|
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
|
|
|
|
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
|
|
|
|
bf_get(lpfc_wcqe_c_request_tag, wcqe));
|
|
|
|
bf_get(lpfc_wcqe_c_request_tag, wcqe));
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
|
|
|
if (unlikely(!cmdiocbq)) {
|
|
|
|
if (unlikely(!cmdiocbq)) {
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
|
"0374 FCP complete with no corresponding "
|
|
|
|
"0374 FCP complete with no corresponding "
|
|
|
|
@ -18947,13 +18853,16 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
|
|
|
|
ctiocb->sli4_lxritag = NO_XRI;
|
|
|
|
ctiocb->sli4_lxritag = NO_XRI;
|
|
|
|
ctiocb->sli4_xritag = NO_XRI;
|
|
|
|
ctiocb->sli4_xritag = NO_XRI;
|
|
|
|
|
|
|
|
|
|
|
|
if (fctl & FC_FC_EX_CTX)
|
|
|
|
if (fctl & FC_FC_EX_CTX) {
|
|
|
|
/* Exchange responder sent the abort so we
|
|
|
|
/* Exchange responder sent the abort so we
|
|
|
|
* own the oxid.
|
|
|
|
* own the oxid.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
ctiocb->abort_bls = LPFC_ABTS_UNSOL_RSP;
|
|
|
|
xri = oxid;
|
|
|
|
xri = oxid;
|
|
|
|
else
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ctiocb->abort_bls = LPFC_ABTS_UNSOL_INT;
|
|
|
|
xri = rxid;
|
|
|
|
xri = rxid;
|
|
|
|
|
|
|
|
}
|
|
|
|
lxri = lpfc_sli4_xri_inrange(phba, xri);
|
|
|
|
lxri = lpfc_sli4_xri_inrange(phba, xri);
|
|
|
|
if (lxri != NO_XRI)
|
|
|
|
if (lxri != NO_XRI)
|
|
|
|
lpfc_set_rrq_active(phba, ndlp, lxri,
|
|
|
|
lpfc_set_rrq_active(phba, ndlp, lxri,
|
|
|
|
|