aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-10-27 13:37:43 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:22:33 -0500
commit87af33fe5f78c27cf9e43c6e586dd6efd4be3e40 (patch)
treee9960c6e95ed599672d5dcec0d3c4e428ae42799 /drivers/scsi/lpfc/lpfc_init.c
parent98c9ea5c026ee47efe2a0f595078dbf199d08f50 (diff)
[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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 729694d97597..ceb185fa3216 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1334,15 +1334,35 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
1334 kfree(HashWorking); 1334 kfree(HashWorking);
1335} 1335}
1336 1336
1337static void 1337void
1338lpfc_cleanup(struct lpfc_vport *vport) 1338lpfc_cleanup(struct lpfc_vport *vport)
1339{ 1339{
1340 struct lpfc_hba *phba = vport->phba;
1340 struct lpfc_nodelist *ndlp, *next_ndlp; 1341 struct lpfc_nodelist *ndlp, *next_ndlp;
1341 1342
1342 /* clean up phba - lpfc specific */ 1343 if (phba->link_state > LPFC_LINK_DOWN)
1343 lpfc_can_disctmo(vport); 1344 lpfc_port_link_failure(vport);
1344 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) 1345
1345 lpfc_nlp_put(ndlp); 1346 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
1347 if (ndlp->nlp_type & NLP_FABRIC)
1348 lpfc_disc_state_machine(vport, ndlp, NULL,
1349 NLP_EVT_DEVICE_RECOVERY);
1350 lpfc_disc_state_machine(vport, ndlp, NULL,
1351 NLP_EVT_DEVICE_RM);
1352 }
1353
1354 /* At this point, ALL ndlp's should be gone */
1355 while (!list_empty(&vport->fc_nodes)) {
1356
1357 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
1358 nlp_listp) {
1359 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1360 "0233 Nodelist x%x not free: %d\n",
1361 ndlp->nlp_DID,
1362 atomic_read(&ndlp->kref.refcount));
1363 lpfc_drop_node(vport, ndlp);
1364 }
1365 }
1346 return; 1366 return;
1347} 1367}
1348 1368
@@ -1463,6 +1483,8 @@ lpfc_offline_prep(struct lpfc_hba * phba)
1463{ 1483{
1464 struct lpfc_vport *vport = phba->pport; 1484 struct lpfc_vport *vport = phba->pport;
1465 struct lpfc_nodelist *ndlp, *next_ndlp; 1485 struct lpfc_nodelist *ndlp, *next_ndlp;
1486 struct lpfc_vport **vports;
1487 int i;
1466 1488
1467 if (vport->fc_flag & FC_OFFLINE_MODE) 1489 if (vport->fc_flag & FC_OFFLINE_MODE)
1468 return; 1490 return;
@@ -1471,10 +1493,32 @@ lpfc_offline_prep(struct lpfc_hba * phba)
1471 1493
1472 lpfc_linkdown(phba); 1494 lpfc_linkdown(phba);
1473 1495
1474 /* Issue an unreg_login to all nodes */ 1496 /* Issue an unreg_login to all nodes on all vports */
1475 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) 1497 vports = lpfc_create_vport_work_array(phba);
1476 if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) 1498 if (vports != NULL) {
1477 lpfc_unreg_rpi(vport, ndlp); 1499 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
1500 struct Scsi_Host *shost;
1501
1502 shost = lpfc_shost_from_vport(vports[i]);
1503 list_for_each_entry_safe(ndlp, next_ndlp,
1504 &vports[i]->fc_nodes,
1505 nlp_listp) {
1506 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
1507 continue;
1508 if (ndlp->nlp_type & NLP_FABRIC) {
1509 lpfc_disc_state_machine(vports[i], ndlp,
1510 NULL, NLP_EVT_DEVICE_RECOVERY);
1511 lpfc_disc_state_machine(vports[i], ndlp,
1512 NULL, NLP_EVT_DEVICE_RM);
1513 }
1514 spin_lock_irq(shost->host_lock);
1515 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
1516 spin_unlock_irq(shost->host_lock);
1517 lpfc_unreg_rpi(vports[i], ndlp);
1518 }
1519 }
1520 }
1521 lpfc_destroy_vport_work_array(vports);
1478 1522
1479 lpfc_sli_flush_mbox_queue(phba); 1523 lpfc_sli_flush_mbox_queue(phba);
1480} 1524}
@@ -1508,7 +1552,6 @@ lpfc_offline(struct lpfc_hba *phba)
1508 if (vports != NULL) 1552 if (vports != NULL)
1509 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { 1553 for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
1510 shost = lpfc_shost_from_vport(vports[i]); 1554 shost = lpfc_shost_from_vport(vports[i]);
1511 lpfc_cleanup(vports[i]);
1512 spin_lock_irq(shost->host_lock); 1555 spin_lock_irq(shost->host_lock);
1513 vports[i]->work_port_events = 0; 1556 vports[i]->work_port_events = 0;
1514 vports[i]->fc_flag |= FC_OFFLINE_MODE; 1557 vports[i]->fc_flag |= FC_OFFLINE_MODE;
@@ -2061,6 +2104,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
2061 2104
2062 fc_remove_host(shost); 2105 fc_remove_host(shost);
2063 scsi_remove_host(shost); 2106 scsi_remove_host(shost);
2107 lpfc_cleanup(vport);
2108
2064 /* 2109 /*
2065 * Bring down the SLI Layer. This step disable all interrupts, 2110 * Bring down the SLI Layer. This step disable all interrupts,
2066 * clears the rings, discards all mailbox commands, and resets 2111 * clears the rings, discards all mailbox commands, and resets
@@ -2075,7 +2120,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
2075 spin_unlock_irq(&phba->hbalock); 2120 spin_unlock_irq(&phba->hbalock);
2076 2121
2077 lpfc_debugfs_terminate(vport); 2122 lpfc_debugfs_terminate(vport);
2078 lpfc_cleanup(vport);
2079 2123
2080 kthread_stop(phba->worker_thread); 2124 kthread_stop(phba->worker_thread);
2081 2125