[SCSI] lpfc 8.2.3 : FC Discovery Fixes
FC Discovery Fixes: - Fix up lpfc_drop_node() vs lpfc_nlp_not_used() usage - Clear ADISC flag when unregistering RPI and REMOVE ndlps if in recovery. - Fix usage of UNUSED list and ndlps - Fix PLOGI race conditions - Reset link if NameServer PLOGI errors occur - Synchronize GID_FT queries with PLOGI receptions Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
committed by
James Bottomley
parent
98c9ea5c02
commit
87af33fe5f
@@ -1334,15 +1334,35 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
|
||||
kfree(HashWorking);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
lpfc_cleanup(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
|
||||
/* clean up phba - lpfc specific */
|
||||
lpfc_can_disctmo(vport);
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
|
||||
lpfc_nlp_put(ndlp);
|
||||
if (phba->link_state > LPFC_LINK_DOWN)
|
||||
lpfc_port_link_failure(vport);
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
if (ndlp->nlp_type & NLP_FABRIC)
|
||||
lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
NLP_EVT_DEVICE_RECOVERY);
|
||||
lpfc_disc_state_machine(vport, ndlp, NULL,
|
||||
NLP_EVT_DEVICE_RM);
|
||||
}
|
||||
|
||||
/* At this point, ALL ndlp's should be gone */
|
||||
while (!list_empty(&vport->fc_nodes)) {
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
|
||||
nlp_listp) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
|
||||
"0233 Nodelist x%x not free: %d\n",
|
||||
ndlp->nlp_DID,
|
||||
atomic_read(&ndlp->kref.refcount));
|
||||
lpfc_drop_node(vport, ndlp);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1463,6 +1483,8 @@ lpfc_offline_prep(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_vport *vport = phba->pport;
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
struct lpfc_vport **vports;
|
||||
int i;
|
||||
|
||||
if (vport->fc_flag & FC_OFFLINE_MODE)
|
||||
return;
|
||||
@@ -1471,10 +1493,32 @@ lpfc_offline_prep(struct lpfc_hba * phba)
|
||||
|
||||
lpfc_linkdown(phba);
|
||||
|
||||
/* Issue an unreg_login to all nodes */
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
|
||||
if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
|
||||
lpfc_unreg_rpi(vport, ndlp);
|
||||
/* Issue an unreg_login to all nodes on all vports */
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports != NULL) {
|
||||
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
shost = lpfc_shost_from_vport(vports[i]);
|
||||
list_for_each_entry_safe(ndlp, next_ndlp,
|
||||
&vports[i]->fc_nodes,
|
||||
nlp_listp) {
|
||||
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
|
||||
continue;
|
||||
if (ndlp->nlp_type & NLP_FABRIC) {
|
||||
lpfc_disc_state_machine(vports[i], ndlp,
|
||||
NULL, NLP_EVT_DEVICE_RECOVERY);
|
||||
lpfc_disc_state_machine(vports[i], ndlp,
|
||||
NULL, NLP_EVT_DEVICE_RM);
|
||||
}
|
||||
spin_lock_irq(shost->host_lock);
|
||||
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
lpfc_unreg_rpi(vports[i], ndlp);
|
||||
}
|
||||
}
|
||||
}
|
||||
lpfc_destroy_vport_work_array(vports);
|
||||
|
||||
lpfc_sli_flush_mbox_queue(phba);
|
||||
}
|
||||
@@ -1508,7 +1552,6 @@ lpfc_offline(struct lpfc_hba *phba)
|
||||
if (vports != NULL)
|
||||
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
|
||||
shost = lpfc_shost_from_vport(vports[i]);
|
||||
lpfc_cleanup(vports[i]);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vports[i]->work_port_events = 0;
|
||||
vports[i]->fc_flag |= FC_OFFLINE_MODE;
|
||||
@@ -2061,6 +2104,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||
|
||||
fc_remove_host(shost);
|
||||
scsi_remove_host(shost);
|
||||
lpfc_cleanup(vport);
|
||||
|
||||
/*
|
||||
* Bring down the SLI Layer. This step disable all interrupts,
|
||||
* clears the rings, discards all mailbox commands, and resets
|
||||
@@ -2075,7 +2120,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
lpfc_debugfs_terminate(vport);
|
||||
lpfc_cleanup(vport);
|
||||
|
||||
kthread_stop(phba->worker_thread);
|
||||
|
||||
|
Reference in New Issue
Block a user