aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/block/cciss.c43
-rw-r--r--drivers/block/cciss.h4
2 files changed, 39 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
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index ae340ffc8f81..4b8933d778f1 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -200,10 +200,14 @@ struct ctlr_info
200 * the above. 200 * the above.
201 */ 201 */
202#define CCISS_BOARD_READY_WAIT_SECS (120) 202#define CCISS_BOARD_READY_WAIT_SECS (120)
203#define CCISS_BOARD_NOT_READY_WAIT_SECS (10)
203#define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100) 204#define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100)
204#define CCISS_BOARD_READY_ITERATIONS \ 205#define CCISS_BOARD_READY_ITERATIONS \
205 ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \ 206 ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \
206 CCISS_BOARD_READY_POLL_INTERVAL_MSECS) 207 CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
208#define CCISS_BOARD_NOT_READY_ITERATIONS \
209 ((CCISS_BOARD_NOT_READY_WAIT_SECS * 1000) / \
210 CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
207#define CCISS_POST_RESET_PAUSE_MSECS (3000) 211#define CCISS_POST_RESET_PAUSE_MSECS (3000)
208#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000) 212#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000)
209#define CCISS_POST_RESET_NOOP_RETRIES (12) 213#define CCISS_POST_RESET_NOOP_RETRIES (12)