[SCSI] aacraid: Relax the tight timeout loop on fib commands
authorBen Collins <bcollins@ubuntu.com>
Mon, 11 Jun 2012 18:44:44 +0000 (14:44 -0400)
committerJames Bottomley <JBottomley@Parallels.com>
Fri, 20 Jul 2012 07:58:44 +0000 (08:58 +0100)
The loop that waited for syncronous fib commands was causing a CPU stall
when a timeout actually occured.

1) Switch to using a more accurate timeout mechanism.
2) Do not pace the loop with udelay(). Use cpu_relax() to allow for
   scheduling to occur.

Signed-off-by: Ben Collins <bcollins@ubuntu.com>
Acked-by: Achim Leubner <Achim_Leubner@pmc-sierra.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/aacraid/commsup.c

index 4b32ca442433036860bc819eff2909efc6155e46..906a5013edae4a87d97e0e57d719235fc9830520 100644 (file)
@@ -564,10 +564,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                         * functioning because an interrupt routing or other
                         * hardware failure has occurred.
                         */
-                       unsigned long count = 36000000L; /* 3 minutes */
+                       unsigned long timeout = jiffies + (180 * HZ); /* 3 minutes */
                        while (down_trylock(&fibptr->event_wait)) {
                                int blink;
-                               if (--count == 0) {
+                               if (time_is_before_eq_jiffies(timeout)) {
                                        struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue];
                                        spin_lock_irqsave(q->lock, qflags);
                                        q->numpending--;
@@ -588,7 +588,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                        }
                                        return -EFAULT;
                                }
-                               udelay(5);
+                               /* We used to udelay() here but that absorbed
+                                * a CPU when a timeout occured. Not very
+                                * useful. */
+                               cpu_relax();
                        }
                } else if (down_interruptible(&fibptr->event_wait)) {
                        /* Do nothing ... satisfy