diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:52:20 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:14 -0400 |
commit | 2534ba756ec407d343af45168273d3a64825a7ba (patch) | |
tree | ebefbc11ba342bd93ceac0946d1e4154809e5d92 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 46fa311e6967b526e1fd9b0b44edda6841dcac27 (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.c | 72 |
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, | |||
1455 | int | 1455 | int |
1456 | lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | 1456 | lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) |
1457 | { | 1457 | { |
1458 | LIST_HEAD(completions); | ||
1458 | struct lpfc_iocbq *iocb, *next_iocb; | 1459 | struct lpfc_iocbq *iocb, *next_iocb; |
1459 | IOCB_t *icmd = NULL, *cmd = NULL; | 1460 | IOCB_t *cmd = NULL; |
1460 | int errcnt; | 1461 | int errcnt; |
1461 | 1462 | ||
1462 | errcnt = 0; | 1463 | errcnt = 0; |
@@ -1465,46 +1466,28 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1465 | * First do the txq. | 1466 | * First do the txq. |
1466 | */ | 1467 | */ |
1467 | spin_lock_irq(phba->host->host_lock); | 1468 | spin_lock_irq(phba->host->host_lock); |
1468 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 1469 | list_splice_init(&pring->txq, &completions); |
1469 | list_del_init(&iocb->list); | ||
1470 | if (iocb->iocb_cmpl) { | ||
1471 | icmd = &iocb->iocb; | ||
1472 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
1473 | icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
1474 | spin_unlock_irq(phba->host->host_lock); | ||
1475 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
1476 | spin_lock_irq(phba->host->host_lock); | ||
1477 | } else | ||
1478 | lpfc_sli_release_iocbq(phba, iocb); | ||
1479 | } | ||
1480 | pring->txq_cnt = 0; | 1470 | pring->txq_cnt = 0; |
1481 | INIT_LIST_HEAD(&(pring->txq)); | ||
1482 | 1471 | ||
1483 | /* Next issue ABTS for everything on the txcmplq */ | 1472 | /* Next issue ABTS for everything on the txcmplq */ |
1484 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 1473 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) |
1485 | cmd = &iocb->iocb; | 1474 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
1486 | 1475 | ||
1487 | /* | 1476 | spin_unlock_irq(phba->host->host_lock); |
1488 | * Imediate abort of IOCB, deque and call compl | ||
1489 | */ | ||
1490 | 1477 | ||
1491 | list_del_init(&iocb->list); | 1478 | while (!list_empty(&completions)) { |
1492 | pring->txcmplq_cnt--; | 1479 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
1480 | cmd = &iocb->iocb; | ||
1481 | list_del(&iocb->list); | ||
1493 | 1482 | ||
1494 | if (iocb->iocb_cmpl) { | 1483 | if (iocb->iocb_cmpl) { |
1495 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | 1484 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
1496 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | 1485 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
1497 | spin_unlock_irq(phba->host->host_lock); | ||
1498 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 1486 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
1499 | spin_lock_irq(phba->host->host_lock); | ||
1500 | } else | 1487 | } else |
1501 | lpfc_sli_release_iocbq(phba, iocb); | 1488 | lpfc_sli_release_iocbq(phba, iocb); |
1502 | } | 1489 | } |
1503 | 1490 | ||
1504 | INIT_LIST_HEAD(&pring->txcmplq); | ||
1505 | pring->txcmplq_cnt = 0; | ||
1506 | spin_unlock_irq(phba->host->host_lock); | ||
1507 | |||
1508 | return errcnt; | 1491 | return errcnt; |
1509 | } | 1492 | } |
1510 | 1493 | ||
@@ -2605,11 +2588,12 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba) | |||
2605 | int | 2588 | int |
2606 | lpfc_sli_hba_down(struct lpfc_hba * phba) | 2589 | lpfc_sli_hba_down(struct lpfc_hba * phba) |
2607 | { | 2590 | { |
2591 | LIST_HEAD(completions); | ||
2608 | struct lpfc_sli *psli; | 2592 | struct lpfc_sli *psli; |
2609 | struct lpfc_sli_ring *pring; | 2593 | struct lpfc_sli_ring *pring; |
2610 | LPFC_MBOXQ_t *pmb; | 2594 | LPFC_MBOXQ_t *pmb; |
2611 | struct lpfc_iocbq *iocb, *next_iocb; | 2595 | struct lpfc_iocbq *iocb; |
2612 | IOCB_t *icmd = NULL; | 2596 | IOCB_t *cmd = NULL; |
2613 | int i; | 2597 | int i; |
2614 | unsigned long flags = 0; | 2598 | unsigned long flags = 0; |
2615 | 2599 | ||
@@ -2617,7 +2601,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) | |||
2617 | lpfc_hba_down_prep(phba); | 2601 | lpfc_hba_down_prep(phba); |
2618 | 2602 | ||
2619 | spin_lock_irqsave(phba->host->host_lock, flags); | 2603 | spin_lock_irqsave(phba->host->host_lock, flags); |
2620 | |||
2621 | for (i = 0; i < psli->num_rings; i++) { | 2604 | for (i = 0; i < psli->num_rings; i++) { |
2622 | pring = &psli->ring[i]; | 2605 | pring = &psli->ring[i]; |
2623 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 2606 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
@@ -2626,28 +2609,25 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) | |||
2626 | * Error everything on the txq since these iocbs have not been | 2609 | * Error everything on the txq since these iocbs have not been |
2627 | * given to the FW yet. | 2610 | * given to the FW yet. |
2628 | */ | 2611 | */ |
2612 | list_splice_init(&pring->txq, &completions); | ||
2629 | pring->txq_cnt = 0; | 2613 | pring->txq_cnt = 0; |
2630 | 2614 | ||
2631 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 2615 | } |
2632 | list_del_init(&iocb->list); | 2616 | spin_unlock_irqrestore(phba->host->host_lock, flags); |
2633 | if (iocb->iocb_cmpl) { | ||
2634 | icmd = &iocb->iocb; | ||
2635 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2636 | icmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2637 | spin_unlock_irqrestore(phba->host->host_lock, | ||
2638 | flags); | ||
2639 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2640 | spin_lock_irqsave(phba->host->host_lock, flags); | ||
2641 | } else | ||
2642 | lpfc_sli_release_iocbq(phba, iocb); | ||
2643 | } | ||
2644 | 2617 | ||
2645 | INIT_LIST_HEAD(&(pring->txq)); | 2618 | while (!list_empty(&completions)) { |
2619 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | ||
2620 | cmd = &iocb->iocb; | ||
2621 | list_del(&iocb->list); | ||
2646 | 2622 | ||
2623 | if (iocb->iocb_cmpl) { | ||
2624 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2625 | cmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2626 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2627 | } else | ||
2628 | lpfc_sli_release_iocbq(phba, iocb); | ||
2647 | } | 2629 | } |
2648 | 2630 | ||
2649 | spin_unlock_irqrestore(phba->host->host_lock, flags); | ||
2650 | |||
2651 | /* Return any active mbox cmds */ | 2631 | /* Return any active mbox cmds */ |
2652 | del_timer_sync(&psli->mbox_tmo); | 2632 | del_timer_sync(&psli->mbox_tmo); |
2653 | spin_lock_irqsave(phba->host->host_lock, flags); | 2633 | spin_lock_irqsave(phba->host->host_lock, flags); |