aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h7
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c64
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c76
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c122
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h7
6 files changed, 97 insertions, 181 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 1251788ce2a3..4132a2dfac54 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -66,8 +66,7 @@ int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
66 66
67int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *, 67int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
68 struct serv_parm *, uint32_t); 68 struct serv_parm *, uint32_t);
69int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp, 69int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
70 int);
71int lpfc_els_abort_flogi(struct lpfc_hba *); 70int lpfc_els_abort_flogi(struct lpfc_hba *);
72int lpfc_initial_flogi(struct lpfc_hba *); 71int lpfc_initial_flogi(struct lpfc_hba *);
73int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t); 72int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
@@ -162,8 +161,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
162struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, 161struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
163 struct lpfc_sli_ring *, 162 struct lpfc_sli_ring *,
164 dma_addr_t); 163 dma_addr_t);
165int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *, 164int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
166 struct lpfc_iocbq *); 165 struct lpfc_iocbq *);
167int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, 166int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
168 uint64_t, lpfc_ctx_cmd); 167 uint64_t, lpfc_ctx_cmd);
169int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, 168int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index e1c61dbb3d0f..4a9e61345693 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -582,24 +582,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
582 icmd = &iocb->iocb; 582 icmd = &iocb->iocb;
583 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { 583 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
584 ndlp = (struct lpfc_nodelist *)(iocb->context1); 584 ndlp = (struct lpfc_nodelist *)(iocb->context1);
585 if (ndlp && (ndlp->nlp_DID == Fabric_DID)) { 585 if (ndlp && (ndlp->nlp_DID == Fabric_DID))
586 list_del(&iocb->list); 586 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
587 pring->txcmplq_cnt--;
588
589 if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {
590 lpfc_sli_issue_abort_iotag32
591 (phba, pring, iocb);
592 }
593 if (iocb->iocb_cmpl) {
594 icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
595 icmd->un.ulpWord[4] =
596 IOERR_SLI_ABORTED;
597 spin_unlock_irq(phba->host->host_lock);
598 (iocb->iocb_cmpl) (phba, iocb, iocb);
599 spin_lock_irq(phba->host->host_lock);
600 } else
601 lpfc_sli_release_iocbq(phba, iocb);
602 }
603 } 587 }
604 } 588 }
605 spin_unlock_irq(phba->host->host_lock); 589 spin_unlock_irq(phba->host->host_lock);
@@ -3245,7 +3229,6 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
3245 struct lpfc_iocbq *tmp_iocb, *piocb; 3229 struct lpfc_iocbq *tmp_iocb, *piocb;
3246 IOCB_t *cmd = NULL; 3230 IOCB_t *cmd = NULL;
3247 struct lpfc_dmabuf *pcmd; 3231 struct lpfc_dmabuf *pcmd;
3248 struct list_head *dlp;
3249 uint32_t *elscmd; 3232 uint32_t *elscmd;
3250 uint32_t els_command; 3233 uint32_t els_command;
3251 uint32_t timeout; 3234 uint32_t timeout;
@@ -3262,7 +3245,6 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
3262 timeout = (uint32_t)(phba->fc_ratov << 1); 3245 timeout = (uint32_t)(phba->fc_ratov << 1);
3263 3246
3264 pring = &phba->sli.ring[LPFC_ELS_RING]; 3247 pring = &phba->sli.ring[LPFC_ELS_RING];
3265 dlp = &pring->txcmplq;
3266 3248
3267 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { 3249 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3268 cmd = &piocb->iocb; 3250 cmd = &piocb->iocb;
@@ -3288,19 +3270,12 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
3288 continue; 3270 continue;
3289 } 3271 }
3290 3272
3291 list_del(&piocb->list);
3292 pring->txcmplq_cnt--;
3293
3294 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { 3273 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
3295 struct lpfc_nodelist *ndlp; 3274 struct lpfc_nodelist *ndlp;
3296 spin_unlock_irq(phba->host->host_lock); 3275 spin_unlock_irq(phba->host->host_lock);
3297 ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); 3276 ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
3298 spin_lock_irq(phba->host->host_lock); 3277 spin_lock_irq(phba->host->host_lock);
3299 remote_ID = ndlp->nlp_DID; 3278 remote_ID = ndlp->nlp_DID;
3300 if (cmd->un.elsreq64.bdl.ulpIoTag32) {
3301 lpfc_sli_issue_abort_iotag32(phba,
3302 pring, piocb);
3303 }
3304 } else { 3279 } else {
3305 remote_ID = cmd->un.elsreq64.remoteID; 3280 remote_ID = cmd->un.elsreq64.remoteID;
3306 } 3281 }
@@ -3312,17 +3287,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
3312 phba->brd_no, els_command, 3287 phba->brd_no, els_command,
3313 remote_ID, cmd->ulpCommand, cmd->ulpIoTag); 3288 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
3314 3289
3315 /* 3290 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
3316 * The iocb has timed out; abort it.
3317 */
3318 if (piocb->iocb_cmpl) {
3319 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3320 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3321 spin_unlock_irq(phba->host->host_lock);
3322 (piocb->iocb_cmpl) (phba, piocb, piocb);
3323 spin_lock_irq(phba->host->host_lock);
3324 } else
3325 lpfc_sli_release_iocbq(phba, piocb);
3326 } 3291 }
3327 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) 3292 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
3328 mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout); 3293 mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
@@ -3336,9 +3301,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
3336 struct lpfc_sli_ring *pring; 3301 struct lpfc_sli_ring *pring;
3337 struct lpfc_iocbq *tmp_iocb, *piocb; 3302 struct lpfc_iocbq *tmp_iocb, *piocb;
3338 IOCB_t *cmd = NULL; 3303 IOCB_t *cmd = NULL;
3339 struct lpfc_dmabuf *pcmd;
3340 uint32_t *elscmd;
3341 uint32_t els_command;
3342 3304
3343 pring = &phba->sli.ring[LPFC_ELS_RING]; 3305 pring = &phba->sli.ring[LPFC_ELS_RING];
3344 spin_lock_irq(phba->host->host_lock); 3306 spin_lock_irq(phba->host->host_lock);
@@ -3357,10 +3319,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
3357 continue; 3319 continue;
3358 } 3320 }
3359 3321
3360 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3361 elscmd = (uint32_t *) (pcmd->virt);
3362 els_command = *elscmd;
3363
3364 list_del(&piocb->list); 3322 list_del(&piocb->list);
3365 pring->txq_cnt--; 3323 pring->txq_cnt--;
3366 3324
@@ -3381,22 +3339,8 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
3381 if (piocb->iocb_flag & LPFC_IO_LIBDFC) { 3339 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3382 continue; 3340 continue;
3383 } 3341 }
3384 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3385 elscmd = (uint32_t *) (pcmd->virt);
3386 els_command = *elscmd;
3387
3388 list_del(&piocb->list);
3389 pring->txcmplq_cnt--;
3390 3342
3391 cmd->ulpStatus = IOSTAT_LOCAL_REJECT; 3343 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
3392 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3393
3394 if (piocb->iocb_cmpl) {
3395 spin_unlock_irq(phba->host->host_lock);
3396 (piocb->iocb_cmpl) (phba, piocb, piocb);
3397 spin_lock_irq(phba->host->host_lock);
3398 } else
3399 lpfc_sli_release_iocbq(phba, piocb);
3400 } 3344 }
3401 spin_unlock_irq(phba->host->host_lock); 3345 spin_unlock_irq(phba->host->host_lock);
3402 return; 3346 return;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bd7bbedb941e..485a13fa527d 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1596,7 +1596,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1596 } 1596 }
1597 spin_unlock_irq(phba->host->host_lock); 1597 spin_unlock_irq(phba->host->host_lock);
1598 1598
1599 lpfc_els_abort(phba,ndlp,0); 1599 lpfc_els_abort(phba,ndlp);
1600 spin_lock_irq(phba->host->host_lock); 1600 spin_lock_irq(phba->host->host_lock);
1601 ndlp->nlp_flag &= ~NLP_DELAY_TMO; 1601 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
1602 spin_unlock_irq(phba->host->host_lock); 1602 spin_unlock_irq(phba->host->host_lock);
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;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 54a8f4d3db13..dcd313ab4a72 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -816,6 +816,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
816 * All other are passed to the completion callback. 816 * All other are passed to the completion callback.
817 */ 817 */
818 if (pring->ringno == LPFC_ELS_RING) { 818 if (pring->ringno == LPFC_ELS_RING) {
819 if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) {
820 cmdiocbp->iocb_flag &=
821 ~LPFC_DRIVER_ABORTED;
822 saveq->iocb.ulpStatus =
823 IOSTAT_LOCAL_REJECT;
824 saveq->iocb.un.ulpWord[4] =
825 IOERR_SLI_ABORTED;
826 }
819 spin_unlock_irqrestore(phba->host->host_lock, 827 spin_unlock_irqrestore(phba->host->host_lock,
820 iflag); 828 iflag);
821 (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); 829 (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
@@ -2728,85 +2736,81 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
2728} 2736}
2729 2737
2730static void 2738static void
2731lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, 2739lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2732 struct lpfc_iocbq * rspiocb) 2740 struct lpfc_iocbq * rspiocb)
2733{ 2741{
2734 struct lpfc_dmabuf *buf_ptr, *buf_ptr1; 2742 spin_lock_irq(phba->host->host_lock);
2735 /* Free the resources associated with the ELS_REQUEST64 IOCB the driver
2736 * just aborted.
2737 * In this case, context2 = cmd, context2->next = rsp, context3 = bpl
2738 */
2739 if (cmdiocb->context2) {
2740 buf_ptr1 = (struct lpfc_dmabuf *) cmdiocb->context2;
2741
2742 /* Free the response IOCB before completing the abort
2743 command. */
2744 buf_ptr = NULL;
2745 list_remove_head((&buf_ptr1->list), buf_ptr,
2746 struct lpfc_dmabuf, list);
2747 if (buf_ptr) {
2748 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
2749 kfree(buf_ptr);
2750 }
2751 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
2752 kfree(buf_ptr1);
2753 }
2754
2755 if (cmdiocb->context3) {
2756 buf_ptr = (struct lpfc_dmabuf *) cmdiocb->context3;
2757 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
2758 kfree(buf_ptr);
2759 }
2760
2761 lpfc_sli_release_iocbq(phba, cmdiocb); 2743 lpfc_sli_release_iocbq(phba, cmdiocb);
2744 spin_unlock_irq(phba->host->host_lock);
2762 return; 2745 return;
2763} 2746}
2764 2747
2765int 2748int
2766lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, 2749lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
2767 struct lpfc_sli_ring * pring, 2750 struct lpfc_sli_ring * pring,
2768 struct lpfc_iocbq * cmdiocb) 2751 struct lpfc_iocbq * cmdiocb)
2769{ 2752{
2770 struct lpfc_iocbq *abtsiocbp; 2753 struct lpfc_iocbq *abtsiocbp;
2771 IOCB_t *icmd = NULL; 2754 IOCB_t *icmd = NULL;
2772 IOCB_t *iabt = NULL; 2755 IOCB_t *iabt = NULL;
2756 int retval = IOCB_ERROR;
2757
2758 /* There are certain command types we don't want
2759 * to abort.
2760 */
2761 icmd = &cmdiocb->iocb;
2762 if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
2763 (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
2764 return 0;
2765
2766 /* If we're unloading, interrupts are disabled so we
2767 * need to cleanup the iocb here.
2768 */
2769 if (phba->fc_flag & FC_UNLOADING)
2770 goto abort_iotag_exit;
2773 2771
2774 /* issue ABTS for this IOCB based on iotag */ 2772 /* issue ABTS for this IOCB based on iotag */
2775 abtsiocbp = lpfc_sli_get_iocbq(phba); 2773 abtsiocbp = lpfc_sli_get_iocbq(phba);
2776 if (abtsiocbp == NULL) 2774 if (abtsiocbp == NULL)
2777 return 0; 2775 return 0;
2778 2776
2777 /* This signals the response to set the correct status
2778 * before calling the completion handler.
2779 */
2780 cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
2781
2779 iabt = &abtsiocbp->iocb; 2782 iabt = &abtsiocbp->iocb;
2780 icmd = &cmdiocb->iocb; 2783 iabt->un.acxri.abortType = ABORT_TYPE_ABTS;
2781 switch (icmd->ulpCommand) { 2784 iabt->un.acxri.abortContextTag = icmd->ulpContext;
2782 case CMD_ELS_REQUEST64_CR: 2785 iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
2783 /* Even though we abort the ELS command, the firmware may access 2786 iabt->ulpLe = 1;
2784 * the BPL or other resources before it processes our 2787 iabt->ulpClass = icmd->ulpClass;
2785 * ABORT_MXRI64. Thus we must delay reusing the cmdiocb
2786 * resources till the actual abort request completes.
2787 */
2788 abtsiocbp->context1 = (void *)((unsigned long)icmd->ulpCommand);
2789 abtsiocbp->context2 = cmdiocb->context2;
2790 abtsiocbp->context3 = cmdiocb->context3;
2791 cmdiocb->context2 = NULL;
2792 cmdiocb->context3 = NULL;
2793 abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl;
2794 break;
2795 default:
2796 lpfc_sli_release_iocbq(phba, abtsiocbp);
2797 return 0;
2798 }
2799 2788
2800 iabt->un.amxri.abortType = ABORT_TYPE_ABTS; 2789 if (phba->hba_state >= LPFC_LINK_UP)
2801 iabt->un.amxri.iotag32 = icmd->un.elsreq64.bdl.ulpIoTag32; 2790 iabt->ulpCommand = CMD_ABORT_XRI_CN;
2791 else
2792 iabt->ulpCommand = CMD_CLOSE_XRI_CN;
2802 2793
2803 iabt->ulpLe = 1; 2794 abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
2804 iabt->ulpClass = CLASS3; 2795 retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
2805 iabt->ulpCommand = CMD_ABORT_MXRI64_CN;
2806 2796
2807 if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) { 2797abort_iotag_exit:
2808 lpfc_sli_release_iocbq(phba, abtsiocbp); 2798
2809 return 0; 2799 /* If we could not issue an abort dequeue the iocb and handle
2800 * the completion here.
2801 */
2802 if (retval == IOCB_ERROR) {
2803 list_del(&cmdiocb->list);
2804 pring->txcmplq_cnt--;
2805
2806 if (cmdiocb->iocb_cmpl) {
2807 icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
2808 icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
2809 spin_unlock_irq(phba->host->host_lock);
2810 (cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
2811 spin_lock_irq(phba->host->host_lock);
2812 } else
2813 lpfc_sli_release_iocbq(phba, cmdiocb);
2810 } 2814 }
2811 2815
2812 return 1; 2816 return 1;
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index a43549959dc7..10dd5a9ddfd3 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -39,9 +39,10 @@ struct lpfc_iocbq {
39 IOCB_t iocb; /* IOCB cmd */ 39 IOCB_t iocb; /* IOCB cmd */
40 uint8_t retry; /* retry counter for IOCB cmd - if needed */ 40 uint8_t retry; /* retry counter for IOCB cmd - if needed */
41 uint8_t iocb_flag; 41 uint8_t iocb_flag;
42#define LPFC_IO_LIBDFC 1 /* libdfc iocb */ 42#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
43#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ 43#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
44#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */ 44#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
45#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
45 46
46 uint8_t abort_count; 47 uint8_t abort_count;
47 uint8_t rsvd2; 48 uint8_t rsvd2;