diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:33 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
commit | 98c9ea5c026ee47efe2a0f595078dbf199d08f50 (patch) | |
tree | 4d07a863ed26b1d3efec0d198ce456e20fad3954 /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 0b727fea7a700e223bf52fb1eaf4c3a27c4340db (diff) |
[SCSI] lpfc 8.2.3 : Miscellaneous Small Fixes - part 1
Miscellaneous Small Fixes - part 1
- Fix typo kmzlloc -> kzalloc
- Fix discovery ndlp use after free panic
- Fix link event causing flood of 0108 messages
- Relieve some mbox congestion on link up with 100 vports
- Fix broken vport parameters
- Prevent lock recursion in logo_reglogin_issue
- Split uses of error variable in lpfc_pci_probe_one into retval and error
- Remove completion code related to dev_loss_tmo
- Remove unused LPFC_MAX_HBQ #define
- Don't compare pointers to 0 for sparse
- Make 2 functions static for sparse
- Fix default rpi cleanup code causing rogue ndlps to remain on the NPR list
- Remove annoying ELS messages when driver is unloaded
- Fix Cannot issue Register Fabric login problems on link up
- Remove LPFC_EVT_DEV_LOSS_DELAY
- Fix FC port swap test leads to device going offline
- Fix vport CT flags to only be set when accepted
- Add code to handle signals during vport_create
- Fix too many retries in FC-AL mode
- Pull lpfc_port_link_failure out of lpfc_linkdown_port
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 123 |
1 files changed, 77 insertions, 46 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 6f5bf8189950..e181a98caf16 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -107,7 +107,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
107 | struct lpfc_nodelist * ndlp; | 107 | struct lpfc_nodelist * ndlp; |
108 | struct lpfc_vport *vport; | 108 | struct lpfc_vport *vport; |
109 | struct lpfc_hba *phba; | 109 | struct lpfc_hba *phba; |
110 | struct completion devloss_compl; | ||
111 | struct lpfc_work_evt *evtp; | 110 | struct lpfc_work_evt *evtp; |
112 | 111 | ||
113 | rdata = rport->dd_data; | 112 | rdata = rport->dd_data; |
@@ -129,7 +128,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
129 | "rport devlosscb: sid:x%x did:x%x flg:x%x", | 128 | "rport devlosscb: sid:x%x did:x%x flg:x%x", |
130 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | 129 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); |
131 | 130 | ||
132 | init_completion(&devloss_compl); | ||
133 | evtp = &ndlp->dev_loss_evt; | 131 | evtp = &ndlp->dev_loss_evt; |
134 | 132 | ||
135 | if (!list_empty(&evtp->evt_listp)) | 133 | if (!list_empty(&evtp->evt_listp)) |
@@ -137,7 +135,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
137 | 135 | ||
138 | spin_lock_irq(&phba->hbalock); | 136 | spin_lock_irq(&phba->hbalock); |
139 | evtp->evt_arg1 = ndlp; | 137 | evtp->evt_arg1 = ndlp; |
140 | evtp->evt_arg2 = &devloss_compl; | ||
141 | evtp->evt = LPFC_EVT_DEV_LOSS; | 138 | evtp->evt = LPFC_EVT_DEV_LOSS; |
142 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 139 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
143 | if (phba->work_wait) | 140 | if (phba->work_wait) |
@@ -145,8 +142,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
145 | 142 | ||
146 | spin_unlock_irq(&phba->hbalock); | 143 | spin_unlock_irq(&phba->hbalock); |
147 | 144 | ||
148 | wait_for_completion(&devloss_compl); | ||
149 | |||
150 | return; | 145 | return; |
151 | } | 146 | } |
152 | 147 | ||
@@ -260,7 +255,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
260 | { | 255 | { |
261 | struct lpfc_work_evt *evtp = NULL; | 256 | struct lpfc_work_evt *evtp = NULL; |
262 | struct lpfc_nodelist *ndlp; | 257 | struct lpfc_nodelist *ndlp; |
263 | struct lpfc_vport *vport; | ||
264 | int free_evt; | 258 | int free_evt; |
265 | 259 | ||
266 | spin_lock_irq(&phba->hbalock); | 260 | spin_lock_irq(&phba->hbalock); |
@@ -270,24 +264,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
270 | spin_unlock_irq(&phba->hbalock); | 264 | spin_unlock_irq(&phba->hbalock); |
271 | free_evt = 1; | 265 | free_evt = 1; |
272 | switch (evtp->evt) { | 266 | switch (evtp->evt) { |
273 | case LPFC_EVT_DEV_LOSS_DELAY: | ||
274 | free_evt = 0; /* evt is part of ndlp */ | ||
275 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | ||
276 | vport = ndlp->vport; | ||
277 | if (!vport) | ||
278 | break; | ||
279 | |||
280 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
281 | "rport devlossdly:did:x%x flg:x%x", | ||
282 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
283 | |||
284 | if (!(vport->load_flag & FC_UNLOADING) && | ||
285 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | ||
286 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { | ||
287 | lpfc_disc_state_machine(vport, ndlp, NULL, | ||
288 | NLP_EVT_DEVICE_RM); | ||
289 | } | ||
290 | break; | ||
291 | case LPFC_EVT_ELS_RETRY: | 267 | case LPFC_EVT_ELS_RETRY: |
292 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | 268 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); |
293 | lpfc_els_retry_delay_handler(ndlp); | 269 | lpfc_els_retry_delay_handler(ndlp); |
@@ -298,7 +274,6 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
298 | lpfc_nlp_get(ndlp); | 274 | lpfc_nlp_get(ndlp); |
299 | lpfc_dev_loss_tmo_handler(ndlp); | 275 | lpfc_dev_loss_tmo_handler(ndlp); |
300 | free_evt = 0; | 276 | free_evt = 0; |
301 | complete((struct completion *)(evtp->evt_arg2)); | ||
302 | lpfc_nlp_put(ndlp); | 277 | lpfc_nlp_put(ndlp); |
303 | break; | 278 | break; |
304 | case LPFC_EVT_ONLINE: | 279 | case LPFC_EVT_ONLINE: |
@@ -552,7 +527,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
552 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | 527 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
553 | continue; | 528 | continue; |
554 | 529 | ||
555 | if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) | 530 | if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || |
531 | ((vport->port_type == LPFC_NPIV_PORT) && | ||
532 | (ndlp->nlp_DID == NameServer_DID))) | ||
556 | lpfc_unreg_rpi(vport, ndlp); | 533 | lpfc_unreg_rpi(vport, ndlp); |
557 | 534 | ||
558 | /* Leave Fabric nodes alone on link down */ | 535 | /* Leave Fabric nodes alone on link down */ |
@@ -570,16 +547,9 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
570 | } | 547 | } |
571 | 548 | ||
572 | static void | 549 | static void |
573 | lpfc_linkdown_port(struct lpfc_vport *vport) | 550 | lpfc_port_link_failure(struct lpfc_vport *vport) |
574 | { | 551 | { |
575 | struct lpfc_nodelist *ndlp, *next_ndlp; | 552 | struct lpfc_nodelist *ndlp, *next_ndlp; |
576 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
577 | |||
578 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | ||
579 | |||
580 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
581 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
582 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
583 | 553 | ||
584 | /* Cleanup any outstanding RSCN activity */ | 554 | /* Cleanup any outstanding RSCN activity */ |
585 | lpfc_els_flush_rscn(vport); | 555 | lpfc_els_flush_rscn(vport); |
@@ -598,6 +568,21 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |||
598 | lpfc_can_disctmo(vport); | 568 | lpfc_can_disctmo(vport); |
599 | } | 569 | } |
600 | 570 | ||
571 | static void | ||
572 | lpfc_linkdown_port(struct lpfc_vport *vport) | ||
573 | { | ||
574 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
575 | |||
576 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | ||
577 | |||
578 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
579 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
580 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
581 | |||
582 | lpfc_port_link_failure(vport); | ||
583 | |||
584 | } | ||
585 | |||
601 | int | 586 | int |
602 | lpfc_linkdown(struct lpfc_hba *phba) | 587 | lpfc_linkdown(struct lpfc_hba *phba) |
603 | { | 588 | { |
@@ -851,8 +836,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
851 | * LPFC_FLOGI while waiting for FLOGI cmpl | 836 | * LPFC_FLOGI while waiting for FLOGI cmpl |
852 | */ | 837 | */ |
853 | if (vport->port_state != LPFC_FLOGI) { | 838 | if (vport->port_state != LPFC_FLOGI) { |
854 | vport->port_state = LPFC_FLOGI; | ||
855 | lpfc_set_disctmo(vport); | ||
856 | lpfc_initial_flogi(vport); | 839 | lpfc_initial_flogi(vport); |
857 | } | 840 | } |
858 | return; | 841 | return; |
@@ -1622,6 +1605,16 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1622 | ndlp->nlp_type &= ~NLP_FC_NODE; | 1605 | ndlp->nlp_type &= ~NLP_FC_NODE; |
1623 | } | 1606 | } |
1624 | 1607 | ||
1608 | if ((old_state == NLP_STE_UNUSED_NODE) && | ||
1609 | (state != NLP_STE_UNUSED_NODE) && | ||
1610 | (ndlp->nlp_flag & NLP_DELAYED_RM)) { | ||
1611 | /* We are using the ndlp after all, so reverse | ||
1612 | * the delayed removal of it. | ||
1613 | */ | ||
1614 | ndlp->nlp_flag &= ~NLP_DELAYED_RM; | ||
1615 | lpfc_nlp_get(ndlp); | ||
1616 | } | ||
1617 | |||
1625 | if (list_empty(&ndlp->nlp_listp)) { | 1618 | if (list_empty(&ndlp->nlp_listp)) { |
1626 | spin_lock_irq(shost->host_lock); | 1619 | spin_lock_irq(shost->host_lock); |
1627 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); | 1620 | list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes); |
@@ -1654,7 +1647,9 @@ void | |||
1654 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1647 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1655 | { | 1648 | { |
1656 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 1649 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1657 | lpfc_nlp_put(ndlp); | 1650 | if (!(ndlp->nlp_flag & NLP_DELAYED_RM)) |
1651 | lpfc_nlp_put(ndlp); | ||
1652 | return; | ||
1658 | } | 1653 | } |
1659 | 1654 | ||
1660 | /* | 1655 | /* |
@@ -1975,11 +1970,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1975 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) | 1970 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) |
1976 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | 1971 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
1977 | 1972 | ||
1978 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) { | ||
1979 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | ||
1980 | complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2)); | ||
1981 | } | ||
1982 | |||
1983 | lpfc_unreg_rpi(vport, ndlp); | 1973 | lpfc_unreg_rpi(vport, ndlp); |
1984 | 1974 | ||
1985 | return 0; | 1975 | return 0; |
@@ -2418,7 +2408,6 @@ lpfc_disc_flush_list(struct lpfc_vport *vport) | |||
2418 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || | 2408 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
2419 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { | 2409 | ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { |
2420 | lpfc_free_tx(phba, ndlp); | 2410 | lpfc_free_tx(phba, ndlp); |
2421 | lpfc_nlp_put(ndlp); | ||
2422 | } | 2411 | } |
2423 | } | 2412 | } |
2424 | } | 2413 | } |
@@ -2516,8 +2505,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
2516 | } | 2505 | } |
2517 | } | 2506 | } |
2518 | if (vport->port_state != LPFC_FLOGI) { | 2507 | if (vport->port_state != LPFC_FLOGI) { |
2519 | vport->port_state = LPFC_FLOGI; | ||
2520 | lpfc_set_disctmo(vport); | ||
2521 | lpfc_initial_flogi(vport); | 2508 | lpfc_initial_flogi(vport); |
2522 | } | 2509 | } |
2523 | break; | 2510 | break; |
@@ -2828,6 +2815,9 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2828 | return; | 2815 | return; |
2829 | } | 2816 | } |
2830 | 2817 | ||
2818 | /* This routine releases all resources associated with a specifc NPort's ndlp | ||
2819 | * and mempool_free's the nodelist. | ||
2820 | */ | ||
2831 | static void | 2821 | static void |
2832 | lpfc_nlp_release(struct kref *kref) | 2822 | lpfc_nlp_release(struct kref *kref) |
2833 | { | 2823 | { |
@@ -2842,16 +2832,57 @@ lpfc_nlp_release(struct kref *kref) | |||
2842 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); | 2832 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); |
2843 | } | 2833 | } |
2844 | 2834 | ||
2835 | /* This routine bumps the reference count for a ndlp structure to ensure | ||
2836 | * that one discovery thread won't free a ndlp while another discovery thread | ||
2837 | * is using it. | ||
2838 | */ | ||
2845 | struct lpfc_nodelist * | 2839 | struct lpfc_nodelist * |
2846 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) | 2840 | lpfc_nlp_get(struct lpfc_nodelist *ndlp) |
2847 | { | 2841 | { |
2848 | if (ndlp) | 2842 | if (ndlp) { |
2843 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2844 | "node get: did:x%x flg:x%x refcnt:x%x", | ||
2845 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2846 | atomic_read(&ndlp->kref.refcount)); | ||
2849 | kref_get(&ndlp->kref); | 2847 | kref_get(&ndlp->kref); |
2848 | } | ||
2850 | return ndlp; | 2849 | return ndlp; |
2851 | } | 2850 | } |
2852 | 2851 | ||
2852 | |||
2853 | /* This routine decrements the reference count for a ndlp structure. If the | ||
2854 | * count goes to 0, this indicates the the associated nodelist should be freed. | ||
2855 | */ | ||
2853 | int | 2856 | int |
2854 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) | 2857 | lpfc_nlp_put(struct lpfc_nodelist *ndlp) |
2855 | { | 2858 | { |
2859 | if (ndlp) { | ||
2860 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2861 | "node put: did:x%x flg:x%x refcnt:x%x", | ||
2862 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2863 | atomic_read(&ndlp->kref.refcount)); | ||
2864 | } | ||
2856 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; | 2865 | return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; |
2857 | } | 2866 | } |
2867 | |||
2868 | /* This routine free's the specified nodelist if it is not in use | ||
2869 | * by any other discovery thread. This routine returns 1 if the ndlp | ||
2870 | * is not being used by anyone and has been freed. A return value of | ||
2871 | * 0 indicates it is being used by another discovery thread and the | ||
2872 | * refcount is left unchanged. | ||
2873 | */ | ||
2874 | int | ||
2875 | lpfc_nlp_not_used(struct lpfc_nodelist *ndlp) | ||
2876 | { | ||
2877 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
2878 | "node not used: did:x%x flg:x%x refcnt:x%x", | ||
2879 | ndlp->nlp_DID, ndlp->nlp_flag, | ||
2880 | atomic_read(&ndlp->kref.refcount)); | ||
2881 | |||
2882 | if (atomic_read(&ndlp->kref.refcount) == 1) { | ||
2883 | lpfc_nlp_put(ndlp); | ||
2884 | return 1; | ||
2885 | } | ||
2886 | return 0; | ||
2887 | } | ||
2888 | |||