diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-08-02 11:10:31 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-08-01 13:24:10 -0400 |
commit | 51ef4c26891a734bc8416b639ad460a8162926bc (patch) | |
tree | 8279e11bf1a0a3200e8aa9bb3d956345ef73533c /drivers/scsi/lpfc/lpfc_els.c | |
parent | 78b2d852a88cd2a55e3ab632109de045d58b83e3 (diff) |
[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.
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_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9365e19696e2..8085900635d4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
196 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 196 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
197 | } | 197 | } |
198 | 198 | ||
199 | /* Save for completion so we can release these resources */ | 199 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
200 | if (elscmd != ELS_CMD_LS_RJT) | ||
201 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
202 | elsiocb->context2 = pcmd; | 200 | elsiocb->context2 = pcmd; |
203 | elsiocb->context3 = pbuflist; | 201 | elsiocb->context3 = pbuflist; |
204 | elsiocb->retry = retry; | 202 | elsiocb->retry = retry; |
@@ -1809,8 +1807,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1809 | "retrying...\n"); | 1807 | "retrying...\n"); |
1810 | lpfc_mbx_unreg_vpi(vport); | 1808 | lpfc_mbx_unreg_vpi(vport); |
1811 | retry = 1; | 1809 | retry = 1; |
1812 | /* Always retry for this case */ | 1810 | /* FDISC retry policy */ |
1813 | cmdiocb->retry = 0; | 1811 | maxretry = 48; |
1812 | if (cmdiocb->retry >= 32) | ||
1813 | delay = 1000; | ||
1814 | } | 1814 | } |
1815 | break; | 1815 | break; |
1816 | 1816 | ||
@@ -1886,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1886 | delay = 1000; | 1886 | delay = 1000; |
1887 | maxretry = 48; | 1887 | maxretry = 48; |
1888 | } else if (cmd == ELS_CMD_FDISC) { | 1888 | } else if (cmd == ELS_CMD_FDISC) { |
1889 | /* Always retry for this case */ | 1889 | /* FDISC retry policy */ |
1890 | cmdiocb->retry = 0; | 1890 | maxretry = 48; |
1891 | if (cmdiocb->retry >= 32) | ||
1892 | delay = 1000; | ||
1891 | } | 1893 | } |
1892 | retry = 1; | 1894 | retry = 1; |
1893 | break; | 1895 | break; |
@@ -2121,9 +2123,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2121 | } | 2123 | } |
2122 | 2124 | ||
2123 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | 2125 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
2124 | "ACC cmpl: status:x%x/x%x did:x%x", | 2126 | "ELS rsp cmpl: status:x%x/x%x did:x%x", |
2125 | irsp->ulpStatus, irsp->un.ulpWord[4], | 2127 | irsp->ulpStatus, irsp->un.ulpWord[4], |
2126 | irsp->un.rcvels.remoteID); | 2128 | cmdiocb->iocb.un.elsreq64.remoteID); |
2127 | /* ELS response tag <ulpIoTag> completes */ | 2129 | /* ELS response tag <ulpIoTag> completes */ |
2128 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2130 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2129 | "0110 ELS response tag x%x completes " | 2131 | "0110 ELS response tag x%x completes " |
@@ -2184,7 +2186,7 @@ out: | |||
2184 | int | 2186 | int |
2185 | lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | 2187 | lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, |
2186 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, | 2188 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, |
2187 | LPFC_MBOXQ_t *mbox, uint8_t newnode) | 2189 | LPFC_MBOXQ_t *mbox) |
2188 | { | 2190 | { |
2189 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2191 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2190 | struct lpfc_hba *phba = vport->phba; | 2192 | struct lpfc_hba *phba = vport->phba; |
@@ -2270,11 +2272,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
2270 | default: | 2272 | default: |
2271 | return 1; | 2273 | return 1; |
2272 | } | 2274 | } |
2273 | |||
2274 | if (newnode) { | ||
2275 | lpfc_nlp_put(ndlp); | ||
2276 | elsiocb->context1 = NULL; | ||
2277 | } | ||
2278 | /* Xmit ELS ACC response tag <ulpIoTag> */ | 2275 | /* Xmit ELS ACC response tag <ulpIoTag> */ |
2279 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2276 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2280 | "0128 Xmit ELS ACC response tag x%x, XRI: x%x, " | 2277 | "0128 Xmit ELS ACC response tag x%x, XRI: x%x, " |
@@ -2333,10 +2330,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2333 | pcmd += sizeof(uint32_t); | 2330 | pcmd += sizeof(uint32_t); |
2334 | *((uint32_t *) (pcmd)) = rejectError; | 2331 | *((uint32_t *) (pcmd)) = rejectError; |
2335 | 2332 | ||
2336 | if (mbox) { | 2333 | if (mbox) |
2337 | elsiocb->context_un.mbox = mbox; | 2334 | elsiocb->context_un.mbox = mbox; |
2338 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
2339 | } | ||
2340 | 2335 | ||
2341 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ | 2336 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ |
2342 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2337 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
@@ -2353,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2353 | phba->fc_stat.elsXmitLSRJT++; | 2348 | phba->fc_stat.elsXmitLSRJT++; |
2354 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; | 2349 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
2355 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2350 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2351 | |||
2352 | /* If the node is in the UNUSED state, and we are sending | ||
2353 | * a reject, we are done with it. Release driver reference | ||
2354 | * count here. The outstanding els will release its reference on | ||
2355 | * completion and the node can be freed then. | ||
2356 | */ | ||
2357 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
2358 | lpfc_nlp_put(ndlp); | ||
2359 | |||
2356 | if (rc == IOCB_ERROR) { | 2360 | if (rc == IOCB_ERROR) { |
2357 | lpfc_els_free_iocb(phba, elsiocb); | 2361 | lpfc_els_free_iocb(phba, elsiocb); |
2358 | return 1; | 2362 | return 1; |
@@ -2747,7 +2751,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) | |||
2747 | 2751 | ||
2748 | static int | 2752 | static int |
2749 | lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | 2753 | lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2750 | struct lpfc_nodelist *ndlp, uint8_t newnode) | 2754 | struct lpfc_nodelist *ndlp) |
2751 | { | 2755 | { |
2752 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2756 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2753 | struct lpfc_hba *phba = vport->phba; | 2757 | struct lpfc_hba *phba = vport->phba; |
@@ -2781,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2781 | "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", | 2785 | "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", |
2782 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | 2786 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); |
2783 | 2787 | ||
2784 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2788 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2785 | newnode); | ||
2786 | return 0; | 2789 | return 0; |
2787 | } | 2790 | } |
2788 | 2791 | ||
@@ -2814,7 +2817,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2814 | ndlp->nlp_flag); | 2817 | ndlp->nlp_flag); |
2815 | 2818 | ||
2816 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, | 2819 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, |
2817 | ndlp, NULL, newnode); | 2820 | ndlp, NULL); |
2818 | return 0; | 2821 | return 0; |
2819 | } | 2822 | } |
2820 | } | 2823 | } |
@@ -2870,8 +2873,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2870 | vport->port_state); | 2873 | vport->port_state); |
2871 | } | 2874 | } |
2872 | /* Send back ACC */ | 2875 | /* Send back ACC */ |
2873 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2876 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2874 | newnode); | ||
2875 | 2877 | ||
2876 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2878 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2877 | lpfc_rscn_recovery_check(vport); | 2879 | lpfc_rscn_recovery_check(vport); |
@@ -2896,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2896 | lpfc_set_disctmo(vport); | 2898 | lpfc_set_disctmo(vport); |
2897 | 2899 | ||
2898 | /* Send back ACC */ | 2900 | /* Send back ACC */ |
2899 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); | 2901 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2900 | 2902 | ||
2901 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2903 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2902 | lpfc_rscn_recovery_check(vport); | 2904 | lpfc_rscn_recovery_check(vport); |
@@ -2965,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) | |||
2965 | 2967 | ||
2966 | static int | 2968 | static int |
2967 | lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | 2969 | lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2968 | struct lpfc_nodelist *ndlp, uint8_t newnode) | 2970 | struct lpfc_nodelist *ndlp) |
2969 | { | 2971 | { |
2970 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2972 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2971 | struct lpfc_hba *phba = vport->phba; | 2973 | struct lpfc_hba *phba = vport->phba; |
@@ -3048,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3048 | } | 3050 | } |
3049 | 3051 | ||
3050 | /* Send back ACC */ | 3052 | /* Send back ACC */ |
3051 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); | 3053 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
3052 | 3054 | ||
3053 | return 0; | 3055 | return 0; |
3054 | } | 3056 | } |
@@ -3409,7 +3411,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3409 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 3411 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
3410 | "0600 FARP-RSP received from DID x%x\n", did); | 3412 | "0600 FARP-RSP received from DID x%x\n", did); |
3411 | /* ACCEPT the Farp resp request */ | 3413 | /* ACCEPT the Farp resp request */ |
3412 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 3414 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
3413 | 3415 | ||
3414 | return 0; | 3416 | return 0; |
3415 | } | 3417 | } |
@@ -3791,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3791 | did, vport->port_state, ndlp->nlp_flag); | 3793 | did, vport->port_state, ndlp->nlp_flag); |
3792 | 3794 | ||
3793 | phba->fc_stat.elsRcvFLOGI++; | 3795 | phba->fc_stat.elsRcvFLOGI++; |
3794 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); | 3796 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); |
3795 | if (newnode) | 3797 | if (newnode) |
3796 | lpfc_drop_node(vport, ndlp); | 3798 | lpfc_drop_node(vport, ndlp); |
3797 | break; | 3799 | break; |
@@ -3821,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3821 | break; | 3823 | break; |
3822 | case ELS_CMD_RSCN: | 3824 | case ELS_CMD_RSCN: |
3823 | phba->fc_stat.elsRcvRSCN++; | 3825 | phba->fc_stat.elsRcvRSCN++; |
3824 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode); | 3826 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); |
3825 | if (newnode) | 3827 | if (newnode) |
3826 | lpfc_drop_node(vport, ndlp); | 3828 | lpfc_drop_node(vport, ndlp); |
3827 | break; | 3829 | break; |
@@ -3951,8 +3953,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3951 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 3953 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
3952 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, | 3954 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, |
3953 | NULL); | 3955 | NULL); |
3954 | if (newnode) | ||
3955 | lpfc_drop_node(vport, ndlp); | ||
3956 | } | 3956 | } |
3957 | 3957 | ||
3958 | return; | 3958 | return; |