aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c328
1 files changed, 269 insertions, 59 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index dc042bd97baa..bd572d6b60af 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.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 *
@@ -272,9 +272,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
272 if (!(vport->load_flag & FC_UNLOADING) && 272 if (!(vport->load_flag & FC_UNLOADING) &&
273 !(ndlp->nlp_flag & NLP_DELAY_TMO) && 273 !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
274 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && 274 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
275 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) { 275 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
276 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); 276 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
277 }
278} 277}
279 278
280 279
@@ -566,9 +565,10 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
566 int rc; 565 int rc;
567 566
568 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { 567 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
568 if (!NLP_CHK_NODE_ACT(ndlp))
569 continue;
569 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 570 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
570 continue; 571 continue;
571
572 if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || 572 if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) ||
573 ((vport->port_type == LPFC_NPIV_PORT) && 573 ((vport->port_type == LPFC_NPIV_PORT) &&
574 (ndlp->nlp_DID == NameServer_DID))) 574 (ndlp->nlp_DID == NameServer_DID)))
@@ -629,9 +629,8 @@ lpfc_linkdown(struct lpfc_hba *phba)
629 LPFC_MBOXQ_t *mb; 629 LPFC_MBOXQ_t *mb;
630 int i; 630 int i;
631 631
632 if (phba->link_state == LPFC_LINK_DOWN) { 632 if (phba->link_state == LPFC_LINK_DOWN)
633 return 0; 633 return 0;
634 }
635 spin_lock_irq(&phba->hbalock); 634 spin_lock_irq(&phba->hbalock);
636 if (phba->link_state > LPFC_LINK_DOWN) { 635 if (phba->link_state > LPFC_LINK_DOWN) {
637 phba->link_state = LPFC_LINK_DOWN; 636 phba->link_state = LPFC_LINK_DOWN;
@@ -684,20 +683,21 @@ lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport)
684 struct lpfc_nodelist *ndlp; 683 struct lpfc_nodelist *ndlp;
685 684
686 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { 685 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
686 if (!NLP_CHK_NODE_ACT(ndlp))
687 continue;
687 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) 688 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
688 continue; 689 continue;
689
690 if (ndlp->nlp_type & NLP_FABRIC) { 690 if (ndlp->nlp_type & NLP_FABRIC) {
691 /* On Linkup its safe to clean up the ndlp 691 /* On Linkup its safe to clean up the ndlp
692 * from Fabric connections. 692 * from Fabric connections.
693 */ 693 */
694 if (ndlp->nlp_DID != Fabric_DID) 694 if (ndlp->nlp_DID != Fabric_DID)
695 lpfc_unreg_rpi(vport, ndlp); 695 lpfc_unreg_rpi(vport, ndlp);
696 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 696 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
697 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { 697 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
698 /* Fail outstanding IO now since device is 698 /* Fail outstanding IO now since device is
699 * marked for PLOGI. 699 * marked for PLOGI.
700 */ 700 */
701 lpfc_unreg_rpi(vport, ndlp); 701 lpfc_unreg_rpi(vport, ndlp);
702 } 702 }
703 } 703 }
@@ -799,21 +799,9 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
799 writel(control, phba->HCregaddr); 799 writel(control, phba->HCregaddr);
800 readl(phba->HCregaddr); /* flush */ 800 readl(phba->HCregaddr); /* flush */
801 spin_unlock_irq(&phba->hbalock); 801 spin_unlock_irq(&phba->hbalock);
802 mempool_free(pmb, phba->mbox_mem_pool);
802 return; 803 return;
803 804
804 vport->num_disc_nodes = 0;
805 /* go thru NPR nodes and issue ELS PLOGIs */
806 if (vport->fc_npr_cnt)
807 lpfc_els_disc_plogi(vport);
808
809 if (!vport->num_disc_nodes) {
810 spin_lock_irq(shost->host_lock);
811 vport->fc_flag &= ~FC_NDISC_ACTIVE;
812 spin_unlock_irq(shost->host_lock);
813 }
814
815 vport->port_state = LPFC_VPORT_READY;
816
817out: 805out:
818 /* Device Discovery completes */ 806 /* Device Discovery completes */
819 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, 807 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
@@ -1133,7 +1121,7 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1133 if (la->attType == AT_LINK_UP) { 1121 if (la->attType == AT_LINK_UP) {
1134 phba->fc_stat.LinkUp++; 1122 phba->fc_stat.LinkUp++;
1135 if (phba->link_flag & LS_LOOPBACK_MODE) { 1123 if (phba->link_flag & LS_LOOPBACK_MODE) {
1136 lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, 1124 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
1137 "1306 Link Up Event in loop back mode " 1125 "1306 Link Up Event in loop back mode "
1138 "x%x received Data: x%x x%x x%x x%x\n", 1126 "x%x received Data: x%x x%x x%x x%x\n",
1139 la->eventTag, phba->fc_eventTag, 1127 la->eventTag, phba->fc_eventTag,
@@ -1150,11 +1138,21 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1150 lpfc_mbx_process_link_up(phba, la); 1138 lpfc_mbx_process_link_up(phba, la);
1151 } else { 1139 } else {
1152 phba->fc_stat.LinkDown++; 1140 phba->fc_stat.LinkDown++;
1153 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, 1141 if (phba->link_flag & LS_LOOPBACK_MODE) {
1142 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
1143 "1308 Link Down Event in loop back mode "
1144 "x%x received "
1145 "Data: x%x x%x x%x\n",
1146 la->eventTag, phba->fc_eventTag,
1147 phba->pport->port_state, vport->fc_flag);
1148 }
1149 else {
1150 lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
1154 "1305 Link Down Event x%x received " 1151 "1305 Link Down Event x%x received "
1155 "Data: x%x x%x x%x\n", 1152 "Data: x%x x%x x%x\n",
1156 la->eventTag, phba->fc_eventTag, 1153 la->eventTag, phba->fc_eventTag,
1157 phba->pport->port_state, vport->fc_flag); 1154 phba->pport->port_state, vport->fc_flag);
1155 }
1158 lpfc_mbx_issue_link_down(phba); 1156 lpfc_mbx_issue_link_down(phba);
1159 } 1157 }
1160 1158
@@ -1305,7 +1303,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1305 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1303 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1306 kfree(mp); 1304 kfree(mp);
1307 mempool_free(pmb, phba->mbox_mem_pool); 1305 mempool_free(pmb, phba->mbox_mem_pool);
1308 lpfc_nlp_put(ndlp);
1309 1306
1310 if (phba->fc_topology == TOPOLOGY_LOOP) { 1307 if (phba->fc_topology == TOPOLOGY_LOOP) {
1311 /* FLOGI failed, use loop map to make discovery list */ 1308 /* FLOGI failed, use loop map to make discovery list */
@@ -1313,6 +1310,10 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1313 1310
1314 /* Start discovery */ 1311 /* Start discovery */
1315 lpfc_disc_start(vport); 1312 lpfc_disc_start(vport);
1313 /* Decrement the reference count to ndlp after the
1314 * reference to the ndlp are done.
1315 */
1316 lpfc_nlp_put(ndlp);
1316 return; 1317 return;
1317 } 1318 }
1318 1319
@@ -1320,6 +1321,10 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1320 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, 1321 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
1321 "0258 Register Fabric login error: 0x%x\n", 1322 "0258 Register Fabric login error: 0x%x\n",
1322 mb->mbxStatus); 1323 mb->mbxStatus);
1324 /* Decrement the reference count to ndlp after the reference
1325 * to the ndlp are done.
1326 */
1327 lpfc_nlp_put(ndlp);
1323 return; 1328 return;
1324 } 1329 }
1325 1330
@@ -1327,8 +1332,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1327 ndlp->nlp_type |= NLP_FABRIC; 1332 ndlp->nlp_type |= NLP_FABRIC;
1328 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); 1333 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1329 1334
1330 lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */
1331
1332 if (vport->port_state == LPFC_FABRIC_CFG_LINK) { 1335 if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
1333 vports = lpfc_create_vport_work_array(phba); 1336 vports = lpfc_create_vport_work_array(phba);
1334 if (vports != NULL) 1337 if (vports != NULL)
@@ -1356,6 +1359,11 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
1356 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1359 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1357 kfree(mp); 1360 kfree(mp);
1358 mempool_free(pmb, phba->mbox_mem_pool); 1361 mempool_free(pmb, phba->mbox_mem_pool);
1362
1363 /* Drop the reference count from the mbox at the end after
1364 * all the current reference to the ndlp have been done.
1365 */
1366 lpfc_nlp_put(ndlp);
1359 return; 1367 return;
1360} 1368}
1361 1369
@@ -1463,9 +1471,8 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1463 * registered the port. 1471 * registered the port.
1464 */ 1472 */
1465 if (ndlp->rport && ndlp->rport->dd_data && 1473 if (ndlp->rport && ndlp->rport->dd_data &&
1466 ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) { 1474 ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp)
1467 lpfc_nlp_put(ndlp); 1475 lpfc_nlp_put(ndlp);
1468 }
1469 1476
1470 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, 1477 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
1471 "rport add: did:x%x flg:x%x type x%x", 1478 "rport add: did:x%x flg:x%x type x%x",
@@ -1660,6 +1667,18 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1660} 1667}
1661 1668
1662void 1669void
1670lpfc_enqueue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1671{
1672 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1673
1674 if (list_empty(&ndlp->nlp_listp)) {
1675 spin_lock_irq(shost->host_lock);
1676 list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
1677 spin_unlock_irq(shost->host_lock);
1678 }
1679}
1680
1681void
1663lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) 1682lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1664{ 1683{
1665 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 1684 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
@@ -1672,7 +1691,80 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1672 list_del_init(&ndlp->nlp_listp); 1691 list_del_init(&ndlp->nlp_listp);
1673 spin_unlock_irq(shost->host_lock); 1692 spin_unlock_irq(shost->host_lock);
1674 lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, 1693 lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
1675 NLP_STE_UNUSED_NODE); 1694 NLP_STE_UNUSED_NODE);
1695}
1696
1697void
1698lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1699{
1700 if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
1701 lpfc_cancel_retry_delay_tmo(vport, ndlp);
1702 if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
1703 lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
1704 lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
1705 NLP_STE_UNUSED_NODE);
1706}
1707
1708struct lpfc_nodelist *
1709lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1710 int state)
1711{
1712 struct lpfc_hba *phba = vport->phba;
1713 uint32_t did;
1714 unsigned long flags;
1715
1716 if (!ndlp)
1717 return NULL;
1718
1719 spin_lock_irqsave(&phba->ndlp_lock, flags);
1720 /* The ndlp should not be in memory free mode */
1721 if (NLP_CHK_FREE_REQ(ndlp)) {
1722 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
1723 lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
1724 "0277 lpfc_enable_node: ndlp:x%p "
1725 "usgmap:x%x refcnt:%d\n",
1726 (void *)ndlp, ndlp->nlp_usg_map,
1727 atomic_read(&ndlp->kref.refcount));
1728 return NULL;
1729 }
1730 /* The ndlp should not already be in active mode */
1731 if (NLP_CHK_NODE_ACT(ndlp)) {
1732 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
1733 lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
1734 "0278 lpfc_enable_node: ndlp:x%p "
1735 "usgmap:x%x refcnt:%d\n",
1736 (void *)ndlp, ndlp->nlp_usg_map,
1737 atomic_read(&ndlp->kref.refcount));
1738 return NULL;
1739 }
1740
1741 /* Keep the original DID */
1742 did = ndlp->nlp_DID;
1743
1744 /* re-initialize ndlp except of ndlp linked list pointer */
1745 memset((((char *)ndlp) + sizeof (struct list_head)), 0,
1746 sizeof (struct lpfc_nodelist) - sizeof (struct list_head));
1747 INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
1748 INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
1749 init_timer(&ndlp->nlp_delayfunc);
1750 ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
1751 ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
1752 ndlp->nlp_DID = did;
1753 ndlp->vport = vport;
1754 ndlp->nlp_sid = NLP_NO_SID;
1755 /* ndlp management re-initialize */
1756 kref_init(&ndlp->kref);
1757 NLP_INT_NODE_ACT(ndlp);
1758
1759 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
1760
1761 if (state != NLP_STE_UNUSED_NODE)
1762 lpfc_nlp_set_state(vport, ndlp, state);
1763
1764 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
1765 "node enable: did:x%x",
1766 ndlp->nlp_DID, 0, 0);
1767 return ndlp;
1676} 1768}
1677 1769
1678void 1770void
@@ -1972,7 +2064,21 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1972 "Data: x%x x%x x%x\n", 2064 "Data: x%x x%x x%x\n",
1973 ndlp->nlp_DID, ndlp->nlp_flag, 2065 ndlp->nlp_DID, ndlp->nlp_flag,
1974 ndlp->nlp_state, ndlp->nlp_rpi); 2066 ndlp->nlp_state, ndlp->nlp_rpi);
1975 lpfc_dequeue_node(vport, ndlp); 2067 if (NLP_CHK_FREE_REQ(ndlp)) {
2068 lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
2069 "0280 lpfc_cleanup_node: ndlp:x%p "
2070 "usgmap:x%x refcnt:%d\n",
2071 (void *)ndlp, ndlp->nlp_usg_map,
2072 atomic_read(&ndlp->kref.refcount));
2073 lpfc_dequeue_node(vport, ndlp);
2074 } else {
2075 lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
2076 "0281 lpfc_cleanup_node: ndlp:x%p "
2077 "usgmap:x%x refcnt:%d\n",
2078 (void *)ndlp, ndlp->nlp_usg_map,
2079 atomic_read(&ndlp->kref.refcount));
2080 lpfc_disable_node(vport, ndlp);
2081 }
1976 2082
1977 /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ 2083 /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
1978 if ((mb = phba->sli.mbox_active)) { 2084 if ((mb = phba->sli.mbox_active)) {
@@ -1994,12 +2100,16 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
1994 } 2100 }
1995 list_del(&mb->list); 2101 list_del(&mb->list);
1996 mempool_free(mb, phba->mbox_mem_pool); 2102 mempool_free(mb, phba->mbox_mem_pool);
1997 lpfc_nlp_put(ndlp); 2103 /* We shall not invoke the lpfc_nlp_put to decrement
2104 * the ndlp reference count as we are in the process
2105 * of lpfc_nlp_release.
2106 */
1998 } 2107 }
1999 } 2108 }
2000 spin_unlock_irq(&phba->hbalock); 2109 spin_unlock_irq(&phba->hbalock);
2001 2110
2002 lpfc_els_abort(phba,ndlp); 2111 lpfc_els_abort(phba, ndlp);
2112
2003 spin_lock_irq(shost->host_lock); 2113 spin_lock_irq(shost->host_lock);
2004 ndlp->nlp_flag &= ~NLP_DELAY_TMO; 2114 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
2005 spin_unlock_irq(shost->host_lock); 2115 spin_unlock_irq(shost->host_lock);
@@ -2057,7 +2167,6 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
2057 } 2167 }
2058 } 2168 }
2059 } 2169 }
2060
2061 lpfc_cleanup_node(vport, ndlp); 2170 lpfc_cleanup_node(vport, ndlp);
2062 2171
2063 /* 2172 /*
@@ -2182,7 +2291,16 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
2182 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 2291 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
2183 spin_unlock_irq(shost->host_lock); 2292 spin_unlock_irq(shost->host_lock);
2184 return ndlp; 2293 return ndlp;
2294 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
2295 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_NPR_NODE);
2296 if (!ndlp)
2297 return NULL;
2298 spin_lock_irq(shost->host_lock);
2299 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
2300 spin_unlock_irq(shost->host_lock);
2301 return ndlp;
2185 } 2302 }
2303
2186 if (vport->fc_flag & FC_RSCN_MODE) { 2304 if (vport->fc_flag & FC_RSCN_MODE) {
2187 if (lpfc_rscn_payload_check(vport, did)) { 2305 if (lpfc_rscn_payload_check(vport, did)) {
2188 /* If we've already recieved a PLOGI from this NPort 2306 /* If we've already recieved a PLOGI from this NPort
@@ -2363,6 +2481,7 @@ lpfc_disc_start(struct lpfc_vport *vport)
2363 * continue discovery. 2481 * continue discovery.
2364 */ 2482 */
2365 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && 2483 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
2484 !(vport->fc_flag & FC_PT2PT) &&
2366 !(vport->fc_flag & FC_RSCN_MODE)) { 2485 !(vport->fc_flag & FC_RSCN_MODE)) {
2367 lpfc_issue_reg_vpi(phba, vport); 2486 lpfc_issue_reg_vpi(phba, vport);
2368 return; 2487 return;
@@ -2485,6 +2604,8 @@ lpfc_disc_flush_list(struct lpfc_vport *vport)
2485 if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) { 2604 if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) {
2486 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, 2605 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
2487 nlp_listp) { 2606 nlp_listp) {
2607 if (!NLP_CHK_NODE_ACT(ndlp))
2608 continue;
2488 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || 2609 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
2489 ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { 2610 ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
2490 lpfc_free_tx(phba, ndlp); 2611 lpfc_free_tx(phba, ndlp);
@@ -2572,6 +2693,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2572 /* Start discovery by sending FLOGI, clean up old rpis */ 2693 /* Start discovery by sending FLOGI, clean up old rpis */
2573 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, 2694 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
2574 nlp_listp) { 2695 nlp_listp) {
2696 if (!NLP_CHK_NODE_ACT(ndlp))
2697 continue;
2575 if (ndlp->nlp_state != NLP_STE_NPR_NODE) 2698 if (ndlp->nlp_state != NLP_STE_NPR_NODE)
2576 continue; 2699 continue;
2577 if (ndlp->nlp_type & NLP_FABRIC) { 2700 if (ndlp->nlp_type & NLP_FABRIC) {
@@ -2618,7 +2741,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
2618 "NameServer login\n"); 2741 "NameServer login\n");
2619 /* Next look for NameServer ndlp */ 2742 /* Next look for NameServer ndlp */
2620 ndlp = lpfc_findnode_did(vport, NameServer_DID); 2743 ndlp = lpfc_findnode_did(vport, NameServer_DID);
2621 if (ndlp) 2744 if (ndlp && NLP_CHK_NODE_ACT(ndlp))
2622 lpfc_els_abort(phba, ndlp); 2745 lpfc_els_abort(phba, ndlp);
2623 2746
2624 /* ReStart discovery */ 2747 /* ReStart discovery */
@@ -2897,6 +3020,7 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2897 ndlp->nlp_sid = NLP_NO_SID; 3020 ndlp->nlp_sid = NLP_NO_SID;
2898 INIT_LIST_HEAD(&ndlp->nlp_listp); 3021 INIT_LIST_HEAD(&ndlp->nlp_listp);
2899 kref_init(&ndlp->kref); 3022 kref_init(&ndlp->kref);
3023 NLP_INT_NODE_ACT(ndlp);
2900 3024
2901 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, 3025 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
2902 "node init: did:x%x", 3026 "node init: did:x%x",
@@ -2911,6 +3035,8 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2911static void 3035static void
2912lpfc_nlp_release(struct kref *kref) 3036lpfc_nlp_release(struct kref *kref)
2913{ 3037{
3038 struct lpfc_hba *phba;
3039 unsigned long flags;
2914 struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, 3040 struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
2915 kref); 3041 kref);
2916 3042
@@ -2918,8 +3044,24 @@ lpfc_nlp_release(struct kref *kref)
2918 "node release: did:x%x flg:x%x type:x%x", 3044 "node release: did:x%x flg:x%x type:x%x",
2919 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); 3045 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
2920 3046
3047 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
3048 "0279 lpfc_nlp_release: ndlp:x%p "
3049 "usgmap:x%x refcnt:%d\n",
3050 (void *)ndlp, ndlp->nlp_usg_map,
3051 atomic_read(&ndlp->kref.refcount));
3052
3053 /* remove ndlp from action. */
2921 lpfc_nlp_remove(ndlp->vport, ndlp); 3054 lpfc_nlp_remove(ndlp->vport, ndlp);
2922 mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); 3055
3056 /* clear the ndlp active flag for all release cases */
3057 phba = ndlp->vport->phba;
3058 spin_lock_irqsave(&phba->ndlp_lock, flags);
3059 NLP_CLR_NODE_ACT(ndlp);
3060 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3061
3062 /* free ndlp memory for final ndlp release */
3063 if (NLP_CHK_FREE_REQ(ndlp))
3064 mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
2923} 3065}
2924 3066
2925/* This routine bumps the reference count for a ndlp structure to ensure 3067/* This routine bumps the reference count for a ndlp structure to ensure
@@ -2929,37 +3071,108 @@ lpfc_nlp_release(struct kref *kref)
2929struct lpfc_nodelist * 3071struct lpfc_nodelist *
2930lpfc_nlp_get(struct lpfc_nodelist *ndlp) 3072lpfc_nlp_get(struct lpfc_nodelist *ndlp)
2931{ 3073{
3074 struct lpfc_hba *phba;
3075 unsigned long flags;
3076
2932 if (ndlp) { 3077 if (ndlp) {
2933 lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, 3078 lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
2934 "node get: did:x%x flg:x%x refcnt:x%x", 3079 "node get: did:x%x flg:x%x refcnt:x%x",
2935 ndlp->nlp_DID, ndlp->nlp_flag, 3080 ndlp->nlp_DID, ndlp->nlp_flag,
2936 atomic_read(&ndlp->kref.refcount)); 3081 atomic_read(&ndlp->kref.refcount));
2937 kref_get(&ndlp->kref); 3082 /* The check of ndlp usage to prevent incrementing the
3083 * ndlp reference count that is in the process of being
3084 * released.
3085 */
3086 phba = ndlp->vport->phba;
3087 spin_lock_irqsave(&phba->ndlp_lock, flags);
3088 if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) {
3089 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3090 lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE,
3091 "0276 lpfc_nlp_get: ndlp:x%p "
3092 "usgmap:x%x refcnt:%d\n",
3093 (void *)ndlp, ndlp->nlp_usg_map,
3094 atomic_read(&ndlp->kref.refcount));
3095 return NULL;
3096 } else
3097 kref_get(&ndlp->kref);
3098 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
2938 } 3099 }
2939 return ndlp; 3100 return ndlp;
2940} 3101}
2941 3102
2942
2943/* This routine decrements the reference count for a ndlp structure. If the 3103/* This routine decrements the reference count for a ndlp structure. If the
2944 * count goes to 0, this indicates the the associated nodelist should be freed. 3104 * count goes to 0, this indicates the the associated nodelist should be
3105 * freed. Returning 1 indicates the ndlp resource has been released; on the
3106 * other hand, returning 0 indicates the ndlp resource has not been released
3107 * yet.
2945 */ 3108 */
2946int 3109int
2947lpfc_nlp_put(struct lpfc_nodelist *ndlp) 3110lpfc_nlp_put(struct lpfc_nodelist *ndlp)
2948{ 3111{
2949 if (ndlp) { 3112 struct lpfc_hba *phba;
2950 lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, 3113 unsigned long flags;
2951 "node put: did:x%x flg:x%x refcnt:x%x", 3114
2952 ndlp->nlp_DID, ndlp->nlp_flag, 3115 if (!ndlp)
2953 atomic_read(&ndlp->kref.refcount)); 3116 return 1;
3117
3118 lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
3119 "node put: did:x%x flg:x%x refcnt:x%x",
3120 ndlp->nlp_DID, ndlp->nlp_flag,
3121 atomic_read(&ndlp->kref.refcount));
3122 phba = ndlp->vport->phba;
3123 spin_lock_irqsave(&phba->ndlp_lock, flags);
3124 /* Check the ndlp memory free acknowledge flag to avoid the
3125 * possible race condition that kref_put got invoked again
3126 * after previous one has done ndlp memory free.
3127 */
3128 if (NLP_CHK_FREE_ACK(ndlp)) {
3129 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3130 lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE,
3131 "0274 lpfc_nlp_put: ndlp:x%p "
3132 "usgmap:x%x refcnt:%d\n",
3133 (void *)ndlp, ndlp->nlp_usg_map,
3134 atomic_read(&ndlp->kref.refcount));
3135 return 1;
2954 } 3136 }
2955 return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; 3137 /* Check the ndlp inactivate log flag to avoid the possible
3138 * race condition that kref_put got invoked again after ndlp
3139 * is already in inactivating state.
3140 */
3141 if (NLP_CHK_IACT_REQ(ndlp)) {
3142 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3143 lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE,
3144 "0275 lpfc_nlp_put: ndlp:x%p "
3145 "usgmap:x%x refcnt:%d\n",
3146 (void *)ndlp, ndlp->nlp_usg_map,
3147 atomic_read(&ndlp->kref.refcount));
3148 return 1;
3149 }
3150 /* For last put, mark the ndlp usage flags to make sure no
3151 * other kref_get and kref_put on the same ndlp shall get
3152 * in between the process when the final kref_put has been
3153 * invoked on this ndlp.
3154 */
3155 if (atomic_read(&ndlp->kref.refcount) == 1) {
3156 /* Indicate ndlp is put to inactive state. */
3157 NLP_SET_IACT_REQ(ndlp);
3158 /* Acknowledge ndlp memory free has been seen. */
3159 if (NLP_CHK_FREE_REQ(ndlp))
3160 NLP_SET_FREE_ACK(ndlp);
3161 }
3162 spin_unlock_irqrestore(&phba->ndlp_lock, flags);
3163 /* Note, the kref_put returns 1 when decrementing a reference
3164 * count that was 1, it invokes the release callback function,
3165 * but it still left the reference count as 1 (not actually
3166 * performs the last decrementation). Otherwise, it actually
3167 * decrements the reference count and returns 0.
3168 */
3169 return kref_put(&ndlp->kref, lpfc_nlp_release);
2956} 3170}
2957 3171
2958/* This routine free's the specified nodelist if it is not in use 3172/* This routine free's the specified nodelist if it is not in use
2959 * by any other discovery thread. This routine returns 1 if the ndlp 3173 * by any other discovery thread. This routine returns 1 if the
2960 * is not being used by anyone and has been freed. A return value of 3174 * ndlp has been freed. A return value of 0 indicates the ndlp is
2961 * 0 indicates it is being used by another discovery thread and the 3175 * not yet been released.
2962 * refcount is left unchanged.
2963 */ 3176 */
2964int 3177int
2965lpfc_nlp_not_used(struct lpfc_nodelist *ndlp) 3178lpfc_nlp_not_used(struct lpfc_nodelist *ndlp)
@@ -2968,11 +3181,8 @@ lpfc_nlp_not_used(struct lpfc_nodelist *ndlp)
2968 "node not used: did:x%x flg:x%x refcnt:x%x", 3181 "node not used: did:x%x flg:x%x refcnt:x%x",
2969 ndlp->nlp_DID, ndlp->nlp_flag, 3182 ndlp->nlp_DID, ndlp->nlp_flag,
2970 atomic_read(&ndlp->kref.refcount)); 3183 atomic_read(&ndlp->kref.refcount));
2971 3184 if (atomic_read(&ndlp->kref.refcount) == 1)
2972 if (atomic_read(&ndlp->kref.refcount) == 1) { 3185 if (lpfc_nlp_put(ndlp))
2973 lpfc_nlp_put(ndlp); 3186 return 1;
2974 return 1;
2975 }
2976 return 0; 3187 return 0;
2977} 3188}
2978