diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:53:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:45 -0400 |
commit | 978e595f88a1fba5869aa42a4af4fba36f33ecac (patch) | |
tree | 60848f49949c5b7b518621ee36cdc6d500244539 /drivers/char/cyclades.c | |
parent | ac0e4b7d319bf284bb64bc7e1c051417386b34a4 (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.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e61939d3331..571e4fab5bf 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 | ||
2583 | static 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 | ||
4274 | static 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 | */ |