diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 164 |
1 files changed, 63 insertions, 101 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 2b877dff5ed4..fb36f26170e4 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1183,6 +1183,7 @@ lpfc_port_link_failure(struct lpfc_vport *vport) void lpfc_linkdown_port(struct lpfc_vport *vport) { + struct lpfc_hba *phba = vport->phba; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if (vport->cfg_enable_fc4_type != LPFC_ENABLE_NVME) @@ -1200,6 +1201,13 @@ lpfc_linkdown_port(struct lpfc_vport *vport) vport->fc_flag &= ~FC_DISC_DELAYED; spin_unlock_irq(shost->host_lock); del_timer_sync(&vport->delayed_disc_tmo); + + if (phba->sli_rev == LPFC_SLI_REV4 && + vport->port_type == LPFC_PHYSICAL_PORT && + phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_CONFIG) { + /* Assume success on link up */ + phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_FABRIC; + } } int @@ -1221,6 +1229,9 @@ lpfc_linkdown(struct lpfc_hba *phba) phba->defer_flogi_acc_flag = false; + /* Clear external loopback plug detected flag */ + phba->link_flag &= ~LS_EXTERNAL_LOOPBACK; + spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_SCAN_DONE); spin_unlock_irq(&phba->hbalock); @@ -1343,10 +1354,12 @@ lpfc_linkup_port(struct lpfc_vport *vport) spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY | - FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY); + FC_RSCN_MEMENTO | FC_RSCN_MODE | + FC_NLP_MORE | FC_RSCN_DISCOVERY); vport->fc_flag |= FC_NDISC_ACTIVE; vport->fc_ns_retry = 0; spin_unlock_irq(shost->host_lock); + lpfc_setup_fdmi_mask(vport); lpfc_linkup_cleanup_nodes(vport); } @@ -1378,8 +1391,8 @@ lpfc_linkup(struct lpfc_hba *phba) phba->pport->rcv_flogi_cnt = 0; spin_unlock_irq(shost->host_lock); - /* reinitialize initial FLOGI flag */ - phba->hba_flag &= ~(HBA_FLOGI_ISSUED); + /* reinitialize initial HBA flag */ + phba->hba_flag &= ~(HBA_FLOGI_ISSUED | HBA_RHBA_CMPL); phba->defer_flogi_acc_flag = false; return 0; @@ -1458,7 +1471,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; LPFC_MBOXQ_t *sparam_mb; - struct lpfc_dmabuf *sparam_mp; u16 status = pmb->u.mb.mbxStatus; int rc; @@ -1507,13 +1519,8 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) sparam_mb->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; rc = lpfc_sli_issue_mbox(phba, sparam_mb, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - sparam_mp = (struct lpfc_dmabuf *) - sparam_mb->ctx_buf; - lpfc_mbuf_free(phba, sparam_mp->virt, - sparam_mp->phys); - kfree(sparam_mp); - sparam_mb->ctx_buf = NULL; - mempool_free(sparam_mb, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, sparam_mb, + MBOX_THD_UNLOCKED); goto sparam_out; } @@ -3312,7 +3319,6 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { - struct lpfc_dmabuf *dmabuf = mboxq->ctx_buf; struct lpfc_vport *vport = mboxq->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); @@ -3393,12 +3399,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) } out_free_mem: - mempool_free(mboxq, phba->mbox_mem_pool); - if (dmabuf) { - lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); - kfree(dmabuf); - } - return; + lpfc_mbox_rsrc_cleanup(phba, mboxq, MBOX_THD_UNLOCKED); } static void @@ -3443,9 +3444,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn)); } - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); /* Check if sending the FLOGI is being deferred to after we get * up to date CSPs from MBX_READ_SPARAM. @@ -3457,12 +3456,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; out: - pmb->ctx_buf = NULL; - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); lpfc_issue_clear_la(phba, vport); - mempool_free(pmb, phba->mbox_mem_pool); - return; } static void @@ -3472,7 +3467,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL; struct Scsi_Host *shost; int i; - struct lpfc_dmabuf *mp; int rc; struct fcf_record *fcf_record; uint32_t fc_flags = 0; @@ -3600,10 +3594,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; rc = lpfc_sli_issue_mbox(phba, sparam_mbox, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - mp = (struct lpfc_dmabuf *)sparam_mbox->ctx_buf; - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(sparam_mbox, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, sparam_mbox, MBOX_THD_UNLOCKED); goto out; } @@ -3879,10 +3870,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } lpfc_mbx_cmpl_read_topology_free_mbuf: - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - return; + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); } /* @@ -3895,9 +3883,13 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); + struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)pmb->ctx_buf; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; + /* The driver calls the state machine with the pmb pointer + * but wants to make sure a stale ctx_buf isn't acted on. + * The ctx_buf is restored later and cleaned up. + */ pmb->ctx_buf = NULL; pmb->ctx_ndlp = NULL; @@ -3934,10 +3926,9 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Call state machine */ lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); + pmb->ctx_buf = mp; + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); /* decrement the node reference count held for this callback * function. */ @@ -4104,11 +4095,15 @@ lpfc_create_static_vport(struct lpfc_hba *phba) vport_buff = (uint8_t *) vport_info; do { - /* free dma buffer from previous round */ + /* While loop iteration forces a free dma buffer from + * the previous loop because the mbox is reused and + * the dump routine is a single-use construct. + */ if (pmb->ctx_buf) { mp = (struct lpfc_dmabuf *)pmb->ctx_buf; lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); + pmb->ctx_buf = NULL; } if (lpfc_dump_static_vport(phba, pmb, offset)) goto out; @@ -4193,16 +4188,8 @@ lpfc_create_static_vport(struct lpfc_hba *phba) out: kfree(vport_info); - if (mbx_wait_rc != MBX_TIMEOUT) { - if (pmb->ctx_buf) { - mp = (struct lpfc_dmabuf *)pmb->ctx_buf; - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - } - mempool_free(pmb, phba->mbox_mem_pool); - } - - return; + if (mbx_wait_rc != MBX_TIMEOUT) + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); } /* @@ -4216,22 +4203,16 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; MAILBOX_t *mb = &pmb->u.mb; - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; struct Scsi_Host *shost; - ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; pmb->ctx_ndlp = NULL; - pmb->ctx_buf = NULL; if (mb->mbxStatus) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0258 Register Fabric login error: 0x%x\n", mb->mbxStatus); - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -4273,9 +4254,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_do_scr_ns_plogi(phba, vport); } - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); /* Drop the reference count from the mbox at the end after * all the current reference to the ndlp have been done. @@ -4369,12 +4348,10 @@ void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { MAILBOX_t *mb = &pmb->u.mb; - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; struct lpfc_vport *vport = pmb->vport; int rc; - pmb->ctx_buf = NULL; pmb->ctx_ndlp = NULL; vport->gidft_inp = 0; @@ -4388,9 +4365,7 @@ out: * callback function. */ lpfc_nlp_put(ndlp); - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); /* If the node is not registered with the scsi or nvme * transport, remove the fabric node. The failed reg_login @@ -4479,10 +4454,7 @@ out: * callback function. */ lpfc_nlp_put(ndlp); - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); return; } @@ -4496,13 +4468,9 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; MAILBOX_t *mb = &pmb->u.mb; - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; - ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; pmb->ctx_ndlp = NULL; - pmb->ctx_buf = NULL; - if (mb->mbxStatus) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0933 %s: Register FC login error: 0x%x\n", @@ -4526,9 +4494,7 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); out: - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); /* Drop the reference count from the mbox at the end after * all the current reference to the ndlp have been done. @@ -5155,7 +5121,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, if (pring->ringno == LPFC_ELS_RING) { switch (ulp_command) { case CMD_GEN_REQUEST64_CR: - if (iocb->context_un.ndlp == ndlp) + if (iocb->ndlp == ndlp) return 1; fallthrough; case CMD_ELS_REQUEST64_CR: @@ -5163,7 +5129,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, return 1; fallthrough; case CMD_XMIT_ELS_RSP64_CX: - if (iocb->context1 == (uint8_t *) ndlp) + if (iocb->ndlp == ndlp) return 1; } } else if (pring->ringno == LPFC_FCP_RING) { @@ -5273,7 +5239,6 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (!ndlp) return; lpfc_issue_els_logo(vport, ndlp, 0); - mempool_free(pmb, phba->mbox_mem_pool); /* Check to see if there are any deferred events to process */ if ((ndlp->nlp_flag & NLP_UNREG_INP) && @@ -5300,6 +5265,13 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_flag &= ~NLP_UNREG_INP; spin_unlock_irq(&ndlp->lock); } + + /* The node has an outstanding reference for the unreg. Now + * that the LOGO action and cleanup are finished, release + * resources. + */ + lpfc_nlp_put(ndlp); + mempool_free(pmb, phba->mbox_mem_pool); } /* @@ -5569,7 +5541,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *mb, *nextmb; - struct lpfc_dmabuf *mp; /* Cleanup node for NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, @@ -5607,16 +5578,11 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && !(mb->mbox_flag & LPFC_MBX_IMED_UNREG) && (ndlp == (struct lpfc_nodelist *)mb->ctx_ndlp)) { - mp = (struct lpfc_dmabuf *)(mb->ctx_buf); - if (mp) { - __lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - } list_del(&mb->list); - mempool_free(mb, phba->mbox_mem_pool); - /* We shall not invoke the lpfc_nlp_put to decrement - * the ndlp reference count as we are in the process - * of lpfc_nlp_release. + lpfc_mbox_rsrc_cleanup(phba, mb, MBOX_THD_LOCKED); + + /* Don't invoke lpfc_nlp_put. The driver is in + * lpfc_nlp_release context. */ } } @@ -6098,7 +6064,7 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) */ spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { - if (iocb->context1 != ndlp) + if (iocb->ndlp != ndlp) continue; ulp_command = get_job_cmnd(phba, iocb); @@ -6112,7 +6078,7 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) /* Next check the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { - if (iocb->context1 != ndlp) + if (iocb->ndlp != ndlp) continue; ulp_command = get_job_cmnd(phba, iocb); @@ -6390,8 +6356,9 @@ restart_disc: lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0231 RSCN timeout Data: x%x " - "x%x\n", - vport->fc_ns_retry, LPFC_MAX_NS_RETRY); + "x%x x%x x%x\n", + vport->fc_ns_retry, LPFC_MAX_NS_RETRY, + vport->port_state, vport->gidft_inp); /* Cleanup any outstanding ELS commands */ lpfc_els_flush_cmd(vport); @@ -6461,11 +6428,9 @@ void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { MAILBOX_t *mb = &pmb->u.mb; - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; struct lpfc_vport *vport = pmb->vport; - pmb->ctx_buf = NULL; pmb->ctx_ndlp = NULL; if (phba->sli_rev < LPFC_SLI_REV4) @@ -6496,10 +6461,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * function. */ lpfc_nlp_put(ndlp); - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - + lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED); return; } |