📄 lpfc_hbadisc.c
字号:
psli->sli_flag |= LPFC_PROCESS_LA; control = readl(phba->HCregaddr); control |= HC_LAINT_ENA; writel(control, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock); return;}static voidlpfc_mbx_cmpl_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ struct lpfc_sli *psli; MAILBOX_t *mb; psli = &phba->sli; mb = &pmb->mb; /* Check for error */ if (mb->mbxStatus) { /* CONFIG_LINK mbox error <mbxStatus> state <hba_state> */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, "%d:0306 CONFIG_LINK mbxStatus error x%x " "HBA state x%x\n", phba->brd_no, mb->mbxStatus, phba->hba_state); lpfc_linkdown(phba); phba->hba_state = LPFC_HBA_ERROR; goto out; } if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { if (phba->fc_topology == TOPOLOGY_LOOP) { /* If we are public loop and L bit was set */ if ((phba->fc_flag & FC_PUBLIC_LOOP) && !(phba->fc_flag & FC_LBIT)) { /* Need to wait for FAN - use discovery timer * for timeout. hba_state is identically * LPFC_LOCAL_CFG_LINK while waiting for FAN */ lpfc_set_disctmo(phba); mempool_free( pmb, phba->mbox_mem_pool); return; } } /* Start discovery by sending a FLOGI hba_state is identically * LPFC_FLOGI while waiting for FLOGI cmpl */ phba->hba_state = LPFC_FLOGI; lpfc_set_disctmo(phba); lpfc_initial_flogi(phba); mempool_free( pmb, phba->mbox_mem_pool); return; } if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { mempool_free( pmb, phba->mbox_mem_pool); return; }out: /* CONFIG_LINK bad hba state <hba_state> */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0200 CONFIG_LINK bad hba state x%x\n", phba->brd_no, phba->hba_state); if (phba->hba_state != LPFC_CLEAR_LA) { lpfc_clear_la(phba, pmb); pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)) == MBX_NOT_FINISHED) { mempool_free( pmb, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; phba->hba_state = LPFC_HBA_READY; } } else { mempool_free( pmb, phba->mbox_mem_pool); } return;}static voidlpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ struct lpfc_sli *psli = &phba->sli; MAILBOX_t *mb = &pmb->mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1; /* Check for error */ if (mb->mbxStatus) { /* READ_SPARAM mbox error <mbxStatus> state <hba_state> */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, "%d:0319 READ_SPARAM mbxStatus error x%x " "hba state x%x>\n", phba->brd_no, mb->mbxStatus, phba->hba_state); lpfc_linkdown(phba); phba->hba_state = LPFC_HBA_ERROR; goto out; } memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, sizeof (struct serv_parm)); memcpy((uint8_t *) & phba->fc_nodename, (uint8_t *) & phba->fc_sparam.nodeName, sizeof (struct lpfc_name)); memcpy((uint8_t *) & phba->fc_portname, (uint8_t *) & phba->fc_sparam.portName, sizeof (struct lpfc_name)); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return;out: pmb->context1 = NULL; lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); if (phba->hba_state != LPFC_CLEAR_LA) { lpfc_clear_la(phba, pmb); pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)) == MBX_NOT_FINISHED) { mempool_free( pmb, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; phba->hba_state = LPFC_HBA_READY; } } else { mempool_free( pmb, phba->mbox_mem_pool); } return;}static voidlpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la){ int i; LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox; sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); spin_lock_irq(phba->host->host_lock); switch(la->UlnkSpeed) { case LA_1GHZ_LINK: phba->fc_linkspeed = LA_1GHZ_LINK; break; case LA_2GHZ_LINK: phba->fc_linkspeed = LA_2GHZ_LINK; break; case LA_4GHZ_LINK: phba->fc_linkspeed = LA_4GHZ_LINK; break; default: phba->fc_linkspeed = LA_UNKNW_LINK; break; } phba->fc_topology = la->topology; if (phba->fc_topology == TOPOLOGY_LOOP) { /* Get Loop Map information */ if (la->il) phba->fc_flag |= FC_LBIT; phba->fc_myDID = la->granted_AL_PA; i = la->un.lilpBde64.tus.f.bdeSize; if (i == 0) { phba->alpa_map[0] = 0; } else { if (phba->cfg_log_verbose & LOG_LINK_EVENT) { int numalpa, j, k; union { uint8_t pamap[16]; struct { uint32_t wd1; uint32_t wd2; uint32_t wd3; uint32_t wd4; } pa; } un; numalpa = phba->alpa_map[0]; j = 0; while (j < numalpa) { memset(un.pamap, 0, 16); for (k = 1; j < numalpa; k++) { un.pamap[k - 1] = phba->alpa_map[j + 1]; j++; if (k == 16) break; } /* Link Up Event ALPA map */ lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, "%d:1304 Link Up Event " "ALPA map Data: x%x " "x%x x%x x%x\n", phba->brd_no, un.pa.wd1, un.pa.wd2, un.pa.wd3, un.pa.wd4); } } } } else { phba->fc_myDID = phba->fc_pref_DID; phba->fc_flag |= FC_LBIT; } spin_unlock_irq(phba->host->host_lock); lpfc_linkup(phba); if (sparam_mbox) { lpfc_read_sparam(phba, sparam_mbox); sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; lpfc_sli_issue_mbox(phba, sparam_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); } if (cfglink_mbox) { phba->hba_state = LPFC_LOCAL_CFG_LINK; lpfc_config_link(phba, cfglink_mbox); cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_config_link; lpfc_sli_issue_mbox(phba, cfglink_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); }}static voidlpfc_mbx_issue_link_down(struct lpfc_hba *phba) { uint32_t control; struct lpfc_sli *psli = &phba->sli; lpfc_linkdown(phba); /* turn on Link Attention interrupts - no CLEAR_LA needed */ spin_lock_irq(phba->host->host_lock); psli->sli_flag |= LPFC_PROCESS_LA; control = readl(phba->HCregaddr); control |= HC_LAINT_ENA; writel(control, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock);}/* * This routine handles processing a READ_LA mailbox * command upon completion. It is setup in the LPFC_MBOXQ * as the completion routine when the command is * handed off to the SLI layer. */voidlpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ READ_LA_VAR *la; MAILBOX_t *mb = &pmb->mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); /* Check for error */ if (mb->mbxStatus) { lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, "%d:1307 READ_LA mbox error x%x state x%x\n", phba->brd_no, mb->mbxStatus, phba->hba_state); lpfc_mbx_issue_link_down(phba); phba->hba_state = LPFC_HBA_ERROR; goto lpfc_mbx_cmpl_read_la_free_mbuf; } la = (READ_LA_VAR *) & pmb->mb.un.varReadLA; memcpy(&phba->alpa_map[0], mp->virt, 128); if (((phba->fc_eventTag + 1) < la->eventTag) || (phba->fc_eventTag == la->eventTag)) { phba->fc_stat.LinkMultiEvent++; if (la->attType == AT_LINK_UP) { if (phba->fc_eventTag != 0) lpfc_linkdown(phba); } } phba->fc_eventTag = la->eventTag; if (la->attType == AT_LINK_UP) { phba->fc_stat.LinkUp++; lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "%d:1303 Link Up Event x%x received " "Data: x%x x%x x%x x%x\n", phba->brd_no, la->eventTag, phba->fc_eventTag, la->granted_AL_PA, la->UlnkSpeed, phba->alpa_map[0]); lpfc_mbx_process_link_up(phba, la); } else { phba->fc_stat.LinkDown++; lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "%d:1305 Link Down Event x%x received " "Data: x%x x%x x%x\n", phba->brd_no, la->eventTag, phba->fc_eventTag, phba->hba_state, phba->fc_flag); lpfc_mbx_issue_link_down(phba); }lpfc_mbx_cmpl_read_la_free_mbuf: lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); return;}/* * This routine handles processing a REG_LOGIN mailbox * command upon completion. It is setup in the LPFC_MBOXQ * as the completion routine when the command is * handed off to the SLI layer. */voidlpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ struct lpfc_sli *psli; MAILBOX_t *mb; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; psli = &phba->sli; mb = &pmb->mb; ndlp = (struct lpfc_nodelist *) pmb->context2; mp = (struct lpfc_dmabuf *) (pmb->context1); pmb->context1 = NULL; /* Good status, call state machine */ lpfc_disc_state_machine(phba, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return;}/* * This routine handles processing a Fabric REG_LOGIN mailbox * command upon completion. It is setup in the LPFC_MBOXQ * as the completion routine when the command is * handed off to the SLI layer. */voidlpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ struct lpfc_sli *psli; MAILBOX_t *mb; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp_fdmi; psli = &phba->sli; mb = &pmb->mb; ndlp = (struct lpfc_nodelist *) pmb->context2; mp = (struct lpfc_dmabuf *) (pmb->context1); if (mb->mbxStatus) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); mempool_free( ndlp, phba->nlp_mem_pool); /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(phba); /* Start discovery */ lpfc_disc_start(phba); return; } pmb->context1 = NULL; ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { /* This NPort has been assigned an NPort_ID by the fabric as a * result of the completed fabric login. Issue a State Change * Registration (SCR) ELS request to the fabric controller * (SCR_DID) so that this NPort gets RSCN events from the * fabric. */ lpfc_issue_els_scr(phba, SCR_DID, 0); /* Allocate a new node instance. If the pool is empty, just * start the discovery process and skip the Nameserver login * process. This is attempted again later on. Otherwise, issue * a Port Login (PLOGI) to the NameServer */ if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) { lpfc_disc_start(phba); } else { lpfc_nlp_init(phba, ndlp, NameServer_DID); ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); if (phba->cfg_fdmi_on) { if ((ndlp_fdmi = mempool_alloc( phba->nlp_mem_pool, GFP_KERNEL))) { lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID); ndlp_fdmi->nlp_type |= NLP_FABRIC; ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_issue_els_plogi(phba, ndlp_fdmi, 0); } } } } lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return;}/* * This routine handles processing a NameServer REG_LOGIN mailbox * command upon completion. It is setup in the LPFC_MBOXQ * as the completion routine when the command is * handed off to the SLI layer. */voidlpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb){ struct lpfc_sli *psli; MAILBOX_t *mb; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; psli = &phba->sli; mb = &pmb->mb; ndlp = (struct lpfc_nodelist *) pmb->context2; mp = (struct lpfc_dmabuf *) (pmb->context1); if (mb->mbxStatus) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); /* RegLogin failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(phba); /* Start discovery */ lpfc_disc_start(phba); return; } pmb->context1 = NULL; ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); if (phba->hba_state < LPFC_HBA_READY) { /* Link up discovery requires Fabrib registration. */ lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID); lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN); lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -