summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:52:20 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 09:33:14 -0500
commit2534ba756ec407d343af45168273d3a64825a7ba (patch)
treeebefbc11ba342bd93ceac0946d1e4154809e5d92 /drivers/scsi/lpfc/lpfc_sli.c
parent46fa311e6967b526e1fd9b0b44edda6841dcac27 (diff)
[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_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c72
1 files changed, 26 insertions, 46 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index dcd313ab4a72..16825243e603 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1455,8 +1455,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
int
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
+ LIST_HEAD(completions);
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *icmd = NULL, *cmd = NULL;
+ IOCB_t *cmd = NULL;
int errcnt;
errcnt = 0;
@@ -1465,46 +1466,28 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
* First do the txq.
*/
spin_lock_irq(phba->host->host_lock);
- list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
- list_del_init(&iocb->list);
- 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);
- }
+ list_splice_init(&pring->txq, &completions);
pring->txq_cnt = 0;
- INIT_LIST_HEAD(&(pring->txq));
/* Next issue ABTS for everything on the txcmplq */
- list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
- cmd = &iocb->iocb;
+ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
+ lpfc_sli_issue_abort_iotag(phba, pring, iocb);
- /*
- * Imediate abort of IOCB, deque and call compl
- */
+ spin_unlock_irq(phba->host->host_lock);
- list_del_init(&iocb->list);
- pring->txcmplq_cnt--;
+ 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;
- 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);
}
- INIT_LIST_HEAD(&pring->txcmplq);
- pring->txcmplq_cnt = 0;
- spin_unlock_irq(phba->host->host_lock);
-
return errcnt;
}
@@ -2605,11 +2588,12 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
int
lpfc_sli_hba_down(struct lpfc_hba * phba)
{
+ LIST_HEAD(completions);
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
LPFC_MBOXQ_t *pmb;
- struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *icmd = NULL;
+ struct lpfc_iocbq *iocb;
+ IOCB_t *cmd = NULL;
int i;
unsigned long flags = 0;
@@ -2617,7 +2601,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
lpfc_hba_down_prep(phba);
spin_lock_irqsave(phba->host->host_lock, flags);
-
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
pring->flag |= LPFC_DEFERRED_RING_EVENT;
@@ -2626,28 +2609,25 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
* Error everything on the txq since these iocbs have not been
* given to the FW yet.
*/
+ list_splice_init(&pring->txq, &completions);
pring->txq_cnt = 0;
- list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
- list_del_init(&iocb->list);
- if (iocb->iocb_cmpl) {
- icmd = &iocb->iocb;
- icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- icmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- spin_unlock_irqrestore(phba->host->host_lock,
- flags);
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- spin_lock_irqsave(phba->host->host_lock, flags);
- } else
- lpfc_sli_release_iocbq(phba, iocb);
- }
+ }
+ spin_unlock_irqrestore(phba->host->host_lock, flags);
- INIT_LIST_HEAD(&(pring->txq));
+ 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_DOWN;
+ (iocb->iocb_cmpl) (phba, iocb, iocb);
+ } else
+ lpfc_sli_release_iocbq(phba, iocb);
}
- spin_unlock_irqrestore(phba->host->host_lock, flags);
-
/* Return any active mbox cmds */
del_timer_sync(&psli->mbox_tmo);
spin_lock_irqsave(phba->host->host_lock, flags);