aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-02-08 18:49:26 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-11 18:52:57 -0500
commite47c9093531d3406a8ae38acca4ce207ef70cc0e (patch)
treecb115ec0b7981a100ef39ecfc68a36aa7e3e0f2e /drivers/scsi/lpfc/lpfc_init.c
parent4660c8ed5aaed99d82785499f034a8cc9199866d (diff)
[SCSI] lpfc 8.2.5 : Correct ndlp referencing issues
Correct ndlp referencing issues: - Fix ndlp kref issues due to race conditions between threads - Fix cancel els delay retry event which missed an ndlp reference count 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.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 6cfeba7454d4..e0363bef6d29 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2007 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2008 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -1422,9 +1422,32 @@ lpfc_cleanup(struct lpfc_vport *vport)
1422 lpfc_port_link_failure(vport); 1422 lpfc_port_link_failure(vport);
1423 1423
1424 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { 1424 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
1425 if (!NLP_CHK_NODE_ACT(ndlp)) {
1426 ndlp = lpfc_enable_node(vport, ndlp,
1427 NLP_STE_UNUSED_NODE);
1428 if (!ndlp)
1429 continue;
1430 spin_lock_irq(&phba->ndlp_lock);
1431 NLP_SET_FREE_REQ(ndlp);
1432 spin_unlock_irq(&phba->ndlp_lock);
1433 /* Trigger the release of the ndlp memory */
1434 lpfc_nlp_put(ndlp);
1435 continue;
1436 }
1437 spin_lock_irq(&phba->ndlp_lock);
1438 if (NLP_CHK_FREE_REQ(ndlp)) {
1439 /* The ndlp should not be in memory free mode already */
1440 spin_unlock_irq(&phba->ndlp_lock);
1441 continue;
1442 } else
1443 /* Indicate request for freeing ndlp memory */
1444 NLP_SET_FREE_REQ(ndlp);
1445 spin_unlock_irq(&phba->ndlp_lock);
1446
1425 if (ndlp->nlp_type & NLP_FABRIC) 1447 if (ndlp->nlp_type & NLP_FABRIC)
1426 lpfc_disc_state_machine(vport, ndlp, NULL, 1448 lpfc_disc_state_machine(vport, ndlp, NULL,
1427 NLP_EVT_DEVICE_RECOVERY); 1449 NLP_EVT_DEVICE_RECOVERY);
1450
1428 lpfc_disc_state_machine(vport, ndlp, NULL, 1451 lpfc_disc_state_machine(vport, ndlp, NULL,
1429 NLP_EVT_DEVICE_RM); 1452 NLP_EVT_DEVICE_RM);
1430 } 1453 }
@@ -1438,6 +1461,17 @@ lpfc_cleanup(struct lpfc_vport *vport)
1438 if (i++ > 3000) { 1461 if (i++ > 3000) {
1439 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, 1462 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1440 "0233 Nodelist not empty\n"); 1463 "0233 Nodelist not empty\n");
1464 list_for_each_entry_safe(ndlp, next_ndlp,
1465 &vport->fc_nodes, nlp_listp) {
1466 lpfc_printf_vlog(ndlp->vport, KERN_ERR,
1467 LOG_NODE,
1468 "0282: did:x%x ndlp:x%p "
1469 "usgmap:x%x refcnt:%d\n",
1470 ndlp->nlp_DID, (void *)ndlp,
1471 ndlp->nlp_usg_map,
1472 atomic_read(
1473 &ndlp->kref.refcount));
1474 }
1441 break; 1475 break;
1442 } 1476 }
1443 1477
@@ -1586,6 +1620,8 @@ lpfc_offline_prep(struct lpfc_hba * phba)
1586 list_for_each_entry_safe(ndlp, next_ndlp, 1620 list_for_each_entry_safe(ndlp, next_ndlp,
1587 &vports[i]->fc_nodes, 1621 &vports[i]->fc_nodes,
1588 nlp_listp) { 1622 nlp_listp) {
1623 if (!NLP_CHK_NODE_ACT(ndlp))
1624 continue;
1589 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 1625 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
1590 continue; 1626 continue;
1591 if (ndlp->nlp_type & NLP_FABRIC) { 1627 if (ndlp->nlp_type & NLP_FABRIC) {
@@ -1905,6 +1941,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
1905 1941
1906 spin_lock_init(&phba->hbalock); 1942 spin_lock_init(&phba->hbalock);
1907 1943
1944 /* Initialize ndlp management spinlock */
1945 spin_lock_init(&phba->ndlp_lock);
1946
1908 phba->pcidev = pdev; 1947 phba->pcidev = pdev;
1909 1948
1910 /* Assign an unused board number */ 1949 /* Assign an unused board number */