aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:53:01 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:15 -0400
commit329f9bc735b4665d42267259b1612191f72c4d42 (patch)
treeb696a632e19afa0d0e42012efd7992690f69e1a1 /drivers/scsi/lpfc/lpfc_hbadisc.c
parent2680eeaaa03e83a87ece2724e71f7cc816cd3ef0 (diff)
[SCSI] lpfc 8.1.12 : Reference count node structures for node lifetime management
Reference count node structures for node lifetime management. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c107
1 files changed, 72 insertions, 35 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 164af8a7e95d..8ba2f4eadcdd 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -158,6 +158,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
158 else { 158 else {
159 rdata->pnode = NULL; 159 rdata->pnode = NULL;
160 ndlp->rport = NULL; 160 ndlp->rport = NULL;
161 lpfc_nlp_put(ndlp);
162 put_device(&rport->dev);
161 } 163 }
162 164
163 return; 165 return;
@@ -960,6 +962,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
960 lpfc_mbuf_free(phba, mp->virt, mp->phys); 962 lpfc_mbuf_free(phba, mp->virt, mp->phys);
961 kfree(mp); 963 kfree(mp);
962 mempool_free( pmb, phba->mbox_mem_pool); 964 mempool_free( pmb, phba->mbox_mem_pool);
965 lpfc_nlp_put(ndlp);
963 966
964 return; 967 return;
965} 968}
@@ -986,11 +989,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
986 ndlp = (struct lpfc_nodelist *) pmb->context2; 989 ndlp = (struct lpfc_nodelist *) pmb->context2;
987 mp = (struct lpfc_dmabuf *) (pmb->context1); 990 mp = (struct lpfc_dmabuf *) (pmb->context1);
988 991
992 pmb->context1 = NULL;
993 pmb->context2 = NULL;
994
989 if (mb->mbxStatus) { 995 if (mb->mbxStatus) {
990 lpfc_mbuf_free(phba, mp->virt, mp->phys); 996 lpfc_mbuf_free(phba, mp->virt, mp->phys);
991 kfree(mp); 997 kfree(mp);
992 mempool_free( pmb, phba->mbox_mem_pool); 998 mempool_free(pmb, phba->mbox_mem_pool);
993 mempool_free( ndlp, phba->nlp_mem_pool); 999 lpfc_nlp_put(ndlp);
994 1000
995 /* FLOGI failed, so just use loop map to make discovery list */ 1001 /* FLOGI failed, so just use loop map to make discovery list */
996 lpfc_disc_list_loopmap(phba); 1002 lpfc_disc_list_loopmap(phba);
@@ -1000,12 +1006,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1000 return; 1006 return;
1001 } 1007 }
1002 1008
1003 pmb->context1 = NULL;
1004
1005 ndlp->nlp_rpi = mb->un.varWords[0]; 1009 ndlp->nlp_rpi = mb->un.varWords[0];
1006 ndlp->nlp_type |= NLP_FABRIC; 1010 ndlp->nlp_type |= NLP_FABRIC;
1007 lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); 1011 lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
1008 1012
1013 lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */
1014
1009 if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { 1015 if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
1010 /* This NPort has been assigned an NPort_ID by the fabric as a 1016 /* This NPort has been assigned an NPort_ID by the fabric as a
1011 * result of the completed fabric login. Issue a State Change 1017 * result of the completed fabric login. Issue a State Change
@@ -1027,7 +1033,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1027 lpfc_disc_start(phba); 1033 lpfc_disc_start(phba);
1028 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1034 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1029 kfree(mp); 1035 kfree(mp);
1030 mempool_free( pmb, phba->mbox_mem_pool); 1036 mempool_free(pmb, phba->mbox_mem_pool);
1031 return; 1037 return;
1032 } else { 1038 } else {
1033 lpfc_nlp_init(phba, ndlp, NameServer_DID); 1039 lpfc_nlp_init(phba, ndlp, NameServer_DID);
@@ -1050,7 +1056,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1050 1056
1051 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1057 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1052 kfree(mp); 1058 kfree(mp);
1053 mempool_free( pmb, phba->mbox_mem_pool); 1059 mempool_free(pmb, phba->mbox_mem_pool);
1054 return; 1060 return;
1055} 1061}
1056 1062
@@ -1075,6 +1081,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1075 mp = (struct lpfc_dmabuf *) (pmb->context1); 1081 mp = (struct lpfc_dmabuf *) (pmb->context1);
1076 1082
1077 if (mb->mbxStatus) { 1083 if (mb->mbxStatus) {
1084 lpfc_nlp_put(ndlp);
1078 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1085 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1079 kfree(mp); 1086 kfree(mp);
1080 mempool_free(pmb, phba->mbox_mem_pool); 1087 mempool_free(pmb, phba->mbox_mem_pool);
@@ -1110,6 +1117,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1110 lpfc_disc_start(phba); 1117 lpfc_disc_start(phba);
1111 } 1118 }
1112 1119
1120 lpfc_nlp_put(ndlp);
1113 lpfc_mbuf_free(phba, mp->virt, mp->phys); 1121 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1114 kfree(mp); 1122 kfree(mp);
1115 mempool_free( pmb, phba->mbox_mem_pool); 1123 mempool_free( pmb, phba->mbox_mem_pool);
@@ -1118,8 +1126,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
1118} 1126}
1119 1127
1120static void 1128static void
1121lpfc_register_remote_port(struct lpfc_hba * phba, 1129lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1122 struct lpfc_nodelist * ndlp)
1123{ 1130{
1124 struct fc_rport *rport; 1131 struct fc_rport *rport;
1125 struct lpfc_rport_data *rdata; 1132 struct lpfc_rport_data *rdata;
@@ -1131,8 +1138,19 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
1131 rport_ids.port_id = ndlp->nlp_DID; 1138 rport_ids.port_id = ndlp->nlp_DID;
1132 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 1139 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
1133 1140
1141 /*
1142 * We leave our node pointer in rport->dd_data when we unregister a
1143 * FCP target port. But fc_remote_port_add zeros the space to which
1144 * rport->dd_data points. So, if we're reusing a previously
1145 * registered port, drop the reference that we took the last time we
1146 * registered the port.
1147 */
1148 if (ndlp->rport && ndlp->rport->dd_data &&
1149 *(struct lpfc_rport_data **) ndlp->rport->dd_data) {
1150 lpfc_nlp_put(ndlp);
1151 }
1134 ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); 1152 ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
1135 if (!rport) { 1153 if (!rport || !get_device(&rport->dev)) {
1136 dev_printk(KERN_WARNING, &phba->pcidev->dev, 1154 dev_printk(KERN_WARNING, &phba->pcidev->dev,
1137 "Warning: fc_remote_port_add failed\n"); 1155 "Warning: fc_remote_port_add failed\n");
1138 return; 1156 return;
@@ -1142,7 +1160,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
1142 rport->maxframe_size = ndlp->nlp_maxframe; 1160 rport->maxframe_size = ndlp->nlp_maxframe;
1143 rport->supported_classes = ndlp->nlp_class_sup; 1161 rport->supported_classes = ndlp->nlp_class_sup;
1144 rdata = rport->dd_data; 1162 rdata = rport->dd_data;
1145 rdata->pnode = ndlp; 1163 rdata->pnode = lpfc_nlp_get(ndlp);
1146 1164
1147 if (ndlp->nlp_type & NLP_FCP_TARGET) 1165 if (ndlp->nlp_type & NLP_FCP_TARGET)
1148 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; 1166 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
@@ -1162,8 +1180,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
1162} 1180}
1163 1181
1164static void 1182static void
1165lpfc_unregister_remote_port(struct lpfc_hba * phba, 1183lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1166 struct lpfc_nodelist * ndlp)
1167{ 1184{
1168 struct fc_rport *rport = ndlp->rport; 1185 struct fc_rport *rport = ndlp->rport;
1169 struct lpfc_rport_data *rdata = rport->dd_data; 1186 struct lpfc_rport_data *rdata = rport->dd_data;
@@ -1171,6 +1188,8 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
1171 if (rport->scsi_target_id == -1) { 1188 if (rport->scsi_target_id == -1) {
1172 ndlp->rport = NULL; 1189 ndlp->rport = NULL;
1173 rdata->pnode = NULL; 1190 rdata->pnode = NULL;
1191 lpfc_nlp_put(ndlp);
1192 put_device(&rport->dev);
1174 } 1193 }
1175 1194
1176 fc_remote_port_delete(rport); 1195 fc_remote_port_delete(rport);
@@ -1416,7 +1435,7 @@ lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1416 lpfc_nlp_counters(phba, ndlp->nlp_state, -1); 1435 lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
1417 lpfc_delink_node(phba, ndlp); 1436 lpfc_delink_node(phba, ndlp);
1418 spin_unlock_irq(phba->host->host_lock); 1437 spin_unlock_irq(phba->host->host_lock);
1419 lpfc_nlp_remove(phba, ndlp); 1438 lpfc_nlp_put(ndlp);
1420} 1439}
1421 1440
1422/* 1441/*
@@ -1654,6 +1673,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1654 } 1673 }
1655 list_del(&mb->list); 1674 list_del(&mb->list);
1656 mempool_free(mb, phba->mbox_mem_pool); 1675 mempool_free(mb, phba->mbox_mem_pool);
1676 lpfc_nlp_put(ndlp);
1657 } 1677 }
1658 } 1678 }
1659 spin_unlock_irq(phba->host->host_lock); 1679 spin_unlock_irq(phba->host->host_lock);
@@ -1679,8 +1699,8 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1679 * If we are in the middle of using the nlp in the discovery state 1699 * If we are in the middle of using the nlp in the discovery state
1680 * machine, defer the free till we reach the end of the state machine. 1700 * machine, defer the free till we reach the end of the state machine.
1681 */ 1701 */
1682int 1702static void
1683lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) 1703lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
1684{ 1704{
1685 struct lpfc_rport_data *rdata; 1705 struct lpfc_rport_data *rdata;
1686 1706
@@ -1688,22 +1708,14 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1688 lpfc_cancel_retry_delay_tmo(phba, ndlp); 1708 lpfc_cancel_retry_delay_tmo(phba, ndlp);
1689 } 1709 }
1690 1710
1691 if (ndlp->nlp_disc_refcnt) { 1711 lpfc_freenode(phba, ndlp);
1692 spin_lock_irq(phba->host->host_lock);
1693 ndlp->nlp_flag |= NLP_DELAY_REMOVE;
1694 spin_unlock_irq(phba->host->host_lock);
1695 } else {
1696 lpfc_freenode(phba, ndlp);
1697
1698 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
1699 rdata = ndlp->rport->dd_data;
1700 rdata->pnode = NULL;
1701 ndlp->rport = NULL;
1702 }
1703 1712
1704 mempool_free( ndlp, phba->nlp_mem_pool); 1713 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
1714 put_device(&ndlp->rport->dev);
1715 rdata = ndlp->rport->dd_data;
1716 rdata->pnode = NULL;
1717 ndlp->rport = NULL;
1705 } 1718 }
1706 return 0;
1707} 1719}
1708 1720
1709static int 1721static int
@@ -2069,14 +2081,14 @@ lpfc_disc_flush_list(struct lpfc_hba * phba)
2069 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, 2081 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
2070 nlp_listp) { 2082 nlp_listp) {
2071 lpfc_free_tx(phba, ndlp); 2083 lpfc_free_tx(phba, ndlp);
2072 lpfc_nlp_remove(phba, ndlp); 2084 lpfc_nlp_put(ndlp);
2073 } 2085 }
2074 } 2086 }
2075 if (phba->fc_adisc_cnt) { 2087 if (phba->fc_adisc_cnt) {
2076 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, 2088 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
2077 nlp_listp) { 2089 nlp_listp) {
2078 lpfc_free_tx(phba, ndlp); 2090 lpfc_free_tx(phba, ndlp);
2079 lpfc_nlp_remove(phba, ndlp); 2091 lpfc_nlp_put(ndlp);
2080 } 2092 }
2081 } 2093 }
2082 return; 2094 return;
@@ -2195,7 +2207,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
2195 /* Next look for NameServer ndlp */ 2207 /* Next look for NameServer ndlp */
2196 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); 2208 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
2197 if (ndlp) 2209 if (ndlp)
2198 lpfc_nlp_remove(phba, ndlp); 2210 lpfc_nlp_put(ndlp);
2199 /* Start discovery */ 2211 /* Start discovery */
2200 lpfc_disc_start(phba); 2212 lpfc_disc_start(phba);
2201 break; 2213 break;
@@ -2373,9 +2385,11 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
2373 mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); 2385 mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
2374 } 2386 }
2375 2387
2388 /* Mailbox took a reference to the node */
2389 lpfc_nlp_put(ndlp);
2376 lpfc_mbuf_free(phba, mp->virt, mp->phys); 2390 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2377 kfree(mp); 2391 kfree(mp);
2378 mempool_free( pmb, phba->mbox_mem_pool); 2392 mempool_free(pmb, phba->mbox_mem_pool);
2379 2393
2380 return; 2394 return;
2381} 2395}
@@ -2460,8 +2474,7 @@ lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order,
2460} 2474}
2461 2475
2462void 2476void
2463lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, 2477lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
2464 uint32_t did)
2465{ 2478{
2466 memset(ndlp, 0, sizeof (struct lpfc_nodelist)); 2479 memset(ndlp, 0, sizeof (struct lpfc_nodelist));
2467 INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); 2480 INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
@@ -2471,5 +2484,29 @@ lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
2471 ndlp->nlp_DID = did; 2484 ndlp->nlp_DID = did;
2472 ndlp->nlp_phba = phba; 2485 ndlp->nlp_phba = phba;
2473 ndlp->nlp_sid = NLP_NO_SID; 2486 ndlp->nlp_sid = NLP_NO_SID;
2487 kref_init(&ndlp->kref);
2474 return; 2488 return;
2475} 2489}
2490
2491void
2492lpfc_nlp_release(struct kref *kref)
2493{
2494 struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
2495 kref);
2496 lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
2497 mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
2498}
2499
2500struct lpfc_nodelist *
2501lpfc_nlp_get(struct lpfc_nodelist *ndlp)
2502{
2503 if (ndlp)
2504 kref_get(&ndlp->kref);
2505 return ndlp;
2506}
2507
2508int
2509lpfc_nlp_put(struct lpfc_nodelist *ndlp)
2510{
2511 return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0;
2512}