📄 lpfc_hbadisc.c
字号:
/* First do ADISCs - if any */ num_sent = lpfc_els_disc_adisc(phba); if (num_sent) return; if ((phba->hba_state < LPFC_HBA_READY) && (!clear_la_pending)) { /* If we get here, there is nothing to ADISC */ if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { phba->hba_state = LPFC_CLEAR_LA; lpfc_clear_la(phba, mbox); mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) { mempool_free( mbox, 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 { /* Next do PLOGIs - if any */ num_sent = lpfc_els_disc_plogi(phba); if (num_sent) return; if (phba->fc_flag & FC_RSCN_MODE) { /* Check to see if more RSCNs came in while we * were processing this one. */ if ((phba->fc_rscn_id_cnt == 0) && (!(phba->fc_flag & FC_RSCN_DISCOVERY))) { spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_RSCN_MODE; spin_unlock_irq(phba->host->host_lock); } else lpfc_els_handle_rscn(phba); } } return;}/* * Ignore completion for all IOCBs on tx and txcmpl queue for ELS * ring the match the sppecified nodelist. */static voidlpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ struct lpfc_sli *psli; IOCB_t *icmd; struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_sli_ring *pring; struct lpfc_dmabuf *mp; psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* Error matching iocb on txq or txcmplq * First check the txq. */ list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { if (iocb->context1 != ndlp) { continue; } icmd = &iocb->iocb; if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { list_del(&iocb->list); pring->txq_cnt--; lpfc_els_free_iocb(phba, iocb); } } /* Next check the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { if (iocb->context1 != ndlp) { continue; } icmd = &iocb->iocb; if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { iocb->iocb_cmpl = NULL; /* context2 = cmd, context2->next = rsp, context3 = bpl */ if (iocb->context2) { /* Free the response IOCB before handling the command. */ mp = (struct lpfc_dmabuf *) (iocb->context2); mp = list_get_first(&mp->list, struct lpfc_dmabuf, list); if (mp) { /* Delay before releasing rsp buffer to * give UNREG mbox a chance to take * effect. */ list_add(&mp->list, &phba->freebufList); } lpfc_mbuf_free(phba, ((struct lpfc_dmabuf *) iocb->context2)->virt, ((struct lpfc_dmabuf *) iocb->context2)->phys); kfree(iocb->context2); } if (iocb->context3) { lpfc_mbuf_free(phba, ((struct lpfc_dmabuf *) iocb->context3)->virt, ((struct lpfc_dmabuf *) iocb->context3)->phys); kfree(iocb->context3); } } } return;}voidlpfc_disc_flush_list(struct lpfc_hba * phba){ struct lpfc_nodelist *ndlp, *next_ndlp; if (phba->fc_plogi_cnt) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, nlp_listp) { lpfc_free_tx(phba, ndlp); lpfc_nlp_remove(phba, ndlp); } } if (phba->fc_adisc_cnt) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, nlp_listp) { lpfc_free_tx(phba, ndlp); lpfc_nlp_remove(phba, ndlp); } } return;}/*****************************************************************************//* * NAME: lpfc_disc_timeout * * FUNCTION: Fibre Channel driver discovery timeout routine. * * EXECUTION ENVIRONMENT: interrupt only * * CALLED FROM: * Timer function * * RETURNS: * none *//*****************************************************************************/voidlpfc_disc_timeout(unsigned long ptr){ struct lpfc_hba *phba = (struct lpfc_hba *)ptr; unsigned long flags = 0; if (unlikely(!phba)) return; spin_lock_irqsave(phba->host->host_lock, flags); if (!(phba->work_hba_events & WORKER_DISC_TMO)) { phba->work_hba_events |= WORKER_DISC_TMO; if (phba->work_wait) wake_up(phba->work_wait); } spin_unlock_irqrestore(phba->host->host_lock, flags); return;}static voidlpfc_disc_timeout_handler(struct lpfc_hba *phba){ struct lpfc_sli *psli; struct lpfc_nodelist *ndlp; LPFC_MBOXQ_t *clearlambox, *initlinkmbox; int rc, clrlaerr = 0; if (unlikely(!phba)) return; if (!(phba->fc_flag & FC_DISC_TMO)) return; psli = &phba->sli; spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_DISC_TMO; spin_unlock_irq(phba->host->host_lock); switch (phba->hba_state) { case LPFC_LOCAL_CFG_LINK: /* hba_state is identically LPFC_LOCAL_CFG_LINK while waiting for FAN */ /* FAN timeout */ lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY, "%d:0221 FAN timeout\n", phba->brd_no); /* Forget about FAN, 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); break; case LPFC_FLOGI: /* hba_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */ /* Initial FLOGI timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0222 Initial FLOGI timeout\n", phba->brd_no); /* Assume no Fabric and go on with discovery. * Check for outstanding ELS FLOGI to abort. */ /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(phba); /* Start discovery */ lpfc_disc_start(phba); break; case LPFC_FABRIC_CFG_LINK: /* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for NameServer login */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0223 Timeout while waiting for NameServer " "login\n", phba->brd_no); /* Next look for NameServer ndlp */ ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); if (ndlp) lpfc_nlp_remove(phba, ndlp); /* Start discovery */ lpfc_disc_start(phba); break; case LPFC_NS_QRY: /* Check for wait for NameServer Rsp timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0224 NameServer Query timeout " "Data: x%x x%x\n", phba->brd_no, phba->fc_ns_retry, LPFC_MAX_NS_RETRY); ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID); if (ndlp) { if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { /* Try it one more time */ rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); if (rc == 0) break; } phba->fc_ns_retry = 0; } /* Nothing to authenticate, so CLEAR_LA right now */ clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!clearlambox) { clrlaerr = 1; lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; break; } phba->hba_state = LPFC_CLEAR_LA; lpfc_clear_la(phba, clearlambox); clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; rc = lpfc_sli_issue_mbox(phba, clearlambox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) { mempool_free(clearlambox, phba->mbox_mem_pool); clrlaerr = 1; break; } /* Setup and issue mailbox INITIALIZE LINK command */ initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!initlinkmbox) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; break; } lpfc_linkdown(phba); lpfc_init_link(phba, initlinkmbox, phba->cfg_topology, phba->cfg_link_speed); initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0; rc = lpfc_sli_issue_mbox(phba, initlinkmbox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) mempool_free(initlinkmbox, phba->mbox_mem_pool); break; case LPFC_DISC_AUTH: /* Node Authentication timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0227 Node Authentication timeout\n", phba->brd_no); lpfc_disc_flush_list(phba); clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!clearlambox) { clrlaerr = 1; lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; break; } phba->hba_state = LPFC_CLEAR_LA; lpfc_clear_la(phba, clearlambox); clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; rc = lpfc_sli_issue_mbox(phba, clearlambox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) { mempool_free(clearlambox, phba->mbox_mem_pool); clrlaerr = 1; } break; case LPFC_CLEAR_LA: /* CLEAR LA timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0228 CLEAR LA timeout\n", phba->brd_no); clrlaerr = 1; break; case LPFC_HBA_READY: if (phba->fc_flag & FC_RSCN_MODE) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0231 RSCN timeout Data: x%x x%x\n", phba->brd_no, phba->fc_ns_retry, LPFC_MAX_NS_RETRY); /* Cleanup any outstanding ELS commands */ lpfc_els_flush_cmd(phba); lpfc_els_flush_rscn(phba); lpfc_disc_flush_list(phba); } break; } if (clrlaerr) { 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_nodev_timeout(unsigned long ptr){ struct lpfc_hba *phba; struct lpfc_nodelist *ndlp; unsigned long iflag; struct lpfc_work_evt *evtp; ndlp = (struct lpfc_nodelist *)ptr; phba = ndlp->nlp_phba; evtp = &ndlp->nodev_timeout_evt; spin_lock_irqsave(phba->host->host_lock, iflag); if (!list_empty(&evtp->evt_listp)) { spin_unlock_irqrestore(phba->host->host_lock, iflag); return; } evtp->evt_arg1 = ndlp; evtp->evt = LPFC_EVT_NODEV_TMO; list_add_tail(&evtp->evt_listp, &phba->work_list); if (phba->work_wait) wake_up(phba->work_wait); spin_unlock_irqrestore(phba->host->host_lock, iflag); 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_fdmi_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; 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); /* Start issuing Fabric-Device Management Interface (FDMI) * command to 0xfffffa (FDMI well known port) */ if (phba->cfg_fdmi_on == 1) { lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA); } else { /* * Delay issuing FDMI command if fdmi-on=2 * (supporting RPA/hostnmae) */ mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); } lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return;}/* * This routine looks up the ndlp lists * for the given RPI. If rpi found * it return the node list pointer * else return NULL. */struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi){ struct lpfc_nodelist *ndlp; struct list_head * lists[]={&phba->fc_nlpunmap_list, &phba->fc_nlpmap_list, &phba->fc_plogi_list, &phba->fc_adisc_list, &phba->fc_reglogin_list}; int i; for (i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -