aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2007-07-17 07:05:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:10 -0400
commit5b21f9dddd0817b761f1407f1950bee4f257411a (patch)
tree5c63ba601347b3723d7466bc5c5afd21256829b4
parentc4923b4f13156455a9e84f0b918866aef300cc57 (diff)
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>
-rw-r--r--drivers/char/isicom.c65
1 files changed, 27 insertions, 38 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 761f77740d67..b133b92a0ad5 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -243,17 +243,18 @@ static inline int WaitTillCardIsFree(u16 base)
243 243
244static int lock_card(struct isi_board *card) 244static int lock_card(struct isi_board *card)
245{ 245{
246 char retries;
247 unsigned long base = card->base; 246 unsigned long base = card->base;
247 unsigned int retries, a;
248 248
249 for (retries = 0; retries < 100; retries++) { 249 for (retries = 0; retries < 10; retries++) {
250 spin_lock_irqsave(&card->card_lock, card->flags); 250 spin_lock_irqsave(&card->card_lock, card->flags);
251 if (inw(base + 0xe) & 0x1) { 251 for (a = 0; a < 10; a++) {
252 return 1; 252 if (inw(base + 0xe) & 0x1)
253 } else { 253 return 1;
254 spin_unlock_irqrestore(&card->card_lock, card->flags); 254 udelay(10);
255 udelay(1000); /* 1ms */
256 } 255 }
256 spin_unlock_irqrestore(&card->card_lock, card->flags);
257 msleep(10);
257 } 258 }
258 printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n", 259 printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
259 card->base); 260 card->base);
@@ -261,23 +262,6 @@ static int lock_card(struct isi_board *card)
261 return 0; /* Failed to acquire the card! */ 262 return 0; /* Failed to acquire the card! */
262} 263}
263 264
264static int lock_card_at_interrupt(struct isi_board *card)
265{
266 unsigned char retries;
267 unsigned long base = card->base;
268
269 for (retries = 0; retries < 200; retries++) {
270 spin_lock_irqsave(&card->card_lock, card->flags);
271
272 if (inw(base + 0xe) & 0x1)
273 return 1;
274 else
275 spin_unlock_irqrestore(&card->card_lock, card->flags);
276 }
277 /* Failing in interrupt is an acceptable event */
278 return 0; /* Failed to acquire the card! */
279}
280
281static void unlock_card(struct isi_board *card) 265static void unlock_card(struct isi_board *card)
282{ 266{
283 spin_unlock_irqrestore(&card->card_lock, card->flags); 267 spin_unlock_irqrestore(&card->card_lock, card->flags);
@@ -415,6 +399,8 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
415 399
416static void isicom_tx(unsigned long _data) 400static void isicom_tx(unsigned long _data)
417{ 401{
402 unsigned long flags;
403 unsigned int retries;
418 short count = (BOARD_COUNT-1), card, base; 404 short count = (BOARD_COUNT-1), card, base;
419 short txcount, wrd, residue, word_count, cnt; 405 short txcount, wrd, residue, word_count, cnt;
420 struct isi_port *port; 406 struct isi_port *port;
@@ -435,32 +421,34 @@ static void isicom_tx(unsigned long _data)
435 count = isi_card[card].port_count; 421 count = isi_card[card].port_count;
436 port = isi_card[card].ports; 422 port = isi_card[card].ports;
437 base = isi_card[card].base; 423 base = isi_card[card].base;
424
425 spin_lock_irqsave(&isi_card[card].card_lock, flags);
426 for (retries = 0; retries < 100; retries++) {
427 if (inw(base + 0xe) & 0x1)
428 break;
429 udelay(2);
430 }
431 if (retries >= 100)
432 goto unlock;
433
438 for (;count > 0;count--, port++) { 434 for (;count > 0;count--, port++) {
439 if (!lock_card_at_interrupt(&isi_card[card]))
440 continue;
441 /* port not active or tx disabled to force flow control */ 435 /* port not active or tx disabled to force flow control */
442 if (!(port->flags & ASYNC_INITIALIZED) || 436 if (!(port->flags & ASYNC_INITIALIZED) ||
443 !(port->status & ISI_TXOK)) 437 !(port->status & ISI_TXOK))
444 unlock_card(&isi_card[card]);
445 continue; 438 continue;
446 439
447 tty = port->tty; 440 tty = port->tty;
448 441
449 442 if (tty == NULL)
450 if (tty == NULL) {
451 unlock_card(&isi_card[card]);
452 continue; 443 continue;
453 }
454 444
455 txcount = min_t(short, TX_SIZE, port->xmit_cnt); 445 txcount = min_t(short, TX_SIZE, port->xmit_cnt);
456 if (txcount <= 0 || tty->stopped || tty->hw_stopped) { 446 if (txcount <= 0 || tty->stopped || tty->hw_stopped)
457 unlock_card(&isi_card[card]);
458 continue; 447 continue;
459 } 448
460 if (!(inw(base + 0x02) & (1 << port->channel))) { 449 if (!(inw(base + 0x02) & (1 << port->channel)))
461 unlock_card(&isi_card[card]);
462 continue; 450 continue;
463 } 451
464 pr_dbg("txing %d bytes, port%d.\n", txcount, 452 pr_dbg("txing %d bytes, port%d.\n", txcount,
465 port->channel + 1); 453 port->channel + 1);
466 outw((port->channel << isi_card[card].shift_count) | txcount, 454 outw((port->channel << isi_card[card].shift_count) | txcount,
@@ -508,9 +496,10 @@ static void isicom_tx(unsigned long _data)
508 port->status &= ~ISI_TXOK; 496 port->status &= ~ISI_TXOK;
509 if (port->xmit_cnt <= WAKEUP_CHARS) 497 if (port->xmit_cnt <= WAKEUP_CHARS)
510 tty_wakeup(tty); 498 tty_wakeup(tty);
511 unlock_card(&isi_card[card]);
512 } 499 }
513 500
501unlock:
502 spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
514 /* schedule another tx for hopefully in about 10ms */ 503 /* schedule another tx for hopefully in about 10ms */
515sched_again: 504sched_again:
516 if (!re_schedule) { 505 if (!re_schedule) {