static char *lpfc_release_version = LPFC_DRIVER_VERSION;
-/*
- * lpfc_ct_unsol_event
- */
static void
-lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
- struct lpfc_dmabuf *mp, uint32_t size)
+lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+ struct lpfc_dmabuf *mp, uint32_t size)
{
if (!mp) {
- printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, "
- "piocbq = %p, status = x%x, mp = %p, size = %d\n",
- __FUNCTION__, __LINE__,
- piocbq, piocbq->iocb.ulpStatus, mp, size);
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "0146 Ignoring unsolicted CT No HBQ "
+ "status = x%x\n",
+ piocbq->iocb.ulpStatus);
}
-
- printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, "
- "buffer = %p, size = %d, status = x%x\n",
- __FUNCTION__, __LINE__,
- piocbq, mp, size,
- piocbq->iocb.ulpStatus);
-
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "0145 Ignoring unsolicted CT HBQ Size:%d "
+ "status = x%x\n",
+ size, piocbq->iocb.ulpStatus);
}
static void
-lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
- struct lpfc_dmabuf *mp, uint32_t size)
+lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+ struct lpfc_dmabuf *mp, uint32_t size)
{
- if (!mp) {
- printk(KERN_ERR "%s (%d): Unsolited CT, no "
- "HBQ buffer, piocbq = %p, status = x%x\n",
- __FUNCTION__, __LINE__,
- piocbq, piocbq->iocb.ulpStatus);
- } else {
- lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
- printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
- "piocbq = %p, buffer = %p, size = %d, "
- "status = x%x\n",
- __FUNCTION__, __LINE__,
- piocbq, mp, size, piocbq->iocb.ulpStatus);
- }
+ lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size);
}
void
struct lpfc_iocbq *iocbq;
dma_addr_t paddr;
uint32_t size;
- struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
- struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
-
- piocbq->context2 = NULL;
- piocbq->context3 = NULL;
+ struct list_head head;
+ struct lpfc_dmabuf *bdeBuf;
if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
/* Not enough posted buffers; Try posting more buffers */
phba->fc_stat.NoRcvBuf++;
if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
- lpfc_post_buffer(phba, pring, 0, 1);
+ lpfc_post_buffer(phba, pring, 2, 1);
return;
}
return;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
- list_for_each_entry(iocbq, &piocbq->list, list) {
+ INIT_LIST_HEAD(&head);
+ list_add_tail(&head, &piocbq->list);
+ list_for_each_entry(iocbq, &head, list) {
icmd = &iocbq->iocb;
- if (icmd->ulpBdeCount == 0) {
- printk(KERN_ERR "%s (%d): Unsolited CT, no "
- "BDE, iocbq = %p, status = x%x\n",
- __FUNCTION__, __LINE__,
- iocbq, iocbq->iocb.ulpStatus);
+ if (icmd->ulpBdeCount == 0)
continue;
- }
-
+ bdeBuf = iocbq->context2;
+ iocbq->context2 = NULL;
size = icmd->un.cont64[0].tus.f.bdeSize;
- lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size);
- lpfc_in_buf_free(phba, bdeBuf1);
+ lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
+ lpfc_in_buf_free(phba, bdeBuf);
if (icmd->ulpBdeCount == 2) {
- lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2,
- size);
- lpfc_in_buf_free(phba, bdeBuf2);
+ bdeBuf = iocbq->context3;
+ iocbq->context3 = NULL;
+ size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize;
+ lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf,
+ size);
+ lpfc_in_buf_free(phba, bdeBuf);
}
}
+ list_del(&head);
} else {
struct lpfc_iocbq *next;
list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
icmd = &iocbq->iocb;
- if (icmd->ulpBdeCount == 0) {
- printk(KERN_ERR "%s (%d): Unsolited CT, no "
- "BDE, iocbq = %p, status = x%x\n",
- __FUNCTION__, __LINE__,
- iocbq, iocbq->iocb.ulpStatus);
- continue;
- }
-
+ if (icmd->ulpBdeCount == 0)
+ lpfc_ct_unsol_buffer(phba, piocbq, NULL, 0);
for (i = 0; i < icmd->ulpBdeCount; i++) {
paddr = getPaddr(icmd->un.cont64[i].addrHigh,
icmd->un.cont64[i].addrLow);
}
list_del(&iocbq->list);
lpfc_sli_release_iocbq(phba, iocbq);
+ lpfc_post_buffer(phba, pring, i, 1);
}
}
}
match = 0;
irsp = &(saveq->iocb);
+ if (irsp->ulpStatus == IOSTAT_NEED_BUFFER)
+ return 1;
if (irsp->ulpCommand == CMD_ASYNC_STATUS) {
if (pring->lpfc_sli_rcv_async_status)
pring->lpfc_sli_rcv_async_status(phba, pring, saveq);
return 1;
}
- if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
- || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
- || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
- || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
- Rctl = FC_ELS_REQ;
- Type = FC_ELS_DATA;
- } else {
- w5p =
- (WORD5 *) & (saveq->iocb.un.
- ulpWord[5]);
- Rctl = w5p->hcsw.Rctl;
- Type = w5p->hcsw.Type;
-
- /* Firmware Workaround */
- if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
- (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
- irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
- Rctl = FC_ELS_REQ;
- Type = FC_ELS_DATA;
- w5p->hcsw.Rctl = Rctl;
- w5p->hcsw.Type = Type;
- }
- }
-
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
- struct lpfc_hbq_entry *hbqe_1, *hbqe_2;
- hbqe_1 = (struct lpfc_hbq_entry *) &saveq->iocb.un.ulpWord[0];
- hbqe_2 = (struct lpfc_hbq_entry *) &saveq->iocb.
- unsli3.sli3Words[4];
-
if (irsp->ulpBdeCount != 0) {
saveq->context2 = lpfc_sli_get_buff(phba, pring,
irsp->un.ulpWord[3]);
"an unsolicited iocb. tag 0x%x\n",
pring->ringno,
irsp->un.ulpWord[3]);
-
}
if (irsp->ulpBdeCount == 2) {
saveq->context3 = lpfc_sli_get_buff(phba, pring,
irsp->unsli3.sli3Words[7]);
}
list_for_each_entry(iocbq, &saveq->list, list) {
- hbqe_1 = (struct lpfc_hbq_entry *) &iocbq->iocb.
- un.ulpWord[0];
- hbqe_2 = (struct lpfc_hbq_entry *) &iocbq->iocb.
- unsli3.sli3Words[4];
irsp = &(iocbq->iocb);
-
if (irsp->ulpBdeCount != 0) {
iocbq->context2 = lpfc_sli_get_buff(phba, pring,
irsp->un.ulpWord[3]);
- if (!saveq->context2)
+ if (!iocbq->context2)
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
if (irsp->ulpBdeCount == 2) {
iocbq->context3 = lpfc_sli_get_buff(phba, pring,
irsp->unsli3.sli3Words[7]);
- if (!saveq->context3)
+ if (!iocbq->context3)
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
}
}
}
+ if (irsp->ulpBdeCount != 0 &&
+ (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX ||
+ irsp->ulpStatus == IOSTAT_INTERMED_RSP)) {
+ int found = 0;
+
+ /* search continue save q for same XRI */
+ list_for_each_entry(iocbq, &pring->iocb_continue_saveq, clist) {
+ if (iocbq->iocb.ulpContext == saveq->iocb.ulpContext) {
+ list_add_tail(&saveq->list, &iocbq->list);
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ list_add_tail(&saveq->clist,
+ &pring->iocb_continue_saveq);
+ if (saveq->iocb.ulpStatus != IOSTAT_INTERMED_RSP) {
+ list_del_init(&iocbq->clist);
+ saveq = iocbq;
+ irsp = &(saveq->iocb);
+ } else
+ return 0;
+ }
+ if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) ||
+ (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) ||
+ (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)) {
+ Rctl = FC_ELS_REQ;
+ Type = FC_ELS_DATA;
+ } else {
+ w5p = (WORD5 *)&(saveq->iocb.un.ulpWord[5]);
+ Rctl = w5p->hcsw.Rctl;
+ Type = w5p->hcsw.Type;
+
+ /* Firmware Workaround */
+ if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
+ (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
+ irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
+ Rctl = FC_ELS_REQ;
+ Type = FC_ELS_DATA;
+ w5p->hcsw.Rctl = Rctl;
+ w5p->hcsw.Type = Type;
+ }
+ }
/* unSolicited Responses */
if (pring->prt[0].profile) {
} else {
/* We must search, based on rctl / type
for the right routine */
- for (i = 0; i < pring->num_mask;
- i++) {
- if ((pring->prt[i].rctl ==
- Rctl)
- && (pring->prt[i].
- type == Type)) {
+ for (i = 0; i < pring->num_mask; i++) {
+ if ((pring->prt[i].rctl == Rctl)
+ && (pring->prt[i].type == Type)) {
if (pring->prt[i].lpfc_sli_rcv_unsol_event)
(pring->prt[i].lpfc_sli_rcv_unsol_event)
(phba, pring, saveq);
writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
- if (list_empty(&(pring->iocb_continueq))) {
- list_add(&rspiocbp->list, &(pring->iocb_continueq));
- } else {
- list_add_tail(&rspiocbp->list,
- &(pring->iocb_continueq));
- }
+ list_add_tail(&rspiocbp->list, &(pring->iocb_continueq));
pring->iocb_continueq_cnt++;
if (irsp->ulpLe) {
iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
if (type == LPFC_SOL_IOCB) {
- spin_unlock_irqrestore(&phba->hbalock,
- iflag);
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
rc = lpfc_sli_process_sol_iocb(phba, pring,
saveq);
spin_lock_irqsave(&phba->hbalock, iflag);
} else if (type == LPFC_UNSOL_IOCB) {
- spin_unlock_irqrestore(&phba->hbalock,
- iflag);
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
rc = lpfc_sli_process_unsol_iocb(phba, pring,
saveq);
spin_lock_irqsave(&phba->hbalock, iflag);
+ if (!rc)
+ free_saveq = 0;
} else if (type == LPFC_ABORT_IOCB) {
if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
((cmdiocbp =
INIT_LIST_HEAD(&pring->txq);
INIT_LIST_HEAD(&pring->txcmplq);
INIT_LIST_HEAD(&pring->iocb_continueq);
+ INIT_LIST_HEAD(&pring->iocb_continue_saveq);
INIT_LIST_HEAD(&pring->postbufq);
}
spin_unlock_irq(&phba->hbalock);