diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:51:38 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:13 -0400 |
commit | 07951076aefa4194e1dbf1d8c89eaff040c45155 (patch) | |
tree | 636052abb3f9f2a1bdc0d9adfec130b224a02289 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | 1dcb58e5680b6673bf984696d3d8b9033b6e41bf (diff) |
[SCSI] lpfc 8.1.12 : Modify ELS abort handling to prevent double completion
Modify ELS abort handling to prevent double completion
Rework portions of ELS abort handling to prevent double completion
- Rework ELS iotags and correct abort routine
- Move the (badly wrong) ELS completion logic from the initial ELS
abort request function to the ELS completion function.
- Fixup the iocb completion handling to account for the ELS abort
completions.
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_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 76 |
1 files changed, 22 insertions, 54 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 0c7e731dc45a..aa7f446c8da1 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -168,8 +168,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, | |||
168 | * routine effectively results in a "software abort". | 168 | * routine effectively results in a "software abort". |
169 | */ | 169 | */ |
170 | int | 170 | int |
171 | lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 171 | lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
172 | int send_abts) | ||
173 | { | 172 | { |
174 | struct lpfc_sli *psli; | 173 | struct lpfc_sli *psli; |
175 | struct lpfc_sli_ring *pring; | 174 | struct lpfc_sli_ring *pring; |
@@ -215,48 +214,17 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
215 | spin_unlock_irq(phba->host->host_lock); | 214 | spin_unlock_irq(phba->host->host_lock); |
216 | } while (found); | 215 | } while (found); |
217 | 216 | ||
218 | /* Everything on txcmplq will be returned by firmware | ||
219 | * with a no rpi / linkdown / abort error. For ring 0, | ||
220 | * ELS discovery, we want to get rid of it right here. | ||
221 | */ | ||
222 | /* Next check the txcmplq */ | 217 | /* Next check the txcmplq */ |
223 | do { | 218 | spin_lock_irq(phba->host->host_lock); |
224 | found = 0; | 219 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
225 | spin_lock_irq(phba->host->host_lock); | 220 | /* Check to see if iocb matches the nport we are looking |
226 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, | 221 | for */ |
227 | list) { | 222 | if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { |
228 | /* Check to see if iocb matches the nport we are looking | 223 | icmd = &iocb->iocb; |
229 | for */ | 224 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
230 | if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { | ||
231 | found = 1; | ||
232 | /* It matches, so deque and call compl with an | ||
233 | error */ | ||
234 | list_del(&iocb->list); | ||
235 | pring->txcmplq_cnt--; | ||
236 | |||
237 | icmd = &iocb->iocb; | ||
238 | /* If the driver is completing an ELS | ||
239 | * command early, flush it out of the firmware. | ||
240 | */ | ||
241 | if (send_abts && | ||
242 | (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) && | ||
243 | (icmd->un.elsreq64.bdl.ulpIoTag32)) { | ||
244 | lpfc_sli_issue_abort_iotag32(phba, | ||
245 | pring, iocb); | ||
246 | } | ||
247 | if (iocb->iocb_cmpl) { | ||
248 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
249 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
250 | spin_unlock_irq(phba->host->host_lock); | ||
251 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
252 | spin_lock_irq(phba->host->host_lock); | ||
253 | } else | ||
254 | lpfc_sli_release_iocbq(phba, iocb); | ||
255 | break; | ||
256 | } | ||
257 | } | 225 | } |
258 | spin_unlock_irq(phba->host->host_lock); | 226 | } |
259 | } while(found); | 227 | spin_unlock_irq(phba->host->host_lock); |
260 | 228 | ||
261 | /* If we are delaying issuing an ELS command, cancel it */ | 229 | /* If we are delaying issuing an ELS command, cancel it */ |
262 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 230 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
@@ -404,7 +372,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
404 | */ | 372 | */ |
405 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { | 373 | if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { |
406 | /* software abort outstanding PLOGI */ | 374 | /* software abort outstanding PLOGI */ |
407 | lpfc_els_abort(phba, ndlp, 1); | 375 | lpfc_els_abort(phba, ndlp); |
408 | } | 376 | } |
409 | 377 | ||
410 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); | 378 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); |
@@ -697,7 +665,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba, | |||
697 | cmdiocb = (struct lpfc_iocbq *) arg; | 665 | cmdiocb = (struct lpfc_iocbq *) arg; |
698 | 666 | ||
699 | /* software abort outstanding PLOGI */ | 667 | /* software abort outstanding PLOGI */ |
700 | lpfc_els_abort(phba, ndlp, 1); | 668 | lpfc_els_abort(phba, ndlp); |
701 | 669 | ||
702 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 670 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); |
703 | return ndlp->nlp_state; | 671 | return ndlp->nlp_state; |
@@ -712,7 +680,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, | |||
712 | cmdiocb = (struct lpfc_iocbq *) arg; | 680 | cmdiocb = (struct lpfc_iocbq *) arg; |
713 | 681 | ||
714 | /* software abort outstanding PLOGI */ | 682 | /* software abort outstanding PLOGI */ |
715 | lpfc_els_abort(phba, ndlp, 1); | 683 | lpfc_els_abort(phba, ndlp); |
716 | 684 | ||
717 | if (evt == NLP_EVT_RCV_LOGO) { | 685 | if (evt == NLP_EVT_RCV_LOGO) { |
718 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 686 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
@@ -855,7 +823,7 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba, | |||
855 | } | 823 | } |
856 | else { | 824 | else { |
857 | /* software abort outstanding PLOGI */ | 825 | /* software abort outstanding PLOGI */ |
858 | lpfc_els_abort(phba, ndlp, 1); | 826 | lpfc_els_abort(phba, ndlp); |
859 | 827 | ||
860 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 828 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
861 | return NLP_STE_FREED_NODE; | 829 | return NLP_STE_FREED_NODE; |
@@ -868,7 +836,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba, | |||
868 | uint32_t evt) | 836 | uint32_t evt) |
869 | { | 837 | { |
870 | /* software abort outstanding PLOGI */ | 838 | /* software abort outstanding PLOGI */ |
871 | lpfc_els_abort(phba, ndlp, 1); | 839 | lpfc_els_abort(phba, ndlp); |
872 | 840 | ||
873 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; | 841 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; |
874 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 842 | ndlp->nlp_state = NLP_STE_NPR_NODE; |
@@ -888,7 +856,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, | |||
888 | struct lpfc_iocbq *cmdiocb; | 856 | struct lpfc_iocbq *cmdiocb; |
889 | 857 | ||
890 | /* software abort outstanding ADISC */ | 858 | /* software abort outstanding ADISC */ |
891 | lpfc_els_abort(phba, ndlp, 1); | 859 | lpfc_els_abort(phba, ndlp); |
892 | 860 | ||
893 | cmdiocb = (struct lpfc_iocbq *) arg; | 861 | cmdiocb = (struct lpfc_iocbq *) arg; |
894 | 862 | ||
@@ -926,7 +894,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba, | |||
926 | cmdiocb = (struct lpfc_iocbq *) arg; | 894 | cmdiocb = (struct lpfc_iocbq *) arg; |
927 | 895 | ||
928 | /* software abort outstanding ADISC */ | 896 | /* software abort outstanding ADISC */ |
929 | lpfc_els_abort(phba, ndlp, 0); | 897 | lpfc_els_abort(phba, ndlp); |
930 | 898 | ||
931 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 899 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); |
932 | return ndlp->nlp_state; | 900 | return ndlp->nlp_state; |
@@ -1016,7 +984,7 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba, | |||
1016 | } | 984 | } |
1017 | else { | 985 | else { |
1018 | /* software abort outstanding ADISC */ | 986 | /* software abort outstanding ADISC */ |
1019 | lpfc_els_abort(phba, ndlp, 1); | 987 | lpfc_els_abort(phba, ndlp); |
1020 | 988 | ||
1021 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 989 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
1022 | return NLP_STE_FREED_NODE; | 990 | return NLP_STE_FREED_NODE; |
@@ -1029,7 +997,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba, | |||
1029 | uint32_t evt) | 997 | uint32_t evt) |
1030 | { | 998 | { |
1031 | /* software abort outstanding ADISC */ | 999 | /* software abort outstanding ADISC */ |
1032 | lpfc_els_abort(phba, ndlp, 1); | 1000 | lpfc_els_abort(phba, ndlp); |
1033 | 1001 | ||
1034 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1002 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
1035 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1003 | ndlp->nlp_state = NLP_STE_NPR_NODE; |
@@ -1230,7 +1198,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba, | |||
1230 | cmdiocb = (struct lpfc_iocbq *) arg; | 1198 | cmdiocb = (struct lpfc_iocbq *) arg; |
1231 | 1199 | ||
1232 | /* Software abort outstanding PRLI before sending acc */ | 1200 | /* Software abort outstanding PRLI before sending acc */ |
1233 | lpfc_els_abort(phba, ndlp, 1); | 1201 | lpfc_els_abort(phba, ndlp); |
1234 | 1202 | ||
1235 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 1203 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); |
1236 | return ndlp->nlp_state; | 1204 | return ndlp->nlp_state; |
@@ -1330,7 +1298,7 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba, | |||
1330 | } | 1298 | } |
1331 | else { | 1299 | else { |
1332 | /* software abort outstanding PLOGI */ | 1300 | /* software abort outstanding PLOGI */ |
1333 | lpfc_els_abort(phba, ndlp, 1); | 1301 | lpfc_els_abort(phba, ndlp); |
1334 | 1302 | ||
1335 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); | 1303 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
1336 | return NLP_STE_FREED_NODE; | 1304 | return NLP_STE_FREED_NODE; |
@@ -1359,7 +1327,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba, | |||
1359 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1327 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) |
1360 | { | 1328 | { |
1361 | /* software abort outstanding PRLI */ | 1329 | /* software abort outstanding PRLI */ |
1362 | lpfc_els_abort(phba, ndlp, 1); | 1330 | lpfc_els_abort(phba, ndlp); |
1363 | 1331 | ||
1364 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1332 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1365 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 1333 | ndlp->nlp_state = NLP_STE_NPR_NODE; |