📄 lpfc_hbadisc.c
字号:
return 1; } return 0;}/* * Free resources associated with LPFC_NODELIST entry * so it can be freed. */static intlpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ LPFC_MBOXQ_t *mb; LPFC_MBOXQ_t *nextmb; struct lpfc_dmabuf *mp; /* Cleanup node for NPort <nlp_DID> */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0900 Cleanup node for NPort x%x " "Data: x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); /* * if unloading the driver - just leave the remote port in place. * The driver unload will force the attached devices to detach * and flush cache's w/o generating flush errors. */ if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { lpfc_unregister_remote_port(phba, ndlp); ndlp->nlp_sid = NLP_NO_SID; } /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ if ((mb = phba->sli.mbox_active)) { if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { mb->context2 = NULL; mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } } list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { mp = (struct lpfc_dmabuf *) (mb->context1); if (mp) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } list_del(&mb->list); mempool_free(mb, phba->mbox_mem_pool); } } lpfc_els_abort(phba,ndlp,0); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_TMO|NLP_DELAY_TMO); spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_tmofunc); del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) list_del_init(&ndlp->nodev_timeout_evt.evt_listp); if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); lpfc_unreg_rpi(phba, ndlp); return (0);}/* * Check to see if we can free the nlp back to the freelist. * If we are in the middle of using the nlp in the discovery state * machine, defer the free till we reach the end of the state machine. */intlpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ if (ndlp->nlp_flag & NLP_NODEV_TMO) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NODEV_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_tmofunc); if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) list_del_init(&ndlp->nodev_timeout_evt.evt_listp); } if (ndlp->nlp_flag & NLP_DELAY_TMO) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); } if (ndlp->nlp_disc_refcnt) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_REMOVE; spin_unlock_irq(phba->host->host_lock); } else { lpfc_freenode(phba, ndlp); mempool_free( ndlp, phba->nlp_mem_pool); } return(0);}static intlpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did){ D_ID mydid; D_ID ndlpdid; D_ID matchdid; if (did == Bcast_DID) return (0); if (ndlp->nlp_DID == 0) { return (0); } /* First check for Direct match */ if (ndlp->nlp_DID == did) return (1); /* Next check for area/domain identically equals 0 match */ mydid.un.word = phba->fc_myDID; if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { return (0); } matchdid.un.word = did; ndlpdid.un.word = ndlp->nlp_DID; if (matchdid.un.b.id == ndlpdid.un.b.id) { if ((mydid.un.b.domain == matchdid.un.b.domain) && (mydid.un.b.area == matchdid.un.b.area)) { if ((ndlpdid.un.b.domain == 0) && (ndlpdid.un.b.area == 0)) { if (ndlpdid.un.b.id) return (1); } return (0); } matchdid.un.word = ndlp->nlp_DID; if ((mydid.un.b.domain == ndlpdid.un.b.domain) && (mydid.un.b.area == ndlpdid.un.b.area)) { if ((matchdid.un.b.domain == 0) && (matchdid.un.b.area == 0)) { if (matchdid.un.b.id) return (1); } } } return (0);}/* Search for a nodelist entry on a specific list */struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did){ struct lpfc_nodelist *ndlp, *next_ndlp; uint32_t data1; if (order & NLP_SEARCH_UNMAPPED) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* FIND node DID unmapped */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0929 FIND node DID unmapped" " Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_MAPPED) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* FIND node DID mapped */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0930 FIND node DID mapped " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_PLOGI) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to PLOGI */ /* FIND node DID plogi */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0908 FIND node DID plogi " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_ADISC) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to ADISC */ /* FIND node DID adisc */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0931 FIND node DID adisc " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_REGLOGIN) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to REGLOGIN */ /* FIND node DID reglogin */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0931 FIND node DID reglogin" " Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_PRLI) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to PRLI */ /* FIND node DID prli */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0931 FIND node DID prli " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_NPR) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to NPR */ /* FIND node DID npr */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0931 FIND node DID npr " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } if (order & NLP_SEARCH_UNUSED) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); /* LOG change to UNUSED */ /* FIND node DID unused */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0931 FIND node DID unused " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); return (ndlp); } } } /* FIND node did <did> NOT FOUND */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", phba->brd_no, did, order); /* no match found */ return NULL;}struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did){ struct lpfc_nodelist *ndlp; uint32_t flg; if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) { if ((phba->hba_state == LPFC_HBA_READY) && ((lpfc_rscn_payload_check(phba, did) == 0))) return NULL; ndlp = (struct lpfc_nodelist *) mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); if (!ndlp) return NULL; lpfc_nlp_init(phba, ndlp, did); ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; return ndlp; } if ((phba->hba_state == LPFC_HBA_READY) && (phba->fc_flag & FC_RSCN_MODE)) { if (lpfc_rscn_payload_check(phba, did)) { ndlp->nlp_flag |= NLP_NPR_2B_DISC; } else { ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ndlp = NULL; } } else { flg = ndlp->nlp_flag & NLP_LIST_MASK; if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) { return NULL; } ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; } return ndlp;}/* Build a list of nodes to discover based on the loopmap */voidlpfc_disc_list_loopmap(struct lpfc_hba * phba){ int j; uint32_t alpa, index; if (phba->hba_state <= LPFC_LINK_DOWN) { return; } if (phba->fc_topology != TOPOLOGY_LOOP) { return; } /* Check for loop map present or not */ if (phba->alpa_map[0]) { for (j = 1; j <= phba->alpa_map[0]; j++) { alpa = phba->alpa_map[j]; if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) { continue; } lpfc_setup_disc_node(phba, alpa); } } else { /* No alpamap, so try all alpa's */ for (j = 0; j < FC_MAXLOOP; j++) { /* If cfg_scan_down is set, start from highest * ALPA (0xef) to lowest (0x1). */ if (phba->cfg_scan_down) index = j; else index = FC_MAXLOOP - j - 1; alpa = lpfcAlpaArray[index]; if ((phba->fc_myDID & 0xff) == alpa) { continue; } lpfc_setup_disc_node(phba, alpa); } } return;}/* Start Link up / RSCN discovery on NPR list */voidlpfc_disc_start(struct lpfc_hba * phba){ struct lpfc_sli *psli; LPFC_MBOXQ_t *mbox; struct lpfc_nodelist *ndlp, *next_ndlp; uint32_t did_changed, num_sent; uint32_t clear_la_pending; int rc; psli = &phba->sli; if (phba->hba_state <= LPFC_LINK_DOWN) { return; } if (phba->hba_state == LPFC_CLEAR_LA) clear_la_pending = 1; else clear_la_pending = 0; if (phba->hba_state < LPFC_HBA_READY) { phba->hba_state = LPFC_DISC_AUTH; } lpfc_set_disctmo(phba); if (phba->fc_prevDID == phba->fc_myDID) { did_changed = 0; } else { did_changed = 1; } phba->fc_prevDID = phba->fc_myDID; phba->num_disc_nodes = 0; /* Start Discovery state <hba_state> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0202 Start Discovery hba state x%x " "Data: x%x x%x x%x\n", phba->brd_no, phba->hba_state, phba->fc_flag, phba->fc_plogi_cnt, phba->fc_adisc_cnt); /* If our did changed, we MUST do PLOGI */ list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, nlp_listp) { if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { if (did_changed) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -