diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:53:01 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:15 -0400 |
commit | 329f9bc735b4665d42267259b1612191f72c4d42 (patch) | |
tree | b696a632e19afa0d0e42012efd7992690f69e1a1 /drivers/scsi/lpfc | |
parent | 2680eeaaa03e83a87ece2724e71f7cc816cd3ef0 (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')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 107 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 107 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 15 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 23 |
6 files changed, 149 insertions, 109 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b80ddb80030c..f61d46fce116 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -51,8 +51,9 @@ int lpfc_can_disctmo(struct lpfc_hba *); | |||
51 | int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *); | 51 | int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *); |
52 | int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, | 52 | int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, |
53 | struct lpfc_iocbq *, struct lpfc_nodelist *); | 53 | struct lpfc_iocbq *, struct lpfc_nodelist *); |
54 | int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *); | ||
55 | void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t); | 54 | void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t); |
55 | struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); | ||
56 | int lpfc_nlp_put(struct lpfc_nodelist *); | ||
56 | struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t); | 57 | struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t); |
57 | void lpfc_disc_list_loopmap(struct lpfc_hba *); | 58 | void lpfc_disc_list_loopmap(struct lpfc_hba *); |
58 | void lpfc_disc_start(struct lpfc_hba *); | 59 | void lpfc_disc_start(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 30b2ba0b06f7..4561327c9946 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -69,7 +69,6 @@ struct lpfc_nodelist { | |||
69 | uint16_t nlp_maxframe; /* Max RCV frame size */ | 69 | uint16_t nlp_maxframe; /* Max RCV frame size */ |
70 | uint8_t nlp_class_sup; /* Supported Classes */ | 70 | uint8_t nlp_class_sup; /* Supported Classes */ |
71 | uint8_t nlp_retry; /* used for ELS retries */ | 71 | uint8_t nlp_retry; /* used for ELS retries */ |
72 | uint8_t nlp_disc_refcnt; /* used for DSM */ | ||
73 | uint8_t nlp_fcp_info; /* class info, bits 0-3 */ | 72 | uint8_t nlp_fcp_info; /* class info, bits 0-3 */ |
74 | #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ | 73 | #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ |
75 | 74 | ||
@@ -80,6 +79,7 @@ struct lpfc_nodelist { | |||
80 | struct lpfc_work_evt els_retry_evt; | 79 | struct lpfc_work_evt els_retry_evt; |
81 | unsigned long last_ramp_up_time; /* jiffy of last ramp up */ | 80 | unsigned long last_ramp_up_time; /* jiffy of last ramp up */ |
82 | unsigned long last_q_full_time; /* jiffy of last queue full */ | 81 | unsigned long last_q_full_time; /* jiffy of last queue full */ |
82 | struct kref kref; | ||
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* Defines for nlp_flag (uint32) */ | 85 | /* Defines for nlp_flag (uint32) */ |
@@ -107,7 +107,6 @@ struct lpfc_nodelist { | |||
107 | ACC */ | 107 | ACC */ |
108 | #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from | 108 | #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from |
109 | NPR list */ | 109 | NPR list */ |
110 | #define NLP_DELAY_REMOVE 0x4000000 /* Defer removal till end of DSM */ | ||
111 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 110 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ |
112 | 111 | ||
113 | /* Defines for list searchs */ | 112 | /* Defines for list searchs */ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 14d204ba8a39..cb63c350c215 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -209,9 +209,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
209 | } | 209 | } |
210 | 210 | ||
211 | /* Save for completion so we can release these resources */ | 211 | /* Save for completion so we can release these resources */ |
212 | elsiocb->context1 = (uint8_t *) ndlp; | 212 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
213 | elsiocb->context2 = (uint8_t *) pcmd; | 213 | elsiocb->context2 = pcmd; |
214 | elsiocb->context3 = (uint8_t *) pbuflist; | 214 | elsiocb->context3 = pbuflist; |
215 | elsiocb->retry = retry; | 215 | elsiocb->retry = retry; |
216 | elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; | 216 | elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; |
217 | 217 | ||
@@ -305,7 +305,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
305 | goto fail_free_mbox; | 305 | goto fail_free_mbox; |
306 | 306 | ||
307 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; | 307 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; |
308 | mbox->context2 = ndlp; | 308 | mbox->context2 = lpfc_nlp_get(ndlp); |
309 | 309 | ||
310 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); | 310 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); |
311 | if (rc == MBX_NOT_FINISHED) | 311 | if (rc == MBX_NOT_FINISHED) |
@@ -314,6 +314,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
314 | return 0; | 314 | return 0; |
315 | 315 | ||
316 | fail_issue_reg_login: | 316 | fail_issue_reg_login: |
317 | lpfc_nlp_put(ndlp); | ||
317 | mp = (struct lpfc_dmabuf *) mbox->context1; | 318 | mp = (struct lpfc_dmabuf *) mbox->context1; |
318 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 319 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
319 | kfree(mp); | 320 | kfree(mp); |
@@ -369,7 +370,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
369 | mempool_free(mbox, phba->mbox_mem_pool); | 370 | mempool_free(mbox, phba->mbox_mem_pool); |
370 | goto fail; | 371 | goto fail; |
371 | } | 372 | } |
372 | mempool_free(ndlp, phba->nlp_mem_pool); | 373 | lpfc_nlp_put(ndlp); |
373 | 374 | ||
374 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID); | 375 | ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID); |
375 | if (!ndlp) { | 376 | if (!ndlp) { |
@@ -392,7 +393,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
392 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 393 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
393 | } else { | 394 | } else { |
394 | /* This side will wait for the PLOGI */ | 395 | /* This side will wait for the PLOGI */ |
395 | mempool_free( ndlp, phba->nlp_mem_pool); | 396 | lpfc_nlp_put(ndlp); |
396 | } | 397 | } |
397 | 398 | ||
398 | spin_lock_irq(phba->host->host_lock); | 399 | spin_lock_irq(phba->host->host_lock); |
@@ -407,8 +408,8 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
407 | } | 408 | } |
408 | 409 | ||
409 | static void | 410 | static void |
410 | lpfc_cmpl_els_flogi(struct lpfc_hba * phba, | 411 | lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
411 | struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb) | 412 | struct lpfc_iocbq *rspiocb) |
412 | { | 413 | { |
413 | IOCB_t *irsp = &rspiocb->iocb; | 414 | IOCB_t *irsp = &rspiocb->iocb; |
414 | struct lpfc_nodelist *ndlp = cmdiocb->context1; | 415 | struct lpfc_nodelist *ndlp = cmdiocb->context1; |
@@ -418,7 +419,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba, | |||
418 | 419 | ||
419 | /* Check to see if link went down during discovery */ | 420 | /* Check to see if link went down during discovery */ |
420 | if (lpfc_els_chk_latt(phba)) { | 421 | if (lpfc_els_chk_latt(phba)) { |
421 | lpfc_nlp_remove(phba, ndlp); | 422 | lpfc_nlp_put(ndlp); |
422 | goto out; | 423 | goto out; |
423 | } | 424 | } |
424 | 425 | ||
@@ -433,13 +434,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba, | |||
433 | phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 434 | phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
434 | spin_unlock_irq(phba->host->host_lock); | 435 | spin_unlock_irq(phba->host->host_lock); |
435 | 436 | ||
436 | /* If private loop, then allow max outstandting els to be | 437 | /* If private loop, then allow max outstanding els to be |
437 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no | 438 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no |
438 | * alpa map would take too long otherwise. | 439 | * alpa map would take too long otherwise. |
439 | */ | 440 | */ |
440 | if (phba->alpa_map[0] == 0) { | 441 | if (phba->alpa_map[0] == 0) { |
441 | phba->cfg_discovery_threads = | 442 | phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; |
442 | LPFC_MAX_DISC_THREADS; | ||
443 | } | 443 | } |
444 | 444 | ||
445 | /* FLOGI failure */ | 445 | /* FLOGI failure */ |
@@ -484,7 +484,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba, | |||
484 | } | 484 | } |
485 | 485 | ||
486 | flogifail: | 486 | flogifail: |
487 | lpfc_nlp_remove(phba, ndlp); | 487 | lpfc_nlp_put(ndlp); |
488 | 488 | ||
489 | if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || | 489 | if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || |
490 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && | 490 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && |
@@ -608,7 +608,7 @@ lpfc_initial_flogi(struct lpfc_hba * phba) | |||
608 | lpfc_dequeue_node(phba, ndlp); | 608 | lpfc_dequeue_node(phba, ndlp); |
609 | } | 609 | } |
610 | if (lpfc_issue_els_flogi(phba, ndlp, 0)) { | 610 | if (lpfc_issue_els_flogi(phba, ndlp, 0)) { |
611 | mempool_free( ndlp, phba->nlp_mem_pool); | 611 | lpfc_nlp_put(ndlp); |
612 | } | 612 | } |
613 | return 1; | 613 | return 1; |
614 | } | 614 | } |
@@ -1334,7 +1334,7 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1334 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 1334 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1335 | ndlp->nlp_DID, ELS_CMD_SCR); | 1335 | ndlp->nlp_DID, ELS_CMD_SCR); |
1336 | if (!elsiocb) { | 1336 | if (!elsiocb) { |
1337 | mempool_free( ndlp, phba->nlp_mem_pool); | 1337 | lpfc_nlp_put(ndlp); |
1338 | return 1; | 1338 | return 1; |
1339 | } | 1339 | } |
1340 | 1340 | ||
@@ -1353,12 +1353,12 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1353 | spin_lock_irq(phba->host->host_lock); | 1353 | spin_lock_irq(phba->host->host_lock); |
1354 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1354 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1355 | spin_unlock_irq(phba->host->host_lock); | 1355 | spin_unlock_irq(phba->host->host_lock); |
1356 | mempool_free( ndlp, phba->nlp_mem_pool); | 1356 | lpfc_nlp_put(ndlp); |
1357 | lpfc_els_free_iocb(phba, elsiocb); | 1357 | lpfc_els_free_iocb(phba, elsiocb); |
1358 | return 1; | 1358 | return 1; |
1359 | } | 1359 | } |
1360 | spin_unlock_irq(phba->host->host_lock); | 1360 | spin_unlock_irq(phba->host->host_lock); |
1361 | mempool_free( ndlp, phba->nlp_mem_pool); | 1361 | lpfc_nlp_put(ndlp); |
1362 | return 0; | 1362 | return 0; |
1363 | } | 1363 | } |
1364 | 1364 | ||
@@ -1387,7 +1387,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1387 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 1387 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, |
1388 | ndlp->nlp_DID, ELS_CMD_RNID); | 1388 | ndlp->nlp_DID, ELS_CMD_RNID); |
1389 | if (!elsiocb) { | 1389 | if (!elsiocb) { |
1390 | mempool_free( ndlp, phba->nlp_mem_pool); | 1390 | lpfc_nlp_put(ndlp); |
1391 | return 1; | 1391 | return 1; |
1392 | } | 1392 | } |
1393 | 1393 | ||
@@ -1420,12 +1420,12 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1420 | spin_lock_irq(phba->host->host_lock); | 1420 | spin_lock_irq(phba->host->host_lock); |
1421 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1421 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1422 | spin_unlock_irq(phba->host->host_lock); | 1422 | spin_unlock_irq(phba->host->host_lock); |
1423 | mempool_free( ndlp, phba->nlp_mem_pool); | 1423 | lpfc_nlp_put(ndlp); |
1424 | lpfc_els_free_iocb(phba, elsiocb); | 1424 | lpfc_els_free_iocb(phba, elsiocb); |
1425 | return 1; | 1425 | return 1; |
1426 | } | 1426 | } |
1427 | spin_unlock_irq(phba->host->host_lock); | 1427 | spin_unlock_irq(phba->host->host_lock); |
1428 | mempool_free( ndlp, phba->nlp_mem_pool); | 1428 | lpfc_nlp_put(ndlp); |
1429 | return 0; | 1429 | return 0; |
1430 | } | 1430 | } |
1431 | 1431 | ||
@@ -1590,7 +1590,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1590 | cmd = *elscmd++; | 1590 | cmd = *elscmd++; |
1591 | } | 1591 | } |
1592 | 1592 | ||
1593 | if(ndlp) | 1593 | if (ndlp) |
1594 | did = ndlp->nlp_DID; | 1594 | did = ndlp->nlp_DID; |
1595 | else { | 1595 | else { |
1596 | /* We should only hit this case for retrying PLOGI */ | 1596 | /* We should only hit this case for retrying PLOGI */ |
@@ -1768,10 +1768,14 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1768 | } | 1768 | } |
1769 | 1769 | ||
1770 | int | 1770 | int |
1771 | lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb) | 1771 | lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) |
1772 | { | 1772 | { |
1773 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; | 1773 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; |
1774 | 1774 | ||
1775 | if (elsiocb->context1) { | ||
1776 | lpfc_nlp_put(elsiocb->context1); | ||
1777 | elsiocb->context1 = NULL; | ||
1778 | } | ||
1775 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ | 1779 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ |
1776 | if (elsiocb->context2) { | 1780 | if (elsiocb->context2) { |
1777 | buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; | 1781 | buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; |
@@ -1828,8 +1832,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1828 | } | 1832 | } |
1829 | 1833 | ||
1830 | static void | 1834 | static void |
1831 | lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1835 | lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1832 | struct lpfc_iocbq * rspiocb) | 1836 | struct lpfc_iocbq *rspiocb) |
1833 | { | 1837 | { |
1834 | IOCB_t *irsp; | 1838 | IOCB_t *irsp; |
1835 | struct lpfc_nodelist *ndlp; | 1839 | struct lpfc_nodelist *ndlp; |
@@ -1844,14 +1848,14 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1844 | 1848 | ||
1845 | 1849 | ||
1846 | /* Check to see if link went down during discovery */ | 1850 | /* Check to see if link went down during discovery */ |
1847 | if ((lpfc_els_chk_latt(phba)) || !ndlp) { | 1851 | if (lpfc_els_chk_latt(phba) || !ndlp) { |
1848 | if (mbox) { | 1852 | if (mbox) { |
1849 | mp = (struct lpfc_dmabuf *) mbox->context1; | 1853 | mp = (struct lpfc_dmabuf *) mbox->context1; |
1850 | if (mp) { | 1854 | if (mp) { |
1851 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1855 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1852 | kfree(mp); | 1856 | kfree(mp); |
1853 | } | 1857 | } |
1854 | mempool_free( mbox, phba->mbox_mem_pool); | 1858 | mempool_free(mbox, phba->mbox_mem_pool); |
1855 | } | 1859 | } |
1856 | goto out; | 1860 | goto out; |
1857 | } | 1861 | } |
@@ -1871,7 +1875,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1871 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { | 1875 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { |
1872 | lpfc_unreg_rpi(phba, ndlp); | 1876 | lpfc_unreg_rpi(phba, ndlp); |
1873 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 1877 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
1874 | mbox->context2 = ndlp; | 1878 | mbox->context2 = lpfc_nlp_get(ndlp); |
1875 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1879 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1876 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); | 1880 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); |
1877 | if (lpfc_sli_issue_mbox(phba, mbox, | 1881 | if (lpfc_sli_issue_mbox(phba, mbox, |
@@ -1879,6 +1883,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1879 | != MBX_NOT_FINISHED) { | 1883 | != MBX_NOT_FINISHED) { |
1880 | goto out; | 1884 | goto out; |
1881 | } | 1885 | } |
1886 | lpfc_nlp_put(ndlp); | ||
1882 | /* NOTE: we should have messages for unsuccessful | 1887 | /* NOTE: we should have messages for unsuccessful |
1883 | reglogin */ | 1888 | reglogin */ |
1884 | } else { | 1889 | } else { |
@@ -1983,8 +1988,10 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1983 | return 1; | 1988 | return 1; |
1984 | } | 1989 | } |
1985 | 1990 | ||
1986 | if (newnode) | 1991 | if (newnode) { |
1992 | lpfc_nlp_put(ndlp); | ||
1987 | elsiocb->context1 = NULL; | 1993 | elsiocb->context1 = NULL; |
1994 | } | ||
1988 | 1995 | ||
1989 | /* Xmit ELS ACC response tag <ulpIoTag> */ | 1996 | /* Xmit ELS ACC response tag <ulpIoTag> */ |
1990 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1997 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -2201,9 +2208,8 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, | |||
2201 | } | 2208 | } |
2202 | 2209 | ||
2203 | static int | 2210 | static int |
2204 | lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, | 2211 | lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, |
2205 | uint8_t format, | 2212 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) |
2206 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | ||
2207 | { | 2213 | { |
2208 | RNID *rn; | 2214 | RNID *rn; |
2209 | IOCB_t *icmd; | 2215 | IOCB_t *icmd; |
@@ -2270,6 +2276,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, | |||
2270 | 2276 | ||
2271 | phba->fc_stat.elsXmitACC++; | 2277 | phba->fc_stat.elsXmitACC++; |
2272 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2278 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2279 | lpfc_nlp_put(ndlp); | ||
2273 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, | 2280 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, |
2274 | * it could be freed */ | 2281 | * it could be freed */ |
2275 | 2282 | ||
@@ -2447,7 +2454,7 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | |||
2447 | } | 2454 | } |
2448 | 2455 | ||
2449 | static int | 2456 | static int |
2450 | lpfc_rscn_recovery_check(struct lpfc_hba * phba) | 2457 | lpfc_rscn_recovery_check(struct lpfc_hba *phba) |
2451 | { | 2458 | { |
2452 | struct lpfc_nodelist *ndlp = NULL, *next_ndlp; | 2459 | struct lpfc_nodelist *ndlp = NULL, *next_ndlp; |
2453 | struct list_head *listp; | 2460 | struct list_head *listp; |
@@ -2703,7 +2710,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2703 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); | 2710 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); |
2704 | lpfc_set_loopback_flag(phba); | 2711 | lpfc_set_loopback_flag(phba); |
2705 | if (rc == MBX_NOT_FINISHED) { | 2712 | if (rc == MBX_NOT_FINISHED) { |
2706 | mempool_free( mbox, phba->mbox_mem_pool); | 2713 | mempool_free(mbox, phba->mbox_mem_pool); |
2707 | } | 2714 | } |
2708 | return 1; | 2715 | return 1; |
2709 | } else if (rc > 0) { /* greater than */ | 2716 | } else if (rc > 0) { /* greater than */ |
@@ -2768,8 +2775,8 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, | |||
2768 | } | 2775 | } |
2769 | 2776 | ||
2770 | static int | 2777 | static int |
2771 | lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2778 | lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
2772 | struct lpfc_nodelist * ndlp) | 2779 | struct lpfc_nodelist *ndlp) |
2773 | { | 2780 | { |
2774 | struct ls_rjt stat; | 2781 | struct ls_rjt stat; |
2775 | 2782 | ||
@@ -2783,7 +2790,7 @@ lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2783 | } | 2790 | } |
2784 | 2791 | ||
2785 | static void | 2792 | static void |
2786 | lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | 2793 | lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
2787 | { | 2794 | { |
2788 | struct lpfc_sli *psli; | 2795 | struct lpfc_sli *psli; |
2789 | struct lpfc_sli_ring *pring; | 2796 | struct lpfc_sli_ring *pring; |
@@ -2806,14 +2813,15 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
2806 | pmb->context2 = NULL; | 2813 | pmb->context2 = NULL; |
2807 | 2814 | ||
2808 | if (mb->mbxStatus) { | 2815 | if (mb->mbxStatus) { |
2809 | mempool_free( pmb, phba->mbox_mem_pool); | 2816 | mempool_free(pmb, phba->mbox_mem_pool); |
2810 | return; | 2817 | return; |
2811 | } | 2818 | } |
2812 | 2819 | ||
2813 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); | 2820 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); |
2814 | mempool_free( pmb, phba->mbox_mem_pool); | 2821 | mempool_free(pmb, phba->mbox_mem_pool); |
2815 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, | 2822 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, |
2816 | ndlp->nlp_DID, ELS_CMD_ACC); | 2823 | ndlp->nlp_DID, ELS_CMD_ACC); |
2824 | lpfc_nlp_put(ndlp); | ||
2817 | if (!elsiocb) | 2825 | if (!elsiocb) |
2818 | return; | 2826 | return; |
2819 | 2827 | ||
@@ -2890,13 +2898,14 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2890 | lpfc_read_lnk_stat(phba, mbox); | 2898 | lpfc_read_lnk_stat(phba, mbox); |
2891 | mbox->context1 = | 2899 | mbox->context1 = |
2892 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); | 2900 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); |
2893 | mbox->context2 = ndlp; | 2901 | mbox->context2 = lpfc_nlp_get(ndlp); |
2894 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; | 2902 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; |
2895 | if (lpfc_sli_issue_mbox (phba, mbox, | 2903 | if (lpfc_sli_issue_mbox (phba, mbox, |
2896 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { | 2904 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { |
2897 | /* Mbox completion will send ELS Response */ | 2905 | /* Mbox completion will send ELS Response */ |
2898 | return 0; | 2906 | return 0; |
2899 | } | 2907 | } |
2908 | lpfc_nlp_put(ndlp); | ||
2900 | mempool_free(mbox, phba->mbox_mem_pool); | 2909 | mempool_free(mbox, phba->mbox_mem_pool); |
2901 | } | 2910 | } |
2902 | } | 2911 | } |
@@ -3281,14 +3290,13 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3281 | } | 3290 | } |
3282 | 3291 | ||
3283 | void | 3292 | void |
3284 | lpfc_els_flush_cmd(struct lpfc_hba * phba) | 3293 | lpfc_els_flush_cmd(struct lpfc_hba *phba) |
3285 | { | 3294 | { |
3286 | LIST_HEAD(completions); | 3295 | LIST_HEAD(completions); |
3287 | struct lpfc_sli_ring *pring; | 3296 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
3288 | struct lpfc_iocbq *tmp_iocb, *piocb; | 3297 | struct lpfc_iocbq *tmp_iocb, *piocb; |
3289 | IOCB_t *cmd = NULL; | 3298 | IOCB_t *cmd = NULL; |
3290 | 3299 | ||
3291 | pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
3292 | spin_lock_irq(phba->host->host_lock); | 3300 | spin_lock_irq(phba->host->host_lock); |
3293 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { | 3301 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { |
3294 | cmd = &piocb->iocb; | 3302 | cmd = &piocb->iocb; |
@@ -3298,12 +3306,11 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3298 | } | 3306 | } |
3299 | 3307 | ||
3300 | /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ | 3308 | /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ |
3301 | if ((cmd->ulpCommand == CMD_QUE_RING_BUF_CN) || | 3309 | if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || |
3302 | (cmd->ulpCommand == CMD_QUE_RING_BUF64_CN) || | 3310 | cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || |
3303 | (cmd->ulpCommand == CMD_CLOSE_XRI_CN) || | 3311 | cmd->ulpCommand == CMD_CLOSE_XRI_CN || |
3304 | (cmd->ulpCommand == CMD_ABORT_XRI_CN)) { | 3312 | cmd->ulpCommand == CMD_ABORT_XRI_CN) |
3305 | continue; | 3313 | continue; |
3306 | } | ||
3307 | 3314 | ||
3308 | list_move_tail(&piocb->list, &completions); | 3315 | list_move_tail(&piocb->list, &completions); |
3309 | pring->txq_cnt--; | 3316 | pring->txq_cnt--; |
@@ -3422,7 +3429,9 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3422 | } | 3429 | } |
3423 | 3430 | ||
3424 | phba->fc_stat.elsRcvFrame++; | 3431 | phba->fc_stat.elsRcvFrame++; |
3425 | elsiocb->context1 = ndlp; | 3432 | if (elsiocb->context1) |
3433 | lpfc_nlp_put(elsiocb->context1); | ||
3434 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
3426 | elsiocb->context2 = mp; | 3435 | elsiocb->context2 = mp; |
3427 | 3436 | ||
3428 | if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { | 3437 | if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { |
@@ -3553,6 +3562,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3553 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp); | 3562 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp); |
3554 | } | 3563 | } |
3555 | 3564 | ||
3565 | lpfc_nlp_put(elsiocb->context1); | ||
3566 | elsiocb->context1 = NULL; | ||
3556 | if (elsiocb->context2) { | 3567 | if (elsiocb->context2) { |
3557 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 3568 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
3558 | kfree(mp); | 3569 | kfree(mp); |
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 | ||
1120 | static void | 1128 | static void |
1121 | lpfc_register_remote_port(struct lpfc_hba * phba, | 1129 | lpfc_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 | ||
1164 | static void | 1182 | static void |
1165 | lpfc_unregister_remote_port(struct lpfc_hba * phba, | 1183 | lpfc_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 | */ |
1682 | int | 1702 | static void |
1683 | lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1703 | lpfc_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 | ||
1709 | static int | 1721 | static 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 | ||
2462 | void | 2476 | void |
2463 | lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 2477 | lpfc_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 | |||
2491 | void | ||
2492 | lpfc_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 | |||
2500 | struct lpfc_nodelist * | ||
2501 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) | ||
2502 | { | ||
2503 | if (ndlp) | ||
2504 | kref_get(&ndlp->kref); | ||
2505 | return ndlp; | ||
2506 | } | ||
2507 | |||
2508 | int | ||
2509 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) | ||
2510 | { | ||
2511 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; | ||
2512 | } | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4df0a77ab12e..388b92a39589 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1187,12 +1187,12 @@ lpfc_cleanup(struct lpfc_hba * phba) | |||
1187 | lpfc_can_disctmo(phba); | 1187 | lpfc_can_disctmo(phba); |
1188 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, | 1188 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, |
1189 | nlp_listp) { | 1189 | nlp_listp) { |
1190 | lpfc_nlp_remove(phba, ndlp); | 1190 | lpfc_nlp_put(ndlp); |
1191 | } | 1191 | } |
1192 | 1192 | ||
1193 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, | 1193 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, |
1194 | nlp_listp) { | 1194 | nlp_listp) { |
1195 | lpfc_nlp_remove(phba, ndlp); | 1195 | lpfc_nlp_put(ndlp); |
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, | 1198 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, |
@@ -1202,27 +1202,27 @@ lpfc_cleanup(struct lpfc_hba * phba) | |||
1202 | 1202 | ||
1203 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, | 1203 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, |
1204 | nlp_listp) { | 1204 | nlp_listp) { |
1205 | lpfc_nlp_remove(phba, ndlp); | 1205 | lpfc_nlp_put(ndlp); |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | 1208 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, |
1209 | nlp_listp) { | 1209 | nlp_listp) { |
1210 | lpfc_nlp_remove(phba, ndlp); | 1210 | lpfc_nlp_put(ndlp); |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, | 1213 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, |
1214 | nlp_listp) { | 1214 | nlp_listp) { |
1215 | lpfc_nlp_remove(phba, ndlp); | 1215 | lpfc_nlp_put(ndlp); |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, | 1218 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, |
1219 | nlp_listp) { | 1219 | nlp_listp) { |
1220 | lpfc_nlp_remove(phba, ndlp); | 1220 | lpfc_nlp_put(ndlp); |
1221 | } | 1221 | } |
1222 | 1222 | ||
1223 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | 1223 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, |
1224 | nlp_listp) { | 1224 | nlp_listp) { |
1225 | lpfc_nlp_remove(phba, ndlp); | 1225 | lpfc_nlp_put(ndlp); |
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | INIT_LIST_HEAD(&phba->fc_nlpmap_list); | 1228 | INIT_LIST_HEAD(&phba->fc_nlpmap_list); |
@@ -1510,7 +1510,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1510 | INIT_LIST_HEAD(&phba->fc_prli_list); | 1510 | INIT_LIST_HEAD(&phba->fc_prli_list); |
1511 | INIT_LIST_HEAD(&phba->fc_npr_list); | 1511 | INIT_LIST_HEAD(&phba->fc_npr_list); |
1512 | 1512 | ||
1513 | |||
1514 | pci_set_master(pdev); | 1513 | pci_set_master(pdev); |
1515 | retval = pci_set_mwi(pdev); | 1514 | retval = pci_set_mwi(pdev); |
1516 | if (retval) | 1515 | if (retval) |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 789a12dc986b..f03284ad25b7 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -353,7 +353,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
353 | * queue this mbox command to be processed later. | 353 | * queue this mbox command to be processed later. |
354 | */ | 354 | */ |
355 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 355 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
356 | mbox->context2 = ndlp; | 356 | /* |
357 | * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox | ||
358 | * command issued in lpfc_cmpl_els_acc(). | ||
359 | */ | ||
357 | ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); | 360 | ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); |
358 | 361 | ||
359 | /* | 362 | /* |
@@ -773,13 +776,14 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
773 | default: | 776 | default: |
774 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 777 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
775 | } | 778 | } |
776 | mbox->context2 = ndlp; | 779 | mbox->context2 = lpfc_nlp_get(ndlp); |
777 | if (lpfc_sli_issue_mbox(phba, mbox, | 780 | if (lpfc_sli_issue_mbox(phba, mbox, |
778 | (MBX_NOWAIT | MBX_STOP_IOCB)) | 781 | (MBX_NOWAIT | MBX_STOP_IOCB)) |
779 | != MBX_NOT_FINISHED) { | 782 | != MBX_NOT_FINISHED) { |
780 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); | 783 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); |
781 | return ndlp->nlp_state; | 784 | return ndlp->nlp_state; |
782 | } | 785 | } |
786 | lpfc_nlp_put(ndlp); | ||
783 | mp = (struct lpfc_dmabuf *)mbox->context1; | 787 | mp = (struct lpfc_dmabuf *)mbox->context1; |
784 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 788 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
785 | kfree(mp); | 789 | kfree(mp); |
@@ -1920,7 +1924,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, | |||
1920 | uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *, | 1924 | uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *, |
1921 | uint32_t); | 1925 | uint32_t); |
1922 | 1926 | ||
1923 | ndlp->nlp_disc_refcnt++; | 1927 | lpfc_nlp_get(ndlp); |
1924 | cur_state = ndlp->nlp_state; | 1928 | cur_state = ndlp->nlp_state; |
1925 | 1929 | ||
1926 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ | 1930 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ |
@@ -1943,18 +1947,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, | |||
1943 | phba->brd_no, | 1947 | phba->brd_no, |
1944 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | 1948 | rc, ndlp->nlp_DID, ndlp->nlp_flag); |
1945 | 1949 | ||
1946 | ndlp->nlp_disc_refcnt--; | 1950 | lpfc_nlp_put(ndlp); |
1947 | 1951 | ||
1948 | /* Check to see if ndlp removal is deferred */ | ||
1949 | if ((ndlp->nlp_disc_refcnt == 0) | ||
1950 | && (ndlp->nlp_flag & NLP_DELAY_REMOVE)) { | ||
1951 | spin_lock_irq(phba->host->host_lock); | ||
1952 | ndlp->nlp_flag &= ~NLP_DELAY_REMOVE; | ||
1953 | spin_unlock_irq(phba->host->host_lock); | ||
1954 | lpfc_nlp_remove(phba, ndlp); | ||
1955 | return NLP_STE_FREED_NODE; | ||
1956 | } | ||
1957 | if (rc == NLP_STE_FREED_NODE) | ||
1958 | return NLP_STE_FREED_NODE; | ||
1959 | return rc; | 1952 | return rc; |
1960 | } | 1953 | } |