diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 17:52:20 +0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 18:33:14 +0400 |
commit | 2534ba756ec407d343af45168273d3a64825a7ba (patch) | |
tree | ebefbc11ba342bd93ceac0946d1e4154809e5d92 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | 46fa311e6967b526e1fd9b0b44edda6841dcac27 (diff) | |
download | linux-2534ba756ec407d343af45168273d3a64825a7ba.tar.xz |
[SCSI] lpfc 8.1.12 : Fix unlock inside list traversal
Fix unlock inside list traversal.
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 | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index aa7f446c8da1..1c78a71b404d 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -170,11 +170,11 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, int lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) { + LIST_HEAD(completions); struct lpfc_sli *psli; struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *icmd; - int found = 0; + IOCB_t *cmd; /* Abort outstanding I/O on NPort <nlp_DID> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, @@ -187,45 +187,40 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) pring = &psli->ring[LPFC_ELS_RING]; /* First check the txq */ - do { - found = 0; - spin_lock_irq(phba->host->host_lock); - list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { - /* Check to see if iocb matches the nport we are looking - for */ - if ((lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))) { - found = 1; - /* It matches, so deque and call compl with an - error */ - list_del(&iocb->list); - pring->txq_cnt--; - if (iocb->iocb_cmpl) { - icmd = &iocb->iocb; - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - spin_unlock_irq(phba->host->host_lock); - (iocb->iocb_cmpl) (phba, iocb, iocb); - spin_lock_irq(phba->host->host_lock); - } else - lpfc_sli_release_iocbq(phba, iocb); - break; - } + spin_lock_irq(phba->host->host_lock); + list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { + /* Check to see if iocb matches the nport we are looking + for */ + if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { + /* It matches, so deque and call compl with an + error */ + list_move_tail(&iocb->list, &completions); + pring->txq_cnt--; } - spin_unlock_irq(phba->host->host_lock); - } while (found); + } /* Next check the txcmplq */ - spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { /* Check to see if iocb matches the nport we are looking for */ - if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { - icmd = &iocb->iocb; + if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) lpfc_sli_issue_abort_iotag(phba, pring, iocb); - } } spin_unlock_irq(phba->host->host_lock); + while (!list_empty(&completions)) { + iocb = list_get_first(&completions, struct lpfc_iocbq, list); + cmd = &iocb->iocb; + list_del(&iocb->list); + + if (iocb->iocb_cmpl) { + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + (iocb->iocb_cmpl) (phba, iocb, iocb); + } else + lpfc_sli_release_iocbq(phba, iocb); + } + /* If we are delaying issuing an ELS command, cancel it */ if (ndlp->nlp_flag & NLP_DELAY_TMO) lpfc_cancel_retry_delay_tmo(phba, ndlp); |