X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fscsi%2Flpfc%2Flpfc_hbadisc.c;h=f9f160ab2ee9184e1623b5a7495b4f377e42df93;hp=a345dde16c86fcf74b121b38d2e505102b3ee698;hb=474ffb74c75ea9845860ffb24cdc127eda0d5657;hpb=12462f2df4d10ea4f6d55b9d438ff788badec3f0 diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index a345dde16c86..f9f160ab2ee9 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -20,6 +20,7 @@ *******************************************************************/ #include +#include #include #include #include @@ -63,6 +64,7 @@ static uint8_t lpfcAlpaArray[] = { static void lpfc_disc_timeout_handler(struct lpfc_vport *); static void lpfc_disc_flush_list(struct lpfc_vport *vport); static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); +static int lpfc_fcf_inuse(struct lpfc_hba *); void lpfc_terminate_rport_io(struct fc_rport *rport) @@ -160,11 +162,17 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) return; } -/* - * This function is called from the worker thread when dev_loss_tmo - * expire. - */ -static void +/** + * lpfc_dev_loss_tmo_handler - Remote node devloss timeout handler + * @ndlp: Pointer to remote node object. + * + * This function is called from the worker thread when devloss timeout timer + * expires. For SLI4 host, this routine shall return 1 when at lease one + * remote node, including this @ndlp, is still in use of FCF; otherwise, this + * routine shall return 0 when there is no remote node is still in use of FCF + * when devloss timeout happened to this @ndlp. + **/ +static int lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) { struct lpfc_rport_data *rdata; @@ -175,17 +183,21 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) int put_node; int put_rport; int warn_on = 0; + int fcf_inuse = 0; rport = ndlp->rport; if (!rport) - return; + return fcf_inuse; rdata = rport->dd_data; name = (uint8_t *) &ndlp->nlp_portname; vport = ndlp->vport; phba = vport->phba; + if (phba->sli_rev == LPFC_SLI_REV4) + fcf_inuse = lpfc_fcf_inuse(phba); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, "rport devlosstmo:did:x%x type:x%x id:x%x", ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); @@ -209,7 +221,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) lpfc_nlp_put(ndlp); if (put_rport) put_device(&rport->dev); - return; + return fcf_inuse; } if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) { @@ -220,7 +232,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) *name, *(name+1), *(name+2), *(name+3), *(name+4), *(name+5), *(name+6), *(name+7), ndlp->nlp_DID); - return; + return fcf_inuse; } if (ndlp->nlp_type & NLP_FABRIC) { @@ -233,7 +245,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) lpfc_nlp_put(ndlp); if (put_rport) put_device(&rport->dev); - return; + return fcf_inuse; } if (ndlp->nlp_sid != NLP_NO_SID) { @@ -280,6 +292,74 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) (ndlp->nlp_state != NLP_STE_PRLI_ISSUE)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); + return fcf_inuse; +} + +/** + * lpfc_sli4_post_dev_loss_tmo_handler - SLI4 post devloss timeout handler + * @phba: Pointer to hba context object. + * @fcf_inuse: SLI4 FCF in-use state reported from devloss timeout handler. + * @nlp_did: remote node identifer with devloss timeout. + * + * This function is called from the worker thread after invoking devloss + * timeout handler and releasing the reference count for the ndlp with + * which the devloss timeout was handled for SLI4 host. For the devloss + * timeout of the last remote node which had been in use of FCF, when this + * routine is invoked, it shall be guaranteed that none of the remote are + * in-use of FCF. When devloss timeout to the last remote using the FCF, + * if the FIP engine is neither in FCF table scan process nor roundrobin + * failover process, the in-use FCF shall be unregistered. If the FIP + * engine is in FCF discovery process, the devloss timeout state shall + * be set for either the FCF table scan process or roundrobin failover + * process to unregister the in-use FCF. + **/ +static void +lpfc_sli4_post_dev_loss_tmo_handler(struct lpfc_hba *phba, int fcf_inuse, + uint32_t nlp_did) +{ + /* If devloss timeout happened to a remote node when FCF had no + * longer been in-use, do nothing. + */ + if (!fcf_inuse) + return; + + if ((phba->hba_flag & HBA_FIP_SUPPORT) && !lpfc_fcf_inuse(phba)) { + spin_lock_irq(&phba->hbalock); + if (phba->fcf.fcf_flag & FCF_DISCOVERY) { + if (phba->hba_flag & HBA_DEVLOSS_TMO) { + spin_unlock_irq(&phba->hbalock); + return; + } + phba->hba_flag |= HBA_DEVLOSS_TMO; + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2847 Last remote node (x%x) using " + "FCF devloss tmo\n", nlp_did); + } + if (phba->fcf.fcf_flag & FCF_REDISC_PROG) { + spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2868 Devloss tmo to FCF rediscovery " + "in progress\n"); + return; + } + if (!(phba->hba_flag & (FCF_TS_INPROG | FCF_RR_INPROG))) { + spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2869 Devloss tmo to idle FIP engine, " + "unreg in-use FCF and rescan.\n"); + /* Unregister in-use FCF and rescan */ + lpfc_unregister_fcf_rescan(phba); + return; + } + spin_unlock_irq(&phba->hbalock); + if (phba->hba_flag & FCF_TS_INPROG) + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2870 FCF table scan in progress\n"); + if (phba->hba_flag & FCF_RR_INPROG) + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2871 FLOGI roundrobin FCF failover " + "in progress\n"); + } lpfc_unregister_unused_fcf(phba); } @@ -408,6 +488,8 @@ lpfc_work_list_done(struct lpfc_hba *phba) struct lpfc_work_evt *evtp = NULL; struct lpfc_nodelist *ndlp; int free_evt; + int fcf_inuse; + uint32_t nlp_did; spin_lock_irq(&phba->hbalock); while (!list_empty(&phba->work_list)) { @@ -427,12 +509,17 @@ lpfc_work_list_done(struct lpfc_hba *phba) break; case LPFC_EVT_DEV_LOSS: ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); - lpfc_dev_loss_tmo_handler(ndlp); + fcf_inuse = lpfc_dev_loss_tmo_handler(ndlp); free_evt = 0; /* decrement the node reference count held for * this queued work */ + nlp_did = ndlp->nlp_DID; lpfc_nlp_put(ndlp); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_post_dev_loss_tmo_handler(phba, + fcf_inuse, + nlp_did); break; case LPFC_EVT_ONLINE: if (phba->link_state < LPFC_LINK_DOWN) @@ -520,6 +607,8 @@ lpfc_work_done(struct lpfc_hba *phba) /* Process SLI4 events */ if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { + if (phba->hba_flag & HBA_RRQ_ACTIVE) + lpfc_handle_rrq_active(phba); if (phba->hba_flag & FCP_XRI_ABORT_EVENT) lpfc_sli4_fcp_xri_abort_event_proc(phba); if (phba->hba_flag & ELS_XRI_ABORT_EVENT) @@ -707,6 +796,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) : NLP_EVT_DEVICE_RECOVERY); } if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) { + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vport); lpfc_mbx_unreg_vpi(vport); spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; @@ -877,6 +968,7 @@ lpfc_linkup(struct lpfc_hba *phba) struct lpfc_vport **vports; int i; + lpfc_cleanup_wt_rrqs(phba); phba->link_state = LPFC_LINK_UP; /* Unblock fabric iocbs if they are blocked */ @@ -975,7 +1067,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); - if (phba->fc_topology == TOPOLOGY_LOOP && + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP && vport->fc_flag & FC_PUBLIC_LOOP && !(vport->fc_flag & FC_LBIT)) { /* Need to wait for FAN - use discovery timer @@ -989,9 +1081,8 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Start discovery by sending a FLOGI. port_state is identically * LPFC_FLOGI while waiting for FLOGI cmpl */ - if (vport->port_state != LPFC_FLOGI) { + if (vport->port_state != LPFC_FLOGI) lpfc_initial_flogi(vport); - } return; out: @@ -1021,8 +1112,7 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) "2017 REG_FCFI mbxStatus error x%x " "HBA state x%x\n", mboxq->u.mb.mbxStatus, vport->port_state); - mempool_free(mboxq, phba->mbox_mem_pool); - return; + goto fail_out; } /* Start FCoE discovery by sending a FLOGI. */ @@ -1031,20 +1121,30 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= FCF_REGISTERED; spin_unlock_irq(&phba->hbalock); + /* If there is a pending FCoE event, restart FCF table scan. */ - if (lpfc_check_pending_fcoe_event(phba, 1)) { - mempool_free(mboxq, phba->mbox_mem_pool); - return; - } + if (lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF)) + goto fail_out; + + /* Mark successful completion of FCF table scan */ spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; + if (vport->port_state != LPFC_FLOGI) { + phba->hba_flag |= FCF_RR_INPROG; + spin_unlock_irq(&phba->hbalock); + lpfc_issue_init_vfi(vport); + goto out; + } spin_unlock_irq(&phba->hbalock); - if (vport->port_state != LPFC_FLOGI) - lpfc_initial_flogi(vport); + goto out; +fail_out: + spin_lock_irq(&phba->hbalock); + phba->hba_flag &= ~FCF_RR_INPROG; + spin_unlock_irq(&phba->hbalock); +out: mempool_free(mboxq, phba->mbox_mem_pool); - return; } /** @@ -1241,10 +1341,9 @@ lpfc_register_fcf(struct lpfc_hba *phba) int rc; spin_lock_irq(&phba->hbalock); - /* If the FCF is not availabe do nothing. */ if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) { - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG); spin_unlock_irq(&phba->hbalock); return; } @@ -1252,19 +1351,22 @@ lpfc_register_fcf(struct lpfc_hba *phba) /* The FCF is already registered, start discovery */ if (phba->fcf.fcf_flag & FCF_REGISTERED) { phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; + if (phba->pport->port_state != LPFC_FLOGI) { + phba->hba_flag |= FCF_RR_INPROG; + spin_unlock_irq(&phba->hbalock); + lpfc_issue_init_vfi(phba->pport); + return; + } spin_unlock_irq(&phba->hbalock); - if (phba->pport->port_state != LPFC_FLOGI) - lpfc_initial_flogi(phba->pport); return; } spin_unlock_irq(&phba->hbalock); - fcf_mbxq = mempool_alloc(phba->mbox_mem_pool, - GFP_KERNEL); + fcf_mbxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!fcf_mbxq) { spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG); spin_unlock_irq(&phba->hbalock); return; } @@ -1275,7 +1377,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG); spin_unlock_irq(&phba->hbalock); mempool_free(fcf_mbxq, phba->mbox_mem_pool); } @@ -1493,7 +1595,7 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) * FCF discovery, no need to restart FCF discovery. */ if ((phba->link_state >= LPFC_LINK_UP) && - (phba->fcoe_eventtag == phba->fcoe_eventtag_at_fcf_scan)) + (phba->fcoe_eventtag == phba->fcoe_eventtag_at_fcf_scan)) return 0; lpfc_printf_log(phba, KERN_INFO, LOG_FIP, @@ -1517,14 +1619,14 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); } else { /* - * Do not continue FCF discovery and clear FCF_DISC_INPROGRESS + * Do not continue FCF discovery and clear FCF_TS_INPROG * flag */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2833 Stop FCF discovery process due to link " "state change (x%x)\n", phba->link_state); spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG); phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | FCF_DISCOVERY); spin_unlock_irq(&phba->hbalock); } @@ -1728,6 +1830,65 @@ lpfc_sli4_fcf_record_match(struct lpfc_hba *phba, return true; } +/** + * lpfc_sli4_fcf_rr_next_proc - processing next roundrobin fcf + * @vport: Pointer to vport object. + * @fcf_index: index to next fcf. + * + * This function processing the roundrobin fcf failover to next fcf index. + * When this function is invoked, there will be a current fcf registered + * for flogi. + * Return: 0 for continue retrying flogi on currently registered fcf; + * 1 for stop flogi on currently registered fcf; + */ +int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *vport, uint16_t fcf_index) +{ + struct lpfc_hba *phba = vport->phba; + int rc; + + if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { + spin_lock_irq(&phba->hbalock); + if (phba->hba_flag & HBA_DEVLOSS_TMO) { + spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2872 Devloss tmo with no eligible " + "FCF, unregister in-use FCF (x%x) " + "and rescan FCF table\n", + phba->fcf.current_rec.fcf_indx); + lpfc_unregister_fcf_rescan(phba); + goto stop_flogi_current_fcf; + } + /* Mark the end to FLOGI roundrobin failover */ + phba->hba_flag &= ~FCF_RR_INPROG; + /* Allow action to new fcf asynchronous event */ + phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_SCAN_DONE); + spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2865 No FCF available, stop roundrobin FCF " + "failover and change port state:x%x/x%x\n", + phba->pport->port_state, LPFC_VPORT_UNKNOWN); + phba->pport->port_state = LPFC_VPORT_UNKNOWN; + goto stop_flogi_current_fcf; + } else { + lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_ELS, + "2794 Try FLOGI roundrobin FCF failover to " + "(x%x)\n", fcf_index); + rc = lpfc_sli4_fcf_rr_read_fcf_rec(phba, fcf_index); + if (rc) + lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, + "2761 FLOGI roundrobin FCF failover " + "failed (rc:x%x) to read FCF (x%x)\n", + rc, phba->fcf.current_rec.fcf_indx); + else + goto stop_flogi_current_fcf; + } + return 0; + +stop_flogi_current_fcf: + lpfc_can_disctmo(vport); + return 1; +} + /** * lpfc_mbx_cmpl_fcf_scan_read_fcf_rec - fcf scan read_fcf mbox cmpl handler. * @phba: pointer to lpfc hba data structure. @@ -1756,7 +1917,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) int rc; /* If there is pending FCoE event restart FCF table scan */ - if (lpfc_check_pending_fcoe_event(phba, 0)) { + if (lpfc_check_pending_fcoe_event(phba, LPFC_SKIP_UNREG_FCF)) { lpfc_sli4_mbox_cmd_free(phba, mboxq); return; } @@ -1765,12 +1926,12 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) new_fcf_record = lpfc_sli4_fcf_rec_mbox_parse(phba, mboxq, &next_fcf_index); if (!new_fcf_record) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, + lpfc_printf_log(phba, KERN_ERR, LOG_FIP, "2765 Mailbox command READ_FCF_RECORD " "failed to retrieve a FCF record.\n"); /* Let next new FCF event trigger fast failover */ spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; spin_unlock_irq(&phba->hbalock); lpfc_sli4_mbox_cmd_free(phba, mboxq); return; @@ -1787,13 +1948,12 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) /* * If the fcf record does not match with connect list entries * read the next entry; otherwise, this is an eligible FCF - * record for round robin FCF failover. + * record for roundrobin FCF failover. */ if (!rc) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, - "2781 FCF record (x%x) failed FCF " - "connection list check, fcf_avail:x%x, " - "fcf_valid:x%x\n", + "2781 FCF (x%x) failed connection " + "list check: (x%x/x%x)\n", bf_get(lpfc_fcf_record_fcf_index, new_fcf_record), bf_get(lpfc_fcf_record_fcf_avail, @@ -1803,6 +1963,16 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if ((phba->fcf.fcf_flag & FCF_IN_USE) && lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec, new_fcf_record, LPFC_FCOE_IGNORE_VID)) { + if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) != + phba->fcf.current_rec.fcf_indx) { + lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + "2862 FCF (x%x) matches property " + "of in-use FCF (x%x)\n", + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record), + phba->fcf.current_rec.fcf_indx); + goto read_next_fcf; + } /* * In case the current in-use FCF record becomes * invalid/unavailable during FCF discovery that @@ -1813,9 +1983,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, "2835 Invalid in-use FCF " - "record (x%x) reported, " - "entering fast FCF failover " - "mode scanning.\n", + "(x%x), enter FCF failover " + "table scan.\n", phba->fcf.current_rec.fcf_indx); spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= FCF_REDISC_FOV; @@ -1844,22 +2013,29 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (phba->fcf.fcf_flag & FCF_IN_USE) { if (lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec, new_fcf_record, vlan_id)) { - phba->fcf.fcf_flag |= FCF_AVAILABLE; - if (phba->fcf.fcf_flag & FCF_REDISC_PEND) - /* Stop FCF redisc wait timer if pending */ - __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); - else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) - /* If in fast failover, mark it's completed */ - phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; - spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2836 The new FCF record (x%x) " - "matches the in-use FCF record " - "(x%x)\n", - phba->fcf.current_rec.fcf_indx, + if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) == + phba->fcf.current_rec.fcf_indx) { + phba->fcf.fcf_flag |= FCF_AVAILABLE; + if (phba->fcf.fcf_flag & FCF_REDISC_PEND) + /* Stop FCF redisc wait timer */ + __lpfc_sli4_stop_fcf_redisc_wait_timer( + phba); + else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) + /* Fast failover, mark completed */ + phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; + spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2836 New FCF matches in-use " + "FCF (x%x)\n", + phba->fcf.current_rec.fcf_indx); + goto out; + } else + lpfc_printf_log(phba, KERN_ERR, LOG_FIP, + "2863 New FCF (x%x) matches " + "property of in-use FCF (x%x)\n", bf_get(lpfc_fcf_record_fcf_index, - new_fcf_record)); - goto out; + new_fcf_record), + phba->fcf.current_rec.fcf_indx); } /* * Read next FCF record from HBA searching for the matching @@ -1953,8 +2129,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) */ if (fcf_rec) { lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2840 Update current FCF record " - "with initial FCF record (x%x)\n", + "2840 Update initial FCF candidate " + "with FCF (x%x)\n", bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, @@ -1984,20 +2160,28 @@ read_next_fcf: */ if (!(phba->fcf.failover_rec.flag & RECORD_VALID)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, - "2782 No suitable FCF record " - "found during this round of " - "post FCF rediscovery scan: " - "fcf_evt_tag:x%x, fcf_index: " - "x%x\n", + "2782 No suitable FCF found: " + "(x%x/x%x)\n", phba->fcoe_eventtag_at_fcf_scan, bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); + spin_lock_irq(&phba->hbalock); + if (phba->hba_flag & HBA_DEVLOSS_TMO) { + phba->hba_flag &= ~FCF_TS_INPROG; + spin_unlock_irq(&phba->hbalock); + /* Unregister in-use FCF and rescan */ + lpfc_printf_log(phba, KERN_INFO, + LOG_FIP, + "2864 On devloss tmo " + "unreg in-use FCF and " + "rescan FCF table\n"); + lpfc_unregister_fcf_rescan(phba); + return; + } /* - * Let next new FCF event trigger fast - * failover + * Let next new FCF event trigger fast failover */ - spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; spin_unlock_irq(&phba->hbalock); return; } @@ -2015,9 +2199,8 @@ read_next_fcf: /* Replace in-use record with the new record */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2842 Replace the current in-use " - "FCF record (x%x) with failover FCF " - "record (x%x)\n", + "2842 Replace in-use FCF (x%x) " + "with failover FCF (x%x)\n", phba->fcf.current_rec.fcf_indx, phba->fcf.failover_rec.fcf_indx); memcpy(&phba->fcf.current_rec, @@ -2029,15 +2212,8 @@ read_next_fcf: * FCF failover. */ spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= - ~(FCF_REDISC_FOV | FCF_REDISC_RRU); + phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; spin_unlock_irq(&phba->hbalock); - /* - * Set up the initial registered FCF index for FLOGI - * round robin FCF failover. - */ - phba->fcf.fcf_rr_init_indx = - phba->fcf.failover_rec.fcf_indx; /* Register to the new FCF record */ lpfc_register_fcf(phba); } else { @@ -2069,28 +2245,6 @@ read_next_fcf: LPFC_FCOE_FCF_GET_FIRST); return; } - - /* - * Otherwise, initial scan or post linkdown rescan, - * register with the best FCF record found so far - * through the FCF scanning process. - */ - - /* - * Mark the initial FCF discovery completed and - * the start of the first round of the roundrobin - * FCF failover. - */ - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= - ~(FCF_INIT_DISC | FCF_REDISC_RRU); - spin_unlock_irq(&phba->hbalock); - /* - * Set up the initial registered FCF index for FLOGI - * round robin FCF failover - */ - phba->fcf.fcf_rr_init_indx = - phba->fcf.current_rec.fcf_indx; /* Register to the new FCF record */ lpfc_register_fcf(phba); } @@ -2106,11 +2260,11 @@ out: } /** - * lpfc_mbx_cmpl_fcf_rr_read_fcf_rec - fcf round robin read_fcf mbox cmpl hdler + * lpfc_mbx_cmpl_fcf_rr_read_fcf_rec - fcf roundrobin read_fcf mbox cmpl hdler * @phba: pointer to lpfc hba data structure. * @mboxq: pointer to mailbox object. * - * This is the callback function for FLOGI failure round robin FCF failover + * This is the callback function for FLOGI failure roundrobin FCF failover * read FCF record mailbox command from the eligible FCF record bmask for * performing the failover. If the FCF read back is not valid/available, it * fails through to retrying FLOGI to the currently registered FCF again. @@ -2125,17 +2279,18 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct fcf_record *new_fcf_record; uint32_t boot_flag, addr_mode; - uint16_t next_fcf_index; + uint16_t next_fcf_index, fcf_index; uint16_t current_fcf_index; uint16_t vlan_id; + int rc; - /* If link state is not up, stop the round robin failover process */ + /* If link state is not up, stop the roundrobin failover process */ if (phba->link_state < LPFC_LINK_UP) { spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_DISCOVERY; + phba->hba_flag &= ~FCF_RR_INPROG; spin_unlock_irq(&phba->hbalock); - lpfc_sli4_mbox_cmd_free(phba, mboxq); - return; + goto out; } /* Parse the FCF record from the non-embedded mailbox command */ @@ -2145,23 +2300,47 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, "2766 Mailbox command READ_FCF_RECORD " "failed to retrieve a FCF record.\n"); - goto out; + goto error_out; } /* Get the needed parameters from FCF record */ - lpfc_match_fcf_conn_list(phba, new_fcf_record, &boot_flag, - &addr_mode, &vlan_id); + rc = lpfc_match_fcf_conn_list(phba, new_fcf_record, &boot_flag, + &addr_mode, &vlan_id); /* Log the FCF record information if turned on */ lpfc_sli4_log_fcf_record_info(phba, new_fcf_record, vlan_id, next_fcf_index); + fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record); + if (!rc) { + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2848 Remove ineligible FCF (x%x) from " + "from roundrobin bmask\n", fcf_index); + /* Clear roundrobin bmask bit for ineligible FCF */ + lpfc_sli4_fcf_rr_index_clear(phba, fcf_index); + /* Perform next round of roundrobin FCF failover */ + fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); + rc = lpfc_sli4_fcf_rr_next_proc(phba->pport, fcf_index); + if (rc) + goto out; + goto error_out; + } + + if (fcf_index == phba->fcf.current_rec.fcf_indx) { + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2760 Perform FLOGI roundrobin FCF failover: " + "FCF (x%x) back to FCF (x%x)\n", + phba->fcf.current_rec.fcf_indx, fcf_index); + /* Wait 500 ms before retrying FLOGI to current FCF */ + msleep(500); + lpfc_issue_init_vfi(phba->pport); + goto out; + } + /* Upload new FCF record to the failover FCF record */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2834 Update the current FCF record (x%x) " - "with the next FCF record (x%x)\n", - phba->fcf.failover_rec.fcf_indx, - bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); + "2834 Update current FCF (x%x) with new FCF (x%x)\n", + phba->fcf.failover_rec.fcf_indx, fcf_index); spin_lock_irq(&phba->hbalock); __lpfc_update_fcf_record(phba, &phba->fcf.failover_rec, new_fcf_record, addr_mode, vlan_id, @@ -2178,14 +2357,13 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) sizeof(struct lpfc_fcf_rec)); lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2783 FLOGI round robin FCF failover from FCF " - "(x%x) to FCF (x%x).\n", - current_fcf_index, - bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); + "2783 Perform FLOGI roundrobin FCF failover: FCF " + "(x%x) to FCF (x%x)\n", current_fcf_index, fcf_index); +error_out: + lpfc_register_fcf(phba); out: lpfc_sli4_mbox_cmd_free(phba, mboxq); - lpfc_register_fcf(phba); } /** @@ -2194,10 +2372,10 @@ out: * @mboxq: pointer to mailbox object. * * This is the callback function of read FCF record mailbox command for - * updating the eligible FCF bmask for FLOGI failure round robin FCF + * updating the eligible FCF bmask for FLOGI failure roundrobin FCF * failover when a new FCF event happened. If the FCF read back is * valid/available and it passes the connection list check, it updates - * the bmask for the eligible FCF record for round robin failover. + * the bmask for the eligible FCF record for roundrobin failover. */ void lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) @@ -2245,6 +2423,63 @@ out: lpfc_sli4_mbox_cmd_free(phba, mboxq); } +/** + * lpfc_init_vfi_cmpl - Completion handler for init_vfi mbox command. + * @phba: pointer to lpfc hba data structure. + * @mboxq: pointer to mailbox data structure. + * + * This function handles completion of init vfi mailbox command. + */ +void +lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) +{ + struct lpfc_vport *vport = mboxq->vport; + + if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, + "2891 Init VFI mailbox failed 0x%x\n", + mboxq->u.mb.mbxStatus); + mempool_free(mboxq, phba->mbox_mem_pool); + lpfc_vport_set_state(vport, FC_VPORT_FAILED); + return; + } + lpfc_initial_flogi(vport); + mempool_free(mboxq, phba->mbox_mem_pool); + return; +} + +/** + * lpfc_issue_init_vfi - Issue init_vfi mailbox command. + * @vport: pointer to lpfc_vport data structure. + * + * This function issue a init_vfi mailbox command to initialize the VFI and + * VPI for the physical port. + */ +void +lpfc_issue_init_vfi(struct lpfc_vport *vport) +{ + LPFC_MBOXQ_t *mboxq; + int rc; + struct lpfc_hba *phba = vport->phba; + + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, "2892 Failed to allocate " + "init_vfi mailbox\n"); + return; + } + lpfc_init_vfi(mboxq, vport); + mboxq->mbox_cmpl = lpfc_init_vfi_cmpl; + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n"); + mempool_free(mboxq, vport->phba->mbox_mem_pool); + } +} + /** * lpfc_init_vpi_cmpl - Completion handler for init_vpi mbox command. * @phba: pointer to lpfc hba data structure. @@ -2352,7 +2587,7 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) FC_VPORT_FAILED); continue; } - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { lpfc_vport_set_state(vports[i], FC_VPORT_LINKDOWN); continue; @@ -2388,7 +2623,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) "2018 REG_VFI mbxStatus error x%x " "HBA state x%x\n", mboxq->u.mb.mbxStatus, vport->port_state); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); /* Start discovery */ @@ -2406,8 +2641,18 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) spin_unlock_irq(shost->host_lock); if (vport->port_state == LPFC_FABRIC_CFG_LINK) { - lpfc_start_fdiscs(phba); - lpfc_do_scr_ns_plogi(phba, vport); + /* For private loop just start discovery and we are done. */ + if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && + (phba->alpa_map[0] == 0) && + !(vport->fc_flag & FC_PUBLIC_LOOP)) { + /* Use loop map to make discovery list */ + lpfc_disc_list_loopmap(vport); + /* Start discovery */ + lpfc_disc_start(vport); + } else { + lpfc_start_fdiscs(phba); + lpfc_do_scr_ns_plogi(phba, vport); + } } fail_free_mem: @@ -2468,7 +2713,7 @@ out: } static void -lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) +lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) { struct lpfc_vport *vport = phba->pport; LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL; @@ -2478,31 +2723,24 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) struct fcf_record *fcf_record; spin_lock_irq(&phba->hbalock); - 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; - case LA_8GHZ_LINK: - phba->fc_linkspeed = LA_8GHZ_LINK; - break; - case LA_10GHZ_LINK: - phba->fc_linkspeed = LA_10GHZ_LINK; + switch (bf_get(lpfc_mbx_read_top_link_spd, la)) { + case LPFC_LINK_SPEED_1GHZ: + case LPFC_LINK_SPEED_2GHZ: + case LPFC_LINK_SPEED_4GHZ: + case LPFC_LINK_SPEED_8GHZ: + case LPFC_LINK_SPEED_10GHZ: + case LPFC_LINK_SPEED_16GHZ: + phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la); break; default: - phba->fc_linkspeed = LA_UNKNW_LINK; + phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN; break; } - phba->fc_topology = la->topology; + phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; /* if npiv is enabled and this adapter supports npiv log @@ -2513,11 +2751,11 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) "1309 Link Up Event npiv not supported in loop " "topology\n"); /* Get Loop Map information */ - if (la->il) + if (bf_get(lpfc_mbx_read_top_il, la)) vport->fc_flag |= FC_LBIT; - vport->fc_myDID = la->granted_AL_PA; - i = la->un.lilpBde64.tus.f.bdeSize; + vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la); + i = la->lilpBde64.tus.f.bdeSize; if (i == 0) { phba->alpa_map[0] = 0; @@ -2588,7 +2826,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) goto out; } - if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) { + if (!(phba->hba_flag & HBA_FCOE_MODE)) { cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!cfglink_mbox) goto out; @@ -2639,7 +2877,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) * and get the FCF Table. */ spin_lock_irq(&phba->hbalock); - if (phba->hba_flag & FCF_DISC_INPROGRESS) { + if (phba->hba_flag & FCF_TS_INPROG) { spin_unlock_irq(&phba->hbalock); return; } @@ -2698,17 +2936,17 @@ lpfc_mbx_issue_link_down(struct lpfc_hba *phba) /* - * This routine handles processing a READ_LA mailbox + * This routine handles processing a READ_TOPOLOGY 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. */ void -lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - READ_LA_VAR *la; + struct lpfc_mbx_read_top *la; MAILBOX_t *mb = &pmb->u.mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); @@ -2721,15 +2959,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mb->mbxStatus, vport->port_state); lpfc_mbx_issue_link_down(phba); phba->link_state = LPFC_HBA_ERROR; - goto lpfc_mbx_cmpl_read_la_free_mbuf; + goto lpfc_mbx_cmpl_read_topology_free_mbuf; } - la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA; + la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop; memcpy(&phba->alpa_map[0], mp->virt, 128); spin_lock_irq(shost->host_lock); - if (la->pb) + if (bf_get(lpfc_mbx_read_top_pb, la)) vport->fc_flag |= FC_BYPASSED_MODE; else vport->fc_flag &= ~FC_BYPASSED_MODE; @@ -2738,41 +2976,48 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if ((phba->fc_eventTag < la->eventTag) || (phba->fc_eventTag == la->eventTag)) { phba->fc_stat.LinkMultiEvent++; - if (la->attType == AT_LINK_UP) + if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) if (phba->fc_eventTag != 0) lpfc_linkdown(phba); } phba->fc_eventTag = la->eventTag; spin_lock_irq(&phba->hbalock); - if (la->mm) + if (bf_get(lpfc_mbx_read_top_mm, la)) phba->sli.sli_flag |= LPFC_MENLO_MAINT; else phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; spin_unlock_irq(&phba->hbalock); phba->link_events++; - if (la->attType == AT_LINK_UP && (!la->mm)) { + if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) && + (!bf_get(lpfc_mbx_read_top_mm, la))) { phba->fc_stat.LinkUp++; if (phba->link_flag & LS_LOOPBACK_MODE) { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1306 Link Up Event in loop back mode " "x%x received Data: x%x x%x x%x x%x\n", la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, + bf_get(lpfc_mbx_read_top_alpa_granted, + la), + bf_get(lpfc_mbx_read_top_link_spd, la), phba->alpa_map[0]); } else { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1303 Link Up Event x%x received " "Data: x%x x%x x%x x%x x%x x%x %d\n", la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, + bf_get(lpfc_mbx_read_top_alpa_granted, + la), + bf_get(lpfc_mbx_read_top_link_spd, la), phba->alpa_map[0], - la->mm, la->fa, + bf_get(lpfc_mbx_read_top_mm, la), + bf_get(lpfc_mbx_read_top_fa, la), phba->wait_4_mlo_maint_flg); } lpfc_mbx_process_link_up(phba, la); - } else if (la->attType == AT_LINK_DOWN) { + } else if (bf_get(lpfc_mbx_read_top_att_type, la) == + LPFC_ATT_LINK_DOWN) { phba->fc_stat.LinkDown++; if (phba->link_flag & LS_LOOPBACK_MODE) { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, @@ -2788,11 +3033,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) "Data: x%x x%x x%x x%x x%x\n", la->eventTag, phba->fc_eventTag, phba->pport->port_state, vport->fc_flag, - la->mm, la->fa); + bf_get(lpfc_mbx_read_top_mm, la), + bf_get(lpfc_mbx_read_top_fa, la)); } lpfc_mbx_issue_link_down(phba); } - if (la->mm && la->attType == AT_LINK_UP) { + if ((bf_get(lpfc_mbx_read_top_mm, la)) && + (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)) { if (phba->link_state != LPFC_LINK_DOWN) { phba->fc_stat.LinkDown++; lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, @@ -2820,14 +3067,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } } - if (la->fa) { - if (la->mm) + if (bf_get(lpfc_mbx_read_top_fa, la)) { + if (bf_get(lpfc_mbx_read_top_mm, la)) lpfc_issue_clear_la(phba, vport); lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "1311 fa %d\n", la->fa); + "1311 fa %d\n", + bf_get(lpfc_mbx_read_top_fa, la)); } -lpfc_mbx_cmpl_read_la_free_mbuf: +lpfc_mbx_cmpl_read_topology_free_mbuf: lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); @@ -2854,8 +3102,8 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; - if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL || - ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { + if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL || + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { /* We rcvd a rscn after issuing this * mbox reg login, we may have cycled * back through the state and be @@ -2867,10 +3115,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; spin_unlock_irq(shost->host_lock); - if (phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_free_rpi(phba, - pmb->u.mb.un.varRegLogin.rpi); - } else /* Good status, call state machine */ lpfc_disc_state_machine(vport, ndlp, pmb, @@ -2916,6 +3160,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_unlock_irq(shost->host_lock); vport->unreg_vpi_cmpl = VPORT_OK; mempool_free(pmb, phba->mbox_mem_pool); + lpfc_cleanup_vports_rrqs(vport); /* * This shost reference might have been taken at the beginning of * lpfc_vport_delete() @@ -3157,7 +3402,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -3179,7 +3424,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -3237,7 +3482,7 @@ out: /* If no other thread is using the ndlp, free it */ lpfc_nlp_not_used(ndlp); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* * RegLogin failed, use loop map to make discovery * list @@ -3253,7 +3498,7 @@ out: } ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -3586,6 +3831,8 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, NLP_INT_NODE_ACT(ndlp); atomic_set(&ndlp->cmd_pending, 0); ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; + if (vport->phba->sli_rev == LPFC_SLI_REV4) + ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); } struct lpfc_nodelist * @@ -3799,7 +4046,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) * by firmware with a no rpi error. */ psli = &phba->sli; - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { /* Now process each ring */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; @@ -3847,7 +4094,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) LPFC_MBOXQ_t *mbox; int rc; - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mbox) { lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); @@ -3859,8 +4106,9 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) } lpfc_no_rpi(phba, ndlp); - ndlp->nlp_rpi = 0; - ndlp->nlp_flag &= ~NLP_RPI_VALID; + if (phba->sli_rev != LPFC_SLI_REV4) + ndlp->nlp_rpi = 0; + ndlp->nlp_flag &= ~NLP_RPI_REGISTERED; ndlp->nlp_flag &= ~NLP_NPR_ADISC; return 1; } @@ -3883,11 +4131,16 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba) int i; vports = lpfc_create_vport_work_array(phba); + if (!vports) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "2884 Vport array allocation failed \n"); + return; + } for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { /* The mempool_alloc might sleep */ spin_unlock_irq(shost->host_lock); lpfc_unreg_rpi(vports[i], ndlp); @@ -3906,6 +4159,11 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) LPFC_MBOXQ_t *mbox; int rc; + if (phba->sli_rev == LPFC_SLI_REV4) { + lpfc_sli4_unreg_all_rpis(vport); + return; + } + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mbox) { lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); @@ -3992,6 +4250,16 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) } spin_lock_irq(&phba->hbalock); + /* Cleanup REG_LOGIN completions which are not yet processed */ + list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) { + if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) || + (ndlp != (struct lpfc_nodelist *) mb->context2)) + continue; + + mb->context2 = NULL; + mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + } + list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { @@ -4001,9 +4269,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) kfree(mp); } list_del(&mb->list); - if (phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_free_rpi(phba, - mb->u.mb.un.varRegLogin.rpi); mempool_free(mb, phba->mbox_mem_pool); /* We shall not invoke the lpfc_nlp_put to decrement * the ndlp reference count as we are in the process @@ -4045,15 +4310,15 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_cancel_retry_delay_tmo(vport, ndlp); if ((ndlp->nlp_flag & NLP_DEFER_RM) && - !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && - !(ndlp->nlp_flag & NLP_RPI_VALID)) { + !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && + !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) { /* For this case we need to cleanup the default rpi * allocated by the firmware. */ if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) { rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, - (uint8_t *) &vport->fc_sparam, mbox, 0); + (uint8_t *) &vport->fc_sparam, mbox, ndlp->nlp_rpi); if (rc) { mempool_free(mbox, phba->mbox_mem_pool); } @@ -4245,7 +4510,7 @@ lpfc_disc_list_loopmap(struct lpfc_vport *vport) if (!lpfc_is_link_up(phba)) return; - if (phba->fc_topology != TOPOLOGY_LOOP) + if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) return; /* Check for loop map present or not */ @@ -4597,7 +4862,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) } } if (vport->port_state != LPFC_FLOGI) { - lpfc_initial_flogi(vport); + if (phba->sli_rev <= LPFC_SLI_REV3) + lpfc_initial_flogi(vport); + else + lpfc_issue_init_vfi(vport); return; } break; @@ -4788,7 +5056,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->context2 = NULL; ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -4912,6 +5180,8 @@ lpfc_nlp_release(struct kref *kref) spin_lock_irqsave(&phba->ndlp_lock, flags); NLP_CLR_NODE_ACT(ndlp); spin_unlock_irqrestore(&phba->ndlp_lock, flags); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); /* free ndlp memory for final ndlp release */ if (NLP_CHK_FREE_REQ(ndlp)) { @@ -5063,6 +5333,10 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) vports = lpfc_create_vport_work_array(phba); + /* If driver cannot allocate memory, indicate fcf is in use */ + if (!vports) + return 1; + for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); @@ -5078,7 +5352,7 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) "logged in\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag); - if (ndlp->nlp_flag & NLP_RPI_VALID) + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) ret = 1; } } @@ -5170,6 +5444,8 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) if (ndlp) lpfc_cancel_retry_delay_tmo(vports[i], ndlp); lpfc_cleanup_pending_mbox(vports[i]); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_unreg_all_rpis(vports[i]); lpfc_mbx_unreg_vpi(vports[i]); shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); @@ -5357,7 +5633,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) * registered, do nothing. */ spin_lock_irq(&phba->hbalock); - if (!(phba->hba_flag & HBA_FCOE_SUPPORT) || + if (!(phba->hba_flag & HBA_FCOE_MODE) || !(phba->fcf.fcf_flag & FCF_REGISTERED) || !(phba->hba_flag & HBA_FIP_SUPPORT) || (phba->fcf.fcf_flag & FCF_DISCOVERY) ||