[SCSI] aacraid: [Fastboot] Panics for AACRAID driver during 'insmod' for kexec test.
authorSalyzyn, Mark <mark_salyzyn@adaptec.com>
Fri, 30 Mar 2007 14:30:48 +0000 (10:30 -0400)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Sun, 1 Apr 2007 17:44:57 +0000 (12:44 -0500)
Attached is the patch I feel will address this issue. As an added
'perk' I have also added the code to detect if the controller was
previously initialized for interrupted operations by ANY operating
system should the reset_devices kernel parameter not be set and we are
dealing with a naïve kexec without the addition of this kernel
parameter. The reset handler is also improved. Related to reset
operations, but not pertinent specifically to this issue, I have also
altered the handling somewhat so that we reset the adapter if we feel
it is taking too long (three minutes) to start up.

We have not unit tested the reset_devices flag propagation to this
driver code, nor have we unit tested the check for the interrupted
operations under the conditions of a naively issued kexec. We are
submitting this modified driver to our Q/A department for integration
testing in our current programs. I would appreciate an ACK to this
patch should it resolve the issue described in this thread...

Signed-off-by: Mark Salyzyn <aacraid@adaptec.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/aacraid/rx.c

index 3e23aa6..0c71315 100644 (file)
@@ -467,16 +467,19 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
        if (bled)
                printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
                        dev->name, dev->id, bled);
-       else
+       else {
                bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
                  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
-       if (bled)
+               if (!bled && (var != 0x00000001))
+                       bled = -EINVAL;
+       }
+       if (bled && (bled != -ETIMEDOUT))
                bled = aac_adapter_sync_cmd(dev, IOP_RESET,
                  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
 
-       if (bled)
+       if (bled && (bled != -ETIMEDOUT))
                return -EINVAL;
-       if (var == 0x3803000F) { /* USE_OTHER_METHOD */
+       if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
                rx_writel(dev, MUnit.reserved2, 3);
                msleep(5000); /* Delay 5 seconds */
                var = 0x00000001;
@@ -526,6 +529,7 @@ int _aac_rx_init(struct aac_dev *dev)
 {
        unsigned long start;
        unsigned long status;
+       int restart = 0;
        int instance = dev->id;
        const char * name = dev->name;
 
@@ -534,15 +538,19 @@ int _aac_rx_init(struct aac_dev *dev)
                goto error_iounmap;
        }
 
+       /* Failure to reset here is an option ... */
+       dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
+       if ((((status & 0xff) != 0xff) || reset_devices) &&
+         !aac_rx_restart_adapter(dev, 0))
+               ++restart;
        /*
         *      Check to see if the board panic'd while booting.
         */
        status = rx_readl(dev, MUnit.OMRx[0]);
        if (status & KERNEL_PANIC) {
-               if ((status = aac_rx_check_health(dev)) <= 0)
-                       goto error_iounmap;
-               if (aac_rx_restart_adapter(dev, status))
+               if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
                        goto error_iounmap;
+               ++restart;
        }
        /*
         *      Check to see if the board failed any self tests.
@@ -565,11 +573,23 @@ int _aac_rx_init(struct aac_dev *dev)
         */
        while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
        {
-               if(time_after(jiffies, start+startup_timeout*HZ)) {
+               if ((restart &&
+                 (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
+                 time_after(jiffies, start+HZ*startup_timeout)) {
                        printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
                                        dev->name, instance, status);
                        goto error_iounmap;
                }
+               if (!restart &&
+                 ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
+                 time_after(jiffies, start + HZ *
+                 ((startup_timeout > 60)
+                   ? (startup_timeout - 60)
+                   : (startup_timeout / 2))))) {
+                       if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
+                               start = jiffies;
+                       ++restart;
+               }
                msleep(1);
        }
        /*