diff options
Diffstat (limited to 'drivers/scsi/aacraid/src.c')
-rw-r--r-- | drivers/scsi/aacraid/src.c | 136 |
1 files changed, 81 insertions, 55 deletions
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 7b0410e0f569..48c2b2b34b72 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -694,33 +694,52 @@ static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev) 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); } -static void aac_send_iop_reset(struct aac_dev *dev, int bled) +static bool aac_is_ctrl_up_and_running(struct aac_dev *dev) { - u32 var, reset_mask; + bool ctrl_up = true; + unsigned long status, start; + bool is_up = false; - aac_dump_fw_fib_iop_reset(dev); + start = jiffies; + do { + schedule(); + status = src_readl(dev, MUnit.OMR); - bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, - 0, 0, 0, 0, 0, 0, &var, - &reset_mask, NULL, NULL, NULL); + if (status == 0xffffffff) + status = 0; - if ((bled || var != 0x00000001) && !dev->doorbell_mask) - bled = -EINVAL; - else if (dev->doorbell_mask) { - reset_mask = dev->doorbell_mask; - bled = 0; - var = 0x00000001; - } + if (status & KERNEL_BOOTING) { + start = jiffies; + continue; + } + + if (time_after(jiffies, start+HZ*SOFT_RESET_TIME)) { + ctrl_up = false; + break; + } + + is_up = status & KERNEL_UP_AND_RUNNING; + + } while (!is_up); + + return ctrl_up; +} + +static void aac_notify_fw_of_iop_reset(struct aac_dev *dev) +{ + aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, NULL, + NULL, NULL, NULL, NULL); +} + +static void aac_send_iop_reset(struct aac_dev *dev) +{ + aac_dump_fw_fib_iop_reset(dev); + + aac_notify_fw_of_iop_reset(dev); aac_set_intx_mode(dev); - if (!bled && (dev->supplement_adapter_info.supported_options2 & - AAC_OPTION_DOORBELL_RESET)) { - src_writel(dev, MUnit.IDR, reset_mask); - } else { - src_writel(dev, MUnit.IDR, 0x100); - } - msleep(30000); + src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK); } static void aac_send_hardware_soft_reset(struct aac_dev *dev) @@ -735,14 +754,14 @@ static void aac_send_hardware_soft_reset(struct aac_dev *dev) static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) { - unsigned long status, start; + bool is_ctrl_up; + int ret = 0; if (bled < 0) goto invalid_out; if (bled) - pr_err("%s%d: adapter kernel panic'd %x.\n", - dev->name, dev->id, bled); + dev_err(&dev->pdev->dev, "adapter kernel panic'd %x.\n", bled); /* * When there is a BlinkLED, IOP_RESET has not effect @@ -752,48 +771,55 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; - switch (reset_type) { - case IOP_HWSOFT_RESET: - aac_send_iop_reset(dev, bled); + dev_err(&dev->pdev->dev, "Controller reset type is %d\n", reset_type); + + if (reset_type & HW_IOP_RESET) { + dev_info(&dev->pdev->dev, "Issuing IOP reset\n"); + aac_send_iop_reset(dev); + /* - * Check to see if KERNEL_UP_AND_RUNNING - * Wait for the adapter to be up and running. - * If !KERNEL_UP_AND_RUNNING issue HW Soft Reset + * Creates a delay or wait till up and running comes thru */ - status = src_readl(dev, MUnit.OMR); - if (dev->sa_firmware - && !(status & KERNEL_UP_AND_RUNNING)) { - start = jiffies; - do { - status = src_readl(dev, MUnit.OMR); - if (time_after(jiffies, - start+HZ*SOFT_RESET_TIME)) { - aac_send_hardware_soft_reset(dev); - start = jiffies; - } - } while (!(status & KERNEL_UP_AND_RUNNING)); + is_ctrl_up = aac_is_ctrl_up_and_running(dev); + if (!is_ctrl_up) + dev_err(&dev->pdev->dev, "IOP reset failed\n"); + else { + dev_info(&dev->pdev->dev, "IOP reset succeded\n"); + goto set_startup; } - break; - case HW_SOFT_RESET: - if (dev->sa_firmware) { - aac_send_hardware_soft_reset(dev); - aac_set_intx_mode(dev); - } - break; - default: - aac_send_iop_reset(dev, bled); - break; } -invalid_out: + if (!dev->sa_firmware) { + dev_err(&dev->pdev->dev, "ARC Reset attempt failed\n"); + ret = -ENODEV; + goto out; + } - if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) - return -ENODEV; + if (reset_type & HW_SOFT_RESET) { + dev_info(&dev->pdev->dev, "Issuing SOFT reset\n"); + aac_send_hardware_soft_reset(dev); + dev->msi_enabled = 0; + is_ctrl_up = aac_is_ctrl_up_and_running(dev); + if (!is_ctrl_up) { + dev_err(&dev->pdev->dev, "SOFT reset failed\n"); + ret = -ENODEV; + goto out; + } else + dev_info(&dev->pdev->dev, "SOFT reset succeded\n"); + } + +set_startup: if (startup_timeout < 300) startup_timeout = 300; - return 0; +out: + return ret; + +invalid_out: + if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) + ret = -ENODEV; +goto out; } /** |