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: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
c4923b4f13
Коммит
5b21f9dddd
|
@ -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++) {
|
||||||
return 1;
|
if (inw(base + 0xe) & 0x1)
|
||||||
} else {
|
return 1;
|
||||||
spin_unlock_irqrestore(&card->card_lock, card->flags);
|
udelay(10);
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче