diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 43 |
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 | ||
4009 | static int __devinit cciss_wait_for_board_ready(ctlr_info_t *h) | 4009 | static 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 |