提交 61910d6a 编写于 作者: J James Smart 提交者: Martin K. Petersen

scsi: lpfc: SLI path split: Refactor CT paths

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

 - Introduce generic lpfc_sli_prep_gen_req jump table routine

 - Introduce generic lpfc_sli_prep_xmit_seq64 jump table routine

 - Rename lpfcdiag_loop_post_rxbufs to lpfcdiag_sli3_loop_post_rxbufs to
   indicate that it is an SLI3 only path

 - Create new prep_wqe routine for unsolicited ELS rsp WQEs.

 - 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-13-jsmart2021@gmail.comCo-developed-by: NJustin Tee <justin.tee@broadcom.com>
Signed-off-by: NJustin Tee <justin.tee@broadcom.com>
Signed-off-by: NJames Smart <jsmart2021@gmail.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
上级 2d1928c5
......@@ -968,6 +968,13 @@ struct lpfc_hba {
struct lpfc_dmabuf *bmp,
u16 cmd_size, u32 did, u32 elscmd,
u8 tmo, u8 expect_rsp);
void (*__lpfc_sli_prep_gen_req)(struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi,
u32 num_entry, u8 tmo);
void (*__lpfc_sli_prep_xmit_seq64)(struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi,
u16 ox_id, u32 num_entry, u8 rctl,
u8 last_seq, u8 cr_cx_cmd);
/* expedite pool */
struct lpfc_epd_pool epd_pool;
......@@ -1849,6 +1856,15 @@ u16 get_job_rcvoxid(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
return iocbq->iocb.unsli3.rcvsli3.ox_id;
}
static inline
u32 get_job_data_placed(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
if (phba->sli_rev == LPFC_SLI_REV4)
return iocbq->wcqe_cmpl.total_data_placed;
else
return iocbq->iocb.un.genreq64.bdl.bdeSize;
}
static inline
u32 get_job_els_rsp64_did(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
......
......@@ -303,13 +303,12 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
struct bsg_job_data *dd_data;
struct bsg_job *job;
struct fc_bsg_reply *bsg_reply;
IOCB_t *rsp;
struct lpfc_dmabuf *bmp, *cmp, *rmp;
struct lpfc_nodelist *ndlp;
struct lpfc_bsg_iocb *iocb;
unsigned long flags;
unsigned int rsp_size;
int rc = 0;
u32 ulp_status, ulp_word4, total_data_placed;
dd_data = cmdiocbq->context1;
......@@ -333,14 +332,16 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
rmp = iocb->rmp;
cmp = cmdiocbq->context2;
bmp = cmdiocbq->context3;
rsp = &rspiocbq->iocb;
ulp_status = get_job_ulpstatus(phba, rspiocbq);
ulp_word4 = get_job_word4(phba, rspiocbq);
total_data_placed = get_job_data_placed(phba, rspiocbq);
/* Copy the completed data or set the error status */
if (job) {
if (rsp->ulpStatus) {
if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
if (ulp_status) {
if (ulp_status == IOSTAT_LOCAL_REJECT) {
switch (ulp_word4 & IOERR_PARAM_MASK) {
case IOERR_SEQUENCE_TIMEOUT:
rc = -ETIMEDOUT;
break;
......@@ -355,10 +356,9 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
rc = -EACCES;
}
} else {
rsp_size = rsp->un.genreq64.bdl.bdeSize;
bsg_reply->reply_payload_rcv_len =
lpfc_bsg_copy_data(rmp, &job->reply_payload,
rsp_size, 0);
total_data_placed, 0);
}
}
......@@ -388,22 +388,21 @@ static int
lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
{
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
struct lpfc_hba *phba = vport->phba;
struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct fc_bsg_reply *bsg_reply = job->reply;
struct ulp_bde64 *bpl = NULL;
uint32_t timeout;
struct lpfc_iocbq *cmdiocbq = NULL;
IOCB_t *cmd;
struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
int request_nseg;
int reply_nseg;
int request_nseg, reply_nseg;
u32 num_entry;
struct bsg_job_data *dd_data;
unsigned long flags;
uint32_t creg_val;
int rc = 0;
int iocb_stat;
u16 ulp_context;
/* in case no data is transferred */
bsg_reply->reply_payload_rcv_len = 0;
......@@ -426,8 +425,6 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
goto free_dd;
}
cmd = &cmdiocbq->iocb;
bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (!bmp) {
rc = -ENOMEM;
......@@ -461,29 +458,21 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
goto free_cmp;
}
cmd->un.genreq64.bdl.ulpIoTag32 = 0;
cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
cmd->un.genreq64.bdl.bdeSize =
(request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
cmd->un.genreq64.w5.hcsw.Dfctl = 0;
cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
cmd->ulpBdeCount = 1;
cmd->ulpLe = 1;
cmd->ulpClass = CLASS3;
cmd->ulpContext = ndlp->nlp_rpi;
num_entry = request_nseg + reply_nseg;
if (phba->sli_rev == LPFC_SLI_REV4)
cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
cmd->ulpOwner = OWN_CHIP;
ulp_context = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
else
ulp_context = ndlp->nlp_rpi;
lpfc_sli_prep_gen_req(phba, cmdiocbq, bmp, ulp_context, num_entry,
phba->fc_ratov * 2);
cmdiocbq->num_bdes = num_entry;
cmdiocbq->vport = phba->pport;
cmdiocbq->context2 = cmp;
cmdiocbq->context3 = bmp;
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
timeout = phba->fc_ratov * 2;
cmd->ulpTimeout = timeout;
cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
cmdiocbq->context1 = dd_data;
......@@ -916,6 +905,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_bsg_event *evt;
struct event_data *evt_dat = NULL;
struct lpfc_iocbq *iocbq;
IOCB_t *iocb = NULL;
size_t offset = 0;
struct list_head head;
struct ulp_bde64 *bde;
......@@ -923,13 +913,13 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
int i;
struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
struct lpfc_hbq_entry *hbqe;
struct lpfc_sli_ct_request *ct_req;
struct bsg_job *job = NULL;
struct fc_bsg_reply *bsg_reply;
struct bsg_job_data *dd_data = NULL;
unsigned long flags;
int size = 0;
u32 bde_count = 0;
INIT_LIST_HEAD(&head);
list_add_tail(&head, &piocbq->list);
......@@ -959,12 +949,17 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
/* take accumulated byte count from the last iocbq */
iocbq = list_entry(head.prev, typeof(*iocbq), list);
evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len;
if (phba->sli_rev == LPFC_SLI_REV4)
evt_dat->len = iocbq->wcqe_cmpl.total_data_placed;
else
evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len;
} else {
list_for_each_entry(iocbq, &head, list) {
for (i = 0; i < iocbq->iocb.ulpBdeCount; i++)
iocb = &iocbq->iocb;
for (i = 0; i < iocb->ulpBdeCount;
i++)
evt_dat->len +=
iocbq->iocb.un.cont64[i].tus.f.bdeSize;
iocb->un.cont64[i].tus.f.bdeSize;
}
}
......@@ -986,20 +981,20 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
bdeBuf1 = iocbq->context2;
bdeBuf2 = iocbq->context3;
}
for (i = 0; i < iocbq->iocb.ulpBdeCount; i++) {
if (phba->sli_rev == LPFC_SLI_REV4)
bde_count = iocbq->wcqe_cmpl.word3;
else
bde_count = iocbq->iocb.ulpBdeCount;
for (i = 0; i < bde_count; i++) {
if (phba->sli3_options &
LPFC_SLI3_HBQ_ENABLED) {
if (i == 0) {
hbqe = (struct lpfc_hbq_entry *)
&iocbq->iocb.un.ulpWord[0];
size = hbqe->bde.tus.f.bdeSize;
size = iocbq->wqe.gen_req.bde.tus.f.bdeSize;
dmabuf = bdeBuf1;
} else if (i == 1) {
hbqe = (struct lpfc_hbq_entry *)
&iocbq->iocb.unsli3.
sli3Words[4];
size = hbqe->bde.tus.f.bdeSize;
size = iocbq->unsol_rcv_len;
dmabuf = bdeBuf2;
}
if ((offset + size) > evt_dat->len)
......@@ -1054,16 +1049,16 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
dmabuf);
} else {
lpfc_sli3_post_buffer(phba,
pring,
1);
pring,
1);
}
break;
default:
if (!(phba->sli3_options &
LPFC_SLI3_HBQ_ENABLED))
lpfc_sli3_post_buffer(phba,
pring,
1);
pring,
1);
break;
}
}
......@@ -1086,14 +1081,15 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->ct_ctx[
evt_dat->immed_dat].SID);
phba->ct_ctx[evt_dat->immed_dat].rxid =
piocbq->iocb.ulpContext;
get_job_ulpcontext(phba, piocbq);
phba->ct_ctx[evt_dat->immed_dat].oxid =
piocbq->iocb.unsli3.rcvsli3.ox_id;
get_job_rcvoxid(phba, piocbq);
phba->ct_ctx[evt_dat->immed_dat].SID =
piocbq->iocb.un.rcvels.remoteID;
bf_get(wqe_els_did,
&piocbq->wqe.xmit_els_rsp.wqe_dest);
phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;
} else
evt_dat->immed_dat = piocbq->iocb.ulpContext;
evt_dat->immed_dat = get_job_ulpcontext(phba, piocbq);
evt_dat->type = FC_REG_CT_EVENT;
list_add(&evt_dat->node, &evt->events_to_see);
......@@ -1459,13 +1455,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp,
int num_entry)
{
IOCB_t *icmd;
struct lpfc_iocbq *ctiocb = NULL;
int rc = 0;
struct lpfc_nodelist *ndlp = NULL;
struct bsg_job_data *dd_data;
unsigned long flags;
uint32_t creg_val;
u16 ulp_context, iotag;
ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
if (!ndlp) {
......@@ -1492,62 +1488,36 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
goto no_ctiocb;
}
icmd = &ctiocb->iocb;
icmd->un.xseq64.bdl.ulpIoTag32 = 0;
icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys);
icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
icmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
icmd->un.xseq64.w5.hcsw.Dfctl = 0;
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL;
icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
/* Fill in rest of iocb */
icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
icmd->ulpBdeCount = 1;
icmd->ulpLe = 1;
icmd->ulpClass = CLASS3;
if (phba->sli_rev == LPFC_SLI_REV4) {
/* Do not issue unsol response if oxid not marked as valid */
if (phba->ct_ctx[tag].valid != UNSOL_VALID) {
rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
icmd->ulpContext = phba->ct_ctx[tag].rxid;
icmd->unsli3.rcvsli3.ox_id = phba->ct_ctx[tag].oxid;
ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
if (!ndlp) {
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
"2721 ndlp null for oxid %x SID %x\n",
icmd->ulpContext,
phba->ct_ctx[tag].SID);
rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
/* get a refernece count so the ndlp doesn't go away while
* we respond
*/
if (!lpfc_nlp_get(ndlp)) {
rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
icmd->un.ulpWord[3] =
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp,
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi],
phba->ct_ctx[tag].oxid, num_entry,
FC_RCTL_DD_SOL_CTL, 1,
CMD_XMIT_SEQUENCE64_WQE);
/* The exchange is done, mark the entry as invalid */
phba->ct_ctx[tag].valid = UNSOL_INVALID;
} else
icmd->ulpContext = (ushort) tag;
iotag = get_wqe_reqtag(ctiocb);
} else {
lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp, 0, tag, num_entry,
FC_RCTL_DD_SOL_CTL, 1,
CMD_XMIT_SEQUENCE64_CX);
ctiocb->num_bdes = num_entry;
iotag = ctiocb->iocb.ulpIoTag;
}
icmd->ulpTimeout = phba->fc_ratov * 2;
ulp_context = get_job_ulpcontext(phba, ctiocb);
/* Xmit CT response on exchange <xid> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
"2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
ulp_context, iotag, tag, phba->link_state);
ctiocb->cmd_flag |= LPFC_IO_LIBDFC;
ctiocb->vport = phba->pport;
......@@ -2633,7 +2603,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
{
struct lpfc_bsg_event *evt;
struct lpfc_iocbq *cmdiocbq, *rspiocbq;
IOCB_t *cmd, *rsp;
struct lpfc_dmabuf *dmabuf;
struct ulp_bde64 *bpl = NULL;
struct lpfc_sli_ct_request *ctreq = NULL;
......@@ -2641,6 +2610,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
int time_left;
int iocb_stat = IOCB_SUCCESS;
unsigned long flags;
u32 status;
*txxri = 0;
*rxxri = 0;
......@@ -2684,9 +2654,6 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
goto err_get_xri_exit;
}
cmd = &cmdiocbq->iocb;
rsp = &rspiocbq->iocb;
memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);
ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;
......@@ -2696,36 +2663,24 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_XRI_SETUP;
ctreq->CommandResponse.bits.Size = 0;
cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(dmabuf->phys);
cmd->un.xseq64.bdl.addrLow = putPaddrLow(dmabuf->phys);
cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
cmd->un.xseq64.bdl.bdeSize = sizeof(*bpl);
cmd->un.xseq64.w5.hcsw.Fctl = LA;
cmd->un.xseq64.w5.hcsw.Dfctl = 0;
cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR;
cmd->ulpBdeCount = 1;
cmd->ulpLe = 1;
cmd->ulpClass = CLASS3;
cmd->ulpContext = rpi;
cmdiocbq->context3 = dmabuf;
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
cmdiocbq->vport = phba->pport;
cmdiocbq->cmd_cmpl = NULL;
lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, dmabuf, rpi, 0, 1,
FC_RCTL_DD_SOL_CTL, 0, CMD_XMIT_SEQUENCE64_CR);
iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
rspiocbq,
(phba->fc_ratov * 2)
+ LPFC_DRVR_TIMEOUT);
if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) {
rspiocbq, (phba->fc_ratov * 2)
+ LPFC_DRVR_TIMEOUT);
status = get_job_ulpstatus(phba, rspiocbq);
if (iocb_stat != IOCB_SUCCESS || status != IOCB_SUCCESS) {
ret_val = -EIO;
goto err_get_xri_exit;
}
*txxri = rsp->ulpContext;
*txxri = get_job_ulpcontext(phba, rspiocbq);
evt->waiting = 1;
evt->wait_time_stamp = jiffies;
......@@ -2926,7 +2881,7 @@ diag_cmd_data_alloc(struct lpfc_hba *phba,
}
/**
* lpfcdiag_loop_post_rxbufs - post the receive buffers for an unsol CT cmd
* lpfcdiag_sli3_loop_post_rxbufs - post the receive buffers for an unsol CT cmd
* @phba: Pointer to HBA context object
* @rxxri: Receive exchange id
* @len: Number of data bytes
......@@ -2934,8 +2889,8 @@ diag_cmd_data_alloc(struct lpfc_hba *phba,
* This function allocates and posts a data buffer of sufficient size to receive
* an unsolicted CT command.
**/
static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
size_t len)
static int lpfcdiag_sli3_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
size_t len)
{
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *cmdiocbq;
......@@ -2972,7 +2927,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
/* Queue buffers for the receive exchange */
num_bde = (uint32_t)rxbuffer->flag;
dmp = &rxbuffer->dma;
cmd = &cmdiocbq->iocb;
i = 0;
......@@ -3040,7 +2994,6 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
ret_val = -EIO;
goto err_post_rxbufs_exit;
}
cmd = &cmdiocbq->iocb;
i = 0;
}
......@@ -3092,7 +3045,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
size_t segment_len = 0, segment_offset = 0, current_offset = 0;
uint16_t rpi = 0;
struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL;
IOCB_t *cmd, *rsp = NULL;
union lpfc_wqe128 *cmdwqe, *rspwqe;
struct lpfc_sli_ct_request *ctreq;
struct lpfc_dmabuf *txbmp;
struct ulp_bde64 *txbpl = NULL;
......@@ -3185,7 +3138,7 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
goto loopback_test_exit;
}
rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
rc = lpfcdiag_sli3_loop_post_rxbufs(phba, rxxri, full_size);
if (rc) {
lpfcdiag_loop_self_unreg(phba, rpi);
goto loopback_test_exit;
......@@ -3228,9 +3181,12 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
goto err_loopback_test_exit;
}
cmd = &cmdiocbq->iocb;
if (phba->sli_rev < LPFC_SLI_REV4)
rsp = &rspiocbq->iocb;
cmdwqe = &cmdiocbq->wqe;
memset(cmdwqe, 0, sizeof(union lpfc_wqe));
if (phba->sli_rev < LPFC_SLI_REV4) {
rspwqe = &rspiocbq->wqe;
memset(rspwqe, 0, sizeof(union lpfc_wqe));
}
INIT_LIST_HEAD(&head);
list_add_tail(&head, &txbuffer->dma.list);
......@@ -3262,42 +3218,32 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
/* Build the XMIT_SEQUENCE iocb */
num_bde = (uint32_t)txbuffer->flag;
cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys);
cmd->un.xseq64.bdl.addrLow = putPaddrLow(txbmp->phys);
cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
cmd->un.xseq64.bdl.bdeSize = (num_bde * sizeof(struct ulp_bde64));
cmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
cmd->un.xseq64.w5.hcsw.Dfctl = 0;
cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
cmd->ulpBdeCount = 1;
cmd->ulpLe = 1;
cmd->ulpClass = CLASS3;
cmdiocbq->num_bdes = num_bde;
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
cmdiocbq->vport = phba->pport;
cmdiocbq->cmd_cmpl = NULL;
cmdiocbq->context3 = txbmp;
if (phba->sli_rev < LPFC_SLI_REV4) {
cmd->ulpContext = txxri;
lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp, 0, txxri,
num_bde, FC_RCTL_DD_UNSOL_CTL, 1,
CMD_XMIT_SEQUENCE64_CX);
} else {
cmd->un.xseq64.bdl.ulpIoTag32 = 0;
cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi];
cmdiocbq->context3 = txbmp;
lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp,
phba->sli4_hba.rpi_ids[rpi], 0xffff,
full_size, FC_RCTL_DD_UNSOL_CTL, 1,
CMD_XMIT_SEQUENCE64_WQE);
cmdiocbq->sli4_xritag = NO_XRI;
cmd->unsli3.rcvsli3.ox_id = 0xffff;
}
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
cmdiocbq->vport = phba->pport;
cmdiocbq->cmd_cmpl = NULL;
iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
rspiocbq, (phba->fc_ratov * 2) +
LPFC_DRVR_TIMEOUT);
if ((iocb_stat != IOCB_SUCCESS) ||
((phba->sli_rev < LPFC_SLI_REV4) &&
(rsp->ulpStatus != IOSTAT_SUCCESS))) {
if (iocb_stat != IOCB_SUCCESS ||
(phba->sli_rev < LPFC_SLI_REV4 &&
(get_job_ulpstatus(phba, rspiocbq) != IOSTAT_SUCCESS))) {
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"3126 Failed loopback test issue iocb: "
"iocb_stat:x%x\n", iocb_stat);
......
......@@ -358,6 +358,14 @@ void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
u32 elscmd, u8 tmo, u8 expect_rsp);
void lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry,
u8 tmo);
void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
u32 num_entry, u8 rctl, u8 last_seq,
u8 cr_cx_cmd);
struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri);
struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba,
struct lpfc_iocbq *piocbq);
......
此差异已折叠。
......@@ -1255,20 +1255,15 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
struct lpfc_sglq *start_sglq = NULL;
struct lpfc_io_buf *lpfc_cmd;
struct lpfc_nodelist *ndlp;
struct lpfc_sli_ring *pring = NULL;
int found = 0;
u8 cmnd;
if (piocbq->cmd_flag & LPFC_IO_NVME_LS)
pring = phba->sli4_hba.nvmels_wq->pring;
else
pring = lpfc_phba_elsring(phba);
lockdep_assert_held(&pring->ring_lock);
cmnd = get_job_cmnd(phba, piocbq);
if (piocbq->cmd_flag & LPFC_IO_FCP) {
lpfc_cmd = (struct lpfc_io_buf *) piocbq->context1;
ndlp = lpfc_cmd->rdata->pnode;
} else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
} else if ((cmnd == CMD_GEN_REQUEST64_CR) &&
!(piocbq->cmd_flag & LPFC_IO_LIBDFC)) {
ndlp = piocbq->context_un.ndlp;
} else if (piocbq->cmd_flag & LPFC_IO_LIBDFC) {
......@@ -3367,6 +3362,56 @@ lpfc_complete_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 0;
}
static void
lpfc_sli_prep_unsol_wqe(struct lpfc_hba *phba,
struct lpfc_iocbq *saveq)
{
IOCB_t *irsp;
union lpfc_wqe128 *wqe;
u16 i = 0;
irsp = &saveq->iocb;
wqe = &saveq->wqe;
/* Fill wcqe with the IOCB status fields */
bf_set(lpfc_wcqe_c_status, &saveq->wcqe_cmpl, irsp->ulpStatus);
saveq->wcqe_cmpl.word3 = irsp->ulpBdeCount;
saveq->wcqe_cmpl.parameter = irsp->un.ulpWord[4];
saveq->wcqe_cmpl.total_data_placed = irsp->unsli3.rcvsli3.acc_len;
/* Source ID */
bf_set(els_rsp64_sid, &wqe->xmit_els_rsp, irsp->un.rcvels.parmRo);
/* rx-id of the response frame */
bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, irsp->ulpContext);
/* ox-id of the frame */
bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com,
irsp->unsli3.rcvsli3.ox_id);
/* DID */
bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest,
irsp->un.rcvels.remoteID);
/* unsol data len */
for (i = 0; i < irsp->ulpBdeCount; i++) {
struct lpfc_hbq_entry *hbqe = NULL;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
if (i == 0) {
hbqe = (struct lpfc_hbq_entry *)
&irsp->un.ulpWord[0];
saveq->wqe.gen_req.bde.tus.f.bdeSize =
hbqe->bde.tus.f.bdeSize;
} else if (i == 1) {
hbqe = (struct lpfc_hbq_entry *)
&irsp->unsli3.sli3Words[4];
saveq->unsol_rcv_len = hbqe->bde.tus.f.bdeSize;
}
}
}
}
/**
* lpfc_sli_process_unsol_iocb - Unsolicited iocb handler
* @phba: Pointer to HBA context object.
......@@ -3387,11 +3432,13 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
IOCB_t * irsp;
WORD5 * w5p;
dma_addr_t paddr;
uint32_t Rctl, Type;
struct lpfc_iocbq *iocbq;
struct lpfc_dmabuf *dmzbuf;
irsp = &(saveq->iocb);
irsp = &saveq->iocb;
saveq->vport = phba->pport;
if (irsp->ulpCommand == CMD_ASYNC_STATUS) {
if (pring->lpfc_sli_rcv_async_status)
......@@ -3409,22 +3456,22 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
if ((irsp->ulpCommand == CMD_IOCB_RET_XRI64_CX) &&
(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) {
(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) {
if (irsp->ulpBdeCount > 0) {
dmzbuf = lpfc_sli_get_buff(phba, pring,
irsp->un.ulpWord[3]);
irsp->un.ulpWord[3]);
lpfc_in_buf_free(phba, dmzbuf);
}
if (irsp->ulpBdeCount > 1) {
dmzbuf = lpfc_sli_get_buff(phba, pring,
irsp->unsli3.sli3Words[3]);
irsp->unsli3.sli3Words[3]);
lpfc_in_buf_free(phba, dmzbuf);
}
if (irsp->ulpBdeCount > 2) {
dmzbuf = lpfc_sli_get_buff(phba, pring,
irsp->unsli3.sli3Words[7]);
irsp->unsli3.sli3Words[7]);
lpfc_in_buf_free(phba, dmzbuf);
}
......@@ -3457,9 +3504,10 @@ 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) {
irsp = &(iocbq->iocb);
irsp = &iocbq->iocb;
if (irsp->ulpBdeCount != 0) {
iocbq->context2 = lpfc_sli_get_buff(phba, pring,
iocbq->context2 = lpfc_sli_get_buff(phba,
pring,
irsp->un.ulpWord[3]);
if (!iocbq->context2)
lpfc_printf_log(phba,
......@@ -3471,7 +3519,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
irsp->un.ulpWord[3]);
}
if (irsp->ulpBdeCount == 2) {
iocbq->context3 = lpfc_sli_get_buff(phba, pring,
iocbq->context3 = lpfc_sli_get_buff(phba,
pring,
irsp->unsli3.sli3Words[7]);
if (!iocbq->context3)
lpfc_printf_log(phba,
......@@ -3484,7 +3533,20 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
irsp->unsli3.sli3Words[7]);
}
}
} else {
paddr = getPaddr(irsp->un.cont64[0].addrHigh,
irsp->un.cont64[0].addrLow);
saveq->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
paddr);
if (irsp->ulpBdeCount == 2) {
paddr = getPaddr(irsp->un.cont64[1].addrHigh,
irsp->un.cont64[1].addrLow);
saveq->context3 = lpfc_sli_ringpostbuf_get(phba,
pring,
paddr);
}
}
if (irsp->ulpBdeCount != 0 &&
(irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX ||
irsp->ulpStatus == IOSTAT_INTERMED_RSP)) {
......@@ -3502,12 +3564,14 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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
irsp = &saveq->iocb;
} else {
return 0;
}
}
if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) ||
(irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) ||
......@@ -3530,6 +3594,19 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
}
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
(irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
if (irsp->unsli3.rcvsli3.vpi == 0xffff)
saveq->vport = phba->pport;
else
saveq->vport = lpfc_find_vport_by_vpid(phba,
irsp->unsli3.rcvsli3.vpi);
}
/* Prepare WQE with Unsol frame */
lpfc_sli_prep_unsol_wqe(phba, saveq);
if (!lpfc_complete_unsol_iocb(phba, pring, saveq, Rctl, Type))
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"0313 Ring %d handler: unexpected Rctl x%x "
......@@ -10570,6 +10647,195 @@ lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
elscmd, tmo, expect_rsp);
}
static void
__lpfc_sli_prep_gen_req_s3(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp,
u16 rpi, u32 num_entry, u8 tmo)
{
IOCB_t *cmd;
cmd = &cmdiocbq->iocb;
memset(cmd, 0, sizeof(*cmd));
cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
cmd->un.genreq64.bdl.bdeSize = num_entry * sizeof(struct ulp_bde64);
cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
cmd->ulpContext = rpi;
cmd->ulpClass = CLASS3;
cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
cmd->ulpBdeCount = 1;
cmd->ulpLe = 1;
cmd->ulpOwner = OWN_CHIP;
cmd->ulpTimeout = tmo;
}
static void
__lpfc_sli_prep_gen_req_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp,
u16 rpi, u32 num_entry, u8 tmo)
{
union lpfc_wqe128 *cmdwqe;
struct ulp_bde64_le *bde, *bpl;
u32 xmit_len = 0, total_len = 0, size, type, i;
cmdwqe = &cmdiocbq->wqe;
memset(cmdwqe, 0, sizeof(*cmdwqe));
/* Calculate total_len and xmit_len */
bpl = (struct ulp_bde64_le *)bmp->virt;
for (i = 0; i < num_entry; i++) {
size = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_SIZE_MASK;
total_len += size;
}
for (i = 0; i < num_entry; i++) {
size = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_SIZE_MASK;
type = le32_to_cpu(bpl[i].type_size) & ULP_BDE64_TYPE_MASK;
if (type != ULP_BDE64_TYPE_BDE_64)
break;
xmit_len += size;
}
/* Words 0 - 2 */
bde = (struct ulp_bde64_le *)&cmdwqe->generic.bde;
bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys));
bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys));
bde->type_size = cpu_to_le32(xmit_len);
bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BLP_64);
/* Word 3 */
cmdwqe->gen_req.request_payload_len = xmit_len;
/* Word 5 */
bf_set(wqe_type, &cmdwqe->gen_req.wge_ctl, FC_TYPE_CT);
bf_set(wqe_rctl, &cmdwqe->gen_req.wge_ctl, FC_RCTL_DD_UNSOL_CTL);
bf_set(wqe_si, &cmdwqe->gen_req.wge_ctl, 1);
bf_set(wqe_la, &cmdwqe->gen_req.wge_ctl, 1);
/* Word 6 */
bf_set(wqe_ctxt_tag, &cmdwqe->gen_req.wqe_com, rpi);
/* Word 7 */
bf_set(wqe_tmo, &cmdwqe->gen_req.wqe_com, tmo);
bf_set(wqe_class, &cmdwqe->gen_req.wqe_com, CLASS3);
bf_set(wqe_cmnd, &cmdwqe->gen_req.wqe_com, CMD_GEN_REQUEST64_CR);
bf_set(wqe_ct, &cmdwqe->gen_req.wqe_com, SLI4_CT_RPI);
/* Word 12 */
cmdwqe->gen_req.max_response_payload_len = total_len - xmit_len;
}
void
lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, u8 tmo)
{
phba->__lpfc_sli_prep_gen_req(cmdiocbq, bmp, rpi, num_entry, tmo);
}
static void
__lpfc_sli_prep_xmit_seq64_s3(struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd)
{
IOCB_t *icmd;
icmd = &cmdiocbq->iocb;
memset(icmd, 0, sizeof(*icmd));
icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys);
icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
icmd->un.xseq64.w5.hcsw.Fctl = LA;
if (last_seq)
icmd->un.xseq64.w5.hcsw.Fctl |= LS;
icmd->un.xseq64.w5.hcsw.Dfctl = 0;
icmd->un.xseq64.w5.hcsw.Rctl = rctl;
icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
icmd->ulpBdeCount = 1;
icmd->ulpLe = 1;
icmd->ulpClass = CLASS3;
switch (cr_cx_cmd) {
case CMD_XMIT_SEQUENCE64_CR:
icmd->ulpContext = rpi;
icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR;
break;
case CMD_XMIT_SEQUENCE64_CX:
icmd->ulpContext = ox_id;
icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
break;
default:
break;
}
}
static void
__lpfc_sli_prep_xmit_seq64_s4(struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
u32 full_size, u8 rctl, u8 last_seq, u8 cr_cx_cmd)
{
union lpfc_wqe128 *wqe;
struct ulp_bde64 *bpl;
struct ulp_bde64_le *bde;
wqe = &cmdiocbq->wqe;
memset(wqe, 0, sizeof(*wqe));
/* Words 0 - 2 */
bpl = (struct ulp_bde64 *)bmp->virt;
if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) {
wqe->xmit_sequence.bde.addrHigh = bpl->addrHigh;
wqe->xmit_sequence.bde.addrLow = bpl->addrLow;
wqe->xmit_sequence.bde.tus.w = bpl->tus.w;
} else {
bde = (struct ulp_bde64_le *)&wqe->xmit_sequence.bde;
bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys));
bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys));
bde->type_size = cpu_to_le32(bpl->tus.f.bdeSize);
bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64);
}
/* Word 5 */
bf_set(wqe_ls, &wqe->xmit_sequence.wge_ctl, last_seq);
bf_set(wqe_la, &wqe->xmit_sequence.wge_ctl, 1);
bf_set(wqe_dfctl, &wqe->xmit_sequence.wge_ctl, 0);
bf_set(wqe_rctl, &wqe->xmit_sequence.wge_ctl, rctl);
bf_set(wqe_type, &wqe->xmit_sequence.wge_ctl, FC_TYPE_CT);
/* Word 6 */
bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, rpi);
bf_set(wqe_cmnd, &wqe->xmit_sequence.wqe_com,
CMD_XMIT_SEQUENCE64_WQE);
/* Word 7 */
bf_set(wqe_class, &wqe->xmit_sequence.wqe_com, CLASS3);
/* Word 9 */
bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ox_id);
/* Word 12 */
if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK))
wqe->xmit_sequence.xmit_len = full_size;
else
wqe->xmit_sequence.xmit_len =
wqe->xmit_sequence.bde.tus.f.bdeSize;
}
void
lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd)
{
phba->__lpfc_sli_prep_xmit_seq64(cmdiocbq, bmp, rpi, ox_id, num_entry,
rctl, last_seq, cr_cx_cmd);
}
/**
* lpfc_sli_api_table_setup - Set up sli api function jump table
* @phba: The hba struct for which this call is being executed.
......@@ -10589,12 +10855,16 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s3;
phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s3;
phba->__lpfc_sli_prep_els_req_rsp = __lpfc_sli_prep_els_req_rsp_s3;
phba->__lpfc_sli_prep_gen_req = __lpfc_sli_prep_gen_req_s3;
phba->__lpfc_sli_prep_xmit_seq64 = __lpfc_sli_prep_xmit_seq64_s3;
break;
case LPFC_PCI_DEV_OC:
phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s4;
phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s4;
phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s4;
phba->__lpfc_sli_prep_els_req_rsp = __lpfc_sli_prep_els_req_rsp_s4;
phba->__lpfc_sli_prep_gen_req = __lpfc_sli_prep_gen_req_s4;
phba->__lpfc_sli_prep_xmit_seq64 = __lpfc_sli_prep_xmit_seq64_s4;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
......@@ -18469,7 +18739,6 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
struct fc_frame_header *fc_hdr;
uint32_t sid;
uint32_t len, tot_len;
struct ulp_bde64 *pbde;
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
/* remove from receive buffer list */
......@@ -18482,40 +18751,40 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
first_iocbq = lpfc_sli_get_iocbq(vport->phba);
if (first_iocbq) {
/* Initialize the first IOCB. */
first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0;
first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS;
first_iocbq->wcqe_cmpl.total_data_placed = 0;
bf_set(lpfc_wcqe_c_status, &first_iocbq->wcqe_cmpl,
IOSTAT_SUCCESS);
first_iocbq->vport = vport;
/* Check FC Header to see what TYPE of frame we are rcv'ing */
if (sli4_type_from_fc_hdr(fc_hdr) == FC_TYPE_ELS) {
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_ELS64_CX;
first_iocbq->iocb.un.rcvels.parmRo =
sli4_did_from_fc_hdr(fc_hdr);
first_iocbq->iocb.ulpPU = PARM_NPIV_DID;
} else
first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX;
first_iocbq->iocb.ulpContext = NO_XRI;
first_iocbq->iocb.unsli3.rcvsli3.ox_id =
be16_to_cpu(fc_hdr->fh_ox_id);
/* iocbq is prepped for internal consumption. Physical vpi. */
first_iocbq->iocb.unsli3.rcvsli3.vpi =
vport->phba->vpi_ids[vport->vpi];
/* put the first buffer into the first IOCBq */
bf_set(els_rsp64_sid, &first_iocbq->wqe.xmit_els_rsp,
sli4_did_from_fc_hdr(fc_hdr));
}
bf_set(wqe_ctxt_tag, &first_iocbq->wqe.xmit_els_rsp.wqe_com,
NO_XRI);
bf_set(wqe_rcvoxid, &first_iocbq->wqe.xmit_els_rsp.wqe_com,
be16_to_cpu(fc_hdr->fh_ox_id));
/* put the first buffer into the first iocb */
tot_len = bf_get(lpfc_rcqe_length,
&seq_dmabuf->cq_event.cqe.rcqe_cmpl);
&seq_dmabuf->cq_event.cqe.rcqe_cmpl);
first_iocbq->context2 = &seq_dmabuf->dbuf;
first_iocbq->context3 = NULL;
first_iocbq->iocb.ulpBdeCount = 1;
/* Keep track of the BDE count */
first_iocbq->wcqe_cmpl.word3 = 1;
if (tot_len > LPFC_DATA_BUF_SIZE)
first_iocbq->iocb.un.cont64[0].tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
first_iocbq->wqe.gen_req.bde.tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
else
first_iocbq->iocb.un.cont64[0].tus.f.bdeSize = tot_len;
first_iocbq->wqe.gen_req.bde.tus.f.bdeSize = tot_len;
first_iocbq->iocb.un.rcvels.remoteID = sid;
first_iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len;
first_iocbq->wcqe_cmpl.total_data_placed = tot_len;
bf_set(wqe_els_did, &first_iocbq->wqe.xmit_els_rsp.wqe_dest,
sid);
}
iocbq = first_iocbq;
/*
......@@ -18529,28 +18798,23 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
}
if (!iocbq->context3) {
iocbq->context3 = d_buf;
iocbq->iocb.ulpBdeCount++;
iocbq->wcqe_cmpl.word3++;
/* We need to get the size out of the right CQE */
hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
len = bf_get(lpfc_rcqe_length,
&hbq_buf->cq_event.cqe.rcqe_cmpl);
pbde = (struct ulp_bde64 *)
&iocbq->iocb.unsli3.sli3Words[4];
if (len > LPFC_DATA_BUF_SIZE)
pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE;
else
pbde->tus.f.bdeSize = len;
iocbq->iocb.unsli3.rcvsli3.acc_len += len;
iocbq->unsol_rcv_len = len;
iocbq->wcqe_cmpl.total_data_placed += len;
tot_len += len;
} else {
iocbq = lpfc_sli_get_iocbq(vport->phba);
if (!iocbq) {
if (first_iocbq) {
first_iocbq->iocb.ulpStatus =
IOSTAT_FCP_RSP_ERROR;
first_iocbq->iocb.un.ulpWord[4] =
IOERR_NO_RESOURCES;
bf_set(lpfc_wcqe_c_status,
&first_iocbq->wcqe_cmpl,
IOSTAT_SUCCESS);
first_iocbq->wcqe_cmpl.parameter =
IOERR_NO_RESOURCES;
}
lpfc_in_buf_free(vport->phba, d_buf);
continue;
......@@ -18561,17 +18825,19 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
&hbq_buf->cq_event.cqe.rcqe_cmpl);
iocbq->context2 = d_buf;
iocbq->context3 = NULL;
iocbq->iocb.ulpBdeCount = 1;
iocbq->wcqe_cmpl.word3 = 1;
if (len > LPFC_DATA_BUF_SIZE)
iocbq->iocb.un.cont64[0].tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
iocbq->wqe.xmit_els_rsp.bde.tus.f.bdeSize =
LPFC_DATA_BUF_SIZE;
else
iocbq->iocb.un.cont64[0].tus.f.bdeSize = len;
iocbq->wqe.xmit_els_rsp.bde.tus.f.bdeSize =
len;
tot_len += len;
iocbq->iocb.unsli3.rcvsli3.acc_len = tot_len;
iocbq->iocb.un.rcvels.remoteID = sid;
iocbq->wcqe_cmpl.total_data_placed = tot_len;
bf_set(wqe_els_did, &iocbq->wqe.xmit_els_rsp.wqe_dest,
sid);
list_add_tail(&iocbq->list, &first_iocbq->list);
}
}
......
......@@ -75,6 +75,7 @@ struct lpfc_iocbq {
IOCB_t iocb; /* SLI-3 */
struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
u32 unsol_rcv_len; /* Receive len in usol path */
uint8_t num_bdes;
uint8_t abort_bls; /* ABTS by initiator or responder */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册