/******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.broadcom.com * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of version 2 of the GNU General * * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful. * * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * * TO BE LEGALLY INVALID. See the GNU General Public License for * * more details, a copy of which can be found in the file COPYING * * included with this package. *
*******************************************************************/
/* * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS
*/
/** * lpfc_ct_unsol_cmpl : Completion callback function for unsol ct commands * @phba : pointer to lpfc hba data structure. * @cmdiocb : pointer to lpfc command iocb data structure. * @rspiocb : pointer to lpfc response iocb data structure. * * This routine is the callback function for issuing unsol ct reject command. * The memory allocated in the reject command path is freed up here.
**/ staticvoid
lpfc_ct_unsol_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb)
{ struct lpfc_nodelist *ndlp; struct lpfc_dmabuf *mp, *bmp;
ndlp = cmdiocb->ndlp; if (ndlp)
lpfc_nlp_put(ndlp);
/* Save for completion so we can release these resources */
cmdiocbq->rsp_dmabuf = mp;
cmdiocbq->bpl_dmabuf = bmp;
cmdiocbq->cmd_cmpl = lpfc_ct_unsol_cmpl;
tmo = (3 * phba->fc_ratov);
/** * lpfc_ct_handle_mibreq - Process an unsolicited CT MIB request data buffer * @phba: pointer to lpfc hba data structure. * @ctiocbq: pointer to lpfc CT command iocb data structure. * * This routine is used for processing the IOCB associated with a unsolicited * CT MIB request. It first determines whether there is an existing ndlp that * matches the DID from the unsolicited IOCB. If not, it will return.
**/ staticvoid
lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq)
{ struct lpfc_sli_ct_request *ct_req; struct lpfc_nodelist *ndlp = NULL; struct lpfc_vport *vport = ctiocbq->vport;
u32 ulp_status = get_job_ulpstatus(phba, ctiocbq);
u32 ulp_word4 = get_job_word4(phba, ctiocbq);
u32 did;
u16 mi_cmd;
did = bf_get(els_rsp64_sid, &ctiocbq->wqe.xmit_els_rsp); if (ulp_status) {
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS, "6438 Unsol CT: status:x%x/x%x did : x%x\n",
ulp_status, ulp_word4, did); return;
}
/* Ignore traffic received during vport shutdown */ if (test_bit(FC_UNLOADING, &vport->load_flag)) return;
ndlp = lpfc_findnode_did(vport, did); if (!ndlp) {
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS, "6439 Unsol CT: NDLP Not Found for DID : x%x",
did); return;
}
mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp);
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS, "6442 MI Cmd: x%x Not Supported\n", mi_cmd);
lpfc_ct_reject_event(ndlp, ct_req,
bf_get(wqe_ctxt_tag,
&ctiocbq->wqe.xmit_els_rsp.wqe_com),
bf_get(wqe_rcvoxid,
&ctiocbq->wqe.xmit_els_rsp.wqe_com));
}
/** * lpfc_ct_unsol_event - Process an unsolicited event from a ct sli ring * @phba: pointer to lpfc hba data structure. * @pring: pointer to a SLI ring. * @ctiocbq: pointer to lpfc ct iocb data structure. * * This routine is used to process an unsolicited event received from a SLI * (Service Level Interface) ring. The actual processing of the data buffer * associated with the unsolicited event is done by invoking appropriate routine * after properly set up the iocb buffer from the SLI ring on which the * unsolicited event was received.
**/ void
lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *ctiocbq)
{ struct lpfc_dmabuf *mp = NULL;
IOCB_t *icmd = &ctiocbq->iocb; int i; struct lpfc_iocbq *iocbq; struct lpfc_iocbq *iocb;
dma_addr_t dma_addr;
uint32_t size; struct list_head head; struct lpfc_sli_ct_request *ct_req; struct lpfc_dmabuf *bdeBuf1 = ctiocbq->cmd_dmabuf; struct lpfc_dmabuf *bdeBuf2 = ctiocbq->bpl_dmabuf;
u32 status, parameter, bde_count = 0; struct lpfc_wcqe_complete *wcqe_cmpl = NULL;
/** * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler * @phba: Pointer to HBA context object. * @dmabuf: pointer to a dmabuf that describes the FC sequence * * This function serves as the upper level protocol abort handler for CT * protocol. * * Return 1 if abort has been handled, 0 otherwise.
**/ int
lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
{ int handled;
/* * lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer * @vport: pointer to a host virtual N_Port data structure. * @bmp: Pointer to BPL for SLI command * @inp: Pointer to data buffer for response data. * @outp: Pointer to data buffer that hold the CT command. * @cmpl: completion routine to call when command completes * @ndlp: Destination NPort nodelist entry * * This function as the final part for issuing a CT command.
*/ staticint
lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *), struct lpfc_nodelist *ndlp, uint32_t event_tag, uint32_t num_entry,
uint32_t tmo, uint8_t retry)
{ struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *geniocb; int rc;
u16 ulp_context;
/* Allocate buffer for command iocb */
geniocb = lpfc_sli_get_iocbq(phba);
if (geniocb == NULL) return 1;
/* Update the num_entry bde count */
geniocb->num_bdes = num_entry;
geniocb->bpl_dmabuf = bmp;
/* Save for completion so we can release these resources */
geniocb->cmd_dmabuf = inp;
geniocb->rsp_dmabuf = outp;
geniocb->event_tag = event_tag;
if (!tmo) { /* FC spec states we need 3 * ratov for CT requests */
tmo = (3 * phba->fc_ratov);
}
/* * lpfc_ct_cmd - Build and issue a CT command * @vport: pointer to a host virtual N_Port data structure. * @inmp: Pointer to data buffer for response data. * @bmp: Pointer to BPL for SLI command * @ndlp: Destination NPort nodelist entry * @cmpl: completion routine to call when command completes * * This function is called for issuing a CT command.
*/ staticint
lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp, void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *),
uint32_t rsp_size, uint8_t retry)
{ struct lpfc_hba *phba = vport->phba; struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt; struct lpfc_dmabuf *outmp; int cnt = 0, status;
__be16 cmdcode = ((struct lpfc_sli_ct_request *)inmp->virt)->
CommandResponse.bits.CmdRsp;
bpl++; /* Skip past ct request */
/* Put buffer(s) for ct rsp in bpl */
outmp = lpfc_alloc_ct_rsp(phba, cmdcode, bpl, rsp_size, &cnt); if (!outmp) return -ENOMEM; /* * Form the CT IOCB. The total number of BDEs in this IOCB * is the single command plus response count from * lpfc_alloc_ct_rsp.
*/
cnt += 1;
status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp,
phba->fc_eventTag, cnt, 0, retry); if (status) {
lpfc_free_ct_rsp(phba, outmp); return -ENOMEM;
} return 0;
}
/* if ndlp needs to be discovered and prior * state of ndlp hit devloss, change state to * allow rediscovery.
*/ if (test_bit(NLP_NPR_2B_DISC, &ndlp->nlp_flag) &&
ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_NPR_NODE);
}
} else {
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "Skip1 GID_FTrsp: did:x%x flg:x%lx cnt:%d",
Did, vport->fc_flag, vport->fc_rscn_id_cnt);
if (!ctptr) {
ctptr = (uint32_t *) mlast->virt;
} else
Cnt -= 16; /* subtract length of CT header */
/* Loop through entire NameServer list of DIDs */ while (Cnt >= sizeof(uint32_t)) { /* Get next DID from NameServer List */
CTentry = *ctptr++;
Did = ((be32_to_cpu(CTentry)) & Mask_DID);
lpfc_ns_rsp_audit_did(vport, Did, fc4_type); if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY))) goto nsout1;
Cnt -= sizeof(uint32_t);
}
ctptr = NULL;
}
/* All GID_FT entries processed. If the driver is running in * in target mode, put impacted nodes into recovery and drop * the RPI to flush outstanding IO.
*/ if (vport->phba->nvmet_support) {
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { if (!test_bit(NLP_NVMET_RECOV, &ndlp->nlp_flag)) continue;
lpfc_disc_state_machine(vport, ndlp, NULL,
NLP_EVT_DEVICE_RECOVERY);
clear_bit(NLP_NVMET_RECOV, &ndlp->nlp_flag);
}
}
/* Ignore response if link flipped after this request was made */ if (cmdiocb->event_tag != phba->fc_eventTag) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "9043 Event tag mismatch. Ignoring NS rsp\n"); goto out;
}
/* Skip processing response on pport if unloading */ if (vport == phba->pport && test_bit(FC_UNLOADING, &vport->load_flag)) { if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport); goto out;
}
if (lpfc_els_chk_latt(vport)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0216 Link event during NS query\n"); if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport);
lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out;
} if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0226 NS query failed due to link event: " "ulp_status x%x ulp_word4 x%x fc_flag x%lx " "port_state x%x gidft_inp x%x\n",
ulp_status, ulp_word4, vport->fc_flag,
vport->port_state, vport->gidft_inp); if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport); if (vport->gidft_inp)
vport->gidft_inp--; goto out;
}
if (test_and_clear_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) { /* This is a GID_FT completing so the gidft_inp counter was * incremented before the GID_FT was issued to the wire.
*/ if (vport->gidft_inp)
vport->gidft_inp--;
/* * Skip processing the NS response * Re-issue the NS cmd
*/
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0151 Process Deferred RSCN Data: x%lx x%x\n",
vport->fc_flag, vport->fc_rscn_id_cnt);
lpfc_els_handle_rscn(vport);
goto out;
}
if (ulp_status) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { if (ulp_status != IOSTAT_LOCAL_REJECT ||
(ulp_word4 & IOERR_PARAM_MASK) !=
IOERR_NO_RESOURCES)
vport->fc_ns_retry++;
type = lpfc_get_gidft_type(vport, cmdiocb); if (type == 0) goto out;
/* Link up / RSCN discovery */ if ((vport->num_disc_nodes == 0) &&
(vport->gidft_inp == 0)) { /* * The driver has cycled through all Nports in the RSCN payload. * Complete the handling by cleaning up and marking the * current driver state.
*/ if (vport->port_state >= LPFC_DISC_AUTH) { if (test_bit(FC_RSCN_MODE, &vport->fc_flag)) {
lpfc_els_flush_rscn(vport); /* RSCN still */
set_bit(FC_RSCN_MODE, &vport->fc_flag);
} else {
lpfc_els_flush_rscn(vport);
}
}
/* Ignore response if link flipped after this request was made */ if (cmdiocb->event_tag != phba->fc_eventTag) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "9044 Event tag mismatch. Ignoring NS rsp\n"); goto out;
}
/* Skip processing response on pport if unloading */ if (vport == phba->pport && test_bit(FC_UNLOADING, &vport->load_flag)) { if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport); goto out;
}
if (lpfc_els_chk_latt(vport)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4108 Link event during NS query\n"); if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport);
lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out;
} if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4166 NS query failed due to link event: " "ulp_status x%x ulp_word4 x%x fc_flag x%lx " "port_state x%x gidft_inp x%x\n",
ulp_status, ulp_word4, vport->fc_flag,
vport->port_state, vport->gidft_inp); if (test_bit(FC_RSCN_MODE, &vport->fc_flag))
lpfc_els_flush_rscn(vport); if (vport->gidft_inp)
vport->gidft_inp--; goto out;
}
if (test_and_clear_bit(FC_RSCN_DEFERRED, &vport->fc_flag)) { /* This is a GID_PT completing so the gidft_inp counter was * incremented before the GID_PT was issued to the wire.
*/ if (vport->gidft_inp)
vport->gidft_inp--;
/* * Skip processing the NS response * Re-issue the NS cmd
*/
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "4167 Process Deferred RSCN Data: x%lx x%x\n",
vport->fc_flag, vport->fc_rscn_id_cnt);
lpfc_els_handle_rscn(vport);
goto out;
}
if (ulp_status) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { if (ulp_status != IOSTAT_LOCAL_REJECT ||
(ulp_word4 & IOERR_PARAM_MASK) !=
IOERR_NO_RESOURCES)
vport->fc_ns_retry++;
/* Link up / RSCN discovery */ if ((vport->num_disc_nodes == 0) &&
(vport->gidft_inp == 0)) { /* * The driver has cycled through all Nports in the RSCN payload. * Complete the handling by cleaning up and marking the * current driver state.
*/ if (vport->port_state >= LPFC_DISC_AUTH) { if (test_bit(FC_RSCN_MODE, &vport->fc_flag)) {
lpfc_els_flush_rscn(vport); /* RSCN still */
set_bit(FC_RSCN_MODE, &vport->fc_flag);
} else {
lpfc_els_flush_rscn(vport);
}
}
/* Ignore response if link flipped after this request was made */ if (cmdiocb->event_tag != phba->fc_eventTag) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "9045 Event tag mismatch. Ignoring NS rsp\n"); goto iocb_free;
}
if (ulp_status == IOSTAT_SUCCESS) { /* Good status, continue checking */
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
case IOERR_NO_RESOURCES: /* We don't increment the retry * count for this case.
*/ break; case IOERR_LINK_DOWN: case IOERR_SLI_ABORTED: case IOERR_SLI_DOWN:
retry = 0; break; default:
cmdiocb->retry++;
}
} else
cmdiocb->retry++;
if (vport->num_disc_nodes == 0) { /* * The driver has cycled through all Nports in the RSCN payload. * Complete the handling by cleaning up and marking the * current driver state.
*/ if (vport->port_state >= LPFC_DISC_AUTH) { if (test_bit(FC_RSCN_MODE, &vport->fc_flag)) {
lpfc_els_flush_rscn(vport); /* RSCN still */
set_bit(FC_RSCN_MODE, &vport->fc_flag);
} else {
lpfc_els_flush_rscn(vport);
}
}
lpfc_disc_start(vport);
}
/* Ignore response if link flipped after this request was made */ if ((uint32_t)cmdiocb->event_tag != phba->fc_eventTag) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "9046 Event tag mismatch. Ignoring NS rsp\n"); goto out;
}
/* Lookup the NPort_ID queried in the GFT_ID and find the * driver's local node. It's an error if the driver * doesn't have one.
*/
ndlp = lpfc_findnode_did(vport, did); if (ndlp) { /* The bitmask value for FCP and NVME FCP types is * the same because they are 32 bits distant from * each other in word0 and word0.
*/ if (fc4_data_0 & LPFC_FC4_TYPE_BITMASK)
ndlp->nlp_fc4_type |= NLP_FC4_FCP; if (fc4_data_1 & LPFC_FC4_TYPE_BITMASK)
ndlp->nlp_fc4_type |= NLP_FC4_NVME;
lpfc_printf_vlog(vport, KERN_INFO,
LOG_DISCOVERY | LOG_NODE, "3064 Setting ndlp x%px, DID x%06x " "with FC4 x%08x, Data: x%08x x%08x " "%d\n",
ndlp, did, ndlp->nlp_fc4_type,
FC_TYPE_FCP, FC_TYPE_NVME,
ndlp->nlp_state);
if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE &&
ndlp->nlp_fc4_type) {
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_PRLI_ISSUE);
lpfc_issue_els_prli(vport, ndlp, 0);
} elseif (!ndlp->nlp_fc4_type) { /* If fc4 type is still unknown, then LOGO */
lpfc_printf_vlog(vport, KERN_INFO,
LOG_DISCOVERY | LOG_NODE, "6443 Sending LOGO ndlp x%px, " "DID x%06x with fc4_type: " "x%08x, state: %d\n",
ndlp, did, ndlp->nlp_fc4_type,
ndlp->nlp_state);
lpfc_issue_els_logo(vport, ndlp, 0);
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_NPR_NODE);
}
}
} else
lpfc_vlog_msg(vport, KERN_WARNING, LOG_DISCOVERY, "3065 GFT_ID status x%08x\n", ulp_status);
out: /* If the caller wanted a synchronous DA_ID completion, signal the * wait obj and clear flag to reset the vport.
*/ if (test_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags)) { if (ndlp->da_id_waitq)
wake_up(ndlp->da_id_waitq);
}
/* * Although the symbolic port name is thought to be an integer * as of January 18, 2016, leave it as a string until more of * the record state becomes defined.
*/ int
lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
size_t size)
{ int n;
/* * Use the lpfc board number as the Symbolic Port * Name object. NPIV is not in play so this integer * value is sufficient and unique per FC-ID.
*/
n = scnprintf(symbol, size, "%d", vport->phba->brd_no); return n;
}
/* * This routine will return the FC4 Type associated with the CT * GID_FT command.
*/ int
lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb)
{ struct lpfc_sli_ct_request *CtReq; struct lpfc_dmabuf *mp;
uint32_t type;
mp = cmdiocb->cmd_dmabuf; if (mp == NULL) return 0;
CtReq = (struct lpfc_sli_ct_request *)mp->virt;
type = (uint32_t)CtReq->un.gid.Fc4Type; if ((type != SLI_CTPT_FCP) && (type != SLI_CTPT_NVME)) return 0; return type;
}
/* The driver always supports FC_TYPE_FCP. However, the * caller can specify NVME (type x28) as well. But only * these that FC4 type is supported.
*/ if (((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
(vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) &&
(context == FC_TYPE_NVME)) { if ((vport == phba->pport) && phba->nvmet_support) {
CtReq->un.rff.fbits = (FC4_FEATURE_TARGET |
FC4_FEATURE_NVME_DISC);
lpfc_nvmet_update_targetport(phba);
} else {
lpfc_nvme_update_localport(vport);
}
CtReq->un.rff.type_code = context;
/** * lpfc_fdmi_rprt_defer - Check for any deferred FDMI RPRT commands * @phba: Pointer to HBA context object. * @mask: Initial port attributes mask * * This function checks to see if any vports have deferred their FDMI RPRT. * A vports RPRT may be deferred if it is issued before the primary ports * RHBA completes.
*/ staticvoid
lpfc_fdmi_rprt_defer(struct lpfc_hba *phba, uint32_t mask)
{ struct lpfc_vport **vports; struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; int i;
set_bit(HBA_RHBA_CMPL, &phba->hba_flag);
vports = lpfc_create_vport_work_array(phba); if (vports) { for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
vport = vports[i];
ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); if (!ndlp) continue; if (vport->ct_flags & FC_CT_RPRT_DEFER) {
vport->ct_flags &= ~FC_CT_RPRT_DEFER;
vport->fdmi_port_mask = mask;
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0);
}
}
}
lpfc_destroy_vport_work_array(phba, vports);
}
/** * lpfc_cmpl_ct_disc_fdmi - Handle a discovery FDMI completion * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to the command IOCBQ. * @rspiocb: Pointer to the response IOCBQ. * * This function to handle the completion of a driver initiated FDMI * CT command issued during discovery.
*/ staticvoid
lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb)
{ struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_dmabuf *inp = cmdiocb->cmd_dmabuf; struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf; struct lpfc_sli_ct_request *CTcmd = inp->virt; struct lpfc_sli_ct_request *CTrsp = outp->virt;
__be16 fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
__be16 fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; struct lpfc_nodelist *ndlp, *free_ndlp = NULL;
uint32_t latt, cmd, err;
u32 ulp_status = get_job_ulpstatus(phba, rspiocb);
u32 ulp_word4 = get_job_word4(phba, rspiocb);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.