diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 10:25:51 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 10:26:01 -0800 |
commit | d2fde28ce793c09c1ea36d981cb6765174fd1eea (patch) | |
tree | d1922f6572702374900dace5dcbb9d794fecc522 /drivers/char/synclinkmp.c | |
parent | 609e5b71d0eca163df017ecfcf917b149875e744 (diff) | |
parent | e65f0f8271b1b0452334e5da37fd35413a000de4 (diff) |
Merge branch 'tty-updates' from Alan
* tty-updates: (75 commits)
serial_8250: support for Sealevel Systems Model 7803 COMM+8
hso maintainers update patch
hso modem detect fix patch against Alan Cox'es tty tree
tty: Fix an ircomm warning and note another bug
drivers/char/cyclades.c: cy_pci_probe: fix error path
Serial: UART driver changes for Cavium OCTEON.
Serial: Allow port type to be specified when calling serial8250_register_port.
8250: Serial driver changes to support future Cavium OCTEON serial patches.
8250: Don't clobber spinlocks.
fix for tty-serial-move-port
tty: We want the port object to be persistent
__FUNCTION__ is gcc-specific, use __func__
serial: RS485 ioctl structure uses __u32 include linux/types.h
tty: Drop the lock_kernel in the private ioctl hook
synclink_cs: Convert to tty_port
tty: use port methods for the rocket driver
tty: kref the rocket driver
tty: make rocketport use standard port->flags
tty: Redo the rocket driver locking
tty: Make epca use the port helpers
...
Diffstat (limited to 'drivers/char/synclinkmp.c')
-rw-r--r-- | drivers/char/synclinkmp.c | 171 |
1 files changed, 71 insertions, 100 deletions
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 6bdb44f7bec2..7b0c5b2dd263 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info); static int startup(SLMP_INFO *info); static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); +static int carrier_raised(struct tty_port *port); static void shutdown(SLMP_INFO *info); static void program_hw(SLMP_INFO *info); static void change_params(SLMP_INFO *info); @@ -800,7 +801,7 @@ cleanup: */ static void close(struct tty_struct *tty, struct file *filp) { - SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO * info = tty->driver_data; if (sanity_check(info, tty->name, "close")) return; @@ -809,70 +810,18 @@ static void close(struct tty_struct *tty, struct file *filp) printk("%s(%d):%s close() entry, count=%d\n", __FILE__,__LINE__, info->device_name, info->port.count); - if (!info->port.count) - return; - - if (tty_hung_up_p(filp)) - goto cleanup; - - if ((tty->count == 1) && (info->port.count != 1)) { - /* - * tty->count is 1 and the tty structure will be freed. - * info->port.count should be one in this case. - * if it's not, correct it so that the port is shutdown. - */ - printk("%s(%d):%s close: bad refcount; tty->count is 1, " - "info->port.count is %d\n", - __FILE__,__LINE__, info->device_name, info->port.count); - info->port.count = 1; - } - - info->port.count--; - - /* if at least one open remaining, leave hardware active */ - if (info->port.count) + if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; - - info->port.flags |= ASYNC_CLOSING; - - /* set tty->closing to notify line discipline to - * only process XON/XOFF characters. Only the N_TTY - * discipline appears to use this (ppp does not). - */ - tty->closing = 1; - - /* wait for transmit data to clear all layers */ - - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):%s close() calling tty_wait_until_sent\n", - __FILE__,__LINE__, info->device_name ); - tty_wait_until_sent(tty, info->port.closing_wait); - } - + if (info->port.flags & ASYNC_INITIALIZED) wait_until_sent(tty, info->timeout); flush_buffer(tty); - tty_ldisc_flush(tty); - shutdown(info); - tty->closing = 0; + tty_port_close_end(&info->port, tty); info->port.tty = NULL; - - if (info->port.blocked_open) { - if (info->port.close_delay) { - msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); - } - wake_up_interruptible(&info->port.open_wait); - } - - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - - wake_up_interruptible(&info->port.close_wait); - cleanup: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, @@ -884,7 +833,7 @@ cleanup: */ static void hangup(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s hangup()\n", @@ -907,7 +856,7 @@ static void hangup(struct tty_struct *tty) */ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -960,7 +909,7 @@ static int write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, ret = 0; - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -1038,7 +987,7 @@ cleanup: */ static int put_char(struct tty_struct *tty, unsigned char ch) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; int ret = 0; @@ -1075,7 +1024,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch) */ static void send_xchar(struct tty_struct *tty, char ch) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -1099,7 +1048,7 @@ static void send_xchar(struct tty_struct *tty, char ch) */ static void wait_until_sent(struct tty_struct *tty, int timeout) { - SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO * info = tty->driver_data; unsigned long orig_jiffies, char_time; if (!info ) @@ -1166,7 +1115,7 @@ exit: */ static int write_room(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; int ret; if (sanity_check(info, tty->name, "write_room")) @@ -1193,7 +1142,7 @@ static int write_room(struct tty_struct *tty) */ static void flush_chars(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if ( debug_level >= DEBUG_LEVEL_INFO ) @@ -1232,7 +1181,7 @@ static void flush_chars(struct tty_struct *tty) */ static void flush_buffer(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -1254,7 +1203,7 @@ static void flush_buffer(struct tty_struct *tty) */ static void tx_hold(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (sanity_check(info, tty->name, "tx_hold")) @@ -1274,7 +1223,7 @@ static void tx_hold(struct tty_struct *tty) */ static void tx_release(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (sanity_check(info, tty->name, "tx_release")) @@ -1304,7 +1253,7 @@ static void tx_release(struct tty_struct *tty) static int do_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; int error; struct mgsl_icount cnow; /* kernel counter temps */ struct serial_icounter_struct __user *p_cuser; /* user space */ @@ -1515,7 +1464,7 @@ done: */ static int chars_in_buffer(struct tty_struct *tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; if (sanity_check(info, tty->name, "chars_in_buffer")) return 0; @@ -1531,7 +1480,7 @@ static int chars_in_buffer(struct tty_struct *tty) */ static void throttle(struct tty_struct * tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -1556,7 +1505,7 @@ static void throttle(struct tty_struct * tty) */ static void unthrottle(struct tty_struct * tty) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -1587,7 +1536,7 @@ static void unthrottle(struct tty_struct * tty) static int set_break(struct tty_struct *tty, int break_state) { unsigned char RegValue; - SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO * info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -3269,7 +3218,7 @@ static int modem_input_wait(SLMP_INFO *info,int arg) */ static int tiocmget(struct tty_struct *tty, struct file *file) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned int result; unsigned long flags; @@ -3295,7 +3244,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file) static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; + SLMP_INFO *info = tty->driver_data; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -3318,7 +3267,28 @@ static int tiocmset(struct tty_struct *tty, struct file *file, return 0; } +static int carrier_raised(struct tty_port *port) +{ + SLMP_INFO *info = container_of(port, SLMP_INFO, port); + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; +} + +static void raise_dtr_rts(struct tty_port *port) +{ + SLMP_INFO *info = container_of(port, SLMP_INFO, port); + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); +} /* Block the current process until the specified port is ready to open. */ @@ -3330,6 +3300,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, bool do_clocal = false; bool extra_count = false; unsigned long flags; + int cd; + struct tty_port *port = &info->port; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready()\n", @@ -3338,7 +3310,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ /* nonblock mode is set or port is not enabled */ /* just verify that callout device is not active */ - info->port.flags |= ASYNC_NORMAL_ACTIVE; + port->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -3347,50 +3319,42 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, info->port.count is dropped by one, so that + * this loop, port->count is dropped by one, so that * close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->port.open_wait, &wait); + add_wait_queue(&port->open_wait, &wait); if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() before block, count=%d\n", - __FILE__,__LINE__, tty->driver->name, info->port.count ); + __FILE__,__LINE__, tty->driver->name, port->count ); spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { extra_count = true; - info->port.count--; + port->count--; } spin_unlock_irqrestore(&info->lock, flags); - info->port.blocked_open++; + port->blocked_open++; while (1) { - if ((tty->termios->c_cflag & CBAUD)) { - spin_lock_irqsave(&info->lock,flags); - info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } + if (tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ - retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ + retval = (port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; break; } - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); + cd = tty_port_carrier_raised(port); - if (!(info->port.flags & ASYNC_CLOSING) && - (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { + if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) break; - } if (signal_pending(current)) { retval = -ERESTARTSYS; @@ -3399,24 +3363,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() count=%d\n", - __FILE__,__LINE__, tty->driver->name, info->port.count ); + __FILE__,__LINE__, tty->driver->name, port->count ); schedule(); } set_current_state(TASK_RUNNING); - remove_wait_queue(&info->port.open_wait, &wait); + remove_wait_queue(&port->open_wait, &wait); if (extra_count) - info->port.count++; - info->port.blocked_open--; + port->count++; + port->blocked_open--; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() after, count=%d\n", - __FILE__,__LINE__, tty->driver->name, info->port.count ); + __FILE__,__LINE__, tty->driver->name, port->count ); if (!retval) - info->port.flags |= ASYNC_NORMAL_ACTIVE; + port->flags |= ASYNC_NORMAL_ACTIVE; return retval; } @@ -3782,6 +3746,11 @@ static void add_device(SLMP_INFO *info) #endif } +static const struct tty_port_operations port_ops = { + .carrier_raised = carrier_raised, + .raise_dtr_rts = raise_dtr_rts, +}; + /* Allocate and initialize a device instance structure * * Return Value: pointer to SLMP_INFO if success, otherwise NULL @@ -3798,6 +3767,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) __FILE__,__LINE__, adapter_num, port_num); } else { tty_port_init(&info->port); + info->port.ops = &port_ops; info->magic = MGSL_MAGIC; INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; @@ -3940,6 +3910,7 @@ static const struct tty_operations ops = { .tiocmset = tiocmset, }; + static void synclinkmp_cleanup(void) { int rc; |