aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2010-10-22 15:21:07 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-10-23 12:45:06 -0400
commitafa842fa641e11a025725883b04d1e144e6bad39 (patch)
tree3cb94bba43974ac3eac1f63ebd96ba1d743bb715 /drivers/block/cciss.c
parent53c2eb24ff49abe1bfc45d067797f74b409690d8 (diff)
cciss: fix board status waiting code
After a reset, we should first wait for the board to become "not ready", and then wait for it to become "ready", instead of immediately waiting for it to become "ready", and do this waiting *after* restoring PCI config space registers. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index f09e6df15aa7..fd08644bf2a0 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -4006,18 +4006,31 @@ static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
4006 return -ENODEV; 4006 return -ENODEV;
4007} 4007}
4008 4008
4009static int __devinit cciss_wait_for_board_ready(ctlr_info_t *h) 4009static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev,
4010 void __iomem *vaddr, int wait_for_ready)
4011#define BOARD_READY 1
4012#define BOARD_NOT_READY 0
4010{ 4013{
4011 int i; 4014 int i, iterations;
4012 u32 scratchpad; 4015 u32 scratchpad;
4013 4016
4014 for (i = 0; i < CCISS_BOARD_READY_ITERATIONS; i++) { 4017 if (wait_for_ready)
4015 scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); 4018 iterations = CCISS_BOARD_READY_ITERATIONS;
4016 if (scratchpad == CCISS_FIRMWARE_READY) 4019 else
4017 return 0; 4020 iterations = CCISS_BOARD_NOT_READY_ITERATIONS;
4021
4022 for (i = 0; i < iterations; i++) {
4023 scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
4024 if (wait_for_ready) {
4025 if (scratchpad == CCISS_FIRMWARE_READY)
4026 return 0;
4027 } else {
4028 if (scratchpad != CCISS_FIRMWARE_READY)
4029 return 0;
4030 }
4018 msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS); 4031 msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS);
4019 } 4032 }
4020 dev_warn(&h->pdev->dev, "board not ready, timed out.\n"); 4033 dev_warn(&pdev->dev, "board not ready, timed out.\n");
4021 return -ENODEV; 4034 return -ENODEV;
4022} 4035}
4023 4036
@@ -4183,7 +4196,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
4183 err = -ENOMEM; 4196 err = -ENOMEM;
4184 goto err_out_free_res; 4197 goto err_out_free_res;
4185 } 4198 }
4186 err = cciss_wait_for_board_ready(h); 4199 err = cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
4187 if (err) 4200 if (err)
4188 goto err_out_free_res; 4201 goto err_out_free_res;
4189 err = cciss_find_cfgtables(h); 4202 err = cciss_find_cfgtables(h);
@@ -4534,6 +4547,20 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4534 need a little pause here */ 4547 need a little pause here */
4535 msleep(CCISS_POST_RESET_PAUSE_MSECS); 4548 msleep(CCISS_POST_RESET_PAUSE_MSECS);
4536 4549
4550 /* Wait for board to become not ready, then ready. */
4551 dev_info(&pdev->dev, "Waiting for board to become ready.\n");
4552 rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
4553 if (rc) /* Don't bail, might be E500, etc. which can't be reset */
4554 dev_warn(&pdev->dev,
4555 "failed waiting for board to become not ready\n");
4556 rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_READY);
4557 if (rc) {
4558 dev_warn(&pdev->dev,
4559 "failed waiting for board to become ready\n");
4560 goto unmap_cfgtable;
4561 }
4562 dev_info(&pdev->dev, "board ready.\n");
4563
4537 /* Controller should be in simple mode at this point. If it's not, 4564 /* Controller should be in simple mode at this point. If it's not,
4538 * It means we're on one of those controllers which doesn't support 4565 * It means we're on one of those controllers which doesn't support
4539 * the doorbell reset method and on which the PCI power management reset 4566 * the doorbell reset method and on which the PCI power management reset