mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
53c2eb24ff
commit
afa842fa64
|
@ -4006,18 +4006,31 @@ static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __devinit cciss_wait_for_board_ready(ctlr_info_t *h)
|
||||
static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev,
|
||||
void __iomem *vaddr, int wait_for_ready)
|
||||
#define BOARD_READY 1
|
||||
#define BOARD_NOT_READY 0
|
||||
{
|
||||
int i;
|
||||
int i, iterations;
|
||||
u32 scratchpad;
|
||||
|
||||
for (i = 0; i < CCISS_BOARD_READY_ITERATIONS; i++) {
|
||||
scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
|
||||
if (scratchpad == CCISS_FIRMWARE_READY)
|
||||
return 0;
|
||||
if (wait_for_ready)
|
||||
iterations = CCISS_BOARD_READY_ITERATIONS;
|
||||
else
|
||||
iterations = CCISS_BOARD_NOT_READY_ITERATIONS;
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
|
||||
if (wait_for_ready) {
|
||||
if (scratchpad == CCISS_FIRMWARE_READY)
|
||||
return 0;
|
||||
} else {
|
||||
if (scratchpad != CCISS_FIRMWARE_READY)
|
||||
return 0;
|
||||
}
|
||||
msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS);
|
||||
}
|
||||
dev_warn(&h->pdev->dev, "board not ready, timed out.\n");
|
||||
dev_warn(&pdev->dev, "board not ready, timed out.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -4183,7 +4196,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
|
|||
err = -ENOMEM;
|
||||
goto err_out_free_res;
|
||||
}
|
||||
err = cciss_wait_for_board_ready(h);
|
||||
err = cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
|
||||
if (err)
|
||||
goto err_out_free_res;
|
||||
err = cciss_find_cfgtables(h);
|
||||
|
@ -4534,6 +4547,20 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
|
|||
need a little pause here */
|
||||
msleep(CCISS_POST_RESET_PAUSE_MSECS);
|
||||
|
||||
/* Wait for board to become not ready, then ready. */
|
||||
dev_info(&pdev->dev, "Waiting for board to become ready.\n");
|
||||
rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
|
||||
if (rc) /* Don't bail, might be E500, etc. which can't be reset */
|
||||
dev_warn(&pdev->dev,
|
||||
"failed waiting for board to become not ready\n");
|
||||
rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_READY);
|
||||
if (rc) {
|
||||
dev_warn(&pdev->dev,
|
||||
"failed waiting for board to become ready\n");
|
||||
goto unmap_cfgtable;
|
||||
}
|
||||
dev_info(&pdev->dev, "board ready.\n");
|
||||
|
||||
/* Controller should be in simple mode at this point. If it's not,
|
||||
* It means we're on one of those controllers which doesn't support
|
||||
* the doorbell reset method and on which the PCI power management reset
|
||||
|
|
|
@ -200,10 +200,14 @@ struct ctlr_info
|
|||
* the above.
|
||||
*/
|
||||
#define CCISS_BOARD_READY_WAIT_SECS (120)
|
||||
#define CCISS_BOARD_NOT_READY_WAIT_SECS (10)
|
||||
#define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100)
|
||||
#define CCISS_BOARD_READY_ITERATIONS \
|
||||
((CCISS_BOARD_READY_WAIT_SECS * 1000) / \
|
||||
CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
|
||||
#define CCISS_BOARD_NOT_READY_ITERATIONS \
|
||||
((CCISS_BOARD_NOT_READY_WAIT_SECS * 1000) / \
|
||||
CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
|
||||
#define CCISS_POST_RESET_PAUSE_MSECS (3000)
|
||||
#define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000)
|
||||
#define CCISS_POST_RESET_NOOP_RETRIES (12)
|
||||
|
|
Loading…
Reference in New Issue