aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:51:38 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:13 -0400
commit07951076aefa4194e1dbf1d8c89eaff040c45155 (patch)
tree636052abb3f9f2a1bdc0d9adfec130b224a02289 /drivers/scsi/lpfc/lpfc_nportdisc.c
parent1dcb58e5680b6673bf984696d3d8b9033b6e41bf (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.c76
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 */
170int 170int
171lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, 171lpfc_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;