Skip to content

Commit

Permalink
Char: isicom, cleanup locking
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jiri Slaby authored and Linus Torvalds committed Jul 17, 2007
1 parent c4923b4 commit 5b21f9d
Showing 1 changed file with 27 additions and 38 deletions.
65 changes: 27 additions & 38 deletions drivers/char/isicom.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,41 +243,25 @@ 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);

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);
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 5b21f9d

Please sign in to comment.