aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/cyclades.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-04-30 03:53:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:45 -0400
commit978e595f88a1fba5869aa42a4af4fba36f33ecac (patch)
tree60848f49949c5b7b518621ee36cdc6d500244539 /drivers/char/cyclades.c
parentac0e4b7d319bf284bb64bc7e1c051417386b34a4 (diff)
tty/serial: lay the foundations for the next set of reworks
- Stop drivers calling their own flush method indirectly, it obfuscates code and it will change soon anyway - A few more lock_kernel paths temporarily needed in some driver internal waiting code - Remove private put_char method that does a write call for one char - we have that anyway - Most but not yet all of the termios copy under lock fixing (some has other dependencies to follow) - Note a few locking bugs in drivers found in the process - Kill remaining [ab]users of TIOCG/SSOFTCAR in the driver, these must go to fix the termios locking Signed-off-by: Alan Cox <alan@redhat.com> Cc: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r--drivers/char/cyclades.c76
1 files changed, 40 insertions, 36 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e61939d3331d..571e4fab5bfa 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2522,6 +2522,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
2522 return; /* Just in case.... */ 2522 return; /* Just in case.... */
2523 2523
2524 orig_jiffies = jiffies; 2524 orig_jiffies = jiffies;
2525 lock_kernel();
2525 /* 2526 /*
2526 * Set the check interval to be 1/5 of the estimated time to 2527 * Set the check interval to be 1/5 of the estimated time to
2527 * send a single character, and make it at least 1. The check 2528 * send a single character, and make it at least 1. The check
@@ -2573,11 +2574,47 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
2573 } 2574 }
2574 /* Run one more char cycle */ 2575 /* Run one more char cycle */
2575 msleep_interruptible(jiffies_to_msecs(char_time * 5)); 2576 msleep_interruptible(jiffies_to_msecs(char_time * 5));
2577 unlock_kernel();
2576#ifdef CY_DEBUG_WAIT_UNTIL_SENT 2578#ifdef CY_DEBUG_WAIT_UNTIL_SENT
2577 printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); 2579 printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
2578#endif 2580#endif
2579} 2581}
2580 2582
2583static void cy_flush_buffer(struct tty_struct *tty)
2584{
2585 struct cyclades_port *info = tty->driver_data;
2586 struct cyclades_card *card;
2587 int channel, retval;
2588 unsigned long flags;
2589
2590#ifdef CY_DEBUG_IO
2591 printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
2592#endif
2593
2594 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
2595 return;
2596
2597 card = info->card;
2598 channel = info->line - card->first_line;
2599
2600 spin_lock_irqsave(&card->card_lock, flags);
2601 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
2602 spin_unlock_irqrestore(&card->card_lock, flags);
2603
2604 if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
2605 buffers as well */
2606 spin_lock_irqsave(&card->card_lock, flags);
2607 retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
2608 if (retval != 0) {
2609 printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
2610 "was %x\n", info->line, retval);
2611 }
2612 spin_unlock_irqrestore(&card->card_lock, flags);
2613 }
2614 tty_wakeup(tty);
2615} /* cy_flush_buffer */
2616
2617
2581/* 2618/*
2582 * This routine is called when a particular tty device is closed. 2619 * This routine is called when a particular tty device is closed.
2583 */ 2620 */
@@ -2689,8 +2726,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
2689 2726
2690 spin_unlock_irqrestore(&card->card_lock, flags); 2727 spin_unlock_irqrestore(&card->card_lock, flags);
2691 shutdown(info); 2728 shutdown(info);
2692 if (tty->driver->flush_buffer) 2729 cy_flush_buffer(tty);
2693 tty->driver->flush_buffer(tty);
2694 tty_ldisc_flush(tty); 2730 tty_ldisc_flush(tty);
2695 spin_lock_irqsave(&card->card_lock, flags); 2731 spin_lock_irqsave(&card->card_lock, flags);
2696 2732
@@ -2881,6 +2917,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
2881 int char_count; 2917 int char_count;
2882 __u32 tx_put, tx_get, tx_bufsize; 2918 __u32 tx_put, tx_get, tx_bufsize;
2883 2919
2920 lock_kernel();
2884 firm_id = card->base_addr + ID_ADDRESS; 2921 firm_id = card->base_addr + ID_ADDRESS;
2885 zfw_ctrl = card->base_addr + 2922 zfw_ctrl = card->base_addr +
2886 (readl(&firm_id->zfwctrl_addr) & 0xfffff); 2923 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -2898,6 +2935,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
2898 printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", 2935 printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
2899 info->line, info->xmit_cnt + char_count); 2936 info->line, info->xmit_cnt + char_count);
2900#endif 2937#endif
2938 unlock_kernel();
2901 return info->xmit_cnt + char_count; 2939 return info->xmit_cnt + char_count;
2902 } 2940 }
2903#endif /* Z_EXT_CHARS_IN_BUFFER */ 2941#endif /* Z_EXT_CHARS_IN_BUFFER */
@@ -4271,40 +4309,6 @@ static void cy_start(struct tty_struct *tty)
4271 } 4309 }
4272} /* cy_start */ 4310} /* cy_start */
4273 4311
4274static void cy_flush_buffer(struct tty_struct *tty)
4275{
4276 struct cyclades_port *info = tty->driver_data;
4277 struct cyclades_card *card;
4278 int channel, retval;
4279 unsigned long flags;
4280
4281#ifdef CY_DEBUG_IO
4282 printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
4283#endif
4284
4285 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
4286 return;
4287
4288 card = info->card;
4289 channel = info->line - card->first_line;
4290
4291 spin_lock_irqsave(&card->card_lock, flags);
4292 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
4293 spin_unlock_irqrestore(&card->card_lock, flags);
4294
4295 if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
4296 buffers as well */
4297 spin_lock_irqsave(&card->card_lock, flags);
4298 retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
4299 if (retval != 0) {
4300 printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
4301 "was %x\n", info->line, retval);
4302 }
4303 spin_unlock_irqrestore(&card->card_lock, flags);
4304 }
4305 tty_wakeup(tty);
4306} /* cy_flush_buffer */
4307
4308/* 4312/*
4309 * cy_hangup() --- called by tty_hangup() when a hangup is signaled. 4313 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
4310 */ 4314 */