scsi: aacraid: Added new IWBR reset

Added a new IWBR soft reset type, reworked the IOP reset interface for
a bit.

Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: Dave Carroll <David.Carroll@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Raghava Aditya Renukunta
2017-02-02 15:53:33 -08:00
committed by Martin K. Petersen
parent 999b3ffc0f
commit 3136432956
7 changed files with 136 additions and 57 deletions

View File

@@ -656,44 +656,100 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
return 0;
}
static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
static void aac_set_intx_mode(struct aac_dev *dev)
{
if (dev->msi_enabled) {
aac_src_access_devreg(dev, AAC_ENABLE_INTX);
dev->msi_enabled = 0;
msleep(5000); /* Delay 5 seconds */
}
}
static void aac_send_iop_reset(struct aac_dev *dev, int bled)
{
u32 var, reset_mask;
if (bled >= 0) {
if (bled)
printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
dev->name, dev->id, bled);
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
if ((bled || (var != 0x00000001)) &&
!dev->doorbell_mask)
return -EINVAL;
else if (dev->doorbell_mask) {
reset_mask = dev->doorbell_mask;
bled = 0;
var = 0x00000001;
}
bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
0, 0, 0, 0, 0, 0, &var,
&reset_mask, NULL, NULL, NULL);
if ((dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 ||
dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) {
aac_src_access_devreg(dev, AAC_ENABLE_INTX);
dev->msi_enabled = 0;
msleep(5000); /* Delay 5 seconds */
}
if (!bled && (dev->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) {
src_writel(dev, MUnit.IDR, reset_mask);
ssleep(45);
} else {
src_writel(dev, MUnit.IDR, 0x100);
ssleep(45);
}
if ((bled || var != 0x00000001) && !dev->doorbell_mask)
bled = -EINVAL;
else if (dev->doorbell_mask) {
reset_mask = dev->doorbell_mask;
bled = 0;
var = 0x00000001;
}
aac_set_intx_mode(dev);
if (!bled && (dev->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) {
src_writel(dev, MUnit.IDR, reset_mask);
} else {
src_writel(dev, MUnit.IDR, 0x100);
}
msleep(30000);
}
static void aac_send_hardware_soft_reset(struct aac_dev *dev)
{
u_int32_t val;
val = readl(((char *)(dev->base) + IBW_SWR_OFFSET));
val |= 0x01;
writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET));
msleep_interruptible(20000);
}
static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
{
unsigned long status, start;
if (bled < 0)
goto invalid_out;
if (bled)
pr_err("%s%d: adapter kernel panic'd %x.\n",
dev->name, dev->id, bled);
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
switch (reset_type) {
case IOP_HWSOFT_RESET:
aac_send_iop_reset(dev, bled);
/*
* 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
*/
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));
}
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 (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
return -ENODEV;
@@ -748,14 +804,15 @@ int aac_src_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
if ((aac_reset_devices || reset_devices) &&
!aac_src_restart_adapter(dev, 0))
!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
++restart;
/*
* Check to see if the board panic'd while booting.
*/
status = src_readl(dev, MUnit.OMR);
if (status & KERNEL_PANIC) {
if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
if (aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET))
goto error_iounmap;
++restart;
}
@@ -796,7 +853,7 @@ int aac_src_init(struct aac_dev *dev)
? (startup_timeout - 60)
: (startup_timeout / 2))))) {
if (likely(!aac_src_restart_adapter(dev,
aac_src_check_health(dev))))
aac_src_check_health(dev), IOP_HWSOFT_RESET)))
start = jiffies;
++restart;
}
@@ -893,7 +950,7 @@ int aac_srcv_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
if ((aac_reset_devices || reset_devices) &&
!aac_src_restart_adapter(dev, 0))
!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
++restart;
/*
* Check to see if flash update is running.
@@ -922,7 +979,8 @@ int aac_srcv_init(struct aac_dev *dev)
*/
status = src_readl(dev, MUnit.OMR);
if (status & KERNEL_PANIC) {
if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
if (aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET))
goto error_iounmap;
++restart;
}
@@ -961,7 +1019,8 @@ int aac_srcv_init(struct aac_dev *dev)
((startup_timeout > 60)
? (startup_timeout - 60)
: (startup_timeout / 2))))) {
if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev))))
if (likely(!aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET)))
start = jiffies;
++restart;
}