提交 6dd9e31c 编写于 作者: J James Smart 提交者: James Bottomley

[SCSI] lpfc 8.3.37: Fixed no-context ABTS failed with BA_RJT

Fixed no-context ABTS received on unsolicited receive queue failed with BA_RJT
Signed-off-by: NJames Smart <james.smart@emulex.com>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 7b15db32
...@@ -466,11 +466,13 @@ enum intr_type_t { ...@@ -466,11 +466,13 @@ enum intr_type_t {
MSIX, MSIX,
}; };
#define LPFC_CT_CTX_MAX 64
struct unsol_rcv_ct_ctx { struct unsol_rcv_ct_ctx {
uint32_t ctxt_id; uint32_t ctxt_id;
uint32_t SID; uint32_t SID;
uint32_t flags; uint32_t valid;
#define UNSOL_VALID 0x00000001 #define UNSOL_INVALID 0
#define UNSOL_VALID 1
uint16_t oxid; uint16_t oxid;
uint16_t rxid; uint16_t rxid;
}; };
...@@ -938,7 +940,7 @@ struct lpfc_hba { ...@@ -938,7 +940,7 @@ struct lpfc_hba {
spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */ spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */
struct list_head ct_ev_waiters; struct list_head ct_ev_waiters;
struct unsol_rcv_ct_ctx ct_ctx[64]; struct unsol_rcv_ct_ctx ct_ctx[LPFC_CT_CTX_MAX];
uint32_t ctx_idx; uint32_t ctx_idx;
uint8_t menlo_flag; /* menlo generic flags */ uint8_t menlo_flag; /* menlo generic flags */
......
...@@ -955,9 +955,9 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -955,9 +955,9 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
spin_lock_irqsave(&phba->ct_ev_lock, flags); spin_lock_irqsave(&phba->ct_ev_lock, flags);
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
evt_dat->immed_dat = phba->ctx_idx; evt_dat->immed_dat = phba->ctx_idx;
phba->ctx_idx = (phba->ctx_idx + 1) % 64; phba->ctx_idx = (phba->ctx_idx + 1) % LPFC_CT_CTX_MAX;
/* Provide warning for over-run of the ct_ctx array */ /* Provide warning for over-run of the ct_ctx array */
if (phba->ct_ctx[evt_dat->immed_dat].flags & if (phba->ct_ctx[evt_dat->immed_dat].valid ==
UNSOL_VALID) UNSOL_VALID)
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
"2717 CT context array entry " "2717 CT context array entry "
...@@ -973,7 +973,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -973,7 +973,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
piocbq->iocb.unsli3.rcvsli3.ox_id; piocbq->iocb.unsli3.rcvsli3.ox_id;
phba->ct_ctx[evt_dat->immed_dat].SID = phba->ct_ctx[evt_dat->immed_dat].SID =
piocbq->iocb.un.rcvels.remoteID; piocbq->iocb.un.rcvels.remoteID;
phba->ct_ctx[evt_dat->immed_dat].flags = UNSOL_VALID; phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;
} else } else
evt_dat->immed_dat = piocbq->iocb.ulpContext; evt_dat->immed_dat = piocbq->iocb.ulpContext;
...@@ -1012,6 +1012,47 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -1012,6 +1012,47 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 1; return 1;
} }
/**
* lpfc_bsg_ct_unsol_abort - handler ct abort to management plane
* @phba: Pointer to HBA context object.
* @dmabuf: pointer to a dmabuf that describes the FC sequence
*
* This function handles abort to the CT command toward management plane
* for SLI4 port.
*
* If the pending context of a CT command to management plane present, clears
* such context and returns 1 for handled; otherwise, it returns 0 indicating
* no context exists.
**/
int
lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
{
struct fc_frame_header fc_hdr;
struct fc_frame_header *fc_hdr_ptr = &fc_hdr;
int ctx_idx, handled = 0;
uint16_t oxid, rxid;
uint32_t sid;
memcpy(fc_hdr_ptr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
sid = sli4_sid_from_fc_hdr(fc_hdr_ptr);
oxid = be16_to_cpu(fc_hdr_ptr->fh_ox_id);
rxid = be16_to_cpu(fc_hdr_ptr->fh_rx_id);
for (ctx_idx = 0; ctx_idx < LPFC_CT_CTX_MAX; ctx_idx++) {
if (phba->ct_ctx[ctx_idx].valid != UNSOL_VALID)
continue;
if (phba->ct_ctx[ctx_idx].rxid != rxid)
continue;
if (phba->ct_ctx[ctx_idx].oxid != oxid)
continue;
if (phba->ct_ctx[ctx_idx].SID != sid)
continue;
phba->ct_ctx[ctx_idx].valid = UNSOL_INVALID;
handled = 1;
}
return handled;
}
/** /**
* lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command
* @job: SET_EVENT fc_bsg_job * @job: SET_EVENT fc_bsg_job
...@@ -1318,7 +1359,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, ...@@ -1318,7 +1359,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
icmd->ulpClass = CLASS3; icmd->ulpClass = CLASS3;
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
/* Do not issue unsol response if oxid not marked as valid */ /* Do not issue unsol response if oxid not marked as valid */
if (!(phba->ct_ctx[tag].flags & UNSOL_VALID)) { if (phba->ct_ctx[tag].valid != UNSOL_VALID) {
rc = IOCB_ERROR; rc = IOCB_ERROR;
goto issue_ct_rsp_exit; goto issue_ct_rsp_exit;
} }
...@@ -1352,7 +1393,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, ...@@ -1352,7 +1393,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
/* The exchange is done, mark the entry as invalid */ /* The exchange is done, mark the entry as invalid */
phba->ct_ctx[tag].flags &= ~UNSOL_VALID; phba->ct_ctx[tag].valid = UNSOL_INVALID;
} else } else
icmd->ulpContext = (ushort) tag; icmd->ulpContext = (ushort) tag;
......
...@@ -164,8 +164,7 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *); ...@@ -164,8 +164,7 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *); struct lpfc_iocbq *);
void lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, int lpfc_ct_handle_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
struct lpfc_iocbq *);
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t); int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_fdmi_tmo(unsigned long); void lpfc_fdmi_tmo(unsigned long);
...@@ -427,6 +426,7 @@ int lpfc_bsg_request(struct fc_bsg_job *); ...@@ -427,6 +426,7 @@ int lpfc_bsg_request(struct fc_bsg_job *);
int lpfc_bsg_timeout(struct fc_bsg_job *); int lpfc_bsg_timeout(struct fc_bsg_job *);
int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *); struct lpfc_iocbq *);
int lpfc_bsg_ct_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *, void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *); struct lpfc_iocbq *);
struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *,
......
...@@ -164,37 +164,24 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -164,37 +164,24 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} }
/** /**
* lpfc_sli4_ct_abort_unsol_event - Default handle for sli4 unsol abort * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
* @phba: Pointer to HBA context object. * @phba: Pointer to HBA context object.
* @pring: Pointer to the driver internal I/O ring. * @dmabuf: pointer to a dmabuf that describes the FC sequence
* @piocbq: Pointer to the IOCBQ.
* *
* This function serves as the default handler for the sli4 unsolicited * This function serves as the upper level protocol abort handler for CT
* abort event. It shall be invoked when there is no application interface * protocol.
* registered unsolicited abort handler. This handler does nothing but *
* just simply releases the dma buffer used by the unsol abort event. * Return 1 if abort has been handled, 0 otherwise.
**/ **/
void int
lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *phba, lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocbq)
{ {
IOCB_t *icmd = &piocbq->iocb; int handled;
struct lpfc_dmabuf *bdeBuf;
uint32_t size;
/* Forward abort event to any process registered to receive ct event */ /* CT upper level goes through BSG */
if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0) handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);
return;
/* If there is no BDE associated with IOCB, there is nothing to do */ return handled;
if (icmd->ulpBdeCount == 0)
return;
bdeBuf = piocbq->context2;
piocbq->context2 = NULL;
size = icmd->un.cont64[0].tus.f.bdeSize;
lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
lpfc_in_buf_free(phba, bdeBuf);
} }
static void static void
......
...@@ -8855,12 +8855,6 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -8855,12 +8855,6 @@ lpfc_sli_setup(struct lpfc_hba *phba)
pring->prt[3].type = FC_TYPE_CT; pring->prt[3].type = FC_TYPE_CT;
pring->prt[3].lpfc_sli_rcv_unsol_event = pring->prt[3].lpfc_sli_rcv_unsol_event =
lpfc_ct_unsol_event; lpfc_ct_unsol_event;
/* abort unsolicited sequence */
pring->prt[4].profile = 0; /* Mask 4 */
pring->prt[4].rctl = FC_RCTL_BA_ABTS;
pring->prt[4].type = FC_TYPE_BLS;
pring->prt[4].lpfc_sli_rcv_unsol_event =
lpfc_sli4_ct_abort_unsol_event;
break; break;
} }
totiocbsize += (pring->sli.sli3.numCiocb * totiocbsize += (pring->sli.sli3.numCiocb *
...@@ -14062,6 +14056,40 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport, ...@@ -14062,6 +14056,40 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
return false; return false;
} }
/**
* lpfc_sli4_abort_ulp_seq - Abort assembled unsol sequence from ulp
* @vport: pointer to a vitural port
* @dmabuf: pointer to a dmabuf that describes the FC sequence
*
* This function tries to abort from the assembed sequence from upper level
* protocol, described by the information from basic abbort @dmabuf. It
* checks to see whether such pending context exists at upper level protocol.
* If so, it shall clean up the pending context.
*
* Return
* true -- if there is matching pending context of the sequence cleaned
* at ulp;
* false -- if there is no matching pending context of the sequence present
* at ulp.
**/
static bool
lpfc_sli4_abort_ulp_seq(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
{
struct lpfc_hba *phba = vport->phba;
int handled;
/* Accepting abort at ulp with SLI4 only */
if (phba->sli_rev < LPFC_SLI_REV4)
return false;
/* Register all caring upper level protocols to attend abort */
handled = lpfc_ct_handle_unsol_abort(phba, dmabuf);
if (handled)
return true;
return false;
}
/** /**
* lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler
* @phba: Pointer to HBA context object. * @phba: Pointer to HBA context object.
...@@ -14077,8 +14105,14 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, ...@@ -14077,8 +14105,14 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmd_iocbq, struct lpfc_iocbq *cmd_iocbq,
struct lpfc_iocbq *rsp_iocbq) struct lpfc_iocbq *rsp_iocbq)
{ {
if (cmd_iocbq) struct lpfc_nodelist *ndlp;
if (cmd_iocbq) {
ndlp = (struct lpfc_nodelist *)cmd_iocbq->context1;
lpfc_nlp_put(ndlp);
lpfc_nlp_not_used(ndlp);
lpfc_sli_release_iocbq(phba, cmd_iocbq); lpfc_sli_release_iocbq(phba, cmd_iocbq);
}
/* Failure means BLS ABORT RSP did not get delivered to remote node*/ /* Failure means BLS ABORT RSP did not get delivered to remote node*/
if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus) if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus)
...@@ -14118,9 +14152,10 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba, ...@@ -14118,9 +14152,10 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba,
* event after aborting the sequence handling. * event after aborting the sequence handling.
**/ **/
static void static void
lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
struct fc_frame_header *fc_hdr) struct fc_frame_header *fc_hdr, bool aborted)
{ {
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *ctiocb = NULL; struct lpfc_iocbq *ctiocb = NULL;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
uint16_t oxid, rxid, xri, lxri; uint16_t oxid, rxid, xri, lxri;
...@@ -14135,12 +14170,27 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, ...@@ -14135,12 +14170,27 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
oxid = be16_to_cpu(fc_hdr->fh_ox_id); oxid = be16_to_cpu(fc_hdr->fh_ox_id);
rxid = be16_to_cpu(fc_hdr->fh_rx_id); rxid = be16_to_cpu(fc_hdr->fh_rx_id);
ndlp = lpfc_findnode_did(phba->pport, sid); ndlp = lpfc_findnode_did(vport, sid);
if (!ndlp) { if (!ndlp) {
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
"1268 Find ndlp returned NULL for oxid:x%x " if (!ndlp) {
"SID:x%x\n", oxid, sid); lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
return; "1268 Failed to allocate ndlp for "
"oxid:x%x SID:x%x\n", oxid, sid);
return;
}
lpfc_nlp_init(vport, ndlp, sid);
/* Put ndlp onto pport node list */
lpfc_enqueue_node(vport, ndlp);
} else if (!NLP_CHK_NODE_ACT(ndlp)) {
/* re-setup ndlp without removing from node list */
ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
if (!ndlp) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
"3275 Failed to active ndlp found "
"for oxid:x%x SID:x%x\n", oxid, sid);
return;
}
} }
/* Allocate buffer for rsp iocb */ /* Allocate buffer for rsp iocb */
...@@ -14164,7 +14214,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, ...@@ -14164,7 +14214,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
icmd->ulpLe = 1; icmd->ulpLe = 1;
icmd->ulpClass = CLASS3; icmd->ulpClass = CLASS3;
icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
ctiocb->context1 = ndlp; ctiocb->context1 = lpfc_nlp_get(ndlp);
ctiocb->iocb_cmpl = NULL; ctiocb->iocb_cmpl = NULL;
ctiocb->vport = phba->pport; ctiocb->vport = phba->pport;
...@@ -14183,14 +14233,24 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, ...@@ -14183,14 +14233,24 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
if (lxri != NO_XRI) if (lxri != NO_XRI)
lpfc_set_rrq_active(phba, ndlp, lxri, lpfc_set_rrq_active(phba, ndlp, lxri,
(xri == oxid) ? rxid : oxid, 0); (xri == oxid) ? rxid : oxid, 0);
/* If the oxid maps to the FCP XRI range or if it is out of range, /* For BA_ABTS from exchange responder, if the logical xri with
* send a BLS_RJT. The driver no longer has that exchange. * the oxid maps to the FCP XRI range, the port no longer has
* Override the IOCB for a BA_RJT. * that exchange context, send a BLS_RJT. Override the IOCB for
* a BA_RJT.
*/
if ((fctl & FC_FC_EX_CTX) &&
(lxri > lpfc_sli4_get_els_iocb_cnt(phba))) {
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE);
}
/* If BA_ABTS failed to abort a partially assembled receive sequence,
* the driver no longer has that exchange, send a BLS_RJT. Override
* the IOCB for a BA_RJT.
*/ */
if (xri > (phba->sli4_hba.max_cfg_param.max_xri + if (aborted == false) {
phba->sli4_hba.max_cfg_param.xri_base) ||
xri > (lpfc_sli4_get_els_iocb_cnt(phba) +
phba->sli4_hba.max_cfg_param.xri_base)) {
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
...@@ -14214,17 +14274,19 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, ...@@ -14214,17 +14274,19 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid); bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid);
/* Xmit CT abts response on exchange <xid> */ /* Xmit CT abts response on exchange <xid> */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"1200 Send BLS cmd x%x on oxid x%x Data: x%x\n", "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state); icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
if (rc == IOCB_ERROR) { if (rc == IOCB_ERROR) {
lpfc_printf_log(phba, KERN_ERR, LOG_ELS, lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"2925 Failed to issue CT ABTS RSP x%x on " "2925 Failed to issue CT ABTS RSP x%x on "
"xri x%x, Data x%x\n", "xri x%x, Data x%x\n",
icmd->un.xseq64.w5.hcsw.Rctl, oxid, icmd->un.xseq64.w5.hcsw.Rctl, oxid,
phba->link_state); phba->link_state);
lpfc_nlp_put(ndlp);
ctiocb->context1 = NULL;
lpfc_sli_release_iocbq(phba, ctiocb); lpfc_sli_release_iocbq(phba, ctiocb);
} }
} }
...@@ -14249,32 +14311,25 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport, ...@@ -14249,32 +14311,25 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct fc_frame_header fc_hdr; struct fc_frame_header fc_hdr;
uint32_t fctl; uint32_t fctl;
bool abts_par; bool aborted;
/* Make a copy of fc_hdr before the dmabuf being released */ /* Make a copy of fc_hdr before the dmabuf being released */
memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
fctl = sli4_fctl_from_fc_hdr(&fc_hdr); fctl = sli4_fctl_from_fc_hdr(&fc_hdr);
if (fctl & FC_FC_EX_CTX) { if (fctl & FC_FC_EX_CTX) {
/* /* ABTS by responder to exchange, no cleanup needed */
* ABTS sent by responder to exchange, just free the buffer aborted = true;
*/
lpfc_in_buf_free(phba, &dmabuf->dbuf);
} else { } else {
/* /* ABTS by initiator to exchange, need to do cleanup */
* ABTS sent by initiator to exchange, need to do cleanup aborted = lpfc_sli4_abort_partial_seq(vport, dmabuf);
*/ if (aborted == false)
/* Try to abort partially assembled seq */ aborted = lpfc_sli4_abort_ulp_seq(vport, dmabuf);
abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf);
/* Send abort to ULP if partially seq abort failed */
if (abts_par == false)
lpfc_sli4_send_seq_to_ulp(vport, dmabuf);
else
lpfc_in_buf_free(phba, &dmabuf->dbuf);
} }
/* Send basic accept (BA_ACC) to the abort requester */ lpfc_in_buf_free(phba, &dmabuf->dbuf);
lpfc_sli4_seq_abort_rsp(phba, &fc_hdr);
/* Respond with BA_ACC or BA_RJT accordingly */
lpfc_sli4_seq_abort_rsp(vport, &fc_hdr, aborted);
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册