lpfc_hbadisc.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,453 行 · 第 1/5 页
C
2,453 行
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); } phba->fc_ns_retry = 0; /* Good status, issue CT Request to NameServer */ if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT)) { /* Cannot issue NameServer Query, so finish up discovery */ lpfc_disc_start(phba); } lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); return;}static voidlpfc_register_remote_port(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ struct fc_rport *rport; struct lpfc_rport_data *rdata; struct fc_rport_identifiers rport_ids; /* Remote port has reappeared. Re-register w/ FC transport */ rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); rport_ids.port_id = ndlp->nlp_DID; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, "Warning: fc_remote_port_add failed\n"); return; } /* initialize static port data */ rport->maxframe_size = ndlp->nlp_maxframe; rport->supported_classes = ndlp->nlp_class_sup; rdata = rport->dd_data; rdata->pnode = ndlp; if (ndlp->nlp_type & NLP_FCP_TARGET) rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; if (ndlp->nlp_type & NLP_FCP_INITIATOR) rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) fc_remote_port_rolechg(rport, rport_ids.roles); if ((rport->scsi_target_id != -1) && (rport->scsi_target_id < MAX_FCP_TARGET)) { ndlp->nlp_sid = rport->scsi_target_id; } return;}static voidlpfc_unregister_remote_port(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ struct fc_rport *rport = ndlp->rport; struct lpfc_rport_data *rdata = rport->dd_data; ndlp->rport = NULL; rdata->pnode = NULL; fc_remote_port_delete(rport); return;}intlpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list){ enum { none, unmapped, mapped } rport_add = none, rport_del = none; struct lpfc_sli *psli; psli = &phba->sli; /* Sanity check to ensure we are not moving to / from the same list */ if ((nlp->nlp_flag & NLP_LIST_MASK) == list) if (list != NLP_NO_LIST) return 0; spin_lock_irq(phba->host->host_lock); switch (nlp->nlp_flag & NLP_LIST_MASK) { case NLP_NO_LIST: /* Not on any list */ break; case NLP_UNUSED_LIST: phba->fc_unused_cnt--; list_del(&nlp->nlp_listp); break; case NLP_PLOGI_LIST: phba->fc_plogi_cnt--; list_del(&nlp->nlp_listp); break; case NLP_ADISC_LIST: phba->fc_adisc_cnt--; list_del(&nlp->nlp_listp); break; case NLP_REGLOGIN_LIST: phba->fc_reglogin_cnt--; list_del(&nlp->nlp_listp); break; case NLP_PRLI_LIST: phba->fc_prli_cnt--; list_del(&nlp->nlp_listp); break; case NLP_UNMAPPED_LIST: phba->fc_unmap_cnt--; list_del(&nlp->nlp_listp); nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; nlp->nlp_type &= ~NLP_FC_NODE; phba->nport_event_cnt++; if (nlp->rport) rport_del = unmapped; break; case NLP_MAPPED_LIST: phba->fc_map_cnt--; list_del(&nlp->nlp_listp); phba->nport_event_cnt++; if (nlp->rport) rport_del = mapped; break; case NLP_NPR_LIST: phba->fc_npr_cnt--; list_del(&nlp->nlp_listp); /* Stop delay tmo if taking node off NPR list */ if ((nlp->nlp_flag & NLP_DELAY_TMO) && (list != NLP_NPR_LIST)) { spin_unlock_irq(phba->host->host_lock); lpfc_cancel_retry_delay_tmo(phba, nlp); spin_lock_irq(phba->host->host_lock); } break; } nlp->nlp_flag &= ~NLP_LIST_MASK; /* Add NPort <did> to <num> list */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0904 Add NPort x%x to %d list Data: x%x\n", phba->brd_no, nlp->nlp_DID, list, nlp->nlp_flag); switch (list) { case NLP_NO_LIST: /* No list, just remove it */ spin_unlock_irq(phba->host->host_lock); lpfc_nlp_remove(phba, nlp); spin_lock_irq(phba->host->host_lock); /* as node removed - stop further transport calls */ rport_del = none; break; case NLP_UNUSED_LIST: nlp->nlp_flag |= list; /* Put it at the end of the unused list */ list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); phba->fc_unused_cnt++; break; case NLP_PLOGI_LIST: nlp->nlp_flag |= list; /* Put it at the end of the plogi list */ list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); phba->fc_plogi_cnt++; break; case NLP_ADISC_LIST: nlp->nlp_flag |= list; /* Put it at the end of the adisc list */ list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); phba->fc_adisc_cnt++; break; case NLP_REGLOGIN_LIST: nlp->nlp_flag |= list; /* Put it at the end of the reglogin list */ list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); phba->fc_reglogin_cnt++; break; case NLP_PRLI_LIST: nlp->nlp_flag |= list; /* Put it at the end of the prli list */ list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); phba->fc_prli_cnt++; break; case NLP_UNMAPPED_LIST: rport_add = unmapped; /* ensure all vestiges of "mapped" significance are gone */ nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); nlp->nlp_flag |= list; /* Put it at the end of the unmap list */ list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); phba->fc_unmap_cnt++; phba->nport_event_cnt++; /* stop nodev tmo if running */ if (nlp->nlp_flag & NLP_NODEV_TMO) { nlp->nlp_flag &= ~NLP_NODEV_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&nlp->nlp_tmofunc); spin_lock_irq(phba->host->host_lock); if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) list_del_init(&nlp->nodev_timeout_evt. evt_listp); } nlp->nlp_flag &= ~NLP_NODEV_REMOVE; nlp->nlp_type |= NLP_FC_NODE; break; case NLP_MAPPED_LIST: rport_add = mapped; nlp->nlp_flag |= list; /* Put it at the end of the map list */ list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); phba->fc_map_cnt++; phba->nport_event_cnt++; /* stop nodev tmo if running */ if (nlp->nlp_flag & NLP_NODEV_TMO) { nlp->nlp_flag &= ~NLP_NODEV_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&nlp->nlp_tmofunc); spin_lock_irq(phba->host->host_lock); if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) list_del_init(&nlp->nodev_timeout_evt. evt_listp); } nlp->nlp_flag &= ~NLP_NODEV_REMOVE; break; case NLP_NPR_LIST: nlp->nlp_flag |= list; /* Put it at the end of the npr list */ list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); phba->fc_npr_cnt++; if (!(nlp->nlp_flag & NLP_NODEV_TMO)) mod_timer(&nlp->nlp_tmofunc, jiffies + HZ * phba->cfg_nodev_tmo); nlp->nlp_flag |= NLP_NODEV_TMO; nlp->nlp_flag &= ~NLP_RCV_PLOGI; break; case NLP_JUST_DQ: break; } spin_unlock_irq(phba->host->host_lock); /* * We make all the calls into the transport after we have * moved the node between lists. This so that we don't * release the lock while in-between lists. */ /* Don't upcall midlayer if we're unloading */ if (!(phba->fc_flag & FC_UNLOADING)) { /* * We revalidate the rport pointer as the "add" function * may have removed the remote port. */ if ((rport_del != none) && nlp->rport) lpfc_unregister_remote_port(phba, nlp); if (rport_add != none) { /* * Tell the fc transport about the port, if we haven't * already. If we have, and it's a scsi entity, be * sure to unblock any attached scsi devices */ if (!nlp->rport) lpfc_register_remote_port(phba, nlp); /* * if we added to Mapped list, but the remote port * registration failed or assigned a target id outside * our presentable range - move the node to the * Unmapped List */ if ((rport_add == mapped) && ((!nlp->rport) || (nlp->rport->scsi_target_id == -1) || (nlp->rport->scsi_target_id >= MAX_FCP_TARGET))) { nlp->nlp_state = NLP_STE_UNMAPPED_NODE; spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= NLP_TGT_NO_SCSIID; spin_unlock_irq(phba->host->host_lock); lpfc_nlp_list(phba, nlp, NLP_UNMAPPED_LIST); } } } return 0;}/* * Start / ReStart rescue timer for Discovery / RSCN handling */voidlpfc_set_disctmo(struct lpfc_hba * phba){ uint32_t tmo; if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { /* For FAN, timeout should be greater then edtov */ tmo = (((phba->fc_edtov + 999) / 1000) + 1); } else { /* Normal discovery timeout should be > then ELS/CT timeout * FC spec states we need 3 * ratov for CT requests */ tmo = ((phba->fc_ratov * 3) + 3); } mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo); spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_DISC_TMO; spin_unlock_irq(phba->host->host_lock); /* Start Discovery Timer state <hba_state> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0247 Start Discovery Timer state x%x " "Data: x%x x%lx x%x x%x\n", phba->brd_no, phba->hba_state, tmo, (unsigned long)&phba->fc_disctmo, phba->fc_plogi_cnt, phba->fc_adisc_cnt); return;}/* * Cancel rescue timer for Discovery / RSCN handling */intlpfc_can_disctmo(struct lpfc_hba * phba){ /* Turn off discovery timer if its running */ if (phba->fc_flag & FC_DISC_TMO) { spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_DISC_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&phba->fc_disctmo); phba->work_hba_events &= ~WORKER_DISC_TMO; } /* Cancel Discovery Timer state <hba_state> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0248 Cancel Discovery Timer 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); return 0;}/* * Check specified ring for outstanding IOCB on the SLI queue * Return true if iocb matches the specified nport */intlpfc_check_sli_ndlp(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocb, struct lpfc_nodelist * ndlp){ struct lpfc_sli *psli; IOCB_t *icmd; psli = &phba->sli; icmd = &iocb->iocb; if (pring->ringno == LPFC_ELS_RING) { switch (icmd->ulpCommand) { case CMD_GEN_REQUEST64_CR: if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) return 1; case CMD_ELS_REQUEST64_CR: if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID) return 1; case CMD_XMIT_ELS_RSP64_CX: if (iocb->context1 == (uint8_t *) ndlp) return 1; } } else if (pring->ringno == psli->ip_ring) { } else if (pring->ringno == psli->fcp_ring) { /* Skip match check if waiting to relogin to FCP target */ if ((ndlp->nlp_type & NLP_FCP_TARGET) && (ndlp->nlp_flag & NLP_DELAY_TMO)) { return 0; } if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) { return 1; } } else if (pring->ringno == psli->next_ring) { } return 0;}/* * Free resources / clean up outstanding I/Os * associated with nlp_rpi in the LPFC_NODELIST entry. */static intlpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp){ struct lpfc_sli *psli; struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; IOCB_t *icmd; uint32_t rpi, i; /* * Everything that matches on txcmplq will be returned * by firmware with a no rpi error. */ psli = &phba->sli; rpi = ndlp->nlp_rpi; if (rpi) { /* Now process each ring */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { /* * Check to see if iocb matches the nport we are * looking for */ if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { /* It matches, so deque and call compl with an error */ list_del(&iocb->list); pring->txq_cnt--; if (iocb->iocb_cmpl) { icmd = &iocb->iocb; icmd->ulpStatus = IOSTAT_LOCAL_REJECT; icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; spin_unlock_irq(phba->host->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?