X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Flpfc%2Flpfc_hbadisc.c;fp=drivers%2Fscsi%2Flpfc%2Flpfc_hbadisc.c;h=a1f751e79405fee9fdc32db86bfc47bd7dcdcd31;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=b2f1552f1848a988d75dea9cf2fcbf5b5a24193d;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b2f1552f1..a1f751e79 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2006 Emulex. All rights reserved. * + * Copyright (C) 2004-2005 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -59,7 +59,6 @@ static void lpfc_disc_timeout_handler(struct lpfc_hba *); static void lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { - uint8_t *name = (uint8_t *)&ndlp->nlp_portname; int warn_on = 0; spin_lock_irq(phba->host->host_lock); @@ -68,15 +67,6 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) return; } - /* - * If a discovery event readded nodev_timer after timer - * firing and before processing the timer, cancel the - * nlp_tmofunc. - */ - spin_unlock_irq(phba->host->host_lock); - del_timer_sync(&ndlp->nlp_tmofunc); - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_NODEV_TMO; if (ndlp->nlp_sid != NLP_NO_SID) { @@ -89,23 +79,15 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) if (warn_on) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0203 Nodev timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", - phba->brd_no, - *name, *(name+1), *(name+2), *(name+3), - *(name+4), *(name+5), *(name+6), *(name+7), - ndlp->nlp_DID, ndlp->nlp_flag, + "%d:0203 Nodev timeout on 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); } else { lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d:0204 Nodev timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", - phba->brd_no, - *name, *(name+1), *(name+2), *(name+3), - *(name+4), *(name+5), *(name+6), *(name+7), - ndlp->nlp_DID, ndlp->nlp_flag, + "%d:0204 Nodev timeout on 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); } @@ -126,7 +108,7 @@ lpfc_work_list_done(struct lpfc_hba * phba) evt_listp); spin_unlock_irq(phba->host->host_lock); free_evt = 1; - switch (evtp->evt) { + switch(evtp->evt) { case LPFC_EVT_NODEV_TMO: ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); lpfc_process_nodev_timeout(phba, ndlp); @@ -138,35 +120,11 @@ lpfc_work_list_done(struct lpfc_hba * phba) free_evt = 0; break; case LPFC_EVT_ONLINE: - if (phba->hba_state < LPFC_LINK_DOWN) - *(int *)(evtp->evt_arg1) = lpfc_online(phba); - else - *(int *)(evtp->evt_arg1) = 0; + *(int *)(evtp->evt_arg1) = lpfc_online(phba); complete((struct completion *)(evtp->evt_arg2)); break; case LPFC_EVT_OFFLINE: - if (phba->hba_state >= LPFC_LINK_DOWN) - lpfc_offline(phba); - lpfc_sli_brdrestart(phba); - *(int *)(evtp->evt_arg1) = - lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY); - complete((struct completion *)(evtp->evt_arg2)); - break; - case LPFC_EVT_WARM_START: - if (phba->hba_state >= LPFC_LINK_DOWN) - lpfc_offline(phba); - lpfc_reset_barrier(phba); - lpfc_sli_brdreset(phba); - lpfc_hba_down_post(phba); - *(int *)(evtp->evt_arg1) = - lpfc_sli_brdready(phba, HS_MBRDY); - complete((struct completion *)(evtp->evt_arg2)); - break; - case LPFC_EVT_KILL: - if (phba->hba_state >= LPFC_LINK_DOWN) - lpfc_offline(phba); - *(int *)(evtp->evt_arg1) - = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); + *(int *)(evtp->evt_arg1) = lpfc_offline(phba); complete((struct completion *)(evtp->evt_arg2)); break; } @@ -193,13 +151,13 @@ lpfc_work_done(struct lpfc_hba * phba) work_hba_events=phba->work_hba_events; spin_unlock_irq(phba->host->host_lock); - if (ha_copy & HA_ERATT) + if(ha_copy & HA_ERATT) lpfc_handle_eratt(phba); - if (ha_copy & HA_MBATT) + if(ha_copy & HA_MBATT) lpfc_sli_handle_mb_event(phba); - if (ha_copy & HA_LATT) + if(ha_copy & HA_LATT) lpfc_handle_latt(phba); if (work_hba_events & WORKER_DISC_TMO) @@ -311,8 +269,8 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2, evtp->evt_arg2 = arg2; evtp->evt = evt; - spin_lock_irq(phba->host->host_lock); list_add_tail(&evtp->evt_listp, &phba->work_list); + spin_lock_irq(phba->host->host_lock); if (phba->work_wait) wake_up(phba->work_wait); spin_unlock_irq(phba->host->host_lock); @@ -325,20 +283,16 @@ lpfc_linkdown(struct lpfc_hba * phba) { struct lpfc_sli *psli; struct lpfc_nodelist *ndlp, *next_ndlp; - struct list_head *listp, *node_list[7]; + struct list_head *listp; + struct list_head *node_list[7]; LPFC_MBOXQ_t *mb; int rc, i; psli = &phba->sli; - /* sysfs or selective reset may call this routine to clean up */ - if (phba->hba_state >= LPFC_LINK_DOWN) { - if (phba->hba_state == LPFC_LINK_DOWN) - return 0; - spin_lock_irq(phba->host->host_lock); - phba->hba_state = LPFC_LINK_DOWN; - spin_unlock_irq(phba->host->host_lock); - } + spin_lock_irq(phba->host->host_lock); + phba->hba_state = LPFC_LINK_DOWN; + spin_unlock_irq(phba->host->host_lock); /* Clean up any firmware default rpi's */ if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { @@ -370,19 +324,32 @@ lpfc_linkdown(struct lpfc_hba * phba) continue; list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { - - rc = lpfc_disc_state_machine(phba, ndlp, NULL, - NLP_EVT_DEVICE_RECOVERY); - - /* Check config parameter use-adisc or FCP-2 */ - if ((rc != NLP_STE_FREED_NODE) && - (phba->cfg_use_adisc == 0) && - !(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) { - /* We know we will have to relogin, so - * unreglogin the rpi right now to fail - * any outstanding I/Os quickly. - */ - lpfc_unreg_rpi(phba, ndlp); + /* Fabric nodes are not handled thru state machine for + link down */ + if (ndlp->nlp_type & NLP_FABRIC) { + /* Remove ALL Fabric nodes except Fabric_DID */ + if (ndlp->nlp_DID != Fabric_DID) { + /* Take it off current list and free */ + lpfc_nlp_list(phba, ndlp, + NLP_NO_LIST); + } + } + else { + + rc = lpfc_disc_state_machine(phba, ndlp, NULL, + NLP_EVT_DEVICE_RECOVERY); + + /* Check config parameter use-adisc or FCP-2 */ + if ((rc != NLP_STE_FREED_NODE) && + (phba->cfg_use_adisc == 0) && + !(ndlp->nlp_fcp_info & + NLP_FCP_2_DEVICE)) { + /* We know we will have to relogin, so + * unreglogin the rpi right now to fail + * any outstanding I/Os quickly. + */ + lpfc_unreg_rpi(phba, ndlp); + } } } } @@ -417,15 +384,13 @@ lpfc_linkdown(struct lpfc_hba * phba) lpfc_can_disctmo(phba); /* Must process IOCBs on all rings to handle ABORTed I/Os */ - return 0; + return (0); } static int lpfc_linkup(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp, *next_ndlp; - struct list_head *listp, *node_list[7]; - int i; spin_lock_irq(phba->host->host_lock); phba->hba_state = LPFC_LINK_UP; @@ -436,33 +401,14 @@ lpfc_linkup(struct lpfc_hba * phba) spin_unlock_irq(phba->host->host_lock); - node_list[0] = &phba->fc_plogi_list; - node_list[1] = &phba->fc_adisc_list; - node_list[2] = &phba->fc_reglogin_list; - node_list[3] = &phba->fc_prli_list; - node_list[4] = &phba->fc_nlpunmap_list; - node_list[5] = &phba->fc_nlpmap_list; - node_list[6] = &phba->fc_npr_list; - for (i = 0; i < 7; i++) { - listp = node_list[i]; - if (list_empty(listp)) - continue; - - list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { - if (phba->fc_flag & FC_LBIT) { - if (ndlp->nlp_type & NLP_FABRIC) { - /* On Linkup its safe to clean up the - * ndlp from Fabric connections. - */ - lpfc_nlp_list(phba, ndlp, - NLP_UNUSED_LIST); - } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { - /* Fail outstanding IO now since device - * is marked for PLOGI. - */ - lpfc_unreg_rpi(phba, ndlp); - } - } + /* + * Clean up old Fabric NLP_FABRIC logins. + */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, + nlp_listp) { + if (ndlp->nlp_DID == Fabric_DID) { + /* Take it off current list and free */ + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } } @@ -516,7 +462,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_els_disc_plogi(phba); } - if (!phba->num_disc_nodes) { + 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); @@ -558,59 +504,80 @@ out: } static void -lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +lpfc_mbx_cmpl_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { - struct lpfc_sli *psli = &phba->sli; - int rc; + struct lpfc_sli *psli; + MAILBOX_t *mb; - if (pmb->mb.mbxStatus) - goto out; + psli = &phba->sli; + mb = &pmb->mb; + /* Check for error */ + if (mb->mbxStatus) { + /* CONFIG_LINK mbox error 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); - mempool_free(pmb, phba->mbox_mem_pool); + lpfc_linkdown(phba); + phba->hba_state = LPFC_HBA_ERROR; + goto out; + } - 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; + 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); - 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: - 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, + /* CONFIG_LINK bad 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); - 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; + 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; } @@ -683,7 +650,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); spin_lock_irq(phba->host->host_lock); - switch (la->UlnkSpeed) { + switch(la->UlnkSpeed) { case LA_1GHZ_LINK: phba->fc_linkspeed = LA_1GHZ_LINK; break; @@ -764,7 +731,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) 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; + cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_config_link; lpfc_sli_issue_mbox(phba, cfglink_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); } @@ -817,13 +784,6 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) 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++; @@ -944,36 +904,32 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) */ 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); + /* 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); + } } } } @@ -981,6 +937,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); + return; } @@ -1071,6 +1028,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba, /* initialize static port data */ rport->maxframe_size = ndlp->nlp_maxframe; rport->supported_classes = ndlp->nlp_class_sup; + if ((rport->scsi_target_id != -1) && + (rport->scsi_target_id < MAX_FCP_TARGET)) { + ndlp->nlp_sid = rport->scsi_target_id; + } rdata = rport->dd_data; rdata->pnode = ndlp; @@ -1083,10 +1044,6 @@ lpfc_register_remote_port(struct lpfc_hba * phba, 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 < LPFC_MAX_TARGET)) { - ndlp->nlp_sid = rport->scsi_target_id; - } return; } @@ -1113,12 +1070,12 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) 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 ((nlp->nlp_flag & NLP_LIST_MASK) == list) { if (list != NLP_NO_LIST) - return 0; + return(0); + } - spin_lock_irq(phba->host->host_lock); - switch (nlp->nlp_flag & NLP_LIST_MASK) { + switch(nlp->nlp_flag & NLP_LIST_MASK) { case NLP_NO_LIST: /* Not on any list */ break; case NLP_UNUSED_LIST: @@ -1144,8 +1101,10 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) case NLP_UNMAPPED_LIST: phba->fc_unmap_cnt--; list_del(&nlp->nlp_listp); + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; nlp->nlp_type &= ~NLP_FC_NODE; + spin_unlock_irq(phba->host->host_lock); phba->nport_event_cnt++; if (nlp->rport) rport_del = unmapped; @@ -1163,14 +1122,19 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) /* 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); + nlp->nlp_flag &= ~NLP_DELAY_TMO; + spin_unlock_irq(phba->host->host_lock); + del_timer_sync(&nlp->nlp_delayfunc); + if (!list_empty(&nlp->els_retry_evt.evt_listp)) + list_del_init(&nlp->els_retry_evt.evt_listp); } break; } + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_LIST_MASK; + spin_unlock_irq(phba->host->host_lock); /* Add NPort to list */ lpfc_printf_log(phba, @@ -1180,40 +1144,48 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) phba->brd_no, nlp->nlp_DID, list, nlp->nlp_flag); - switch (list) { + 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the prli list */ list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); phba->fc_prli_cnt++; @@ -1222,28 +1194,31 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) rport_add = unmapped; /* ensure all vestiges of "mapped" significance are gone */ nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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) { + spin_lock_irq(phba->host->host_lock); 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; + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the map list */ list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); phba->fc_map_cnt++; @@ -1251,35 +1226,41 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) /* 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: + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; + spin_unlock_irq(phba->host->host_lock); /* 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)) + /* + * Sanity check for Fabric entity. + * Set nodev_tmo for NPR state, for Fabric use 1 sec. + */ + if (nlp->nlp_type & NLP_FABRIC) { + mod_timer(&nlp->nlp_tmofunc, jiffies + HZ); + } + else { mod_timer(&nlp->nlp_tmofunc, - jiffies + HZ * phba->cfg_nodev_tmo); - + jiffies + HZ * phba->cfg_nodev_tmo); + } + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= NLP_NODEV_TMO; nlp->nlp_flag &= ~NLP_RCV_PLOGI; + spin_unlock_irq(phba->host->host_lock); 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 @@ -1313,7 +1294,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) if ((rport_add == mapped) && ((!nlp->rport) || (nlp->rport->scsi_target_id == -1) || - (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) { + (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; @@ -1322,7 +1303,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) } } } - return 0; + return (0); } /* @@ -1333,15 +1314,7 @@ lpfc_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); - } + tmo = ((phba->fc_ratov * 2) + 1); mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo); spin_lock_irq(phba->host->host_lock); @@ -1381,7 +1354,7 @@ lpfc_can_disctmo(struct lpfc_hba * phba) phba->brd_no, phba->hba_state, phba->fc_flag, phba->fc_plogi_cnt, phba->fc_adisc_cnt); - return 0; + return (0); } /* @@ -1402,13 +1375,11 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, switch (icmd->ulpCommand) { case CMD_GEN_REQUEST64_CR: if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) - return 1; + 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; + return (1); } } else if (pring->ringno == psli->ip_ring) { @@ -1416,15 +1387,15 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, /* 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; + return (0); } if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) { - return 1; + return (1); } } else if (pring->ringno == psli->next_ring) { } - return 0; + return (0); } /* @@ -1485,7 +1456,7 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) } } - return 0; + return (0); } /* @@ -1557,8 +1528,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } } - - spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { @@ -1571,7 +1540,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) mempool_free(mb, phba->mbox_mem_pool); } } - spin_unlock_irq(phba->host->host_lock); lpfc_els_abort(phba,ndlp,0); spin_lock_irq(phba->host->host_lock); @@ -1579,7 +1547,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_tmofunc); - ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) @@ -1589,7 +1556,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) lpfc_unreg_rpi(phba, ndlp); - return 0; + return (0); } /* @@ -1612,18 +1579,24 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) if (ndlp->nlp_flag & NLP_DELAY_TMO) { - lpfc_cancel_retry_delay_tmo(phba, ndlp); + 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 { + } + else { lpfc_freenode(phba, ndlp); mempool_free( ndlp, phba->nlp_mem_pool); } - return 0; + return(0); } static int @@ -1634,20 +1607,20 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) D_ID matchdid; if (did == Bcast_DID) - return 0; + return (0); if (ndlp->nlp_DID == 0) { - return 0; + return (0); } /* First check for Direct match */ if (ndlp->nlp_DID == did) - return 1; + 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; + return (0); } matchdid.un.word = did; @@ -1658,9 +1631,9 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) if ((ndlpdid.un.b.domain == 0) && (ndlpdid.un.b.area == 0)) { if (ndlpdid.un.b.id) - return 1; + return (1); } - return 0; + return (0); } matchdid.un.word = ndlp->nlp_DID; @@ -1669,11 +1642,11 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) if ((matchdid.un.b.domain == 0) && (matchdid.un.b.area == 0)) { if (matchdid.un.b.id) - return 1; + return (1); } } } - return 0; + return (0); } /* Search for a nodelist entry on a specific list */ @@ -1683,7 +1656,6 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) struct lpfc_nodelist *ndlp, *next_ndlp; uint32_t data1; - spin_lock_irq(phba->host->host_lock); if (order & NLP_SEARCH_UNMAPPED) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, nlp_listp) { @@ -1699,8 +1671,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1721,8 +1692,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1744,8 +1714,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1767,8 +1736,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1785,13 +1753,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to REGLOGIN */ /* FIND node DID reglogin */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0901 FIND node DID reglogin" + "%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); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1808,13 +1775,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to PRLI */ /* FIND node DID prli */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0902 FIND node DID prli " + "%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); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1831,13 +1797,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to NPR */ /* FIND node DID npr */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0903 FIND node DID npr " + "%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); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } @@ -1854,19 +1819,16 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to UNUSED */ /* FIND node DID unused */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0905 FIND node DID unused " + "%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); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + return (ndlp); } } } - spin_unlock_irq(phba->host->host_lock); - /* FIND node did NOT FOUND */ lpfc_printf_log(phba, KERN_INFO, @@ -1884,9 +1846,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) struct lpfc_nodelist *ndlp; uint32_t flg; - ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); - if (!ndlp) { - if ((phba->fc_flag & FC_RSCN_MODE) && + 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 *) @@ -1899,21 +1860,22 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) ndlp->nlp_flag |= NLP_NPR_2B_DISC; return ndlp; } - if (phba->fc_flag & FC_RSCN_MODE) { + 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; - - /* Since this node is marked for discovery, - * delay timeout is not needed. - */ - if (ndlp->nlp_flag & NLP_DELAY_TMO) - lpfc_cancel_retry_delay_tmo(phba, ndlp); - } else + } + else { + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ndlp = NULL; - } else { + } + } + else { flg = ndlp->nlp_flag & NLP_LIST_MASK; - if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) + 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; @@ -2061,7 +2023,8 @@ lpfc_disc_start(struct lpfc_hba * phba) spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_RSCN_MODE; spin_unlock_irq(phba->host->host_lock); - } else + } + else lpfc_els_handle_rscn(phba); } } @@ -2211,7 +2174,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_hba *phba) { struct lpfc_sli *psli; - struct lpfc_nodelist *ndlp, *next_ndlp; + struct lpfc_nodelist *ndlp; LPFC_MBOXQ_t *clearlambox, *initlinkmbox; int rc, clrlaerr = 0; @@ -2238,19 +2201,10 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) "%d:0221 FAN timeout\n", phba->brd_no); - /* Start discovery by sending FLOGI, clean up old rpis */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, - nlp_listp) { - if (ndlp->nlp_type & NLP_FABRIC) { - /* Clean up the ndlp on Fabric connections */ - lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { - /* Fail outstanding IO now since device - * is marked for PLOGI. - */ - lpfc_unreg_rpi(phba, ndlp); - } - } + /* 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); @@ -2338,7 +2292,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!initlinkmbox) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0206 Device Discovery " + "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; @@ -2368,7 +2322,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) if (!clearlambox) { clrlaerr = 1; lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0207 Device Discovery " + "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; @@ -2516,57 +2470,11 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) &phba->fc_reglogin_list}; int i; - spin_lock_irq(phba->host->host_lock); for (i = 0; i < ARRAY_SIZE(lists); i++ ) list_for_each_entry(ndlp, lists[i], nlp_listp) - if (ndlp->nlp_rpi == rpi) { - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - spin_unlock_irq(phba->host->host_lock); - return NULL; -} + if (ndlp->nlp_rpi == rpi) + return (ndlp); -/* - * This routine looks up the ndlp lists - * for the given WWPN. If WWPN found - * it return the node list pointer - * else return NULL. - */ -struct lpfc_nodelist * -lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, - struct lpfc_name * wwpn) -{ - struct lpfc_nodelist *ndlp; - struct list_head * lists[]={&phba->fc_nlpunmap_list, - &phba->fc_nlpmap_list, - &phba->fc_npr_list, - &phba->fc_plogi_list, - &phba->fc_adisc_list, - &phba->fc_reglogin_list, - &phba->fc_prli_list}; - uint32_t search[]={NLP_SEARCH_UNMAPPED, - NLP_SEARCH_MAPPED, - NLP_SEARCH_NPR, - NLP_SEARCH_PLOGI, - NLP_SEARCH_ADISC, - NLP_SEARCH_REGLOGIN, - NLP_SEARCH_PRLI}; - int i; - - spin_lock_irq(phba->host->host_lock); - for (i = 0; i < ARRAY_SIZE(lists); i++ ) { - if (!(order & search[i])) - continue; - list_for_each_entry(ndlp, lists[i], nlp_listp) { - if (memcmp(&ndlp->nlp_portname, wwpn, - sizeof(struct lpfc_name)) == 0) { - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - spin_unlock_irq(phba->host->host_lock); return NULL; }