diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:43 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
commit | 87af33fe5f78c27cf9e43c6e586dd6efd4be3e40 (patch) | |
tree | e9960c6e95ed599672d5dcec0d3c4e428ae42799 /drivers/scsi/lpfc/lpfc_init.c | |
parent | 98c9ea5c026ee47efe2a0f595078dbf199d08f50 (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.c | 66 |
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 | ||
1337 | static void | 1337 | void |
1338 | lpfc_cleanup(struct lpfc_vport *vport) | 1338 | lpfc_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 | ||