3186 lines · c
1/*******************************************************************2 * This file is part of the Emulex Linux Device Driver for *3 * Fibre Channel Host Bus Adapters. *4 * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *5 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *6 * Copyright (C) 2004-2016 Emulex. All rights reserved. *7 * EMULEX and SLI are trademarks of Emulex. *8 * www.broadcom.com *9 * Portions Copyright (C) 2004-2005 Christoph Hellwig *10 * *11 * This program is free software; you can redistribute it and/or *12 * modify it under the terms of version 2 of the GNU General *13 * Public License as published by the Free Software Foundation. *14 * This program is distributed in the hope that it will be useful. *15 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *16 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *17 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *18 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *19 * TO BE LEGALLY INVALID. See the GNU General Public License for *20 * more details, a copy of which can be found in the file COPYING *21 * included with this package. *22 *******************************************************************/23 24#include <linux/blkdev.h>25#include <linux/pci.h>26#include <linux/slab.h>27#include <linux/interrupt.h>28 29#include <scsi/scsi.h>30#include <scsi/scsi_device.h>31#include <scsi/scsi_host.h>32#include <scsi/scsi_transport_fc.h>33#include <scsi/fc/fc_fs.h>34 35#include "lpfc_hw4.h"36#include "lpfc_hw.h"37#include "lpfc_sli.h"38#include "lpfc_sli4.h"39#include "lpfc_nl.h"40#include "lpfc_disc.h"41#include "lpfc.h"42#include "lpfc_scsi.h"43#include "lpfc_nvme.h"44#include "lpfc_logmsg.h"45#include "lpfc_crtn.h"46#include "lpfc_vport.h"47#include "lpfc_debugfs.h"48 49 50/* Called to clear RSCN discovery flags when driver is unloading. */51static bool52lpfc_check_unload_and_clr_rscn(unsigned long *fc_flag)53{54 /* If unloading, then clear the FC_RSCN_DEFERRED flag */55 if (test_bit(FC_UNLOADING, fc_flag)) {56 clear_bit(FC_RSCN_DEFERRED, fc_flag);57 return false;58 }59 return test_bit(FC_RSCN_DEFERRED, fc_flag);60}61 62/* Called to verify a rcv'ed ADISC was intended for us. */63static int64lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,65 struct lpfc_name *nn, struct lpfc_name *pn)66{67 /* First, we MUST have a RPI registered */68 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))69 return 0;70 71 /* Compare the ADISC rsp WWNN / WWPN matches our internal node72 * table entry for that node.73 */74 if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))75 return 0;76 77 if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))78 return 0;79 80 /* we match, return success */81 return 1;82}83 84int85lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,86 struct serv_parm *sp, uint32_t class, int flogi)87{88 volatile struct serv_parm *hsp = &vport->fc_sparam;89 uint16_t hsp_value, ssp_value = 0;90 91 /*92 * The receive data field size and buffer-to-buffer receive data field93 * size entries are 16 bits but are represented as two 8-bit fields in94 * the driver data structure to account for rsvd bits and other control95 * bits. Reconstruct and compare the fields as a 16-bit values before96 * correcting the byte values.97 */98 if (sp->cls1.classValid) {99 if (!flogi) {100 hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |101 hsp->cls1.rcvDataSizeLsb);102 ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |103 sp->cls1.rcvDataSizeLsb);104 if (!ssp_value)105 goto bad_service_param;106 if (ssp_value > hsp_value) {107 sp->cls1.rcvDataSizeLsb =108 hsp->cls1.rcvDataSizeLsb;109 sp->cls1.rcvDataSizeMsb =110 hsp->cls1.rcvDataSizeMsb;111 }112 }113 } else if (class == CLASS1)114 goto bad_service_param;115 if (sp->cls2.classValid) {116 if (!flogi) {117 hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |118 hsp->cls2.rcvDataSizeLsb);119 ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |120 sp->cls2.rcvDataSizeLsb);121 if (!ssp_value)122 goto bad_service_param;123 if (ssp_value > hsp_value) {124 sp->cls2.rcvDataSizeLsb =125 hsp->cls2.rcvDataSizeLsb;126 sp->cls2.rcvDataSizeMsb =127 hsp->cls2.rcvDataSizeMsb;128 }129 }130 } else if (class == CLASS2)131 goto bad_service_param;132 if (sp->cls3.classValid) {133 if (!flogi) {134 hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |135 hsp->cls3.rcvDataSizeLsb);136 ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |137 sp->cls3.rcvDataSizeLsb);138 if (!ssp_value)139 goto bad_service_param;140 if (ssp_value > hsp_value) {141 sp->cls3.rcvDataSizeLsb =142 hsp->cls3.rcvDataSizeLsb;143 sp->cls3.rcvDataSizeMsb =144 hsp->cls3.rcvDataSizeMsb;145 }146 }147 } else if (class == CLASS3)148 goto bad_service_param;149 150 /*151 * Preserve the upper four bits of the MSB from the PLOGI response.152 * These bits contain the Buffer-to-Buffer State Change Number153 * from the target and need to be passed to the FW.154 */155 hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;156 ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;157 if (ssp_value > hsp_value) {158 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;159 sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |160 (hsp->cmn.bbRcvSizeMsb & 0x0F);161 }162 163 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));164 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));165 return 1;166bad_service_param:167 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,168 "0207 Device %x "169 "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "170 "invalid service parameters. Ignoring device.\n",171 ndlp->nlp_DID,172 sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],173 sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],174 sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],175 sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);176 return 0;177}178 179static void *180lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,181 struct lpfc_iocbq *rspiocb)182{183 struct lpfc_dmabuf *pcmd, *prsp;184 uint32_t *lp;185 void *ptr = NULL;186 u32 ulp_status = get_job_ulpstatus(phba, rspiocb);187 188 pcmd = cmdiocb->cmd_dmabuf;189 190 /* For lpfc_els_abort, cmd_dmabuf could be zero'ed to delay191 * freeing associated memory till after ABTS completes.192 */193 if (pcmd) {194 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf,195 list);196 if (prsp) {197 lp = (uint32_t *) prsp->virt;198 ptr = (void *)((uint8_t *)lp + sizeof(uint32_t));199 }200 } else {201 /* Force ulp_status error since we are returning NULL ptr */202 if (!(ulp_status)) {203 if (phba->sli_rev == LPFC_SLI_REV4) {204 bf_set(lpfc_wcqe_c_status, &rspiocb->wcqe_cmpl,205 IOSTAT_LOCAL_REJECT);206 rspiocb->wcqe_cmpl.parameter = IOERR_SLI_ABORTED;207 } else {208 rspiocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;209 rspiocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;210 }211 }212 ptr = NULL;213 }214 return ptr;215}216 217 218 219/*220 * Free resources / clean up outstanding I/Os221 * associated with a LPFC_NODELIST entry. This222 * routine effectively results in a "software abort".223 */224void225lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)226{227 LIST_HEAD(abort_list);228 LIST_HEAD(drv_cmpl_list);229 struct lpfc_sli_ring *pring;230 struct lpfc_iocbq *iocb, *next_iocb;231 int retval = 0;232 233 pring = lpfc_phba_elsring(phba);234 235 /* In case of error recovery path, we might have a NULL pring here */236 if (unlikely(!pring))237 return;238 239 /* Abort outstanding I/O on NPort <nlp_DID> */240 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,241 "2819 Abort outstanding I/O on NPort x%x "242 "Data: x%x x%x x%x\n",243 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,244 ndlp->nlp_rpi);245 /* Clean up all fabric IOs first.*/246 lpfc_fabric_abort_nport(ndlp);247 248 /*249 * Lock the ELS ring txcmplq for SLI3/SLI4 and build a local list250 * of all ELS IOs that need an ABTS. The IOs need to stay on the251 * txcmplq so that the abort operation completes them successfully.252 */253 spin_lock_irq(&phba->hbalock);254 if (phba->sli_rev == LPFC_SLI_REV4)255 spin_lock(&pring->ring_lock);256 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {257 /* Add to abort_list on on NDLP match. */258 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))259 list_add_tail(&iocb->dlist, &abort_list);260 }261 if (phba->sli_rev == LPFC_SLI_REV4)262 spin_unlock(&pring->ring_lock);263 spin_unlock_irq(&phba->hbalock);264 265 /* Abort the targeted IOs and remove them from the abort list. */266 list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {267 spin_lock_irq(&phba->hbalock);268 list_del_init(&iocb->dlist);269 retval = lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);270 spin_unlock_irq(&phba->hbalock);271 272 if (retval && test_bit(FC_UNLOADING, &phba->pport->load_flag)) {273 list_del_init(&iocb->list);274 list_add_tail(&iocb->list, &drv_cmpl_list);275 }276 }277 278 lpfc_sli_cancel_iocbs(phba, &drv_cmpl_list, IOSTAT_LOCAL_REJECT,279 IOERR_SLI_ABORTED);280 281 /* Make sure HBA is alive */282 lpfc_issue_hb_tmo(phba);283 284 INIT_LIST_HEAD(&abort_list);285 286 /* Now process the txq */287 spin_lock_irq(&phba->hbalock);288 if (phba->sli_rev == LPFC_SLI_REV4)289 spin_lock(&pring->ring_lock);290 291 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {292 /* Check to see if iocb matches the nport we are looking for */293 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {294 list_del_init(&iocb->list);295 list_add_tail(&iocb->list, &abort_list);296 }297 }298 299 if (phba->sli_rev == LPFC_SLI_REV4)300 spin_unlock(&pring->ring_lock);301 spin_unlock_irq(&phba->hbalock);302 303 /* Cancel all the IOCBs from the completions list */304 lpfc_sli_cancel_iocbs(phba, &abort_list,305 IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);306 307 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);308}309 310/* lpfc_defer_plogi_acc - Issue PLOGI ACC after reg_login completes311 * @phba: pointer to lpfc hba data structure.312 * @login_mbox: pointer to REG_RPI mailbox object313 *314 * The ACC for a rcv'ed PLOGI is deferred until AFTER the REG_RPI completes315 */316static void317lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)318{319 struct lpfc_iocbq *save_iocb;320 struct lpfc_nodelist *ndlp;321 MAILBOX_t *mb = &login_mbox->u.mb;322 323 int rc;324 325 ndlp = login_mbox->ctx_ndlp;326 save_iocb = login_mbox->ctx_u.save_iocb;327 328 if (mb->mbxStatus == MBX_SUCCESS) {329 /* Now that REG_RPI completed successfully,330 * we can now proceed with sending the PLOGI ACC.331 */332 rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,333 save_iocb, ndlp, NULL);334 if (rc) {335 lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,336 "4576 PLOGI ACC fails pt2pt discovery: "337 "DID %x Data: %x\n", ndlp->nlp_DID, rc);338 }339 }340 341 /* Now process the REG_RPI cmpl */342 lpfc_mbx_cmpl_reg_login(phba, login_mbox);343 ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;344 kfree(save_iocb);345}346 347static int348lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,349 struct lpfc_iocbq *cmdiocb)350{351 struct lpfc_hba *phba = vport->phba;352 struct lpfc_dmabuf *pcmd;353 uint64_t nlp_portwwn = 0;354 uint32_t *lp;355 union lpfc_wqe128 *wqe;356 IOCB_t *icmd;357 struct serv_parm *sp;358 uint32_t ed_tov;359 LPFC_MBOXQ_t *link_mbox;360 LPFC_MBOXQ_t *login_mbox;361 struct lpfc_iocbq *save_iocb;362 struct ls_rjt stat;363 uint32_t vid, flag;364 int rc;365 u32 remote_did;366 367 memset(&stat, 0, sizeof (struct ls_rjt));368 pcmd = cmdiocb->cmd_dmabuf;369 lp = (uint32_t *) pcmd->virt;370 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));371 if (wwn_to_u64(sp->portName.u.wwn) == 0) {372 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,373 "0140 PLOGI Reject: invalid pname\n");374 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;375 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;376 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,377 NULL);378 return 0;379 }380 if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {381 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,382 "0141 PLOGI Reject: invalid nname\n");383 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;384 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;385 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,386 NULL);387 return 0;388 }389 390 nlp_portwwn = wwn_to_u64(ndlp->nlp_portname.u.wwn);391 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {392 /* Reject this request because invalid parameters */393 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;394 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;395 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,396 NULL);397 return 0;398 }399 400 if (phba->sli_rev == LPFC_SLI_REV4)401 wqe = &cmdiocb->wqe;402 else403 icmd = &cmdiocb->iocb;404 405 /* PLOGI chkparm OK */406 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,407 "0114 PLOGI chkparm OK Data: x%x x%x x%x "408 "x%x x%x x%lx\n",409 ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,410 ndlp->nlp_rpi, vport->port_state,411 vport->fc_flag);412 413 if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)414 ndlp->nlp_fcp_info |= CLASS2;415 else416 ndlp->nlp_fcp_info |= CLASS3;417 418 ndlp->nlp_class_sup = 0;419 if (sp->cls1.classValid)420 ndlp->nlp_class_sup |= FC_COS_CLASS1;421 if (sp->cls2.classValid)422 ndlp->nlp_class_sup |= FC_COS_CLASS2;423 if (sp->cls3.classValid)424 ndlp->nlp_class_sup |= FC_COS_CLASS3;425 if (sp->cls4.classValid)426 ndlp->nlp_class_sup |= FC_COS_CLASS4;427 ndlp->nlp_maxframe =428 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;429 /* if already logged in, do implicit logout */430 switch (ndlp->nlp_state) {431 case NLP_STE_NPR_NODE:432 if (!(ndlp->nlp_flag & NLP_NPR_ADISC))433 break;434 fallthrough;435 case NLP_STE_REG_LOGIN_ISSUE:436 case NLP_STE_PRLI_ISSUE:437 case NLP_STE_UNMAPPED_NODE:438 case NLP_STE_MAPPED_NODE:439 /* For initiators, lpfc_plogi_confirm_nport skips fabric did.440 * For target mode, execute implicit logo.441 * Fabric nodes go into NPR.442 */443 if (!(ndlp->nlp_type & NLP_FABRIC) &&444 !(phba->nvmet_support)) {445 /* Clear ndlp info, since follow up PRLI may have446 * updated ndlp information447 */448 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);449 ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);450 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;451 ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;452 ndlp->nlp_flag &= ~NLP_FIRSTBURST;453 454 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,455 ndlp, NULL);456 return 1;457 }458 if (nlp_portwwn != 0 &&459 nlp_portwwn != wwn_to_u64(sp->portName.u.wwn))460 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,461 "0143 PLOGI recv'd from DID: x%x "462 "WWPN changed: old %llx new %llx\n",463 ndlp->nlp_DID,464 (unsigned long long)nlp_portwwn,465 (unsigned long long)466 wwn_to_u64(sp->portName.u.wwn));467 468 /* Notify transport of connectivity loss to trigger cleanup. */469 if (phba->nvmet_support &&470 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)471 lpfc_nvmet_invalidate_host(phba, ndlp);472 473 ndlp->nlp_prev_state = ndlp->nlp_state;474 /* rport needs to be unregistered first */475 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);476 break;477 }478 479 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);480 ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);481 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;482 ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;483 ndlp->nlp_flag &= ~NLP_FIRSTBURST;484 485 login_mbox = NULL;486 link_mbox = NULL;487 save_iocb = NULL;488 489 /* Check for Nport to NPort pt2pt protocol */490 if (test_bit(FC_PT2PT, &vport->fc_flag) &&491 !test_bit(FC_PT2PT_PLOGI, &vport->fc_flag)) {492 /* rcv'ed PLOGI decides what our NPortId will be */493 if (phba->sli_rev == LPFC_SLI_REV4) {494 vport->fc_myDID = bf_get(els_rsp64_sid,495 &cmdiocb->wqe.xmit_els_rsp);496 } else {497 vport->fc_myDID = icmd->un.rcvels.parmRo;498 }499 500 /* If there is an outstanding FLOGI, abort it now.501 * The remote NPort is not going to ACC our FLOGI502 * if its already issuing a PLOGI for pt2pt mode.503 * This indicates our FLOGI was dropped; however, we504 * must have ACCed the remote NPorts FLOGI to us505 * to make it here.506 */507 if (test_bit(HBA_FLOGI_OUTSTANDING, &phba->hba_flag))508 lpfc_els_abort_flogi(phba);509 510 ed_tov = be32_to_cpu(sp->cmn.e_d_tov);511 if (sp->cmn.edtovResolution) {512 /* E_D_TOV ticks are in nanoseconds */513 ed_tov = (phba->fc_edtov + 999999) / 1000000;514 }515 516 /*517 * For pt-to-pt, use the larger EDTOV518 * RATOV = 2 * EDTOV519 */520 if (ed_tov > phba->fc_edtov)521 phba->fc_edtov = ed_tov;522 phba->fc_ratov = (2 * phba->fc_edtov) / 1000;523 524 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));525 526 /* Issue CONFIG_LINK for SLI3 or REG_VFI for SLI4,527 * to account for updated TOV's / parameters528 */529 if (phba->sli_rev == LPFC_SLI_REV4)530 lpfc_issue_reg_vfi(vport);531 else {532 link_mbox = mempool_alloc(phba->mbox_mem_pool,533 GFP_KERNEL);534 if (!link_mbox)535 goto out;536 lpfc_config_link(phba, link_mbox);537 link_mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;538 link_mbox->vport = vport;539 540 /* The default completion handling for CONFIG_LINK541 * does not require the ndlp so no reference is needed.542 */543 link_mbox->ctx_ndlp = ndlp;544 545 rc = lpfc_sli_issue_mbox(phba, link_mbox, MBX_NOWAIT);546 if (rc == MBX_NOT_FINISHED) {547 mempool_free(link_mbox, phba->mbox_mem_pool);548 goto out;549 }550 }551 552 lpfc_can_disctmo(vport);553 }554 555 ndlp->nlp_flag &= ~NLP_SUPPRESS_RSP;556 if ((phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) &&557 sp->cmn.valid_vendor_ver_level) {558 vid = be32_to_cpu(sp->un.vv.vid);559 flag = be32_to_cpu(sp->un.vv.flags);560 if ((vid == LPFC_VV_EMLX_ID) && (flag & LPFC_VV_SUPPRESS_RSP))561 ndlp->nlp_flag |= NLP_SUPPRESS_RSP;562 }563 564 login_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);565 if (!login_mbox)566 goto out;567 568 save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL);569 if (!save_iocb)570 goto out;571 572 /* Save info from cmd IOCB to be used in rsp after all mbox completes */573 memcpy((uint8_t *)save_iocb, (uint8_t *)cmdiocb,574 sizeof(struct lpfc_iocbq));575 576 /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */577 if (phba->sli_rev == LPFC_SLI_REV4)578 lpfc_unreg_rpi(vport, ndlp);579 580 /* Issue REG_LOGIN first, before ACCing the PLOGI, thus we will581 * always be deferring the ACC.582 */583 if (phba->sli_rev == LPFC_SLI_REV4)584 remote_did = bf_get(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest);585 else586 remote_did = icmd->un.rcvels.remoteID;587 rc = lpfc_reg_rpi(phba, vport->vpi, remote_did,588 (uint8_t *)sp, login_mbox, ndlp->nlp_rpi);589 if (rc)590 goto out;591 592 login_mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;593 login_mbox->vport = vport;594 595 /*596 * If there is an outstanding PLOGI issued, abort it before597 * sending ACC rsp for received PLOGI. If pending plogi598 * is not canceled here, the plogi will be rejected by599 * remote port and will be retried. On a configuration with600 * single discovery thread, this will cause a huge delay in601 * discovery. Also this will cause multiple state machines602 * running in parallel for this node.603 * This only applies to a fabric environment.604 */605 if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&606 test_bit(FC_FABRIC, &vport->fc_flag)) {607 /* software abort outstanding PLOGI */608 lpfc_els_abort(phba, ndlp);609 }610 611 if ((vport->port_type == LPFC_NPIV_PORT &&612 vport->cfg_restrict_login)) {613 614 /* no deferred ACC */615 kfree(save_iocb);616 617 /* This is an NPIV SLI4 instance that does not need to register618 * a default RPI.619 */620 if (phba->sli_rev == LPFC_SLI_REV4) {621 lpfc_mbox_rsrc_cleanup(phba, login_mbox,622 MBOX_THD_UNLOCKED);623 login_mbox = NULL;624 } else {625 /* In order to preserve RPIs, we want to cleanup626 * the default RPI the firmware created to rcv627 * this ELS request. The only way to do this is628 * to register, then unregister the RPI.629 */630 spin_lock_irq(&ndlp->lock);631 ndlp->nlp_flag |= (NLP_RM_DFLT_RPI | NLP_ACC_REGLOGIN |632 NLP_RCV_PLOGI);633 spin_unlock_irq(&ndlp->lock);634 }635 636 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;637 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;638 rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,639 ndlp, login_mbox);640 if (rc && login_mbox)641 lpfc_mbox_rsrc_cleanup(phba, login_mbox,642 MBOX_THD_UNLOCKED);643 return 1;644 }645 646 /* So the order here should be:647 * SLI3 pt2pt648 * Issue CONFIG_LINK mbox649 * CONFIG_LINK cmpl650 * SLI4 pt2pt651 * Issue REG_VFI mbox652 * REG_VFI cmpl653 * SLI4654 * Issue UNREG RPI mbx655 * UNREG RPI cmpl656 * Issue REG_RPI mbox657 * REG RPI cmpl658 * Issue PLOGI ACC659 * PLOGI ACC cmpl660 */661 login_mbox->mbox_cmpl = lpfc_defer_plogi_acc;662 login_mbox->ctx_ndlp = lpfc_nlp_get(ndlp);663 if (!login_mbox->ctx_ndlp)664 goto out;665 666 login_mbox->ctx_u.save_iocb = save_iocb; /* For PLOGI ACC */667 668 spin_lock_irq(&ndlp->lock);669 ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);670 spin_unlock_irq(&ndlp->lock);671 672 /* Start the ball rolling by issuing REG_LOGIN here */673 rc = lpfc_sli_issue_mbox(phba, login_mbox, MBX_NOWAIT);674 if (rc == MBX_NOT_FINISHED) {675 lpfc_nlp_put(ndlp);676 goto out;677 }678 lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);679 680 return 1;681out:682 kfree(save_iocb);683 if (login_mbox)684 mempool_free(login_mbox, phba->mbox_mem_pool);685 686 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;687 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;688 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);689 return 0;690}691 692/**693 * lpfc_mbx_cmpl_resume_rpi - Resume RPI completion routine694 * @phba: pointer to lpfc hba data structure.695 * @mboxq: pointer to mailbox object696 *697 * This routine is invoked to issue a completion to a rcv'ed698 * ADISC or PDISC after the paused RPI has been resumed.699 **/700static void701lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)702{703 struct lpfc_vport *vport;704 struct lpfc_iocbq *elsiocb;705 struct lpfc_nodelist *ndlp;706 uint32_t cmd;707 708 elsiocb = mboxq->ctx_u.save_iocb;709 ndlp = mboxq->ctx_ndlp;710 vport = mboxq->vport;711 cmd = elsiocb->drvrTimeout;712 713 if (cmd == ELS_CMD_ADISC) {714 lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);715 } else {716 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,717 ndlp, NULL);718 }719 720 /* This nlp_put pairs with lpfc_sli4_resume_rpi */721 lpfc_nlp_put(ndlp);722 723 kfree(elsiocb);724 mempool_free(mboxq, phba->mbox_mem_pool);725}726 727static int728lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,729 struct lpfc_iocbq *cmdiocb)730{731 struct lpfc_hba *phba = vport->phba;732 struct lpfc_iocbq *elsiocb;733 struct lpfc_dmabuf *pcmd;734 struct serv_parm *sp;735 struct lpfc_name *pnn, *ppn;736 struct ls_rjt stat;737 ADISC *ap;738 uint32_t *lp;739 uint32_t cmd;740 741 pcmd = cmdiocb->cmd_dmabuf;742 lp = (uint32_t *) pcmd->virt;743 744 cmd = *lp++;745 if (cmd == ELS_CMD_ADISC) {746 ap = (ADISC *) lp;747 pnn = (struct lpfc_name *) & ap->nodeName;748 ppn = (struct lpfc_name *) & ap->portName;749 } else {750 sp = (struct serv_parm *) lp;751 pnn = (struct lpfc_name *) & sp->nodeName;752 ppn = (struct lpfc_name *) & sp->portName;753 }754 755 if (get_job_ulpstatus(phba, cmdiocb) == 0 &&756 lpfc_check_adisc(vport, ndlp, pnn, ppn)) {757 758 /*759 * As soon as we send ACC, the remote NPort can760 * start sending us data. Thus, for SLI4 we must761 * resume the RPI before the ACC goes out.762 */763 if (vport->phba->sli_rev == LPFC_SLI_REV4) {764 elsiocb = kmalloc(sizeof(struct lpfc_iocbq),765 GFP_KERNEL);766 if (elsiocb) {767 /* Save info from cmd IOCB used in rsp */768 memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb,769 sizeof(struct lpfc_iocbq));770 771 /* Save the ELS cmd */772 elsiocb->drvrTimeout = cmd;773 774 if (lpfc_sli4_resume_rpi(ndlp,775 lpfc_mbx_cmpl_resume_rpi,776 elsiocb))777 kfree(elsiocb);778 goto out;779 }780 }781 782 if (cmd == ELS_CMD_ADISC) {783 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);784 } else {785 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,786 ndlp, NULL);787 }788out:789 /* If we are authenticated, move to the proper state.790 * It is possible an ADISC arrived and the remote nport791 * is already in MAPPED or UNMAPPED state. Catch this792 * condition and don't set the nlp_state again because793 * it causes an unnecessary transport unregister/register.794 *795 * Nodes marked for ADISC will move MAPPED or UNMAPPED state796 * after issuing ADISC797 */798 if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) {799 if ((ndlp->nlp_state != NLP_STE_MAPPED_NODE) &&800 !(ndlp->nlp_flag & NLP_NPR_ADISC))801 lpfc_nlp_set_state(vport, ndlp,802 NLP_STE_MAPPED_NODE);803 }804 805 return 1;806 }807 /* Reject this request because invalid parameters */808 stat.un.b.lsRjtRsvd0 = 0;809 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;810 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;811 stat.un.b.vendorUnique = 0;812 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);813 814 /* 1 sec timeout */815 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));816 817 spin_lock_irq(&ndlp->lock);818 ndlp->nlp_flag |= NLP_DELAY_TMO;819 spin_unlock_irq(&ndlp->lock);820 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;821 ndlp->nlp_prev_state = ndlp->nlp_state;822 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);823 return 0;824}825 826static int827lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,828 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)829{830 struct lpfc_hba *phba = vport->phba;831 struct lpfc_vport **vports;832 int i, active_vlink_present = 0 ;833 834 /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */835 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary836 * PLOGIs during LOGO storms from a device.837 */838 spin_lock_irq(&ndlp->lock);839 ndlp->nlp_flag |= NLP_LOGO_ACC;840 spin_unlock_irq(&ndlp->lock);841 if (els_cmd == ELS_CMD_PRLO)842 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);843 else844 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);845 846 /* This clause allows the initiator to ACC the LOGO back to the847 * Fabric Domain Controller. It does deliberately skip all other848 * steps because some fabrics send RDP requests after logging out849 * from the initiator.850 */851 if (ndlp->nlp_type & NLP_FABRIC &&852 ((ndlp->nlp_DID & WELL_KNOWN_DID_MASK) != WELL_KNOWN_DID_MASK))853 return 0;854 855 /* Notify transport of connectivity loss to trigger cleanup. */856 if (phba->nvmet_support &&857 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)858 lpfc_nvmet_invalidate_host(phba, ndlp);859 860 if (ndlp->nlp_DID == Fabric_DID) {861 if (vport->port_state <= LPFC_FDISC ||862 test_bit(FC_PT2PT, &vport->fc_flag))863 goto out;864 lpfc_linkdown_port(vport);865 set_bit(FC_VPORT_LOGO_RCVD, &vport->fc_flag);866 vports = lpfc_create_vport_work_array(phba);867 if (vports) {868 for (i = 0; i <= phba->max_vports && vports[i] != NULL;869 i++) {870 if (!test_bit(FC_VPORT_LOGO_RCVD,871 &vports[i]->fc_flag) &&872 vports[i]->port_state > LPFC_FDISC) {873 active_vlink_present = 1;874 break;875 }876 }877 lpfc_destroy_vport_work_array(phba, vports);878 }879 880 /*881 * Don't re-instantiate if vport is marked for deletion.882 * If we are here first then vport_delete is going to wait883 * for discovery to complete.884 */885 if (!test_bit(FC_UNLOADING, &vport->load_flag) &&886 active_vlink_present) {887 /*888 * If there are other active VLinks present,889 * re-instantiate the Vlink using FDISC.890 */891 mod_timer(&ndlp->nlp_delayfunc,892 jiffies + msecs_to_jiffies(1000));893 spin_lock_irq(&ndlp->lock);894 ndlp->nlp_flag |= NLP_DELAY_TMO;895 spin_unlock_irq(&ndlp->lock);896 ndlp->nlp_last_elscmd = ELS_CMD_FDISC;897 vport->port_state = LPFC_FDISC;898 } else {899 clear_bit(FC_LOGO_RCVD_DID_CHNG, &phba->pport->fc_flag);900 lpfc_retry_pport_discovery(phba);901 }902 } else {903 lpfc_printf_vlog(vport, KERN_INFO,904 LOG_NODE | LOG_ELS | LOG_DISCOVERY,905 "3203 LOGO recover nport x%06x state x%x "906 "ntype x%x fc_flag x%lx\n",907 ndlp->nlp_DID, ndlp->nlp_state,908 ndlp->nlp_type, vport->fc_flag);909 910 /* Special cases for rports that recover post LOGO. */911 if ((!(ndlp->nlp_type == NLP_FABRIC) &&912 (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) ||913 test_bit(FC_PT2PT, &vport->fc_flag))) ||914 (ndlp->nlp_state >= NLP_STE_ADISC_ISSUE ||915 ndlp->nlp_state <= NLP_STE_PRLI_ISSUE)) {916 mod_timer(&ndlp->nlp_delayfunc,917 jiffies + msecs_to_jiffies(1000 * 1));918 spin_lock_irq(&ndlp->lock);919 ndlp->nlp_flag |= NLP_DELAY_TMO;920 spin_unlock_irq(&ndlp->lock);921 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;922 lpfc_printf_vlog(vport, KERN_INFO,923 LOG_NODE | LOG_ELS | LOG_DISCOVERY,924 "3204 Start nlpdelay on DID x%06x "925 "nflag x%x lastels x%x ref cnt %u",926 ndlp->nlp_DID, ndlp->nlp_flag,927 ndlp->nlp_last_elscmd,928 kref_read(&ndlp->kref));929 }930 }931out:932 /* Unregister from backend, could have been skipped due to ADISC */933 lpfc_nlp_unreg_node(vport, ndlp);934 935 ndlp->nlp_prev_state = ndlp->nlp_state;936 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);937 938 spin_lock_irq(&ndlp->lock);939 ndlp->nlp_flag &= ~NLP_NPR_ADISC;940 spin_unlock_irq(&ndlp->lock);941 /* The driver has to wait until the ACC completes before it continues942 * processing the LOGO. The action will resume in943 * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an944 * unreg_login, the driver waits so the ACC does not get aborted.945 */946 return 0;947}948 949static uint32_t950lpfc_rcv_prli_support_check(struct lpfc_vport *vport,951 struct lpfc_nodelist *ndlp,952 struct lpfc_iocbq *cmdiocb)953{954 struct ls_rjt stat;955 uint32_t *payload;956 uint32_t cmd;957 PRLI *npr;958 959 payload = cmdiocb->cmd_dmabuf->virt;960 cmd = *payload;961 npr = (PRLI *)((uint8_t *)payload + sizeof(uint32_t));962 963 if (vport->phba->nvmet_support) {964 /* Must be a NVME PRLI */965 if (cmd == ELS_CMD_PRLI)966 goto out;967 } else {968 /* Initiator mode. */969 if (!vport->nvmei_support && (cmd == ELS_CMD_NVMEPRLI))970 goto out;971 972 /* NPIV ports will RJT initiator only functions */973 if (vport->port_type == LPFC_NPIV_PORT &&974 npr->initiatorFunc && !npr->targetFunc)975 goto out;976 }977 return 1;978out:979 lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY,980 "6115 Rcv PRLI (%x) check failed: ndlp rpi %d "981 "state x%x flags x%x port_type: x%x "982 "npr->initfcn: x%x npr->tgtfcn: x%x\n",983 cmd, ndlp->nlp_rpi, ndlp->nlp_state,984 ndlp->nlp_flag, vport->port_type,985 npr->initiatorFunc, npr->targetFunc);986 memset(&stat, 0, sizeof(struct ls_rjt));987 stat.un.b.lsRjtRsnCode = LSRJT_CMD_UNSUPPORTED;988 stat.un.b.lsRjtRsnCodeExp = LSEXP_REQ_UNSUPPORTED;989 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,990 ndlp, NULL);991 return 0;992}993 994static void995lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,996 struct lpfc_iocbq *cmdiocb)997{998 struct lpfc_hba *phba = vport->phba;999 struct lpfc_dmabuf *pcmd;1000 uint32_t *lp;1001 PRLI *npr;1002 struct fc_rport *rport = ndlp->rport;1003 u32 roles;1004 1005 pcmd = cmdiocb->cmd_dmabuf;1006 lp = (uint32_t *)pcmd->virt;1007 npr = (PRLI *)((uint8_t *)lp + sizeof(uint32_t));1008 1009 if ((npr->prliType == PRLI_FCP_TYPE) ||1010 (npr->prliType == PRLI_NVME_TYPE)) {1011 if (npr->initiatorFunc) {1012 if (npr->prliType == PRLI_FCP_TYPE)1013 ndlp->nlp_type |= NLP_FCP_INITIATOR;1014 if (npr->prliType == PRLI_NVME_TYPE)1015 ndlp->nlp_type |= NLP_NVME_INITIATOR;1016 }1017 if (npr->targetFunc) {1018 if (npr->prliType == PRLI_FCP_TYPE)1019 ndlp->nlp_type |= NLP_FCP_TARGET;1020 if (npr->prliType == PRLI_NVME_TYPE)1021 ndlp->nlp_type |= NLP_NVME_TARGET;1022 if (npr->writeXferRdyDis)1023 ndlp->nlp_flag |= NLP_FIRSTBURST;1024 }1025 if (npr->Retry && ndlp->nlp_type &1026 (NLP_FCP_INITIATOR | NLP_FCP_TARGET))1027 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;1028 1029 if (npr->Retry && phba->nsler &&1030 ndlp->nlp_type & (NLP_NVME_INITIATOR | NLP_NVME_TARGET))1031 ndlp->nlp_nvme_info |= NLP_NVME_NSLER;1032 1033 1034 /* If this driver is in nvme target mode, set the ndlp's fc41035 * type to NVME provided the PRLI response claims NVME FC41036 * type. Target mode does not issue gft_id so doesn't get1037 * the fc4 type set until now.1038 */1039 if (phba->nvmet_support && (npr->prliType == PRLI_NVME_TYPE)) {1040 ndlp->nlp_fc4_type |= NLP_FC4_NVME;1041 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);1042 }1043 1044 /* Fabric Controllers send FCP PRLI as an initiator but should1045 * not get recognized as FCP type and registered with transport.1046 */1047 if (npr->prliType == PRLI_FCP_TYPE &&1048 !(ndlp->nlp_type & NLP_FABRIC))1049 ndlp->nlp_fc4_type |= NLP_FC4_FCP;1050 }1051 if (rport) {1052 /* We need to update the rport role values */1053 roles = FC_RPORT_ROLE_UNKNOWN;1054 if (ndlp->nlp_type & NLP_FCP_INITIATOR)1055 roles |= FC_RPORT_ROLE_FCP_INITIATOR;1056 if (ndlp->nlp_type & NLP_FCP_TARGET)1057 roles |= FC_RPORT_ROLE_FCP_TARGET;1058 1059 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,1060 "rport rolechg: role:x%x did:x%x flg:x%x",1061 roles, ndlp->nlp_DID, ndlp->nlp_flag);1062 1063 if (vport->cfg_enable_fc4_type != LPFC_ENABLE_NVME)1064 fc_remote_port_rolechg(rport, roles);1065 }1066}1067 1068static uint32_t1069lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)1070{1071 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {1072 spin_lock_irq(&ndlp->lock);1073 ndlp->nlp_flag &= ~NLP_NPR_ADISC;1074 spin_unlock_irq(&ndlp->lock);1075 return 0;1076 }1077 1078 if (!test_bit(FC_PT2PT, &vport->fc_flag)) {1079 /* Check config parameter use-adisc or FCP-2 */1080 if (vport->cfg_use_adisc &&1081 (test_bit(FC_RSCN_MODE, &vport->fc_flag) ||1082 ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&1083 (ndlp->nlp_type & NLP_FCP_TARGET)))) {1084 spin_lock_irq(&ndlp->lock);1085 ndlp->nlp_flag |= NLP_NPR_ADISC;1086 spin_unlock_irq(&ndlp->lock);1087 return 1;1088 }1089 }1090 1091 spin_lock_irq(&ndlp->lock);1092 ndlp->nlp_flag &= ~NLP_NPR_ADISC;1093 spin_unlock_irq(&ndlp->lock);1094 lpfc_unreg_rpi(vport, ndlp);1095 return 0;1096}1097 1098/**1099 * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd.1100 * @phba : Pointer to lpfc_hba structure.1101 * @vport: Pointer to lpfc_vport structure.1102 * @ndlp: Pointer to lpfc_nodelist structure.1103 * @rpi : rpi to be release.1104 *1105 * This function will send a unreg_login mailbox command to the firmware1106 * to release a rpi.1107 **/1108static void1109lpfc_release_rpi(struct lpfc_hba *phba, struct lpfc_vport *vport,1110 struct lpfc_nodelist *ndlp, uint16_t rpi)1111{1112 LPFC_MBOXQ_t *pmb;1113 int rc;1114 1115 /* If there is already an UNREG in progress for this ndlp,1116 * no need to queue up another one.1117 */1118 if (ndlp->nlp_flag & NLP_UNREG_INP) {1119 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,1120 "1435 release_rpi SKIP UNREG x%x on "1121 "NPort x%x deferred x%x flg x%x "1122 "Data: x%px\n",1123 ndlp->nlp_rpi, ndlp->nlp_DID,1124 ndlp->nlp_defer_did,1125 ndlp->nlp_flag, ndlp);1126 return;1127 }1128 1129 pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,1130 GFP_KERNEL);1131 if (!pmb)1132 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1133 "2796 mailbox memory allocation failed \n");1134 else {1135 lpfc_unreg_login(phba, vport->vpi, rpi, pmb);1136 pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;1137 pmb->vport = vport;1138 pmb->ctx_ndlp = lpfc_nlp_get(ndlp);1139 if (!pmb->ctx_ndlp) {1140 mempool_free(pmb, phba->mbox_mem_pool);1141 return;1142 }1143 1144 if (((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) &&1145 (!test_bit(FC_OFFLINE_MODE, &vport->fc_flag)))1146 ndlp->nlp_flag |= NLP_UNREG_INP;1147 1148 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,1149 "1437 release_rpi UNREG x%x "1150 "on NPort x%x flg x%x\n",1151 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag);1152 1153 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);1154 if (rc == MBX_NOT_FINISHED) {1155 lpfc_nlp_put(ndlp);1156 mempool_free(pmb, phba->mbox_mem_pool);1157 }1158 }1159}1160 1161static uint32_t1162lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1163 void *arg, uint32_t evt)1164{1165 struct lpfc_hba *phba;1166 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;1167 uint16_t rpi;1168 1169 phba = vport->phba;1170 /* Release the RPI if reglogin completing */1171 if (!test_bit(FC_UNLOADING, &phba->pport->load_flag) &&1172 evt == NLP_EVT_CMPL_REG_LOGIN && !pmb->u.mb.mbxStatus) {1173 rpi = pmb->u.mb.un.varWords[0];1174 lpfc_release_rpi(phba, vport, ndlp, rpi);1175 }1176 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1177 "0271 Illegal State Transition: node x%x "1178 "event x%x, state x%x Data: x%x x%x\n",1179 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,1180 ndlp->nlp_flag);1181 return ndlp->nlp_state;1182}1183 1184static uint32_t1185lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1186 void *arg, uint32_t evt)1187{1188 /* This transition is only legal if we previously1189 * rcv'ed a PLOGI. Since we don't want 2 discovery threads1190 * working on the same NPortID, do nothing for this thread1191 * to stop it.1192 */1193 if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {1194 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1195 "0272 Illegal State Transition: node x%x "1196 "event x%x, state x%x Data: x%x x%x\n",1197 ndlp->nlp_DID, evt, ndlp->nlp_state,1198 ndlp->nlp_rpi, ndlp->nlp_flag);1199 }1200 return ndlp->nlp_state;1201}1202 1203/* Start of Discovery State Machine routines */1204 1205static uint32_t1206lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1207 void *arg, uint32_t evt)1208{1209 struct lpfc_iocbq *cmdiocb;1210 1211 cmdiocb = (struct lpfc_iocbq *) arg;1212 1213 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {1214 return ndlp->nlp_state;1215 }1216 return NLP_STE_FREED_NODE;1217}1218 1219static uint32_t1220lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1221 void *arg, uint32_t evt)1222{1223 lpfc_issue_els_logo(vport, ndlp, 0);1224 return ndlp->nlp_state;1225}1226 1227static uint32_t1228lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1229 void *arg, uint32_t evt)1230{1231 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1232 1233 spin_lock_irq(&ndlp->lock);1234 ndlp->nlp_flag |= NLP_LOGO_ACC;1235 spin_unlock_irq(&ndlp->lock);1236 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);1237 1238 return ndlp->nlp_state;1239}1240 1241static uint32_t1242lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1243 void *arg, uint32_t evt)1244{1245 return NLP_STE_FREED_NODE;1246}1247 1248static uint32_t1249lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1250 void *arg, uint32_t evt)1251{1252 return NLP_STE_FREED_NODE;1253}1254 1255static uint32_t1256lpfc_device_recov_unused_node(struct lpfc_vport *vport,1257 struct lpfc_nodelist *ndlp,1258 void *arg, uint32_t evt)1259{1260 return ndlp->nlp_state;1261}1262 1263static uint32_t1264lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1265 void *arg, uint32_t evt)1266{1267 struct lpfc_hba *phba = vport->phba;1268 struct lpfc_iocbq *cmdiocb = arg;1269 struct lpfc_dmabuf *pcmd = cmdiocb->cmd_dmabuf;1270 uint32_t *lp = (uint32_t *) pcmd->virt;1271 struct serv_parm *sp = (struct serv_parm *) (lp + 1);1272 struct ls_rjt stat;1273 int port_cmp;1274 1275 memset(&stat, 0, sizeof (struct ls_rjt));1276 1277 /* For a PLOGI, we only accept if our portname is less1278 * than the remote portname.1279 */1280 phba->fc_stat.elsLogiCol++;1281 port_cmp = memcmp(&vport->fc_portname, &sp->portName,1282 sizeof(struct lpfc_name));1283 1284 if (port_cmp >= 0) {1285 /* Reject this request because the remote node will accept1286 ours */1287 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;1288 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;1289 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,1290 NULL);1291 } else {1292 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) &&1293 (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&1294 (vport->num_disc_nodes)) {1295 spin_lock_irq(&ndlp->lock);1296 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;1297 spin_unlock_irq(&ndlp->lock);1298 /* Check if there are more PLOGIs to be sent */1299 lpfc_more_plogi(vport);1300 if (vport->num_disc_nodes == 0) {1301 clear_bit(FC_NDISC_ACTIVE, &vport->fc_flag);1302 lpfc_can_disctmo(vport);1303 lpfc_end_rscn(vport);1304 }1305 }1306 } /* If our portname was less */1307 1308 return ndlp->nlp_state;1309}1310 1311static uint32_t1312lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1313 void *arg, uint32_t evt)1314{1315 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1316 struct ls_rjt stat;1317 1318 memset(&stat, 0, sizeof (struct ls_rjt));1319 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;1320 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;1321 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);1322 return ndlp->nlp_state;1323}1324 1325static uint32_t1326lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1327 void *arg, uint32_t evt)1328{1329 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1330 1331 /* Retrieve RPI from LOGO IOCB. RPI is used for CMD_ABORT_XRI_CN */1332 if (vport->phba->sli_rev == LPFC_SLI_REV3)1333 ndlp->nlp_rpi = cmdiocb->iocb.ulpIoTag;1334 /* software abort outstanding PLOGI */1335 lpfc_els_abort(vport->phba, ndlp);1336 1337 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);1338 return ndlp->nlp_state;1339}1340 1341static uint32_t1342lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1343 void *arg, uint32_t evt)1344{1345 struct lpfc_hba *phba = vport->phba;1346 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1347 1348 /* software abort outstanding PLOGI */1349 lpfc_els_abort(phba, ndlp);1350 1351 if (evt == NLP_EVT_RCV_LOGO) {1352 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);1353 } else {1354 lpfc_issue_els_logo(vport, ndlp, 0);1355 }1356 1357 /* Put ndlp in npr state set plogi timer for 1 sec */1358 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1));1359 spin_lock_irq(&ndlp->lock);1360 ndlp->nlp_flag |= NLP_DELAY_TMO;1361 spin_unlock_irq(&ndlp->lock);1362 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;1363 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;1364 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1365 1366 return ndlp->nlp_state;1367}1368 1369static uint32_t1370lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,1371 struct lpfc_nodelist *ndlp,1372 void *arg,1373 uint32_t evt)1374{1375 struct lpfc_hba *phba = vport->phba;1376 struct lpfc_iocbq *cmdiocb, *rspiocb;1377 struct lpfc_dmabuf *pcmd, *prsp;1378 uint32_t *lp;1379 uint32_t vid, flag;1380 struct serv_parm *sp;1381 uint32_t ed_tov;1382 LPFC_MBOXQ_t *mbox;1383 int rc;1384 u32 ulp_status;1385 u32 did;1386 1387 cmdiocb = (struct lpfc_iocbq *) arg;1388 rspiocb = cmdiocb->rsp_iocb;1389 1390 ulp_status = get_job_ulpstatus(phba, rspiocb);1391 1392 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {1393 /* Recovery from PLOGI collision logic */1394 return ndlp->nlp_state;1395 }1396 1397 if (ulp_status)1398 goto out;1399 1400 pcmd = cmdiocb->cmd_dmabuf;1401 1402 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);1403 if (!prsp)1404 goto out;1405 1406 lp = (uint32_t *) prsp->virt;1407 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));1408 1409 /* Some switches have FDMI servers returning 0 for WWN */1410 if ((ndlp->nlp_DID != FDMI_DID) &&1411 (wwn_to_u64(sp->portName.u.wwn) == 0 ||1412 wwn_to_u64(sp->nodeName.u.wwn) == 0)) {1413 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1414 "0142 PLOGI RSP: Invalid WWN.\n");1415 goto out;1416 }1417 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))1418 goto out;1419 /* PLOGI chkparm OK */1420 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,1421 "0121 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",1422 ndlp->nlp_DID, ndlp->nlp_state,1423 ndlp->nlp_flag, ndlp->nlp_rpi);1424 if (vport->cfg_fcp_class == 2 && (sp->cls2.classValid))1425 ndlp->nlp_fcp_info |= CLASS2;1426 else1427 ndlp->nlp_fcp_info |= CLASS3;1428 1429 ndlp->nlp_class_sup = 0;1430 if (sp->cls1.classValid)1431 ndlp->nlp_class_sup |= FC_COS_CLASS1;1432 if (sp->cls2.classValid)1433 ndlp->nlp_class_sup |= FC_COS_CLASS2;1434 if (sp->cls3.classValid)1435 ndlp->nlp_class_sup |= FC_COS_CLASS3;1436 if (sp->cls4.classValid)1437 ndlp->nlp_class_sup |= FC_COS_CLASS4;1438 ndlp->nlp_maxframe =1439 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;1440 1441 if (test_bit(FC_PT2PT, &vport->fc_flag) &&1442 test_bit(FC_PT2PT_PLOGI, &vport->fc_flag)) {1443 ed_tov = be32_to_cpu(sp->cmn.e_d_tov);1444 if (sp->cmn.edtovResolution) {1445 /* E_D_TOV ticks are in nanoseconds */1446 ed_tov = (phba->fc_edtov + 999999) / 1000000;1447 }1448 1449 ndlp->nlp_flag &= ~NLP_SUPPRESS_RSP;1450 if ((phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) &&1451 sp->cmn.valid_vendor_ver_level) {1452 vid = be32_to_cpu(sp->un.vv.vid);1453 flag = be32_to_cpu(sp->un.vv.flags);1454 if ((vid == LPFC_VV_EMLX_ID) &&1455 (flag & LPFC_VV_SUPPRESS_RSP))1456 ndlp->nlp_flag |= NLP_SUPPRESS_RSP;1457 }1458 1459 /*1460 * Use the larger EDTOV1461 * RATOV = 2 * EDTOV for pt-to-pt1462 */1463 if (ed_tov > phba->fc_edtov)1464 phba->fc_edtov = ed_tov;1465 phba->fc_ratov = (2 * phba->fc_edtov) / 1000;1466 1467 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));1468 1469 /* Issue config_link / reg_vfi to account for updated TOV's */1470 if (phba->sli_rev == LPFC_SLI_REV4) {1471 lpfc_issue_reg_vfi(vport);1472 } else {1473 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);1474 if (!mbox) {1475 lpfc_printf_vlog(vport, KERN_ERR,1476 LOG_TRACE_EVENT,1477 "0133 PLOGI: no memory "1478 "for config_link "1479 "Data: x%x x%x x%x x%x\n",1480 ndlp->nlp_DID, ndlp->nlp_state,1481 ndlp->nlp_flag, ndlp->nlp_rpi);1482 goto out;1483 }1484 1485 lpfc_config_link(phba, mbox);1486 1487 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;1488 mbox->vport = vport;1489 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);1490 if (rc == MBX_NOT_FINISHED) {1491 mempool_free(mbox, phba->mbox_mem_pool);1492 goto out;1493 }1494 }1495 }1496 1497 lpfc_unreg_rpi(vport, ndlp);1498 1499 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);1500 if (!mbox) {1501 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1502 "0018 PLOGI: no memory for reg_login "1503 "Data: x%x x%x x%x x%x\n",1504 ndlp->nlp_DID, ndlp->nlp_state,1505 ndlp->nlp_flag, ndlp->nlp_rpi);1506 goto out;1507 }1508 1509 did = get_job_els_rsp64_did(phba, cmdiocb);1510 1511 if (lpfc_reg_rpi(phba, vport->vpi, did,1512 (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {1513 switch (ndlp->nlp_DID) {1514 case NameServer_DID:1515 mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;1516 /* Fabric Controller Node needs these parameters. */1517 memcpy(&ndlp->fc_sparam, sp, sizeof(struct serv_parm));1518 break;1519 case FDMI_DID:1520 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;1521 break;1522 default:1523 ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;1524 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;1525 }1526 1527 mbox->ctx_ndlp = lpfc_nlp_get(ndlp);1528 if (!mbox->ctx_ndlp)1529 goto out;1530 1531 mbox->vport = vport;1532 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)1533 != MBX_NOT_FINISHED) {1534 lpfc_nlp_set_state(vport, ndlp,1535 NLP_STE_REG_LOGIN_ISSUE);1536 return ndlp->nlp_state;1537 }1538 if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)1539 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;1540 /* decrement node reference count to the failed mbox1541 * command1542 */1543 lpfc_nlp_put(ndlp);1544 lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);1545 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1546 "0134 PLOGI: cannot issue reg_login "1547 "Data: x%x x%x x%x x%x\n",1548 ndlp->nlp_DID, ndlp->nlp_state,1549 ndlp->nlp_flag, ndlp->nlp_rpi);1550 } else {1551 mempool_free(mbox, phba->mbox_mem_pool);1552 1553 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1554 "0135 PLOGI: cannot format reg_login "1555 "Data: x%x x%x x%x x%x\n",1556 ndlp->nlp_DID, ndlp->nlp_state,1557 ndlp->nlp_flag, ndlp->nlp_rpi);1558 }1559 1560 1561out:1562 if (ndlp->nlp_DID == NameServer_DID) {1563 lpfc_vport_set_state(vport, FC_VPORT_FAILED);1564 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1565 "0261 Cannot Register NameServer login\n");1566 }1567 1568 /*1569 ** In case the node reference counter does not go to zero, ensure that1570 ** the stale state for the node is not processed.1571 */1572 1573 ndlp->nlp_prev_state = ndlp->nlp_state;1574 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1575 return NLP_STE_FREED_NODE;1576}1577 1578static uint32_t1579lpfc_cmpl_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1580 void *arg, uint32_t evt)1581{1582 return ndlp->nlp_state;1583}1584 1585static uint32_t1586lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport,1587 struct lpfc_nodelist *ndlp, void *arg, uint32_t evt)1588{1589 struct lpfc_hba *phba;1590 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;1591 MAILBOX_t *mb = &pmb->u.mb;1592 uint16_t rpi;1593 1594 phba = vport->phba;1595 /* Release the RPI */1596 if (!test_bit(FC_UNLOADING, &phba->pport->load_flag) &&1597 !mb->mbxStatus) {1598 rpi = pmb->u.mb.un.varWords[0];1599 lpfc_release_rpi(phba, vport, ndlp, rpi);1600 }1601 return ndlp->nlp_state;1602}1603 1604static uint32_t1605lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1606 void *arg, uint32_t evt)1607{1608 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {1609 spin_lock_irq(&ndlp->lock);1610 ndlp->nlp_flag |= NLP_NODEV_REMOVE;1611 spin_unlock_irq(&ndlp->lock);1612 return ndlp->nlp_state;1613 } else {1614 /* software abort outstanding PLOGI */1615 lpfc_els_abort(vport->phba, ndlp);1616 1617 lpfc_drop_node(vport, ndlp);1618 return NLP_STE_FREED_NODE;1619 }1620}1621 1622static uint32_t1623lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,1624 struct lpfc_nodelist *ndlp,1625 void *arg,1626 uint32_t evt)1627{1628 struct lpfc_hba *phba = vport->phba;1629 1630 /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */1631 if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))1632 return ndlp->nlp_state;1633 1634 /* software abort outstanding PLOGI */1635 lpfc_els_abort(phba, ndlp);1636 1637 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;1638 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1639 spin_lock_irq(&ndlp->lock);1640 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);1641 spin_unlock_irq(&ndlp->lock);1642 1643 return ndlp->nlp_state;1644}1645 1646static uint32_t1647lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1648 void *arg, uint32_t evt)1649{1650 struct lpfc_hba *phba = vport->phba;1651 struct lpfc_iocbq *cmdiocb;1652 1653 /* software abort outstanding ADISC */1654 lpfc_els_abort(phba, ndlp);1655 1656 cmdiocb = (struct lpfc_iocbq *) arg;1657 1658 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {1659 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {1660 spin_lock_irq(&ndlp->lock);1661 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;1662 spin_unlock_irq(&ndlp->lock);1663 if (vport->num_disc_nodes)1664 lpfc_more_adisc(vport);1665 }1666 return ndlp->nlp_state;1667 }1668 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1669 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);1670 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);1671 1672 return ndlp->nlp_state;1673}1674 1675static uint32_t1676lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1677 void *arg, uint32_t evt)1678{1679 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1680 1681 if (lpfc_rcv_prli_support_check(vport, ndlp, cmdiocb))1682 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);1683 return ndlp->nlp_state;1684}1685 1686static uint32_t1687lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1688 void *arg, uint32_t evt)1689{1690 struct lpfc_hba *phba = vport->phba;1691 struct lpfc_iocbq *cmdiocb;1692 1693 cmdiocb = (struct lpfc_iocbq *) arg;1694 1695 /* software abort outstanding ADISC */1696 lpfc_els_abort(phba, ndlp);1697 1698 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);1699 return ndlp->nlp_state;1700}1701 1702static uint32_t1703lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,1704 struct lpfc_nodelist *ndlp,1705 void *arg, uint32_t evt)1706{1707 struct lpfc_iocbq *cmdiocb;1708 1709 cmdiocb = (struct lpfc_iocbq *) arg;1710 1711 lpfc_rcv_padisc(vport, ndlp, cmdiocb);1712 return ndlp->nlp_state;1713}1714 1715static uint32_t1716lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1717 void *arg, uint32_t evt)1718{1719 struct lpfc_iocbq *cmdiocb;1720 1721 cmdiocb = (struct lpfc_iocbq *) arg;1722 1723 /* Treat like rcv logo */1724 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);1725 return ndlp->nlp_state;1726}1727 1728static uint32_t1729lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,1730 struct lpfc_nodelist *ndlp,1731 void *arg, uint32_t evt)1732{1733 struct lpfc_hba *phba = vport->phba;1734 struct lpfc_iocbq *cmdiocb, *rspiocb;1735 ADISC *ap;1736 int rc;1737 u32 ulp_status;1738 1739 cmdiocb = (struct lpfc_iocbq *) arg;1740 rspiocb = cmdiocb->rsp_iocb;1741 1742 ulp_status = get_job_ulpstatus(phba, rspiocb);1743 1744 ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);1745 1746 if ((ulp_status) ||1747 (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {1748 /* 1 sec timeout */1749 mod_timer(&ndlp->nlp_delayfunc,1750 jiffies + msecs_to_jiffies(1000));1751 spin_lock_irq(&ndlp->lock);1752 ndlp->nlp_flag |= NLP_DELAY_TMO;1753 spin_unlock_irq(&ndlp->lock);1754 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;1755 1756 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1757 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1758 lpfc_unreg_rpi(vport, ndlp);1759 return ndlp->nlp_state;1760 }1761 1762 if (phba->sli_rev == LPFC_SLI_REV4) {1763 rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);1764 if (rc) {1765 /* Stay in state and retry. */1766 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1767 return ndlp->nlp_state;1768 }1769 }1770 1771 if (ndlp->nlp_type & NLP_FCP_TARGET)1772 ndlp->nlp_fc4_type |= NLP_FC4_FCP;1773 1774 if (ndlp->nlp_type & NLP_NVME_TARGET)1775 ndlp->nlp_fc4_type |= NLP_FC4_NVME;1776 1777 if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) {1778 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1779 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);1780 } else {1781 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1782 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);1783 }1784 1785 return ndlp->nlp_state;1786}1787 1788static uint32_t1789lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,1790 void *arg, uint32_t evt)1791{1792 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {1793 spin_lock_irq(&ndlp->lock);1794 ndlp->nlp_flag |= NLP_NODEV_REMOVE;1795 spin_unlock_irq(&ndlp->lock);1796 return ndlp->nlp_state;1797 } else {1798 /* software abort outstanding ADISC */1799 lpfc_els_abort(vport->phba, ndlp);1800 1801 lpfc_drop_node(vport, ndlp);1802 return NLP_STE_FREED_NODE;1803 }1804}1805 1806static uint32_t1807lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,1808 struct lpfc_nodelist *ndlp,1809 void *arg,1810 uint32_t evt)1811{1812 struct lpfc_hba *phba = vport->phba;1813 1814 /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */1815 if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))1816 return ndlp->nlp_state;1817 1818 /* software abort outstanding ADISC */1819 lpfc_els_abort(phba, ndlp);1820 1821 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;1822 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1823 spin_lock_irq(&ndlp->lock);1824 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);1825 spin_unlock_irq(&ndlp->lock);1826 lpfc_disc_set_adisc(vport, ndlp);1827 return ndlp->nlp_state;1828}1829 1830static uint32_t1831lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,1832 struct lpfc_nodelist *ndlp,1833 void *arg,1834 uint32_t evt)1835{1836 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1837 1838 lpfc_rcv_plogi(vport, ndlp, cmdiocb);1839 return ndlp->nlp_state;1840}1841 1842static uint32_t1843lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,1844 struct lpfc_nodelist *ndlp,1845 void *arg,1846 uint32_t evt)1847{1848 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1849 struct ls_rjt stat;1850 1851 if (!lpfc_rcv_prli_support_check(vport, ndlp, cmdiocb)) {1852 return ndlp->nlp_state;1853 }1854 if (vport->phba->nvmet_support) {1855 /* NVME Target mode. Handle and respond to the PRLI and1856 * transition to UNMAPPED provided the RPI has completed1857 * registration.1858 */1859 if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {1860 lpfc_rcv_prli(vport, ndlp, cmdiocb);1861 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);1862 } else {1863 /* RPI registration has not completed. Reject the PRLI1864 * to prevent an illegal state transition when the1865 * rpi registration does complete.1866 */1867 memset(&stat, 0, sizeof(struct ls_rjt));1868 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;1869 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;1870 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,1871 ndlp, NULL);1872 return ndlp->nlp_state;1873 }1874 } else {1875 /* Initiator mode. */1876 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);1877 }1878 return ndlp->nlp_state;1879}1880 1881static uint32_t1882lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,1883 struct lpfc_nodelist *ndlp,1884 void *arg,1885 uint32_t evt)1886{1887 struct lpfc_hba *phba = vport->phba;1888 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1889 LPFC_MBOXQ_t *mb;1890 LPFC_MBOXQ_t *nextmb;1891 1892 cmdiocb = (struct lpfc_iocbq *) arg;1893 1894 /* cleanup any ndlp on mbox q waiting for reglogin cmpl */1895 if ((mb = phba->sli.mbox_active)) {1896 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&1897 (ndlp == mb->ctx_ndlp)) {1898 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;1899 lpfc_nlp_put(ndlp);1900 mb->ctx_ndlp = NULL;1901 mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;1902 }1903 }1904 1905 spin_lock_irq(&phba->hbalock);1906 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {1907 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&1908 (ndlp == mb->ctx_ndlp)) {1909 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;1910 lpfc_nlp_put(ndlp);1911 list_del(&mb->list);1912 phba->sli.mboxq_cnt--;1913 lpfc_mbox_rsrc_cleanup(phba, mb, MBOX_THD_LOCKED);1914 }1915 }1916 spin_unlock_irq(&phba->hbalock);1917 1918 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);1919 return ndlp->nlp_state;1920}1921 1922static uint32_t1923lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,1924 struct lpfc_nodelist *ndlp,1925 void *arg,1926 uint32_t evt)1927{1928 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;1929 1930 lpfc_rcv_padisc(vport, ndlp, cmdiocb);1931 return ndlp->nlp_state;1932}1933 1934static uint32_t1935lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,1936 struct lpfc_nodelist *ndlp,1937 void *arg,1938 uint32_t evt)1939{1940 struct lpfc_iocbq *cmdiocb;1941 1942 cmdiocb = (struct lpfc_iocbq *) arg;1943 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);1944 return ndlp->nlp_state;1945}1946 1947static uint32_t1948lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,1949 struct lpfc_nodelist *ndlp,1950 void *arg,1951 uint32_t evt)1952{1953 struct lpfc_hba *phba = vport->phba;1954 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;1955 MAILBOX_t *mb = &pmb->u.mb;1956 uint32_t did = mb->un.varWords[1];1957 1958 if (mb->mbxStatus) {1959 /* RegLogin failed */1960 lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,1961 "0246 RegLogin failed Data: x%x x%x x%x x%x "1962 "x%x\n",1963 did, mb->mbxStatus, vport->port_state,1964 mb->un.varRegLogin.vpi,1965 mb->un.varRegLogin.rpi);1966 /*1967 * If RegLogin failed due to lack of HBA resources do not1968 * retry discovery.1969 */1970 if (mb->mbxStatus == MBXERR_RPI_FULL) {1971 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;1972 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);1973 return ndlp->nlp_state;1974 }1975 1976 /* Put ndlp in npr state set plogi timer for 1 sec */1977 mod_timer(&ndlp->nlp_delayfunc,1978 jiffies + msecs_to_jiffies(1000 * 1));1979 spin_lock_irq(&ndlp->lock);1980 ndlp->nlp_flag |= NLP_DELAY_TMO;1981 spin_unlock_irq(&ndlp->lock);1982 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;1983 1984 lpfc_issue_els_logo(vport, ndlp, 0);1985 return ndlp->nlp_state;1986 }1987 1988 /* SLI4 ports have preallocated logical rpis. */1989 if (phba->sli_rev < LPFC_SLI_REV4)1990 ndlp->nlp_rpi = mb->un.varWords[0];1991 1992 ndlp->nlp_flag |= NLP_RPI_REGISTERED;1993 1994 /* Only if we are not a fabric nport do we issue PRLI */1995 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,1996 "3066 RegLogin Complete on x%x x%x x%x\n",1997 did, ndlp->nlp_type, ndlp->nlp_fc4_type);1998 if (!(ndlp->nlp_type & NLP_FABRIC) &&1999 (phba->nvmet_support == 0)) {2000 /* The driver supports FCP and NVME concurrently. If the2001 * ndlp's nlp_fc4_type is still zero, the driver doesn't2002 * know what PRLI to send yet. Figure that out now and2003 * call PRLI depending on the outcome.2004 */2005 if (test_bit(FC_PT2PT, &vport->fc_flag)) {2006 /* If we are pt2pt, there is no Fabric to determine2007 * the FC4 type of the remote nport. So if NVME2008 * is configured try it.2009 */2010 ndlp->nlp_fc4_type |= NLP_FC4_FCP;2011 if ((!test_bit(FC_PT2PT_NO_NVME, &vport->fc_flag)) &&2012 (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH ||2013 vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) {2014 ndlp->nlp_fc4_type |= NLP_FC4_NVME;2015 /* We need to update the localport also */2016 lpfc_nvme_update_localport(vport);2017 }2018 2019 } else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {2020 ndlp->nlp_fc4_type |= NLP_FC4_FCP;2021 2022 } else if (ndlp->nlp_fc4_type == 0) {2023 /* If we are only configured for FCP, the driver2024 * should just issue PRLI for FCP. Otherwise issue2025 * GFT_ID to determine if remote port supports NVME.2026 */2027 if (vport->cfg_enable_fc4_type != LPFC_ENABLE_FCP) {2028 lpfc_ns_cmd(vport, SLI_CTNS_GFT_ID, 0,2029 ndlp->nlp_DID);2030 return ndlp->nlp_state;2031 }2032 ndlp->nlp_fc4_type = NLP_FC4_FCP;2033 }2034 2035 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;2036 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);2037 if (lpfc_issue_els_prli(vport, ndlp, 0)) {2038 lpfc_issue_els_logo(vport, ndlp, 0);2039 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;2040 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2041 }2042 } else {2043 if (test_bit(FC_PT2PT, &vport->fc_flag) && phba->nvmet_support)2044 phba->targetport->port_id = vport->fc_myDID;2045 2046 /* Only Fabric ports should transition. NVME target2047 * must complete PRLI.2048 */2049 if (ndlp->nlp_type & NLP_FABRIC) {2050 ndlp->nlp_fc4_type &= ~NLP_FC4_FCP;2051 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;2052 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);2053 }2054 }2055 return ndlp->nlp_state;2056}2057 2058static uint32_t2059lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,2060 struct lpfc_nodelist *ndlp,2061 void *arg,2062 uint32_t evt)2063{2064 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {2065 spin_lock_irq(&ndlp->lock);2066 ndlp->nlp_flag |= NLP_NODEV_REMOVE;2067 spin_unlock_irq(&ndlp->lock);2068 return ndlp->nlp_state;2069 } else {2070 lpfc_drop_node(vport, ndlp);2071 return NLP_STE_FREED_NODE;2072 }2073}2074 2075static uint32_t2076lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,2077 struct lpfc_nodelist *ndlp,2078 void *arg,2079 uint32_t evt)2080{2081 /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */2082 if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))2083 return ndlp->nlp_state;2084 2085 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;2086 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2087 spin_lock_irq(&ndlp->lock);2088 2089 /* If we are a target we won't immediately transition into PRLI,2090 * so if REG_LOGIN already completed we don't need to ignore it.2091 */2092 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED) ||2093 !vport->phba->nvmet_support)2094 ndlp->nlp_flag |= NLP_IGNR_REG_CMPL;2095 2096 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2097 spin_unlock_irq(&ndlp->lock);2098 lpfc_disc_set_adisc(vport, ndlp);2099 return ndlp->nlp_state;2100}2101 2102static uint32_t2103lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2104 void *arg, uint32_t evt)2105{2106 struct lpfc_iocbq *cmdiocb;2107 2108 cmdiocb = (struct lpfc_iocbq *) arg;2109 2110 lpfc_rcv_plogi(vport, ndlp, cmdiocb);2111 return ndlp->nlp_state;2112}2113 2114static uint32_t2115lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2116 void *arg, uint32_t evt)2117{2118 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2119 2120 if (!lpfc_rcv_prli_support_check(vport, ndlp, cmdiocb))2121 return ndlp->nlp_state;2122 lpfc_rcv_prli(vport, ndlp, cmdiocb);2123 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);2124 return ndlp->nlp_state;2125}2126 2127static uint32_t2128lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2129 void *arg, uint32_t evt)2130{2131 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2132 2133 /* Software abort outstanding PRLI before sending acc */2134 lpfc_els_abort(vport->phba, ndlp);2135 2136 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);2137 return ndlp->nlp_state;2138}2139 2140static uint32_t2141lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2142 void *arg, uint32_t evt)2143{2144 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2145 2146 lpfc_rcv_padisc(vport, ndlp, cmdiocb);2147 return ndlp->nlp_state;2148}2149 2150/* This routine is envoked when we rcv a PRLO request from a nport2151 * we are logged into. We should send back a PRLO rsp setting the2152 * appropriate bits.2153 * NEXT STATE = PRLI_ISSUE2154 */2155static uint32_t2156lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2157 void *arg, uint32_t evt)2158{2159 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2160 2161 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);2162 return ndlp->nlp_state;2163}2164 2165static uint32_t2166lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2167 void *arg, uint32_t evt)2168{2169 struct lpfc_iocbq *cmdiocb, *rspiocb;2170 struct lpfc_hba *phba = vport->phba;2171 PRLI *npr;2172 struct lpfc_nvme_prli *nvpr;2173 void *temp_ptr;2174 u32 ulp_status;2175 bool acc_imode_sps = false;2176 2177 cmdiocb = (struct lpfc_iocbq *) arg;2178 rspiocb = cmdiocb->rsp_iocb;2179 2180 ulp_status = get_job_ulpstatus(phba, rspiocb);2181 2182 /* A solicited PRLI is either FCP or NVME. The PRLI cmd/rsp2183 * format is different so NULL the two PRLI types so that the2184 * driver correctly gets the correct context.2185 */2186 npr = NULL;2187 nvpr = NULL;2188 temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);2189 if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ)2190 npr = (PRLI *) temp_ptr;2191 else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ)2192 nvpr = (struct lpfc_nvme_prli *) temp_ptr;2193 2194 if (ulp_status) {2195 if ((vport->port_type == LPFC_NPIV_PORT) &&2196 vport->cfg_restrict_login) {2197 goto out;2198 }2199 2200 /* Adjust the nlp_type accordingly if the PRLI failed */2201 if (npr)2202 ndlp->nlp_fc4_type &= ~NLP_FC4_FCP;2203 if (nvpr)2204 ndlp->nlp_fc4_type &= ~NLP_FC4_NVME;2205 2206 /* We can't set the DSM state till BOTH PRLIs complete */2207 goto out_err;2208 }2209 2210 if (npr && npr->prliType == PRLI_FCP_TYPE) {2211 lpfc_printf_vlog(vport, KERN_INFO,2212 LOG_ELS | LOG_NODE | LOG_DISCOVERY,2213 "6028 FCP NPR PRLI Cmpl Init %d Target %d "2214 "EIP %d AccCode x%x\n",2215 npr->initiatorFunc, npr->targetFunc,2216 npr->estabImagePair, npr->acceptRspCode);2217 2218 if (npr->acceptRspCode == PRLI_INV_SRV_PARM) {2219 /* Strict initiators don't establish an image pair. */2220 if (npr->initiatorFunc && !npr->targetFunc &&2221 !npr->estabImagePair)2222 acc_imode_sps = true;2223 }2224 2225 if (npr->acceptRspCode == PRLI_REQ_EXECUTED || acc_imode_sps) {2226 if (npr->initiatorFunc)2227 ndlp->nlp_type |= NLP_FCP_INITIATOR;2228 if (npr->targetFunc) {2229 ndlp->nlp_type |= NLP_FCP_TARGET;2230 if (npr->writeXferRdyDis)2231 ndlp->nlp_flag |= NLP_FIRSTBURST;2232 }2233 if (npr->Retry)2234 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;2235 }2236 } else if (nvpr &&2237 (bf_get_be32(prli_acc_rsp_code, nvpr) ==2238 PRLI_REQ_EXECUTED) &&2239 (bf_get_be32(prli_type_code, nvpr) ==2240 PRLI_NVME_TYPE)) {2241 2242 /* Complete setting up the remote ndlp personality. */2243 if (bf_get_be32(prli_init, nvpr))2244 ndlp->nlp_type |= NLP_NVME_INITIATOR;2245 2246 if (phba->nsler && bf_get_be32(prli_nsler, nvpr) &&2247 bf_get_be32(prli_conf, nvpr))2248 2249 ndlp->nlp_nvme_info |= NLP_NVME_NSLER;2250 else2251 ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;2252 2253 /* Target driver cannot solicit NVME FB. */2254 if (bf_get_be32(prli_tgt, nvpr)) {2255 /* Complete the nvme target roles. The transport2256 * needs to know if the rport is capable of2257 * discovery in addition to its role.2258 */2259 ndlp->nlp_type |= NLP_NVME_TARGET;2260 if (bf_get_be32(prli_disc, nvpr))2261 ndlp->nlp_type |= NLP_NVME_DISCOVERY;2262 2263 /*2264 * If prli_fba is set, the Target supports FirstBurst.2265 * If prli_fb_sz is 0, the FirstBurst size is unlimited,2266 * otherwise it defines the actual size supported by2267 * the NVME Target.2268 */2269 if ((bf_get_be32(prli_fba, nvpr) == 1) &&2270 (phba->cfg_nvme_enable_fb) &&2271 (!phba->nvmet_support)) {2272 /* Both sides support FB. The target's first2273 * burst size is a 512 byte encoded value.2274 */2275 ndlp->nlp_flag |= NLP_FIRSTBURST;2276 ndlp->nvme_fb_size = bf_get_be32(prli_fb_sz,2277 nvpr);2278 2279 /* Expressed in units of 512 bytes */2280 if (ndlp->nvme_fb_size)2281 ndlp->nvme_fb_size <<=2282 LPFC_NVME_FB_SHIFT;2283 else2284 ndlp->nvme_fb_size = LPFC_NVME_MAX_FB;2285 }2286 }2287 2288 lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,2289 "6029 NVME PRLI Cmpl w1 x%08x "2290 "w4 x%08x w5 x%08x flag x%x, "2291 "fcp_info x%x nlp_type x%x\n",2292 be32_to_cpu(nvpr->word1),2293 be32_to_cpu(nvpr->word4),2294 be32_to_cpu(nvpr->word5),2295 ndlp->nlp_flag, ndlp->nlp_fcp_info,2296 ndlp->nlp_type);2297 }2298 if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&2299 (vport->port_type == LPFC_NPIV_PORT) &&2300 vport->cfg_restrict_login) {2301out:2302 spin_lock_irq(&ndlp->lock);2303 ndlp->nlp_flag |= NLP_TARGET_REMOVE;2304 spin_unlock_irq(&ndlp->lock);2305 lpfc_issue_els_logo(vport, ndlp, 0);2306 2307 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;2308 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2309 return ndlp->nlp_state;2310 }2311 2312out_err:2313 /* The ndlp state cannot move to MAPPED or UNMAPPED before all PRLIs2314 * are complete.2315 */2316 if (ndlp->fc4_prli_sent == 0) {2317 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;2318 if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET))2319 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);2320 else if (ndlp->nlp_type &2321 (NLP_FCP_INITIATOR | NLP_NVME_INITIATOR))2322 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);2323 } else2324 lpfc_printf_vlog(vport,2325 KERN_INFO, LOG_ELS,2326 "3067 PRLI's still outstanding "2327 "on x%06x - count %d, Pend Node Mode "2328 "transition...\n",2329 ndlp->nlp_DID, ndlp->fc4_prli_sent);2330 2331 return ndlp->nlp_state;2332}2333 2334/*! lpfc_device_rm_prli_issue2335 *2336 * \pre2337 * \post2338 * \param phba2339 * \param ndlp2340 * \param arg2341 * \param evt2342 * \return uint32_t2343 *2344 * \b Description:2345 * This routine is envoked when we a request to remove a nport we are in the2346 * process of PRLIing. We should software abort outstanding prli, unreg2347 * login, send a logout. We will change node state to UNUSED_NODE, put it2348 * on plogi list so it can be freed when LOGO completes.2349 *2350 */2351 2352static uint32_t2353lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2354 void *arg, uint32_t evt)2355{2356 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {2357 spin_lock_irq(&ndlp->lock);2358 ndlp->nlp_flag |= NLP_NODEV_REMOVE;2359 spin_unlock_irq(&ndlp->lock);2360 return ndlp->nlp_state;2361 } else {2362 /* software abort outstanding PLOGI */2363 lpfc_els_abort(vport->phba, ndlp);2364 2365 lpfc_drop_node(vport, ndlp);2366 return NLP_STE_FREED_NODE;2367 }2368}2369 2370 2371/*! lpfc_device_recov_prli_issue2372 *2373 * \pre2374 * \post2375 * \param phba2376 * \param ndlp2377 * \param arg2378 * \param evt2379 * \return uint32_t2380 *2381 * \b Description:2382 * The routine is envoked when the state of a device is unknown, like2383 * during a link down. We should remove the nodelist entry from the2384 * unmapped list, issue a UNREG_LOGIN, do a software abort of the2385 * outstanding PRLI command, then free the node entry.2386 */2387static uint32_t2388lpfc_device_recov_prli_issue(struct lpfc_vport *vport,2389 struct lpfc_nodelist *ndlp,2390 void *arg,2391 uint32_t evt)2392{2393 struct lpfc_hba *phba = vport->phba;2394 2395 /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */2396 if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))2397 return ndlp->nlp_state;2398 2399 /* software abort outstanding PRLI */2400 lpfc_els_abort(phba, ndlp);2401 2402 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;2403 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2404 spin_lock_irq(&ndlp->lock);2405 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2406 spin_unlock_irq(&ndlp->lock);2407 lpfc_disc_set_adisc(vport, ndlp);2408 return ndlp->nlp_state;2409}2410 2411static uint32_t2412lpfc_rcv_plogi_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2413 void *arg, uint32_t evt)2414{2415 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;2416 struct ls_rjt stat;2417 2418 memset(&stat, 0, sizeof(struct ls_rjt));2419 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;2420 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;2421 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);2422 return ndlp->nlp_state;2423}2424 2425static uint32_t2426lpfc_rcv_prli_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2427 void *arg, uint32_t evt)2428{2429 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;2430 struct ls_rjt stat;2431 2432 memset(&stat, 0, sizeof(struct ls_rjt));2433 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;2434 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;2435 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);2436 return ndlp->nlp_state;2437}2438 2439static uint32_t2440lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2441 void *arg, uint32_t evt)2442{2443 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;2444 2445 spin_lock_irq(&ndlp->lock);2446 ndlp->nlp_flag |= NLP_LOGO_ACC;2447 spin_unlock_irq(&ndlp->lock);2448 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);2449 return ndlp->nlp_state;2450}2451 2452static uint32_t2453lpfc_rcv_padisc_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2454 void *arg, uint32_t evt)2455{2456 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;2457 struct ls_rjt stat;2458 2459 memset(&stat, 0, sizeof(struct ls_rjt));2460 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;2461 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;2462 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);2463 return ndlp->nlp_state;2464}2465 2466static uint32_t2467lpfc_rcv_prlo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2468 void *arg, uint32_t evt)2469{2470 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;2471 struct ls_rjt stat;2472 2473 memset(&stat, 0, sizeof(struct ls_rjt));2474 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;2475 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;2476 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);2477 return ndlp->nlp_state;2478}2479 2480static uint32_t2481lpfc_cmpl_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2482 void *arg, uint32_t evt)2483{2484 ndlp->nlp_prev_state = NLP_STE_LOGO_ISSUE;2485 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2486 spin_lock_irq(&ndlp->lock);2487 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2488 spin_unlock_irq(&ndlp->lock);2489 lpfc_disc_set_adisc(vport, ndlp);2490 return ndlp->nlp_state;2491}2492 2493static uint32_t2494lpfc_device_rm_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2495 void *arg, uint32_t evt)2496{2497 /*2498 * DevLoss has timed out and is calling for Device Remove.2499 * In this case, abort the LOGO and cleanup the ndlp2500 */2501 2502 lpfc_unreg_rpi(vport, ndlp);2503 /* software abort outstanding PLOGI */2504 lpfc_els_abort(vport->phba, ndlp);2505 lpfc_drop_node(vport, ndlp);2506 return NLP_STE_FREED_NODE;2507}2508 2509static uint32_t2510lpfc_device_recov_logo_issue(struct lpfc_vport *vport,2511 struct lpfc_nodelist *ndlp,2512 void *arg, uint32_t evt)2513{2514 /*2515 * Device Recovery events have no meaning for a node with a LOGO2516 * outstanding. The LOGO has to complete first and handle the2517 * node from that point.2518 */2519 return ndlp->nlp_state;2520}2521 2522static uint32_t2523lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2524 void *arg, uint32_t evt)2525{2526 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2527 2528 lpfc_rcv_plogi(vport, ndlp, cmdiocb);2529 return ndlp->nlp_state;2530}2531 2532static uint32_t2533lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2534 void *arg, uint32_t evt)2535{2536 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2537 2538 if (!lpfc_rcv_prli_support_check(vport, ndlp, cmdiocb))2539 return ndlp->nlp_state;2540 2541 lpfc_rcv_prli(vport, ndlp, cmdiocb);2542 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);2543 return ndlp->nlp_state;2544}2545 2546static uint32_t2547lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2548 void *arg, uint32_t evt)2549{2550 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2551 2552 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);2553 return ndlp->nlp_state;2554}2555 2556static uint32_t2557lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2558 void *arg, uint32_t evt)2559{2560 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2561 2562 lpfc_rcv_padisc(vport, ndlp, cmdiocb);2563 return ndlp->nlp_state;2564}2565 2566static uint32_t2567lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2568 void *arg, uint32_t evt)2569{2570 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2571 2572 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);2573 return ndlp->nlp_state;2574}2575 2576static uint32_t2577lpfc_device_rm_unmap_node(struct lpfc_vport *vport,2578 struct lpfc_nodelist *ndlp,2579 void *arg,2580 uint32_t evt)2581{2582 lpfc_drop_node(vport, ndlp);2583 return NLP_STE_FREED_NODE;2584}2585 2586static uint32_t2587lpfc_device_recov_unmap_node(struct lpfc_vport *vport,2588 struct lpfc_nodelist *ndlp,2589 void *arg,2590 uint32_t evt)2591{2592 ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;2593 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2594 spin_lock_irq(&ndlp->lock);2595 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2596 ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);2597 spin_unlock_irq(&ndlp->lock);2598 lpfc_disc_set_adisc(vport, ndlp);2599 2600 return ndlp->nlp_state;2601}2602 2603static uint32_t2604lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2605 void *arg, uint32_t evt)2606{2607 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2608 2609 lpfc_rcv_plogi(vport, ndlp, cmdiocb);2610 return ndlp->nlp_state;2611}2612 2613static uint32_t2614lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2615 void *arg, uint32_t evt)2616{2617 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2618 2619 if (!lpfc_rcv_prli_support_check(vport, ndlp, cmdiocb))2620 return ndlp->nlp_state;2621 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);2622 return ndlp->nlp_state;2623}2624 2625static uint32_t2626lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2627 void *arg, uint32_t evt)2628{2629 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2630 2631 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);2632 return ndlp->nlp_state;2633}2634 2635static uint32_t2636lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,2637 struct lpfc_nodelist *ndlp,2638 void *arg, uint32_t evt)2639{2640 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2641 2642 lpfc_rcv_padisc(vport, ndlp, cmdiocb);2643 return ndlp->nlp_state;2644}2645 2646static uint32_t2647lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2648 void *arg, uint32_t evt)2649{2650 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2651 2652 /* flush the target */2653 lpfc_sli_abort_iocb(vport, ndlp->nlp_sid, 0, LPFC_CTX_TGT);2654 2655 /* Send PRLO_ACC */2656 spin_lock_irq(&ndlp->lock);2657 ndlp->nlp_flag |= NLP_LOGO_ACC;2658 spin_unlock_irq(&ndlp->lock);2659 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);2660 2661 /* Save ELS_CMD_PRLO as the last elscmd and then set to NPR.2662 * lpfc_cmpl_els_logo_acc is expected to restart discovery.2663 */2664 ndlp->nlp_last_elscmd = ELS_CMD_PRLO;2665 ndlp->nlp_prev_state = ndlp->nlp_state;2666 2667 lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_ELS | LOG_DISCOVERY,2668 "3422 DID x%06x nflag x%x lastels x%x ref cnt %u\n",2669 ndlp->nlp_DID, ndlp->nlp_flag,2670 ndlp->nlp_last_elscmd,2671 kref_read(&ndlp->kref));2672 2673 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2674 2675 return ndlp->nlp_state;2676}2677 2678static uint32_t2679lpfc_device_recov_mapped_node(struct lpfc_vport *vport,2680 struct lpfc_nodelist *ndlp,2681 void *arg,2682 uint32_t evt)2683{2684 lpfc_disc_set_adisc(vport, ndlp);2685 2686 ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;2687 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);2688 spin_lock_irq(&ndlp->lock);2689 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2690 ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);2691 spin_unlock_irq(&ndlp->lock);2692 return ndlp->nlp_state;2693}2694 2695static uint32_t2696lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2697 void *arg, uint32_t evt)2698{2699 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2700 2701 /* Ignore PLOGI if we have an outstanding LOGO */2702 if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC))2703 return ndlp->nlp_state;2704 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {2705 lpfc_cancel_retry_delay_tmo(vport, ndlp);2706 spin_lock_irq(&ndlp->lock);2707 ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC);2708 spin_unlock_irq(&ndlp->lock);2709 } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {2710 /* send PLOGI immediately, move to PLOGI issue state */2711 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {2712 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;2713 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);2714 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);2715 }2716 }2717 return ndlp->nlp_state;2718}2719 2720static uint32_t2721lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2722 void *arg, uint32_t evt)2723{2724 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2725 struct ls_rjt stat;2726 2727 memset(&stat, 0, sizeof (struct ls_rjt));2728 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;2729 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;2730 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);2731 2732 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {2733 /*2734 * ADISC nodes will be handled in regular discovery path after2735 * receiving response from NS.2736 *2737 * For other nodes, Send PLOGI to trigger an implicit LOGO.2738 */2739 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {2740 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;2741 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);2742 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);2743 }2744 }2745 return ndlp->nlp_state;2746}2747 2748static uint32_t2749lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2750 void *arg, uint32_t evt)2751{2752 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2753 2754 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);2755 return ndlp->nlp_state;2756}2757 2758static uint32_t2759lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2760 void *arg, uint32_t evt)2761{2762 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2763 2764 lpfc_rcv_padisc(vport, ndlp, cmdiocb);2765 /*2766 * Do not start discovery if discovery is about to start2767 * or discovery in progress for this node. Starting discovery2768 * here will affect the counting of discovery threads.2769 */2770 if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&2771 !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {2772 /*2773 * ADISC nodes will be handled in regular discovery path after2774 * receiving response from NS.2775 *2776 * For other nodes, Send PLOGI to trigger an implicit LOGO.2777 */2778 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {2779 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;2780 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);2781 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);2782 }2783 }2784 return ndlp->nlp_state;2785}2786 2787static uint32_t2788lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2789 void *arg, uint32_t evt)2790{2791 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;2792 2793 spin_lock_irq(&ndlp->lock);2794 ndlp->nlp_flag |= NLP_LOGO_ACC;2795 spin_unlock_irq(&ndlp->lock);2796 2797 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);2798 2799 if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {2800 mod_timer(&ndlp->nlp_delayfunc,2801 jiffies + msecs_to_jiffies(1000 * 1));2802 spin_lock_irq(&ndlp->lock);2803 ndlp->nlp_flag |= NLP_DELAY_TMO;2804 ndlp->nlp_flag &= ~NLP_NPR_ADISC;2805 spin_unlock_irq(&ndlp->lock);2806 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;2807 } else {2808 spin_lock_irq(&ndlp->lock);2809 ndlp->nlp_flag &= ~NLP_NPR_ADISC;2810 spin_unlock_irq(&ndlp->lock);2811 }2812 return ndlp->nlp_state;2813}2814 2815static uint32_t2816lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2817 void *arg, uint32_t evt)2818{2819 struct lpfc_hba *phba = vport->phba;2820 struct lpfc_iocbq *cmdiocb, *rspiocb;2821 u32 ulp_status;2822 2823 cmdiocb = (struct lpfc_iocbq *) arg;2824 rspiocb = cmdiocb->rsp_iocb;2825 2826 ulp_status = get_job_ulpstatus(phba, rspiocb);2827 2828 if (ulp_status)2829 return NLP_STE_FREED_NODE;2830 2831 return ndlp->nlp_state;2832}2833 2834static uint32_t2835lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2836 void *arg, uint32_t evt)2837{2838 struct lpfc_hba *phba = vport->phba;2839 struct lpfc_iocbq *cmdiocb, *rspiocb;2840 u32 ulp_status;2841 2842 cmdiocb = (struct lpfc_iocbq *) arg;2843 rspiocb = cmdiocb->rsp_iocb;2844 2845 ulp_status = get_job_ulpstatus(phba, rspiocb);2846 2847 if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {2848 lpfc_drop_node(vport, ndlp);2849 return NLP_STE_FREED_NODE;2850 }2851 return ndlp->nlp_state;2852}2853 2854static uint32_t2855lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2856 void *arg, uint32_t evt)2857{2858 /* For the fabric port just clear the fc flags. */2859 if (ndlp->nlp_DID == Fabric_DID) {2860 clear_bit(FC_FABRIC, &vport->fc_flag);2861 clear_bit(FC_PUBLIC_LOOP, &vport->fc_flag);2862 }2863 lpfc_unreg_rpi(vport, ndlp);2864 return ndlp->nlp_state;2865}2866 2867static uint32_t2868lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2869 void *arg, uint32_t evt)2870{2871 struct lpfc_hba *phba = vport->phba;2872 struct lpfc_iocbq *cmdiocb, *rspiocb;2873 u32 ulp_status;2874 2875 cmdiocb = (struct lpfc_iocbq *) arg;2876 rspiocb = cmdiocb->rsp_iocb;2877 2878 ulp_status = get_job_ulpstatus(phba, rspiocb);2879 2880 if (ulp_status && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {2881 lpfc_drop_node(vport, ndlp);2882 return NLP_STE_FREED_NODE;2883 }2884 return ndlp->nlp_state;2885}2886 2887static uint32_t2888lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,2889 struct lpfc_nodelist *ndlp,2890 void *arg, uint32_t evt)2891{2892 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;2893 MAILBOX_t *mb = &pmb->u.mb;2894 2895 if (!mb->mbxStatus) {2896 /* SLI4 ports have preallocated logical rpis. */2897 if (vport->phba->sli_rev < LPFC_SLI_REV4)2898 ndlp->nlp_rpi = mb->un.varWords[0];2899 ndlp->nlp_flag |= NLP_RPI_REGISTERED;2900 if (ndlp->nlp_flag & NLP_LOGO_ACC) {2901 lpfc_unreg_rpi(vport, ndlp);2902 }2903 } else {2904 if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {2905 lpfc_drop_node(vport, ndlp);2906 return NLP_STE_FREED_NODE;2907 }2908 }2909 return ndlp->nlp_state;2910}2911 2912static uint32_t2913lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2914 void *arg, uint32_t evt)2915{2916 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {2917 spin_lock_irq(&ndlp->lock);2918 ndlp->nlp_flag |= NLP_NODEV_REMOVE;2919 spin_unlock_irq(&ndlp->lock);2920 return ndlp->nlp_state;2921 }2922 lpfc_drop_node(vport, ndlp);2923 return NLP_STE_FREED_NODE;2924}2925 2926static uint32_t2927lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,2928 void *arg, uint32_t evt)2929{2930 /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */2931 if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))2932 return ndlp->nlp_state;2933 2934 lpfc_cancel_retry_delay_tmo(vport, ndlp);2935 spin_lock_irq(&ndlp->lock);2936 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);2937 ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);2938 spin_unlock_irq(&ndlp->lock);2939 return ndlp->nlp_state;2940}2941 2942 2943/* This next section defines the NPort Discovery State Machine */2944 2945/* There are 4 different double linked lists nodelist entries can reside on.2946 * The plogi list and adisc list are used when Link Up discovery or RSCN2947 * processing is needed. Each list holds the nodes that we will send PLOGI2948 * or ADISC on. These lists will keep track of what nodes will be effected2949 * by an RSCN, or a Link Up (Typically, all nodes are effected on Link Up).2950 * The unmapped_list will contain all nodes that we have successfully logged2951 * into at the Fibre Channel level. The mapped_list will contain all nodes2952 * that are mapped FCP targets.2953 */2954/*2955 * The bind list is a list of undiscovered (potentially non-existent) nodes2956 * that we have saved binding information on. This information is used when2957 * nodes transition from the unmapped to the mapped list.2958 */2959/* For UNUSED_NODE state, the node has just been allocated .2960 * For PLOGI_ISSUE and REG_LOGIN_ISSUE, the node is on2961 * the PLOGI list. For REG_LOGIN_COMPL, the node is taken off the PLOGI list2962 * and put on the unmapped list. For ADISC processing, the node is taken off2963 * the ADISC list and placed on either the mapped or unmapped list (depending2964 * on its previous state). Once on the unmapped list, a PRLI is issued and the2965 * state changed to PRLI_ISSUE. When the PRLI completion occurs, the state is2966 * changed to UNMAPPED_NODE. If the completion indicates a mapped2967 * node, the node is taken off the unmapped list. The binding list is checked2968 * for a valid binding, or a binding is automatically assigned. If binding2969 * assignment is unsuccessful, the node is left on the unmapped list. If2970 * binding assignment is successful, the associated binding list entry (if2971 * any) is removed, and the node is placed on the mapped list.2972 */2973/*2974 * For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped2975 * lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers2976 * expire, all effected nodes will receive a DEVICE_RM event.2977 */2978/*2979 * For a Link Up or RSCN, all nodes will move from the mapped / unmapped lists2980 * to either the ADISC or PLOGI list. After a Nameserver query or ALPA loopmap2981 * check, additional nodes may be added or removed (via DEVICE_RM) to / from2982 * the PLOGI or ADISC lists. Once the PLOGI and ADISC lists are populated,2983 * we will first process the ADISC list. 32 entries are processed initially and2984 * ADISC is initited for each one. Completions / Events for each node are2985 * funnelled thru the state machine. As each node finishes ADISC processing, it2986 * starts ADISC for any nodes waiting for ADISC processing. If no nodes are2987 * waiting, and the ADISC list count is identically 0, then we are done. For2988 * Link Up discovery, since all nodes on the PLOGI list are UNREG_LOGIN'ed, we2989 * can issue a CLEAR_LA and reenable Link Events. Next we will process the PLOGI2990 * list. 32 entries are processed initially and PLOGI is initited for each one.2991 * Completions / Events for each node are funnelled thru the state machine. As2992 * each node finishes PLOGI processing, it starts PLOGI for any nodes waiting2993 * for PLOGI processing. If no nodes are waiting, and the PLOGI list count is2994 * indentically 0, then we are done. We have now completed discovery / RSCN2995 * handling. Upon completion, ALL nodes should be on either the mapped or2996 * unmapped lists.2997 */2998 2999static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])3000 (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {3001 /* Action routine Event Current State */3002 lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */3003 lpfc_rcv_els_unused_node, /* RCV_PRLI */3004 lpfc_rcv_logo_unused_node, /* RCV_LOGO */3005 lpfc_rcv_els_unused_node, /* RCV_ADISC */3006 lpfc_rcv_els_unused_node, /* RCV_PDISC */3007 lpfc_rcv_els_unused_node, /* RCV_PRLO */3008 lpfc_disc_illegal, /* CMPL_PLOGI */3009 lpfc_disc_illegal, /* CMPL_PRLI */3010 lpfc_cmpl_logo_unused_node, /* CMPL_LOGO */3011 lpfc_disc_illegal, /* CMPL_ADISC */3012 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3013 lpfc_device_rm_unused_node, /* DEVICE_RM */3014 lpfc_device_recov_unused_node, /* DEVICE_RECOVERY */3015 3016 lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */3017 lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */3018 lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */3019 lpfc_rcv_els_plogi_issue, /* RCV_ADISC */3020 lpfc_rcv_els_plogi_issue, /* RCV_PDISC */3021 lpfc_rcv_els_plogi_issue, /* RCV_PRLO */3022 lpfc_cmpl_plogi_plogi_issue, /* CMPL_PLOGI */3023 lpfc_disc_illegal, /* CMPL_PRLI */3024 lpfc_cmpl_logo_plogi_issue, /* CMPL_LOGO */3025 lpfc_disc_illegal, /* CMPL_ADISC */3026 lpfc_cmpl_reglogin_plogi_issue,/* CMPL_REG_LOGIN */3027 lpfc_device_rm_plogi_issue, /* DEVICE_RM */3028 lpfc_device_recov_plogi_issue, /* DEVICE_RECOVERY */3029 3030 lpfc_rcv_plogi_adisc_issue, /* RCV_PLOGI ADISC_ISSUE */3031 lpfc_rcv_prli_adisc_issue, /* RCV_PRLI */3032 lpfc_rcv_logo_adisc_issue, /* RCV_LOGO */3033 lpfc_rcv_padisc_adisc_issue, /* RCV_ADISC */3034 lpfc_rcv_padisc_adisc_issue, /* RCV_PDISC */3035 lpfc_rcv_prlo_adisc_issue, /* RCV_PRLO */3036 lpfc_disc_illegal, /* CMPL_PLOGI */3037 lpfc_disc_illegal, /* CMPL_PRLI */3038 lpfc_disc_illegal, /* CMPL_LOGO */3039 lpfc_cmpl_adisc_adisc_issue, /* CMPL_ADISC */3040 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3041 lpfc_device_rm_adisc_issue, /* DEVICE_RM */3042 lpfc_device_recov_adisc_issue, /* DEVICE_RECOVERY */3043 3044 lpfc_rcv_plogi_reglogin_issue, /* RCV_PLOGI REG_LOGIN_ISSUE */3045 lpfc_rcv_prli_reglogin_issue, /* RCV_PLOGI */3046 lpfc_rcv_logo_reglogin_issue, /* RCV_LOGO */3047 lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */3048 lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */3049 lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */3050 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */3051 lpfc_disc_illegal, /* CMPL_PRLI */3052 lpfc_disc_illegal, /* CMPL_LOGO */3053 lpfc_disc_illegal, /* CMPL_ADISC */3054 lpfc_cmpl_reglogin_reglogin_issue,/* CMPL_REG_LOGIN */3055 lpfc_device_rm_reglogin_issue, /* DEVICE_RM */3056 lpfc_device_recov_reglogin_issue,/* DEVICE_RECOVERY */3057 3058 lpfc_rcv_plogi_prli_issue, /* RCV_PLOGI PRLI_ISSUE */3059 lpfc_rcv_prli_prli_issue, /* RCV_PRLI */3060 lpfc_rcv_logo_prli_issue, /* RCV_LOGO */3061 lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */3062 lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */3063 lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */3064 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */3065 lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */3066 lpfc_disc_illegal, /* CMPL_LOGO */3067 lpfc_disc_illegal, /* CMPL_ADISC */3068 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3069 lpfc_device_rm_prli_issue, /* DEVICE_RM */3070 lpfc_device_recov_prli_issue, /* DEVICE_RECOVERY */3071 3072 lpfc_rcv_plogi_logo_issue, /* RCV_PLOGI LOGO_ISSUE */3073 lpfc_rcv_prli_logo_issue, /* RCV_PRLI */3074 lpfc_rcv_logo_logo_issue, /* RCV_LOGO */3075 lpfc_rcv_padisc_logo_issue, /* RCV_ADISC */3076 lpfc_rcv_padisc_logo_issue, /* RCV_PDISC */3077 lpfc_rcv_prlo_logo_issue, /* RCV_PRLO */3078 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */3079 lpfc_disc_illegal, /* CMPL_PRLI */3080 lpfc_cmpl_logo_logo_issue, /* CMPL_LOGO */3081 lpfc_disc_illegal, /* CMPL_ADISC */3082 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3083 lpfc_device_rm_logo_issue, /* DEVICE_RM */3084 lpfc_device_recov_logo_issue, /* DEVICE_RECOVERY */3085 3086 lpfc_rcv_plogi_unmap_node, /* RCV_PLOGI UNMAPPED_NODE */3087 lpfc_rcv_prli_unmap_node, /* RCV_PRLI */3088 lpfc_rcv_logo_unmap_node, /* RCV_LOGO */3089 lpfc_rcv_padisc_unmap_node, /* RCV_ADISC */3090 lpfc_rcv_padisc_unmap_node, /* RCV_PDISC */3091 lpfc_rcv_prlo_unmap_node, /* RCV_PRLO */3092 lpfc_disc_illegal, /* CMPL_PLOGI */3093 lpfc_disc_illegal, /* CMPL_PRLI */3094 lpfc_disc_illegal, /* CMPL_LOGO */3095 lpfc_disc_illegal, /* CMPL_ADISC */3096 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3097 lpfc_device_rm_unmap_node, /* DEVICE_RM */3098 lpfc_device_recov_unmap_node, /* DEVICE_RECOVERY */3099 3100 lpfc_rcv_plogi_mapped_node, /* RCV_PLOGI MAPPED_NODE */3101 lpfc_rcv_prli_mapped_node, /* RCV_PRLI */3102 lpfc_rcv_logo_mapped_node, /* RCV_LOGO */3103 lpfc_rcv_padisc_mapped_node, /* RCV_ADISC */3104 lpfc_rcv_padisc_mapped_node, /* RCV_PDISC */3105 lpfc_rcv_prlo_mapped_node, /* RCV_PRLO */3106 lpfc_disc_illegal, /* CMPL_PLOGI */3107 lpfc_disc_illegal, /* CMPL_PRLI */3108 lpfc_disc_illegal, /* CMPL_LOGO */3109 lpfc_disc_illegal, /* CMPL_ADISC */3110 lpfc_disc_illegal, /* CMPL_REG_LOGIN */3111 lpfc_disc_illegal, /* DEVICE_RM */3112 lpfc_device_recov_mapped_node, /* DEVICE_RECOVERY */3113 3114 lpfc_rcv_plogi_npr_node, /* RCV_PLOGI NPR_NODE */3115 lpfc_rcv_prli_npr_node, /* RCV_PRLI */3116 lpfc_rcv_logo_npr_node, /* RCV_LOGO */3117 lpfc_rcv_padisc_npr_node, /* RCV_ADISC */3118 lpfc_rcv_padisc_npr_node, /* RCV_PDISC */3119 lpfc_rcv_prlo_npr_node, /* RCV_PRLO */3120 lpfc_cmpl_plogi_npr_node, /* CMPL_PLOGI */3121 lpfc_cmpl_prli_npr_node, /* CMPL_PRLI */3122 lpfc_cmpl_logo_npr_node, /* CMPL_LOGO */3123 lpfc_cmpl_adisc_npr_node, /* CMPL_ADISC */3124 lpfc_cmpl_reglogin_npr_node, /* CMPL_REG_LOGIN */3125 lpfc_device_rm_npr_node, /* DEVICE_RM */3126 lpfc_device_recov_npr_node, /* DEVICE_RECOVERY */3127};3128 3129int3130lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,3131 void *arg, uint32_t evt)3132{3133 uint32_t cur_state, rc;3134 uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,3135 uint32_t);3136 uint32_t got_ndlp = 0;3137 uint32_t data1;3138 3139 if (lpfc_nlp_get(ndlp))3140 got_ndlp = 1;3141 3142 cur_state = ndlp->nlp_state;3143 3144 data1 = (((uint32_t)ndlp->nlp_fc4_type << 16) |3145 ((uint32_t)ndlp->nlp_type));3146 /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */3147 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,3148 "0211 DSM in event x%x on NPort x%x in "3149 "state %d rpi x%x Data: x%x x%x\n",3150 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_rpi,3151 ndlp->nlp_flag, data1);3152 3153 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,3154 "DSM in: evt:%d ste:%d did:x%x",3155 evt, cur_state, ndlp->nlp_DID);3156 3157 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];3158 rc = (func) (vport, ndlp, arg, evt);3159 3160 /* DSM out state <rc> on NPort <nlp_DID> */3161 if (got_ndlp) {3162 data1 = (((uint32_t)ndlp->nlp_fc4_type << 16) |3163 ((uint32_t)ndlp->nlp_type));3164 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,3165 "0212 DSM out state %d on NPort x%x "3166 "rpi x%x Data: x%x x%x\n",3167 rc, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp->nlp_flag,3168 data1);3169 3170 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,3171 "DSM out: ste:%d did:x%x flg:x%x",3172 rc, ndlp->nlp_DID, ndlp->nlp_flag);3173 /* Decrement the ndlp reference count held for this function */3174 lpfc_nlp_put(ndlp);3175 } else {3176 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,3177 "0213 DSM out state %d on NPort free\n", rc);3178 3179 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,3180 "DSM out: ste:%d did:x%x flg:x%x",3181 rc, 0, 0);3182 }3183 3184 return rc;3185}3186