Commit 6831ce12 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: SLI path split: Refactor base ELS paths and the FLOGI path

The patch refactors the general ELS handling paths to migrate to SLI-4
structures or common element abstractions. The fabric login paths are
revised as part of this patch:

 - New generic lpfc_sli_prep_els_req_rsp jump table routine

 - Introduce ls_rjt_error_be and ulp_bde64_le unions to correct legacy
   endianness assignments

 - 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.

 - Clean up poor indentation on some of the ELS paths

Link: https://lore.kernel.org/r/20220225022308.16486-5-jsmart2021@gmail.comCo-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 56134142
......@@ -961,7 +961,13 @@ struct lpfc_hba {
int (*lpfc_bg_scsi_prep_dma_buf)
(struct lpfc_hba *, struct lpfc_io_buf *);
/* Add new entries here */
/* Prep SLI WQE/IOCB jump table entries */
void (*__lpfc_sli_prep_els_req_rsp)(struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp,
u16 cmd_size, u32 did, u32 elscmd,
u8 tmo, u8 expect_rsp);
/* expedite pool */
struct lpfc_epd_pool epd_pool;
......@@ -1833,3 +1839,12 @@ u16 get_job_ulpcontext(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
else
return iocbq->iocb.ulpContext;
}
static inline
u32 get_job_els_rsp64_did(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
if (phba->sli_rev == LPFC_SLI_REV4)
return bf_get(wqe_els_did, &iocbq->wqe.els_req.wqe_dest);
else
return iocbq->iocb.un.elsreq64.remoteID;
}
......@@ -353,6 +353,11 @@ int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
struct lpfc_iocbq *pwqe);
int lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocb, void *cmpl);
void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
u32 elscmd, u8 tmo, u8 expect_rsp);
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);
......
......@@ -982,7 +982,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
goto out;
}
if (lpfc_error_lost_link(irsp)) {
if (lpfc_error_lost_link(irsp->ulpStatus, irsp->un.ulpWord[4])) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0226 NS query failed due to link event\n");
if (vport->fc_flag & FC_RSCN_MODE)
......@@ -1199,7 +1199,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
goto out;
}
if (lpfc_error_lost_link(irsp)) {
if (lpfc_error_lost_link(irsp->ulpStatus, irsp->un.ulpWord[4])) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"4166 NS query failed due to link event\n");
if (vport->fc_flag & FC_RSCN_MODE)
......
This diff is collapsed.
......@@ -664,6 +664,7 @@ struct fc_vft_header {
struct ls_rjt { /* Structure is in Big Endian format */
union {
__be32 ls_rjt_error_be;
uint32_t lsRjtError;
struct {
uint8_t lsRjtRsvd0; /* FC Word 0, bit 24:31 */
......@@ -4376,16 +4377,15 @@ lpfc_is_LC_HBA(unsigned short device)
}
/*
* Determine if an IOCB failed because of a link event or firmware reset.
* Determine if failed because of a link event or firmware reset.
*/
static inline int
lpfc_error_lost_link(IOCB_t *iocbp)
lpfc_error_lost_link(u32 ulp_status, u32 ulp_word4)
{
return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT &&
(iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED ||
iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
return (ulp_status == IOSTAT_LOCAL_REJECT &&
(ulp_word4 == IOERR_SLI_ABORTED ||
ulp_word4 == IOERR_LINK_DOWN ||
ulp_word4 == IOERR_SLI_DOWN));
}
#define MENLO_TRANSPORT_TYPE 0xfe
......
......@@ -61,6 +61,7 @@
((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))
#define get_wqe_reqtag(x) (((x)->wqe.words[9] >> 0) & 0xFFFF)
#define get_wqe_tmo(x) (((x)->wqe.words[7] >> 24) & 0x00FF)
#define get_job_ulpword(x, y) ((x)->iocb.un.ulpWord[y])
......@@ -237,6 +238,34 @@ struct lpfc_sli_intf {
/* PORT_CAPABILITIES constants. */
#define LPFC_MAX_SUPPORTED_PAGES 8
enum ulp_bde64_word3 {
ULP_BDE64_SIZE_MASK = 0xffffff,
ULP_BDE64_TYPE_SHIFT = 24,
ULP_BDE64_TYPE_MASK = (0xff << ULP_BDE64_TYPE_SHIFT),
/* BDE (Host_resident) */
ULP_BDE64_TYPE_BDE_64 = (0x00 << ULP_BDE64_TYPE_SHIFT),
/* Immediate Data BDE */
ULP_BDE64_TYPE_BDE_IMMED = (0x01 << ULP_BDE64_TYPE_SHIFT),
/* BDE (Port-resident) */
ULP_BDE64_TYPE_BDE_64P = (0x02 << ULP_BDE64_TYPE_SHIFT),
/* Input BDE (Host-resident) */
ULP_BDE64_TYPE_BDE_64I = (0x08 << ULP_BDE64_TYPE_SHIFT),
/* Input BDE (Port-resident) */
ULP_BDE64_TYPE_BDE_64IP = (0x0A << ULP_BDE64_TYPE_SHIFT),
/* BLP (Host-resident) */
ULP_BDE64_TYPE_BLP_64 = (0x40 << ULP_BDE64_TYPE_SHIFT),
/* BLP (Port-resident) */
ULP_BDE64_TYPE_BLP_64P = (0x42 << ULP_BDE64_TYPE_SHIFT),
};
struct ulp_bde64_le {
__le32 type_size; /* type 31:24, size 23:0 */
__le32 addr_low;
__le32 addr_high;
};
struct ulp_bde64 {
union ULP_BDE_TUS {
uint32_t w;
......
......@@ -11159,6 +11159,130 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
return phba->__lpfc_sli_issue_iocb(phba, ring_number, piocb, flag);
}
static void
__lpfc_sli_prep_els_req_rsp_s3(struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
u32 elscmd, u8 tmo, u8 expect_rsp)
{
struct lpfc_hba *phba = vport->phba;
IOCB_t *cmd;
cmd = &cmdiocbq->iocb;
memset(cmd, 0, sizeof(*cmd));
cmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
cmd->un.elsreq64.bdl.addrLow = putPaddrLow(bmp->phys);
cmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
if (expect_rsp) {
cmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
cmd->un.elsreq64.remoteID = did; /* DID */
cmd->ulpCommand = CMD_ELS_REQUEST64_CR;
cmd->ulpTimeout = tmo;
} else {
cmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
cmd->un.genreq64.xmit_els_remoteID = did; /* DID */
cmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
}
cmd->ulpBdeCount = 1;
cmd->ulpLe = 1;
cmd->ulpClass = CLASS3;
/* If we have NPIV enabled, we want to send ELS traffic by VPI. */
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
if (expect_rsp) {
cmd->un.elsreq64.myID = vport->fc_myDID;
/* For ELS_REQUEST64_CR, use the VPI by default */
cmd->ulpContext = phba->vpi_ids[vport->vpi];
}
cmd->ulpCt_h = 0;
/* The CT field must be 0=INVALID_RPI for the ECHO cmd */
if (elscmd == ELS_CMD_ECHO)
cmd->ulpCt_l = 0; /* context = invalid RPI */
else
cmd->ulpCt_l = 1; /* context = VPI */
}
}
static void
__lpfc_sli_prep_els_req_rsp_s4(struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
u32 elscmd, u8 tmo, u8 expect_rsp)
{
struct lpfc_hba *phba = vport->phba;
union lpfc_wqe128 *wqe;
struct ulp_bde64_le *bde;
wqe = &cmdiocbq->wqe;
memset(wqe, 0, sizeof(*wqe));
/* Word 0 - 2 BDE */
bde = (struct ulp_bde64_le *)&wqe->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(cmd_size);
bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64);
if (expect_rsp) {
bf_set(wqe_cmnd, &wqe->els_req.wqe_com, CMD_ELS_REQUEST64_CR);
/* Transfer length */
wqe->els_req.payload_len = cmd_size;
wqe->els_req.max_response_payload_len = FCELSSIZE;
/* DID */
bf_set(wqe_els_did, &wqe->els_req.wqe_dest, did);
} else {
/* DID */
bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, did);
/* Transfer length */
wqe->xmit_els_rsp.response_payload_len = cmd_size;
bf_set(wqe_cmnd, &wqe->xmit_els_rsp.wqe_com,
CMD_XMIT_ELS_RSP64_CX);
}
bf_set(wqe_tmo, &wqe->generic.wqe_com, tmo);
bf_set(wqe_reqtag, &wqe->generic.wqe_com, cmdiocbq->iotag);
bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
/* If we have NPIV enabled, we want to send ELS traffic by VPI.
* For SLI4, since the driver controls VPIs we also want to include
* all ELS pt2pt protocol traffic as well.
*/
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) ||
(vport->fc_flag & FC_PT2PT)) {
if (expect_rsp) {
bf_set(els_req64_sid, &wqe->els_req, vport->fc_myDID);
/* For ELS_REQUEST64_CR, use the VPI by default */
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
phba->vpi_ids[vport->vpi]);
}
/* The CT field must be 0=INVALID_RPI for the ECHO cmd */
if (elscmd == ELS_CMD_ECHO)
bf_set(wqe_ct, &wqe->generic.wqe_com, 0);
else
bf_set(wqe_ct, &wqe->generic.wqe_com, 1);
}
}
void
lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
u16 cmd_size, u32 did, u32 elscmd, u8 tmo,
u8 expect_rsp)
{
phba->__lpfc_sli_prep_els_req_rsp(cmdiocbq, vport, bmp, cmd_size, did,
elscmd, tmo, expect_rsp);
}
/**
* lpfc_sli_api_table_setup - Set up sli api function jump table
* @phba: The hba struct for which this call is being executed.
......@@ -11177,11 +11301,13 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s3;
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;
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;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
......@@ -19214,7 +19340,7 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
struct fc_frame_header *fc_hdr;
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *iocbq = NULL;
union lpfc_wqe *wqe;
union lpfc_wqe128 *pwqe;
struct lpfc_dmabuf *pcmd = NULL;
uint32_t frame_len;
int rc;
......@@ -19249,34 +19375,46 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
/* copyin the payload */
memcpy(pcmd->virt, dmabuf->dbuf.virt, frame_len);
/* fill in BDE's for command */
iocbq->iocb.un.xseq64.bdl.addrHigh = putPaddrHigh(pcmd->phys);
iocbq->iocb.un.xseq64.bdl.addrLow = putPaddrLow(pcmd->phys);
iocbq->iocb.un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDE_64;
iocbq->iocb.un.xseq64.bdl.bdeSize = frame_len;
iocbq->context2 = pcmd;
iocbq->vport = vport;
iocbq->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK;
iocbq->cmd_flag |= LPFC_USE_FCPWQIDX;
iocbq->num_bdes = 0;
pwqe = &iocbq->wqe;
/* fill in BDE's for command */
pwqe->gen_req.bde.addrHigh = putPaddrHigh(pcmd->phys);
pwqe->gen_req.bde.addrLow = putPaddrLow(pcmd->phys);
pwqe->gen_req.bde.tus.f.bdeSize = frame_len;
pwqe->gen_req.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
pwqe->send_frame.frame_len = frame_len;
pwqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((__be32 *)fc_hdr));
pwqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((__be32 *)fc_hdr + 1));
pwqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((__be32 *)fc_hdr + 2));
pwqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((__be32 *)fc_hdr + 3));
pwqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((__be32 *)fc_hdr + 4));
pwqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((__be32 *)fc_hdr + 5));
pwqe->generic.wqe_com.word7 = 0;
pwqe->generic.wqe_com.word10 = 0;
bf_set(wqe_cmnd, &pwqe->generic.wqe_com, CMD_SEND_FRAME);
bf_set(wqe_sof, &pwqe->generic.wqe_com, 0x2E); /* SOF byte */
bf_set(wqe_eof, &pwqe->generic.wqe_com, 0x41); /* EOF byte */
bf_set(wqe_lenloc, &pwqe->generic.wqe_com, 1);
bf_set(wqe_xbl, &pwqe->generic.wqe_com, 1);
bf_set(wqe_dbde, &pwqe->generic.wqe_com, 1);
bf_set(wqe_xc, &pwqe->generic.wqe_com, 1);
bf_set(wqe_cmd_type, &pwqe->generic.wqe_com, 0xA);
bf_set(wqe_cqid, &pwqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
bf_set(wqe_xri_tag, &pwqe->generic.wqe_com, iocbq->sli4_xritag);
bf_set(wqe_reqtag, &pwqe->generic.wqe_com, iocbq->iotag);
bf_set(wqe_class, &pwqe->generic.wqe_com, CLASS3);
pwqe->generic.wqe_com.abort_tag = iocbq->iotag;
/*
* Setup rest of the iocb as though it were a WQE
* Build the SEND_FRAME WQE
*/
wqe = (union lpfc_wqe *)&iocbq->iocb;
wqe->send_frame.frame_len = frame_len;
wqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((uint32_t *)fc_hdr));
wqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((uint32_t *)fc_hdr + 1));
wqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((uint32_t *)fc_hdr + 2));
wqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((uint32_t *)fc_hdr + 3));
wqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((uint32_t *)fc_hdr + 4));
wqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((uint32_t *)fc_hdr + 5));
iocbq->iocb.ulpCommand = CMD_SEND_FRAME;
iocbq->iocb.ulpLe = 1;
iocbq->cmd_cmpl = lpfc_sli4_mds_loopback_cmpl;
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0);
if (rc == IOCB_ERROR)
goto exit;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment