Char: isicom, cleanup locking
authorJiri Slaby <jirislaby@gmail.com>
Tue, 17 Jul 2007 11:05:17 +0000 (04:05 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 17 Jul 2007 17:23:10 +0000 (10:23 -0700)
Don't spin processor when not needed (use sleep instead of delay).  Don't
release the lock when needed in next iteration -- this actually fixes a bug --
missing braces

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/isicom.c

index 761f77740d67dda027d8ff82ea6effc1b77f31ee..b133b92a0ad5c01fe5eef2b8ec71408649b4b1e2 100644 (file)
@@ -243,17 +243,18 @@ static inline int WaitTillCardIsFree(u16 base)
 
 static int lock_card(struct isi_board *card)
 {
-       char            retries;
        unsigned long base = card->base;
+       unsigned int retries, a;
 
-       for (retries = 0; retries < 100; retries++) {
+       for (retries = 0; retries < 10; retries++) {
                spin_lock_irqsave(&card->card_lock, card->flags);
-               if (inw(base + 0xe) & 0x1) {
-                       return 1;
-               } else {
-                       spin_unlock_irqrestore(&card->card_lock, card->flags);
-                       udelay(1000);   /* 1ms */
+               for (a = 0; a < 10; a++) {
+                       if (inw(base + 0xe) & 0x1)
+                               return 1;
+                       udelay(10);
                }
+               spin_unlock_irqrestore(&card->card_lock, card->flags);
+               msleep(10);
        }
        printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
                card->base);
@@ -261,23 +262,6 @@ static int lock_card(struct isi_board *card)
        return 0;       /* Failed to acquire the card! */
 }
 
-static int lock_card_at_interrupt(struct isi_board *card)
-{
-       unsigned char           retries;
-       unsigned long base = card->base;
-
-       for (retries = 0; retries < 200; retries++) {
-               spin_lock_irqsave(&card->card_lock, card->flags);
-
-               if (inw(base + 0xe) & 0x1)
-                       return 1;
-               else
-                       spin_unlock_irqrestore(&card->card_lock, card->flags);
-       }
-       /* Failing in interrupt is an acceptable event */
-       return 0;       /* Failed to acquire the card! */
-}
-
 static void unlock_card(struct isi_board *card)
 {
        spin_unlock_irqrestore(&card->card_lock, card->flags);
@@ -415,6 +399,8 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
 
 static void isicom_tx(unsigned long _data)
 {
+       unsigned long flags;
+       unsigned int retries;
        short count = (BOARD_COUNT-1), card, base;
        short txcount, wrd, residue, word_count, cnt;
        struct isi_port *port;
@@ -435,32 +421,34 @@ static void isicom_tx(unsigned long _data)
        count = isi_card[card].port_count;
        port = isi_card[card].ports;
        base = isi_card[card].base;
+
+       spin_lock_irqsave(&isi_card[card].card_lock, flags);
+       for (retries = 0; retries < 100; retries++) {
+               if (inw(base + 0xe) & 0x1)
+                       break;
+               udelay(2);
+       }
+       if (retries >= 100)
+               goto unlock;
+
        for (;count > 0;count--, port++) {
-               if (!lock_card_at_interrupt(&isi_card[card]))
-                       continue;
                /* port not active or tx disabled to force flow control */
                if (!(port->flags & ASYNC_INITIALIZED) ||
                                !(port->status & ISI_TXOK))
-                       unlock_card(&isi_card[card]);
                        continue;
 
                tty = port->tty;
 
-
-               if (tty == NULL) {
-                       unlock_card(&isi_card[card]);
+               if (tty == NULL)
                        continue;
-               }
 
                txcount = min_t(short, TX_SIZE, port->xmit_cnt);
-               if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
-                       unlock_card(&isi_card[card]);
+               if (txcount <= 0 || tty->stopped || tty->hw_stopped)
                        continue;
-               }
-               if (!(inw(base + 0x02) & (1 << port->channel))) {
-                       unlock_card(&isi_card[card]);
+
+               if (!(inw(base + 0x02) & (1 << port->channel)))
                        continue;
-               }
+
                pr_dbg("txing %d bytes, port%d.\n", txcount,
                        port->channel + 1);
                outw((port->channel << isi_card[card].shift_count) | txcount,
@@ -508,9 +496,10 @@ static void isicom_tx(unsigned long _data)
                        port->status &= ~ISI_TXOK;
                if (port->xmit_cnt <= WAKEUP_CHARS)
                        tty_wakeup(tty);
-               unlock_card(&isi_card[card]);
        }
 
+unlock:
+       spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
        /*      schedule another tx for hopefully in about 10ms */
 sched_again:
        if (!re_schedule) {