Commit 5b21f9dd authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

Char: isicom, cleanup locking

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: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c4923b4f
...@@ -243,17 +243,18 @@ static inline int WaitTillCardIsFree(u16 base) ...@@ -243,17 +243,18 @@ static inline int WaitTillCardIsFree(u16 base)
static int lock_card(struct isi_board *card) static int lock_card(struct isi_board *card)
{ {
char retries;
unsigned long base = card->base; 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); spin_lock_irqsave(&card->card_lock, card->flags);
if (inw(base + 0xe) & 0x1) { for (a = 0; a < 10; a++) {
if (inw(base + 0xe) & 0x1)
return 1; return 1;
} else { udelay(10);
spin_unlock_irqrestore(&card->card_lock, card->flags);
udelay(1000); /* 1ms */
} }
spin_unlock_irqrestore(&card->card_lock, card->flags);
msleep(10);
} }
printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n", printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
card->base); card->base);
...@@ -261,23 +262,6 @@ static int lock_card(struct isi_board *card) ...@@ -261,23 +262,6 @@ static int lock_card(struct isi_board *card)
return 0; /* Failed to acquire the 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) static void unlock_card(struct isi_board *card)
{ {
spin_unlock_irqrestore(&card->card_lock, card->flags); spin_unlock_irqrestore(&card->card_lock, card->flags);
...@@ -415,6 +399,8 @@ static inline int __isicom_paranoia_check(struct isi_port const *port, ...@@ -415,6 +399,8 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
static void isicom_tx(unsigned long _data) static void isicom_tx(unsigned long _data)
{ {
unsigned long flags;
unsigned int retries;
short count = (BOARD_COUNT-1), card, base; short count = (BOARD_COUNT-1), card, base;
short txcount, wrd, residue, word_count, cnt; short txcount, wrd, residue, word_count, cnt;
struct isi_port *port; struct isi_port *port;
...@@ -435,32 +421,34 @@ static void isicom_tx(unsigned long _data) ...@@ -435,32 +421,34 @@ static void isicom_tx(unsigned long _data)
count = isi_card[card].port_count; count = isi_card[card].port_count;
port = isi_card[card].ports; port = isi_card[card].ports;
base = isi_card[card].base; 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++) { for (;count > 0;count--, port++) {
if (!lock_card_at_interrupt(&isi_card[card]))
continue;
/* port not active or tx disabled to force flow control */ /* port not active or tx disabled to force flow control */
if (!(port->flags & ASYNC_INITIALIZED) || if (!(port->flags & ASYNC_INITIALIZED) ||
!(port->status & ISI_TXOK)) !(port->status & ISI_TXOK))
unlock_card(&isi_card[card]);
continue; continue;
tty = port->tty; tty = port->tty;
if (tty == NULL)
if (tty == NULL) {
unlock_card(&isi_card[card]);
continue; continue;
}
txcount = min_t(short, TX_SIZE, port->xmit_cnt); txcount = min_t(short, TX_SIZE, port->xmit_cnt);
if (txcount <= 0 || tty->stopped || tty->hw_stopped) { if (txcount <= 0 || tty->stopped || tty->hw_stopped)
unlock_card(&isi_card[card]);
continue; continue;
}
if (!(inw(base + 0x02) & (1 << port->channel))) { if (!(inw(base + 0x02) & (1 << port->channel)))
unlock_card(&isi_card[card]);
continue; continue;
}
pr_dbg("txing %d bytes, port%d.\n", txcount, pr_dbg("txing %d bytes, port%d.\n", txcount,
port->channel + 1); port->channel + 1);
outw((port->channel << isi_card[card].shift_count) | txcount, outw((port->channel << isi_card[card].shift_count) | txcount,
...@@ -508,9 +496,10 @@ static void isicom_tx(unsigned long _data) ...@@ -508,9 +496,10 @@ static void isicom_tx(unsigned long _data)
port->status &= ~ISI_TXOK; port->status &= ~ISI_TXOK;
if (port->xmit_cnt <= WAKEUP_CHARS) if (port->xmit_cnt <= WAKEUP_CHARS)
tty_wakeup(tty); 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 */ /* schedule another tx for hopefully in about 10ms */
sched_again: sched_again:
if (!re_schedule) { if (!re_schedule) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment