diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-01-11 01:53:27 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-23 12:29:24 -0500 |
commit | fa4066b672821d24cb7180b8d0434b01a7043172 (patch) | |
tree | 3a42b4c706b002a165c762f7a613052a0633903e | |
parent | c95d6c6c2b0a303a113fd468efce7430d5b20eac (diff) |
[SCSI] lpfc 8.2.4 : Rework misplaced reference taking on node structure
Rework misplaced reference taking on node structure
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 172 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 37 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 2 |
5 files changed, 157 insertions, 58 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 3759ae1dc5e7..92441ce610ed 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -561,7 +561,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
561 | if (vport->load_flag & FC_UNLOADING) | 561 | if (vport->load_flag & FC_UNLOADING) |
562 | goto out; | 562 | goto out; |
563 | 563 | ||
564 | |||
565 | if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { | 564 | if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { |
566 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 565 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
567 | "0216 Link event during NS query\n"); | 566 | "0216 Link event during NS query\n"); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 8da6e8be9d83..c6b739dc6bc3 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -120,12 +120,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
120 | pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 120 | pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
121 | if (pcmd) | 121 | if (pcmd) |
122 | pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys); | 122 | pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys); |
123 | if (!pcmd || !pcmd->virt) { | 123 | if (!pcmd || !pcmd->virt) |
124 | kfree(pcmd); | 124 | goto els_iocb_free_pcmb_exit; |
125 | |||
126 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
127 | return NULL; | ||
128 | } | ||
129 | 125 | ||
130 | INIT_LIST_HEAD(&pcmd->list); | 126 | INIT_LIST_HEAD(&pcmd->list); |
131 | 127 | ||
@@ -135,13 +131,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
135 | if (prsp) | 131 | if (prsp) |
136 | prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 132 | prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
137 | &prsp->phys); | 133 | &prsp->phys); |
138 | if (!prsp || !prsp->virt) { | 134 | if (!prsp || !prsp->virt) |
139 | kfree(prsp); | 135 | goto els_iocb_free_prsp_exit; |
140 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | ||
141 | kfree(pcmd); | ||
142 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
143 | return NULL; | ||
144 | } | ||
145 | INIT_LIST_HEAD(&prsp->list); | 136 | INIT_LIST_HEAD(&prsp->list); |
146 | } else { | 137 | } else { |
147 | prsp = NULL; | 138 | prsp = NULL; |
@@ -152,15 +143,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
152 | if (pbuflist) | 143 | if (pbuflist) |
153 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 144 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
154 | &pbuflist->phys); | 145 | &pbuflist->phys); |
155 | if (!pbuflist || !pbuflist->virt) { | 146 | if (!pbuflist || !pbuflist->virt) |
156 | lpfc_sli_release_iocbq(phba, elsiocb); | 147 | goto els_iocb_free_pbuf_exit; |
157 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | ||
158 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); | ||
159 | kfree(pcmd); | ||
160 | kfree(prsp); | ||
161 | kfree(pbuflist); | ||
162 | return NULL; | ||
163 | } | ||
164 | 148 | ||
165 | INIT_LIST_HEAD(&pbuflist->list); | 149 | INIT_LIST_HEAD(&pbuflist->list); |
166 | 150 | ||
@@ -205,7 +189,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
205 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 189 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
206 | } | 190 | } |
207 | 191 | ||
192 | /* prevent preparing iocb with NULL ndlp reference */ | ||
208 | elsiocb->context1 = lpfc_nlp_get(ndlp); | 193 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
194 | if (!elsiocb->context1) | ||
195 | goto els_iocb_free_pbuf_exit; | ||
209 | elsiocb->context2 = pcmd; | 196 | elsiocb->context2 = pcmd; |
210 | elsiocb->context3 = pbuflist; | 197 | elsiocb->context3 = pbuflist; |
211 | elsiocb->retry = retry; | 198 | elsiocb->retry = retry; |
@@ -231,8 +218,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
231 | cmdSize); | 218 | cmdSize); |
232 | } | 219 | } |
233 | return elsiocb; | 220 | return elsiocb; |
234 | } | ||
235 | 221 | ||
222 | els_iocb_free_pbuf_exit: | ||
223 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); | ||
224 | kfree(pbuflist); | ||
225 | |||
226 | els_iocb_free_prsp_exit: | ||
227 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | ||
228 | kfree(prsp); | ||
229 | |||
230 | els_iocb_free_pcmb_exit: | ||
231 | kfree(pcmd); | ||
232 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
233 | return NULL; | ||
234 | } | ||
236 | 235 | ||
237 | static int | 236 | static int |
238 | lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) | 237 | lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) |
@@ -513,6 +512,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
513 | 512 | ||
514 | /* Check to see if link went down during discovery */ | 513 | /* Check to see if link went down during discovery */ |
515 | if (lpfc_els_chk_latt(vport)) { | 514 | if (lpfc_els_chk_latt(vport)) { |
515 | /* One additional decrement on node reference count to | ||
516 | * trigger the release of the node | ||
517 | */ | ||
516 | lpfc_nlp_put(ndlp); | 518 | lpfc_nlp_put(ndlp); |
517 | goto out; | 519 | goto out; |
518 | } | 520 | } |
@@ -731,6 +733,9 @@ lpfc_initial_flogi(struct lpfc_vport *vport) | |||
731 | } | 733 | } |
732 | 734 | ||
733 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { | 735 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { |
736 | /* This decrement of reference count to node shall kick off | ||
737 | * the release of the node. | ||
738 | */ | ||
734 | lpfc_nlp_put(ndlp); | 739 | lpfc_nlp_put(ndlp); |
735 | } | 740 | } |
736 | return 1; | 741 | return 1; |
@@ -754,7 +759,11 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) | |||
754 | lpfc_dequeue_node(vport, ndlp); | 759 | lpfc_dequeue_node(vport, ndlp); |
755 | } | 760 | } |
756 | if (lpfc_issue_els_fdisc(vport, ndlp, 0)) { | 761 | if (lpfc_issue_els_fdisc(vport, ndlp, 0)) { |
762 | /* decrement node reference count to trigger the release of | ||
763 | * the node. | ||
764 | */ | ||
757 | lpfc_nlp_put(ndlp); | 765 | lpfc_nlp_put(ndlp); |
766 | return 0; | ||
758 | } | 767 | } |
759 | return 1; | 768 | return 1; |
760 | } | 769 | } |
@@ -1557,6 +1566,9 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1557 | ndlp->nlp_DID, ELS_CMD_SCR); | 1566 | ndlp->nlp_DID, ELS_CMD_SCR); |
1558 | 1567 | ||
1559 | if (!elsiocb) { | 1568 | if (!elsiocb) { |
1569 | /* This will trigger the release of the node just | ||
1570 | * allocated | ||
1571 | */ | ||
1560 | lpfc_nlp_put(ndlp); | 1572 | lpfc_nlp_put(ndlp); |
1561 | return 1; | 1573 | return 1; |
1562 | } | 1574 | } |
@@ -1578,10 +1590,17 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1578 | phba->fc_stat.elsXmitSCR++; | 1590 | phba->fc_stat.elsXmitSCR++; |
1579 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1591 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
1580 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1592 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1593 | /* The additional lpfc_nlp_put will cause the following | ||
1594 | * lpfc_els_free_iocb routine to trigger the rlease of | ||
1595 | * the node. | ||
1596 | */ | ||
1581 | lpfc_nlp_put(ndlp); | 1597 | lpfc_nlp_put(ndlp); |
1582 | lpfc_els_free_iocb(phba, elsiocb); | 1598 | lpfc_els_free_iocb(phba, elsiocb); |
1583 | return 1; | 1599 | return 1; |
1584 | } | 1600 | } |
1601 | /* This will cause the callback-function lpfc_cmpl_els_cmd to | ||
1602 | * trigger the release of node. | ||
1603 | */ | ||
1585 | lpfc_nlp_put(ndlp); | 1604 | lpfc_nlp_put(ndlp); |
1586 | return 0; | 1605 | return 0; |
1587 | } | 1606 | } |
@@ -1613,6 +1632,9 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1613 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | 1632 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1614 | ndlp->nlp_DID, ELS_CMD_RNID); | 1633 | ndlp->nlp_DID, ELS_CMD_RNID); |
1615 | if (!elsiocb) { | 1634 | if (!elsiocb) { |
1635 | /* This will trigger the release of the node just | ||
1636 | * allocated | ||
1637 | */ | ||
1616 | lpfc_nlp_put(ndlp); | 1638 | lpfc_nlp_put(ndlp); |
1617 | return 1; | 1639 | return 1; |
1618 | } | 1640 | } |
@@ -1649,10 +1671,17 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
1649 | phba->fc_stat.elsXmitFARPR++; | 1671 | phba->fc_stat.elsXmitFARPR++; |
1650 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1672 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
1651 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1673 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1674 | /* The additional lpfc_nlp_put will cause the following | ||
1675 | * lpfc_els_free_iocb routine to trigger the release of | ||
1676 | * the node. | ||
1677 | */ | ||
1652 | lpfc_nlp_put(ndlp); | 1678 | lpfc_nlp_put(ndlp); |
1653 | lpfc_els_free_iocb(phba, elsiocb); | 1679 | lpfc_els_free_iocb(phba, elsiocb); |
1654 | return 1; | 1680 | return 1; |
1655 | } | 1681 | } |
1682 | /* This will cause the callback-function lpfc_cmpl_els_cmd to | ||
1683 | * trigger the release of the node. | ||
1684 | */ | ||
1656 | lpfc_nlp_put(ndlp); | 1685 | lpfc_nlp_put(ndlp); |
1657 | return 0; | 1686 | return 0; |
1658 | } | 1687 | } |
@@ -1712,7 +1741,10 @@ lpfc_els_retry_delay(unsigned long ptr) | |||
1712 | return; | 1741 | return; |
1713 | } | 1742 | } |
1714 | 1743 | ||
1715 | evtp->evt_arg1 = ndlp; | 1744 | /* We need to hold the node by incrementing the reference |
1745 | * count until the queued work is done | ||
1746 | */ | ||
1747 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | ||
1716 | evtp->evt = LPFC_EVT_ELS_RETRY; | 1748 | evtp->evt = LPFC_EVT_ELS_RETRY; |
1717 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 1749 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
1718 | if (phba->work_wait) | 1750 | if (phba->work_wait) |
@@ -2190,6 +2222,11 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2190 | * thread, just unregister the RPI. | 2222 | * thread, just unregister the RPI. |
2191 | */ | 2223 | */ |
2192 | lpfc_unreg_rpi(vport, ndlp); | 2224 | lpfc_unreg_rpi(vport, ndlp); |
2225 | } else { | ||
2226 | /* Indicate the node has already released, should | ||
2227 | * not reference to it from within lpfc_els_free_iocb. | ||
2228 | */ | ||
2229 | cmdiocb->context1 = NULL; | ||
2193 | } | 2230 | } |
2194 | } | 2231 | } |
2195 | lpfc_els_free_iocb(phba, cmdiocb); | 2232 | lpfc_els_free_iocb(phba, cmdiocb); |
@@ -2208,7 +2245,6 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2208 | mempool_free(pmb, phba->mbox_mem_pool); | 2245 | mempool_free(pmb, phba->mbox_mem_pool); |
2209 | if (ndlp) { | 2246 | if (ndlp) { |
2210 | lpfc_nlp_put(ndlp); | 2247 | lpfc_nlp_put(ndlp); |
2211 | |||
2212 | /* This is the end of the default RPI cleanup logic for this | 2248 | /* This is the end of the default RPI cleanup logic for this |
2213 | * ndlp. If no other discovery threads are using this ndlp. | 2249 | * ndlp. If no other discovery threads are using this ndlp. |
2214 | * we should free all resources associated with it. | 2250 | * we should free all resources associated with it. |
@@ -2236,11 +2272,13 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2236 | if (cmdiocb->context_un.mbox) | 2272 | if (cmdiocb->context_un.mbox) |
2237 | mbox = cmdiocb->context_un.mbox; | 2273 | mbox = cmdiocb->context_un.mbox; |
2238 | 2274 | ||
2239 | /* First determine if this is a LS_RJT cmpl */ | 2275 | /* First determine if this is a LS_RJT cmpl. Note, this callback |
2276 | * function can have cmdiocb->contest1 (ndlp) field set to NULL. | ||
2277 | */ | ||
2240 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt); | 2278 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt); |
2241 | if (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT) { | 2279 | if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) { |
2242 | /* A LS_RJT associated with Default RPI cleanup | 2280 | /* A LS_RJT associated with Default RPI cleanup has its own |
2243 | * has its own seperate code path. | 2281 | * seperate code path. |
2244 | */ | 2282 | */ |
2245 | if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI)) | 2283 | if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI)) |
2246 | ls_rjt = 1; | 2284 | ls_rjt = 1; |
@@ -2257,8 +2295,14 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2257 | mempool_free(mbox, phba->mbox_mem_pool); | 2295 | mempool_free(mbox, phba->mbox_mem_pool); |
2258 | } | 2296 | } |
2259 | if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI)) | 2297 | if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI)) |
2260 | if (lpfc_nlp_not_used(ndlp)) | 2298 | if (lpfc_nlp_not_used(ndlp)) { |
2261 | ndlp = NULL; | 2299 | ndlp = NULL; |
2300 | /* Indicate the node has already released, | ||
2301 | * should not reference to it from within | ||
2302 | * the routine lpfc_els_free_iocb. | ||
2303 | */ | ||
2304 | cmdiocb->context1 = NULL; | ||
2305 | } | ||
2262 | goto out; | 2306 | goto out; |
2263 | } | 2307 | } |
2264 | 2308 | ||
@@ -2302,14 +2346,27 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2302 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | 2346 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
2303 | ndlp->nlp_rpi); | 2347 | ndlp->nlp_rpi); |
2304 | 2348 | ||
2305 | if (lpfc_nlp_not_used(ndlp)) | 2349 | if (lpfc_nlp_not_used(ndlp)) { |
2306 | ndlp = NULL; | 2350 | ndlp = NULL; |
2351 | /* Indicate node has already been released, | ||
2352 | * should not reference to it from within | ||
2353 | * the routine lpfc_els_free_iocb. | ||
2354 | */ | ||
2355 | cmdiocb->context1 = NULL; | ||
2356 | } | ||
2307 | } else { | 2357 | } else { |
2308 | /* Do not drop node for lpfc_els_abort'ed ELS cmds */ | 2358 | /* Do not drop node for lpfc_els_abort'ed ELS cmds */ |
2309 | if (!lpfc_error_lost_link(irsp) && | 2359 | if (!lpfc_error_lost_link(irsp) && |
2310 | ndlp->nlp_flag & NLP_ACC_REGLOGIN) { | 2360 | ndlp->nlp_flag & NLP_ACC_REGLOGIN) { |
2311 | if (lpfc_nlp_not_used(ndlp)) | 2361 | if (lpfc_nlp_not_used(ndlp)) { |
2312 | ndlp = NULL; | 2362 | ndlp = NULL; |
2363 | /* Indicate node has already been | ||
2364 | * released, should not reference | ||
2365 | * to it from within the routine | ||
2366 | * lpfc_els_free_iocb. | ||
2367 | */ | ||
2368 | cmdiocb->context1 = NULL; | ||
2369 | } | ||
2313 | } | 2370 | } |
2314 | } | 2371 | } |
2315 | mp = (struct lpfc_dmabuf *) mbox->context1; | 2372 | mp = (struct lpfc_dmabuf *) mbox->context1; |
@@ -2331,7 +2388,12 @@ out: | |||
2331 | * resources. | 2388 | * resources. |
2332 | */ | 2389 | */ |
2333 | if (ls_rjt) | 2390 | if (ls_rjt) |
2334 | lpfc_nlp_not_used(ndlp); | 2391 | if (lpfc_nlp_not_used(ndlp)) |
2392 | /* Indicate node has already been released, | ||
2393 | * should not reference to it from within | ||
2394 | * the routine lpfc_els_free_iocb. | ||
2395 | */ | ||
2396 | cmdiocb->context1 = NULL; | ||
2335 | } | 2397 | } |
2336 | 2398 | ||
2337 | lpfc_els_free_iocb(phba, cmdiocb); | 2399 | lpfc_els_free_iocb(phba, cmdiocb); |
@@ -3292,7 +3354,10 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3292 | elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, | 3354 | elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, |
3293 | lpfc_max_els_tries, ndlp, | 3355 | lpfc_max_els_tries, ndlp, |
3294 | ndlp->nlp_DID, ELS_CMD_ACC); | 3356 | ndlp->nlp_DID, ELS_CMD_ACC); |
3357 | |||
3358 | /* Decrement the ndlp reference count from previous mbox command */ | ||
3295 | lpfc_nlp_put(ndlp); | 3359 | lpfc_nlp_put(ndlp); |
3360 | |||
3296 | if (!elsiocb) | 3361 | if (!elsiocb) |
3297 | return; | 3362 | return; |
3298 | 3363 | ||
@@ -3375,11 +3440,13 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3375 | mbox->context2 = lpfc_nlp_get(ndlp); | 3440 | mbox->context2 = lpfc_nlp_get(ndlp); |
3376 | mbox->vport = vport; | 3441 | mbox->vport = vport; |
3377 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; | 3442 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; |
3378 | if (lpfc_sli_issue_mbox (phba, mbox, MBX_NOWAIT) | 3443 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
3379 | != MBX_NOT_FINISHED) | 3444 | != MBX_NOT_FINISHED) |
3380 | /* Mbox completion will send ELS Response */ | 3445 | /* Mbox completion will send ELS Response */ |
3381 | return 0; | 3446 | return 0; |
3382 | 3447 | /* Decrement reference count used for the failed mbox | |
3448 | * command. | ||
3449 | */ | ||
3383 | lpfc_nlp_put(ndlp); | 3450 | lpfc_nlp_put(ndlp); |
3384 | mempool_free(mbox, phba->mbox_mem_pool); | 3451 | mempool_free(mbox, phba->mbox_mem_pool); |
3385 | } | 3452 | } |
@@ -4284,7 +4351,6 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
4284 | spin_lock_irq(shost->host_lock); | 4351 | spin_lock_irq(shost->host_lock); |
4285 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | 4352 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
4286 | spin_unlock_irq(shost->host_lock); | 4353 | spin_unlock_irq(shost->host_lock); |
4287 | lpfc_nlp_put(ndlp); | ||
4288 | 4354 | ||
4289 | if (mb->mbxStatus) { | 4355 | if (mb->mbxStatus) { |
4290 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 4356 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
@@ -4317,6 +4383,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
4317 | else | 4383 | else |
4318 | lpfc_do_scr_ns_plogi(phba, vport); | 4384 | lpfc_do_scr_ns_plogi(phba, vport); |
4319 | } | 4385 | } |
4386 | |||
4387 | /* Now, we decrement the ndlp reference count held for this | ||
4388 | * callback function | ||
4389 | */ | ||
4390 | lpfc_nlp_put(ndlp); | ||
4391 | |||
4320 | mempool_free(pmb, phba->mbox_mem_pool); | 4392 | mempool_free(pmb, phba->mbox_mem_pool); |
4321 | return; | 4393 | return; |
4322 | } | 4394 | } |
@@ -4336,26 +4408,29 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, | |||
4336 | mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; | 4408 | mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; |
4337 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) | 4409 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
4338 | == MBX_NOT_FINISHED) { | 4410 | == MBX_NOT_FINISHED) { |
4411 | /* mailbox command not success, decrement ndlp | ||
4412 | * reference count for this command | ||
4413 | */ | ||
4414 | lpfc_nlp_put(ndlp); | ||
4339 | mempool_free(mbox, phba->mbox_mem_pool); | 4415 | mempool_free(mbox, phba->mbox_mem_pool); |
4340 | spin_lock_irq(shost->host_lock); | ||
4341 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | ||
4342 | spin_unlock_irq(shost->host_lock); | ||
4343 | 4416 | ||
4344 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
4345 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 4417 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
4346 | "0253 Register VPI: Can't send mbox\n"); | 4418 | "0253 Register VPI: Can't send mbox\n"); |
4419 | goto mbox_err_exit; | ||
4347 | } | 4420 | } |
4348 | } else { | 4421 | } else { |
4349 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
4350 | |||
4351 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 4422 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
4352 | "0254 Register VPI: no memory\n"); | 4423 | "0254 Register VPI: no memory\n"); |
4353 | 4424 | goto mbox_err_exit; | |
4354 | spin_lock_irq(shost->host_lock); | ||
4355 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | ||
4356 | spin_unlock_irq(shost->host_lock); | ||
4357 | lpfc_nlp_put(ndlp); | ||
4358 | } | 4425 | } |
4426 | return; | ||
4427 | |||
4428 | mbox_err_exit: | ||
4429 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
4430 | spin_lock_irq(shost->host_lock); | ||
4431 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | ||
4432 | spin_unlock_irq(shost->host_lock); | ||
4433 | return; | ||
4359 | } | 4434 | } |
4360 | 4435 | ||
4361 | static void | 4436 | static void |
@@ -4436,7 +4511,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4436 | else | 4511 | else |
4437 | lpfc_do_scr_ns_plogi(phba, vport); | 4512 | lpfc_do_scr_ns_plogi(phba, vport); |
4438 | 4513 | ||
4439 | lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */ | 4514 | /* Unconditionaly kick off releasing fabric node for vports */ |
4515 | lpfc_nlp_put(ndlp); | ||
4440 | } | 4516 | } |
4441 | 4517 | ||
4442 | out: | 4518 | out: |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 644d96012d56..dc042bd97baa 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -149,7 +149,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
149 | return; | 149 | return; |
150 | 150 | ||
151 | spin_lock_irq(&phba->hbalock); | 151 | spin_lock_irq(&phba->hbalock); |
152 | evtp->evt_arg1 = ndlp; | 152 | /* We need to hold the node by incrementing the reference |
153 | * count until this queued work is done | ||
154 | */ | ||
155 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | ||
153 | evtp->evt = LPFC_EVT_DEV_LOSS; | 156 | evtp->evt = LPFC_EVT_DEV_LOSS; |
154 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 157 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
155 | if (phba->work_wait) | 158 | if (phba->work_wait) |
@@ -300,12 +303,18 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
300 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | 303 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); |
301 | lpfc_els_retry_delay_handler(ndlp); | 304 | lpfc_els_retry_delay_handler(ndlp); |
302 | free_evt = 0; /* evt is part of ndlp */ | 305 | free_evt = 0; /* evt is part of ndlp */ |
306 | /* decrement the node reference count held | ||
307 | * for this queued work | ||
308 | */ | ||
309 | lpfc_nlp_put(ndlp); | ||
303 | break; | 310 | break; |
304 | case LPFC_EVT_DEV_LOSS: | 311 | case LPFC_EVT_DEV_LOSS: |
305 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); | 312 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); |
306 | lpfc_nlp_get(ndlp); | ||
307 | lpfc_dev_loss_tmo_handler(ndlp); | 313 | lpfc_dev_loss_tmo_handler(ndlp); |
308 | free_evt = 0; | 314 | free_evt = 0; |
315 | /* decrement the node reference count held for | ||
316 | * this queued work | ||
317 | */ | ||
309 | lpfc_nlp_put(ndlp); | 318 | lpfc_nlp_put(ndlp); |
310 | break; | 319 | break; |
311 | case LPFC_EVT_ONLINE: | 320 | case LPFC_EVT_ONLINE: |
@@ -1176,6 +1185,9 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1176 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1185 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1177 | kfree(mp); | 1186 | kfree(mp); |
1178 | mempool_free(pmb, phba->mbox_mem_pool); | 1187 | mempool_free(pmb, phba->mbox_mem_pool); |
1188 | /* decrement the node reference count held for this callback | ||
1189 | * function. | ||
1190 | */ | ||
1179 | lpfc_nlp_put(ndlp); | 1191 | lpfc_nlp_put(ndlp); |
1180 | 1192 | ||
1181 | return; | 1193 | return; |
@@ -1363,6 +1375,9 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1363 | 1375 | ||
1364 | if (mb->mbxStatus) { | 1376 | if (mb->mbxStatus) { |
1365 | out: | 1377 | out: |
1378 | /* decrement the node reference count held for this | ||
1379 | * callback function. | ||
1380 | */ | ||
1366 | lpfc_nlp_put(ndlp); | 1381 | lpfc_nlp_put(ndlp); |
1367 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1382 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1368 | kfree(mp); | 1383 | kfree(mp); |
@@ -1414,6 +1429,9 @@ out: | |||
1414 | goto out; | 1429 | goto out; |
1415 | } | 1430 | } |
1416 | 1431 | ||
1432 | /* decrement the node reference count held for this | ||
1433 | * callback function. | ||
1434 | */ | ||
1417 | lpfc_nlp_put(ndlp); | 1435 | lpfc_nlp_put(ndlp); |
1418 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1436 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1419 | kfree(mp); | 1437 | kfree(mp); |
@@ -1661,13 +1679,14 @@ void | |||
1661 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1679 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1662 | { | 1680 | { |
1663 | /* | 1681 | /* |
1664 | * Use of lpfc_drop_node and UNUSED list. lpfc_drop_node should | 1682 | * Use of lpfc_drop_node and UNUSED list: lpfc_drop_node should |
1665 | * be used if we wish to issue the "last" lpfc_nlp_put() to remove | 1683 | * be used if we wish to issue the "last" lpfc_nlp_put() to remove |
1666 | * the ndlp from the vport. The ndlp resides on the UNUSED list | 1684 | * the ndlp from the vport. The ndlp marked as UNUSED on the list |
1667 | * until ALL other outstanding threads have completed. Thus, if a | 1685 | * until ALL other outstanding threads have completed. We check |
1668 | * ndlp is on the UNUSED list already, we should never do another | 1686 | * that the ndlp not already in the UNUSED state before we proceed. |
1669 | * lpfc_drop_node() on it. | ||
1670 | */ | 1687 | */ |
1688 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
1689 | return; | ||
1671 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1690 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1672 | lpfc_nlp_put(ndlp); | 1691 | lpfc_nlp_put(ndlp); |
1673 | return; | 1692 | return; |
@@ -2767,7 +2786,9 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2767 | else | 2786 | else |
2768 | mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60); | 2787 | mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60); |
2769 | 2788 | ||
2770 | /* Mailbox took a reference to the node */ | 2789 | /* decrement the node reference count held for this callback |
2790 | * function. | ||
2791 | */ | ||
2771 | lpfc_nlp_put(ndlp); | 2792 | lpfc_nlp_put(ndlp); |
2772 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2793 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
2773 | kfree(mp); | 2794 | kfree(mp); |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 783659aa2102..4a0e3406e37a 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -922,6 +922,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, | |||
922 | NLP_STE_REG_LOGIN_ISSUE); | 922 | NLP_STE_REG_LOGIN_ISSUE); |
923 | return ndlp->nlp_state; | 923 | return ndlp->nlp_state; |
924 | } | 924 | } |
925 | /* decrement node reference count to the failed mbox | ||
926 | * command | ||
927 | */ | ||
925 | lpfc_nlp_put(ndlp); | 928 | lpfc_nlp_put(ndlp); |
926 | mp = (struct lpfc_dmabuf *) mbox->context1; | 929 | mp = (struct lpfc_dmabuf *) mbox->context1; |
927 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 930 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 584c5451641f..fdd01e384e36 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -2605,7 +2605,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
2605 | "1806 Mbox x%x failed. No vport\n", | 2605 | "1806 Mbox x%x failed. No vport\n", |
2606 | pmbox->mb.mbxCommand); | 2606 | pmbox->mb.mbxCommand); |
2607 | dump_stack(); | 2607 | dump_stack(); |
2608 | return MBXERR_ERROR; | 2608 | return MBX_NOT_FINISHED; |
2609 | } | 2609 | } |
2610 | } | 2610 | } |
2611 | 2611 | ||