Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 77114
b: refs/heads/master
c: 9c2face
h: refs/heads/master
v: v3
  • Loading branch information
James Smart authored and James Bottomley committed Jan 23, 2008
1 parent 7141c9d commit 23681be
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 112 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 83108bd3826310def1e49330558467406c46b970
refs/heads/master: 9c2face68782d5b7a322df6aade0512b47d29f10
92 changes: 34 additions & 58 deletions trunk/drivers/scsi/lpfc/lpfc_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,45 +57,27 @@

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
Expand All @@ -109,11 +91,8 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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);
Expand All @@ -122,7 +101,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* 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;
}

Expand All @@ -133,38 +112,34 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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);
Expand All @@ -176,6 +151,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
list_del(&iocbq->list);
lpfc_sli_release_iocbq(phba, iocbq);
lpfc_post_buffer(phba, pring, i, 1);
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions trunk/drivers/scsi/lpfc/lpfc_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -2994,6 +2994,34 @@ typedef struct {
#endif
} RCV_ELS_REQ64;

/* IOCB Command template for RCV_SEQ64 */
struct rcv_seq64 {
struct ulp_bde64 elsReq;
uint32_t hbq_1;
uint32_t parmRo;
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rctl:8;
uint32_t type:8;
uint32_t dfctl:8;
uint32_t ls:1;
uint32_t fs:1;
uint32_t rsvd2:3;
uint32_t si:1;
uint32_t bc:1;
uint32_t rsvd3:1;
#else /* __LITTLE_ENDIAN_BITFIELD */
uint32_t rsvd3:1;
uint32_t bc:1;
uint32_t si:1;
uint32_t rsvd2:3;
uint32_t fs:1;
uint32_t ls:1;
uint32_t dfctl:8;
uint32_t type:8;
uint32_t rctl:8;
#endif
};

/* IOCB Command template for all 64 bit FCP Initiator commands */
typedef struct {
ULP_BDL bdl;
Expand Down Expand Up @@ -3085,6 +3113,7 @@ typedef struct _IOCB { /* IOCB structure */
FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */
ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */
QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */
struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */

uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */
} un;
Expand Down
109 changes: 56 additions & 53 deletions trunk/drivers/scsi/lpfc/lpfc_sli.c
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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);
Expand All @@ -970,36 +972,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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]);
Expand All @@ -1011,7 +984,6 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
"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,
Expand All @@ -1026,16 +998,11 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *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,
Expand All @@ -1047,7 +1014,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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,
Expand All @@ -1059,6 +1026,49 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
}
}
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) {
Expand All @@ -1069,12 +1079,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} 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);
Expand Down Expand Up @@ -1641,12 +1648,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,

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) {
Expand Down Expand Up @@ -1711,17 +1713,17 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
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 =
Expand Down Expand Up @@ -3238,6 +3240,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
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);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/scsi/lpfc/lpfc_sli.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef enum _lpfc_ctx_cmd {
struct lpfc_iocbq {
/* lpfc_iocbqs are used in double linked lists */
struct list_head list;
struct list_head clist;
uint16_t iotag; /* pre-assigned IO tag */
uint16_t rsvd1;

Expand Down Expand Up @@ -160,6 +161,7 @@ struct lpfc_sli_ring {
struct list_head iocb_continueq;
uint16_t iocb_continueq_cnt; /* current length of queue */
uint16_t iocb_continueq_max; /* max length */
struct list_head iocb_continue_saveq;

struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK];
uint32_t num_mask; /* number of mask entries in prt array */
Expand Down

0 comments on commit 23681be

Please sign in to comment.