lpfc_hbadisc.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,453 行 · 第 1/5 页
C
2,453 行
mb = &pmb->mb; /* Since we don't do discovery right now, turn these off here */ 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; /* Check for error */ if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) { /* CLEAR_LA mbox error <mbxStatus> state <hba_state> */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, "%d:0320 CLEAR_LA mbxStatus error x%x hba " "state x%x\n", phba->brd_no, mb->mbxStatus, phba->hba_state); phba->hba_state = LPFC_HBA_ERROR; goto out; } if (phba->fc_flag & FC_ABORT_DISCOVERY) goto out; phba->num_disc_nodes = 0; /* go thru NPR list and issue ELS PLOGIs */ if (phba->fc_npr_cnt) { lpfc_els_disc_plogi(phba); } if (!phba->num_disc_nodes) { spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_NDISC_ACTIVE; spin_unlock_irq(phba->host->host_lock); } phba->hba_state = LPFC_HBA_READY;out: /* Device Discovery completes */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0225 Device Discovery completes\n", phba->brd_no); mempool_free( pmb, phba->mbox_mem_pool); spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_ABORT_DISCOVERY; if (phba->fc_flag & FC_ESTABLISH_LINK) { phba->fc_flag &= ~FC_ESTABLISH_LINK; } spin_unlock_irq(phba->host->host_lock); del_timer_sync(&phba->fc_estabtmo); lpfc_can_disctmo(phba); /* turn on Link Attention interrupts */ 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); return;}static voidlpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb){ struct lpfc_sli *psli = &phba->sli; int rc; if (pmb->mb.mbxStatus) goto out; mempool_free(pmb, phba->mbox_mem_pool); if (phba->fc_topology == TOPOLOGY_LOOP && 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); 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); return;out: lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, "%d:0306 CONFIG_LINK mbxStatus error x%x " "HBA state x%x\n", phba->brd_no, pmb->mb.mbxStatus, phba->hba_state); lpfc_linkdown(phba); phba->hba_state = LPFC_HBA_ERROR; lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0200 CONFIG_LINK bad hba state x%x\n", phba->brd_no, phba->hba_state); lpfc_clear_la(phba, pmb); pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == 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; } 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_local_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); spin_lock_irq(phba->host->host_lock); if (la->pb) phba->fc_flag |= FC_BYPASSED_MODE; else phba->fc_flag &= ~FC_BYPASSED_MODE; spin_unlock_irq(phba->host->host_lock); 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); ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); if (!ndlp) { /* Allocate a new node instance. If the pool is empty, * start the discovery process and skip the Nameserver * login process. This is attempted again later on. * Otherwise, issue a Port Login (PLOGI) to NameServer. */ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); if (!ndlp) { lpfc_disc_start(phba); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return; } 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, NameServer_DID, 0); if (phba->cfg_fdmi_on) { ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); if (ndlp_fdmi) { 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, FDMI_DID, 0); } } } lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?