scsi: aacraid: Added new IWBR reset
authorRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Thu, 2 Feb 2017 23:53:33 +0000 (15:53 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 3 Feb 2017 15:35:04 +0000 (10:35 -0500)
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>
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/aacraid/src.c

index 4c04fd84dd81d5a0ab3ee80f091117b5438f66bd..1a09618b859d079e06d352b72d00e313e2e8bcc0 100644 (file)
@@ -4007,8 +4007,6 @@ static long aac_build_sghba(struct scsi_cmnd *scsicmd,
        u32 cur_size;
        struct aac_hba_sgl *sge;
 
-
-
        nseg = scsi_dma_map(scsicmd);
        if (nseg <= 0) {
                byte_count = nseg;
index 10984a4abee64e0bb57a60f8a5fe7ef67cf45811..6f465c0bb4d1745bdb718c7a883a8e48a6175f29 100644 (file)
@@ -878,7 +878,7 @@ struct adapter_ops
        void (*adapter_enable_int)(struct aac_dev *dev);
        int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
        int  (*adapter_check_health)(struct aac_dev *dev);
-       int  (*adapter_restart)(struct aac_dev *dev, int bled);
+       int  (*adapter_restart)(struct aac_dev *dev, int bled, u8 reset_type);
        void (*adapter_start)(struct aac_dev *dev);
        /* Transport operations */
        int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
@@ -1657,8 +1657,8 @@ struct aac_dev
 #define aac_adapter_check_health(dev) \
        (dev)->a_ops.adapter_check_health(dev)
 
-#define aac_adapter_restart(dev,bled) \
-       (dev)->a_ops.adapter_restart(dev,bled)
+#define aac_adapter_restart(dev, bled, reset_type) \
+       ((dev)->a_ops.adapter_restart(dev, bled, reset_type))
 
 #define aac_adapter_start(dev) \
        ((dev)->a_ops.adapter_start(dev))
@@ -2333,6 +2333,13 @@ struct revision
 #define FSACTL_FORCE_DELETE_DISK               CTL_CODE(2120, METHOD_NEITHER)
 #define FSACTL_GET_CONTAINERS                  2131
 #define FSACTL_SEND_LARGE_FIB                  CTL_CODE(2138, METHOD_BUFFERED)
+/* flags defined for IOP & HW SOFT RESET */
+#define HW_IOP_RESET                           0x01
+#define HW_SOFT_RESET                          0x02
+#define IOP_HWSOFT_RESET                       (HW_IOP_RESET | HW_SOFT_RESET)
+/* HW Soft Reset register offset */
+#define IBW_SWR_OFFSET                         0x4000
+#define SOFT_RESET_TIME                        60
 
 
 struct aac_common
@@ -2569,7 +2576,7 @@ unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
                        int isAif, int isFastResponse,
                        struct hw_fib *aif_fib);
-int aac_reset_adapter(struct aac_dev * dev, int forced);
+int aac_reset_adapter(struct aac_dev *dev, int forced, u8 reset_type);
 int aac_check_health(struct aac_dev * dev);
 int aac_command_thread(void *data);
 int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
index 09da354e99567fc0747cd483cfae1968e05fc3d1..2393bd9aff0e81f85b49add339bae8267f958aa8 100644 (file)
@@ -1455,7 +1455,7 @@ retry_next:
        }
 }
 
-static int _aac_reset_adapter(struct aac_dev *aac, int forced)
+static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
 {
        int index, quirks;
        int retval;
@@ -1464,6 +1464,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
        struct scsi_cmnd *command;
        struct scsi_cmnd *command_list;
        int jafo = 0;
+       int bled;
 
        /*
         * Assumptions:
@@ -1488,7 +1489,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
         *      If a positive health, means in a known DEAD PANIC
         * state and the adapter could be reset to `try again'.
         */
-       retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac));
+       bled = forced ? 0 : aac_adapter_check_health(aac);
+       retval = aac_adapter_restart(aac, bled, reset_type);
 
        if (retval)
                goto out;
@@ -1598,11 +1600,12 @@ out:
        return retval;
 }
 
-int aac_reset_adapter(struct aac_dev * aac, int forced)
+int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
 {
        unsigned long flagv = 0;
        int retval;
        struct Scsi_Host * host;
+       int bled;
 
        if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
                return -EBUSY;
@@ -1651,7 +1654,9 @@ int aac_reset_adapter(struct aac_dev * aac, int forced)
        if (forced < 2)
                aac_send_shutdown(aac);
        spin_lock_irqsave(host->host_lock, flagv);
-       retval = _aac_reset_adapter(aac, forced ? forced : ((aac_check_reset != 0) && (aac_check_reset != 1)));
+       bled = forced ? forced :
+                       (aac_check_reset != 0 && aac_check_reset != 1);
+       retval = _aac_reset_adapter(aac, bled, reset_type);
        spin_unlock_irqrestore(host->host_lock, flagv);
 
        if ((forced < 2) && (retval == -ENODEV)) {
@@ -1697,6 +1702,7 @@ int aac_check_health(struct aac_dev * aac)
        unsigned long time_now, flagv = 0;
        struct list_head * entry;
        struct Scsi_Host * host;
+       int bled;
 
        /* Extending the scope of fib_lock slightly to protect aac->in_reset */
        if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
@@ -1814,7 +1820,8 @@ int aac_check_health(struct aac_dev * aac)
        host = aac->scsi_host_ptr;
        if (aac->thread->pid != current->pid)
                spin_lock_irqsave(host->host_lock, flagv);
-       BlinkLED = _aac_reset_adapter(aac, aac_check_reset != 1);
+       bled = aac_check_reset != 1 ? 1 : 0;
+       _aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET);
        if (aac->thread->pid != current->pid)
                spin_unlock_irqrestore(host->host_lock, flagv);
        return BlinkLED;
index 58bed5df08608ca864344ba8a4eff7459faaafae..46d9596f882d9260d79d294af74dd60e9dcf7a67 100644 (file)
@@ -569,7 +569,7 @@ static ssize_t aac_show_unique_id(struct device *dev,
                memcpy(sn, aac->fsa_dev[sdev_id(sdev)].identifier, sizeof(sn));
 
        return snprintf(buf, 16 * 2 + 2,
-               "%02X%02X%02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X%02X%02X\n",
+               "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
                sn[0], sn[1], sn[2], sn[3],
                sn[4], sn[5], sn[6], sn[7],
                sn[8], sn[9], sn[10], sn[11],
@@ -899,7 +899,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
                           !(aac->supplement_adapter_info.SupportedOptions2 &
                            AAC_OPTION_IGNORE_RESET))) {
                        /* Bypass wait for command quiesce */
-                       aac_reset_adapter(aac, 2);
+                       aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET);
                }
                ret = SUCCESS;
        }
@@ -1167,10 +1167,16 @@ static ssize_t aac_store_reset_adapter(struct device *device,
                                       const char *buf, size_t count)
 {
        int retval = -EACCES;
+       int bled = 0;
+       struct aac_dev *aac;
+
 
        if (!capable(CAP_SYS_ADMIN))
                return retval;
-       retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
+
+       aac = (struct aac_dev *)class_to_shost(device)->hostdata;
+       bled = buf[0] == '!' ? 1:0;
+       retval = aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET);
        if (retval >= 0)
                retval = count;
        return retval;
index 67213b95b8b6b12e4fa6fba70769edb70f3fc909..8287e09f5ecf0b37842469aa91a730d89d481810 100644 (file)
@@ -470,7 +470,7 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
        return 0;
 }
 
-static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
+static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
 {
        u32 var = 0;
 
@@ -559,7 +559,7 @@ int _aac_rx_init(struct aac_dev *dev)
        dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
        dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
        if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) &&
-         !aac_rx_restart_adapter(dev, 0))
+         !aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
                /* Make sure the Hardware FIFO is empty */
                while ((++restart < 512) &&
                  (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL));
@@ -568,7 +568,8 @@ int _aac_rx_init(struct aac_dev *dev)
         */
        status = rx_readl(dev, MUnit.OMRx[0]);
        if (status & KERNEL_PANIC) {
-               if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
+               if (aac_rx_restart_adapter(dev,
+                       aac_rx_check_health(dev), IOP_HWSOFT_RESET))
                        goto error_iounmap;
                ++restart;
        }
@@ -606,7 +607,8 @@ int _aac_rx_init(struct aac_dev *dev)
                  ((startup_timeout > 60)
                    ? (startup_timeout - 60)
                    : (startup_timeout / 2))))) {
-                       if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
+                       if (likely(!aac_rx_restart_adapter(dev,
+                               aac_rx_check_health(dev), IOP_HWSOFT_RESET)))
                                start = jiffies;
                        ++restart;
                }
index b8538e017e10458444335ff85544ef4533cc1507..6124f1b13bf3f012a60dabb6a082077f9759a2b3 100644 (file)
@@ -257,7 +257,7 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
                        NULL, NULL, NULL, NULL, NULL);
 }
 
-static int aac_sa_restart_adapter(struct aac_dev *dev, int bled)
+static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
 {
        return -EINVAL;
 }
index 1dd62a4aad2c31ce12b4a6ee8a34b9ffaa19ac2f..874096e54a21237b63b170a11b73a10c6a6468be 100644 (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",
+       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)
+               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;
-               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;
-               }
 
-               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 */
-               }
+       dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
 
-               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);
+       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;
                }