diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 23:12:24 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 23:12:24 (GMT) |
commit | 94b5aff4c6f72fee6b0f49d49e4fa8b204e8ded9 (patch) | |
tree | 39197121b6ef8cddaa0f4057fe24b4ced58e8982 /drivers/isdn | |
parent | 5d4e2d08e7fdf7339f84a1c670d296a77e02f881 (diff) | |
parent | 59bd234b72fc29887839d792b7d6c7e8d2a577a6 (diff) | |
download | linux-94b5aff4c6f72fee6b0f49d49e4fa8b204e8ded9.tar.xz |
Merge tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY updates from Greg Kroah-Hartman:
"Here's the big TTY/serial driver pull request for the 3.5-rc1 merge
window.
Nothing major in here, just lots of incremental changes from Alan and
Jiri reworking some tty core things to behave better and to get a more
solid grasp on some of the nasty tty locking issues.
There are a few tty and serial driver updates in here as well.
All of this has been in the linux-next releases for a while with no
problems.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (115 commits)
serial: bfin_uart: Make MMR access compatible with 32 bits bf609 style controller.
serial: bfin_uart: RTS and CTS MMRs can be either 16-bit width or 32-bit width.
serial: bfin_uart: narrow the reboot condition in DMA tx interrupt
serial: bfin_uart: Adapt bf5xx serial driver to bf60x serial4 controller.
Revert "serial_core: Update buffer overrun statistics."
tty: hvc_xen: NULL dereference on allocation failure
tty: Fix LED error return
tty: Allow uart_register/unregister/register
tty: move global ldisc idle waitqueue to the individual ldisc
serial8250-em: Add DT support
serial8250-em: clk_get() IS_ERR() error handling fix
serial_core: Update buffer overrun statistics.
tty: drop the pty lock during hangup
cris: fix missing tty arg in wait_event_interruptible_tty call
tty/amiserial: Add missing argument for tty_unlock()
tty_lock: Localise the lock
pty: Lock the devpts bits privately
tty_lock: undo the old tty_lock use on the ctty
serial8250-em: Emma Mobile UART driver V2
Add missing call to uart_update_timeout()
...
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/i4l/isdn_common.c | 5 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_tty.c | 466 |
2 files changed, 179 insertions, 292 deletions
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index d9f5524..8c610fa 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -46,7 +46,6 @@ static DEFINE_MUTEX(isdn_mutex); static char *isdn_revision = "$Revision: 1.1.2.3 $"; extern char *isdn_net_revision; -extern char *isdn_tty_revision; #ifdef CONFIG_ISDN_PPP extern char *isdn_ppp_revision; #else @@ -2327,8 +2326,6 @@ static int __init isdn_init(void) dev->chanmap[i] = -1; dev->m_idx[i] = -1; strcpy(dev->num[i], "???"); - init_waitqueue_head(&dev->mdm.info[i].open_wait); - init_waitqueue_head(&dev->mdm.info[i].close_wait); } if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); @@ -2353,8 +2350,6 @@ static int __init isdn_init(void) strcpy(tmprev, isdn_revision); printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_tty_revision); - printk("%s/", isdn_getrev(tmprev)); strcpy(tmprev, isdn_net_revision); printk("%s/", isdn_getrev(tmprev)); strcpy(tmprev, isdn_ppp_revision); diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3831abd..7bc5067 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1,5 +1,4 @@ -/* $Id: isdn_tty.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $ - * +/* * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) @@ -12,6 +11,7 @@ #undef ISDN_TTY_STAT_DEBUG #include <linux/isdn.h> +#include <linux/serial.h> /* ASYNC_* flags */ #include <linux/slab.h> #include <linux/delay.h> #include <linux/mutex.h> @@ -48,9 +48,6 @@ static int bit2si[8] = static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.1.2.3 $"; - - /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() * to stuff incoming data directly into a tty's flip-buffer. This * is done to speed up tty-receiving if the receive-queue is empty. @@ -68,49 +65,54 @@ isdn_tty_try_read(modem_info *info, struct sk_buff *skb) struct tty_struct *tty; char last; - if (info->online) { - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - len = skb->len + if (!info->online) + return 0; + + tty = info->port.tty; + if (!tty) + return 0; + + if (!(info->mcr & UART_MCR_RTS)) + return 0; + + len = skb->len #ifdef CONFIG_ISDN_AUDIO - + ISDN_AUDIO_SKB_DLECOUNT(skb) + + ISDN_AUDIO_SKB_DLECOUNT(skb) #endif - ; + ; + + c = tty_buffer_request_room(tty, len); + if (c < len) + return 0; - c = tty_buffer_request_room(tty, len); - if (c >= len) { -#ifdef CONFIG_ISDN_AUDIO - if (ISDN_AUDIO_SKB_DLECOUNT(skb)) { - int l = skb->len; - unsigned char *dp = skb->data; - while (--l) { - if (*dp == DLE) - tty_insert_flip_char(tty, DLE, 0); - tty_insert_flip_char(tty, *dp++, 0); - } - if (*dp == DLE) - tty_insert_flip_char(tty, DLE, 0); - last = *dp; - } else { -#endif - if (len > 1) - tty_insert_flip_string(tty, skb->data, len - 1); - last = skb->data[len - 1]; #ifdef CONFIG_ISDN_AUDIO - } + if (ISDN_AUDIO_SKB_DLECOUNT(skb)) { + int l = skb->len; + unsigned char *dp = skb->data; + while (--l) { + if (*dp == DLE) + tty_insert_flip_char(tty, DLE, 0); + tty_insert_flip_char(tty, *dp++, 0); + } + if (*dp == DLE) + tty_insert_flip_char(tty, DLE, 0); + last = *dp; + } else { #endif - if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP) - tty_insert_flip_char(tty, last, 0xFF); - else - tty_insert_flip_char(tty, last, TTY_NORMAL); - tty_flip_buffer_push(tty); - kfree_skb(skb); - return 1; - } - } - } + if (len > 1) + tty_insert_flip_string(tty, skb->data, len - 1); + last = skb->data[len - 1]; +#ifdef CONFIG_ISDN_AUDIO } - return 0; +#endif + if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP) + tty_insert_flip_char(tty, last, 0xFF); + else + tty_insert_flip_char(tty, last, TTY_NORMAL); + tty_flip_buffer_push(tty); + kfree_skb(skb); + + return 1; } /* isdn_tty_readmodem() is called periodically from within timer-interrupt. @@ -128,35 +130,39 @@ isdn_tty_readmodem(void) modem_info *info; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if ((midx = dev->m_idx[i]) >= 0) { - info = &dev->mdm.info[midx]; - if (info->online) { - r = 0; + midx = dev->m_idx[i]; + if (midx < 0) + continue; + + info = &dev->mdm.info[midx]; + if (!info->online) + continue; + + r = 0; #ifdef CONFIG_ISDN_AUDIO - isdn_audio_eval_dtmf(info); - if ((info->vonline & 1) && (info->emu.vpar[1])) - isdn_audio_eval_silence(info); -#endif - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - /* CISCO AsyncPPP Hack */ - if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) - r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0); - else - r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1); - if (r) - tty_flip_buffer_push(tty); - } else - r = 1; - } else - r = 1; - if (r) { - info->rcvsched = 0; - resched = 1; - } else - info->rcvsched = 1; - } - } + isdn_audio_eval_dtmf(info); + if ((info->vonline & 1) && (info->emu.vpar[1])) + isdn_audio_eval_silence(info); +#endif + tty = info->port.tty; + if (tty) { + if (info->mcr & UART_MCR_RTS) { + /* CISCO AsyncPPP Hack */ + if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) + r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0); + else + r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1); + if (r) + tty_flip_buffer_push(tty); + } else + r = 1; + } else + r = 1; + if (r) { + info->rcvsched = 0; + resched = 1; + } else + info->rcvsched = 1; } if (!resched) isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0); @@ -294,7 +300,7 @@ isdn_tty_tint(modem_info *info) len = skb->len; if ((slen = isdn_writebuf_skb_stub(info->isdn_driver, info->isdn_channel, 1, skb)) == len) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; info->send_outstanding++; info->msr &= ~UART_MSR_CTS; info->lsr &= ~UART_LSR_TEMT; @@ -327,7 +333,7 @@ isdn_tty_countDLE(unsigned char *buf, int len) static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len) { - unsigned char *p = &info->xmit_buf[info->xmit_count]; + unsigned char *p = &info->port.xmit_buf[info->xmit_count]; int count = 0; while (len > 0) { @@ -471,7 +477,7 @@ isdn_tty_senddown(modem_info *info) return; } skb_reserve(skb, skb_res); - memcpy(skb_put(skb, buflen), info->xmit_buf, buflen); + memcpy(skb_put(skb, buflen), info->port.xmit_buf, buflen); info->xmit_count = 0; #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 2) { @@ -699,7 +705,7 @@ isdn_tty_modem_hup(modem_info *info, int local) printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); #endif info->rcvsched = 0; - isdn_tty_flush_buffer(info->tty); + isdn_tty_flush_buffer(info->port.tty); if (info->online) { info->last_lhup = local; info->online = 0; @@ -997,20 +1003,21 @@ isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine) static void isdn_tty_change_speed(modem_info *info) { + struct tty_port *port = &info->port; uint cflag, cval, quot; int i; - if (!info->tty || !info->tty->termios) + if (!port->tty || !port->tty->termios) return; - cflag = info->tty->termios->c_cflag; + cflag = port->tty->termios->c_cflag; quot = i = cflag & CBAUD; if (i & CBAUDEX) { i &= ~CBAUDEX; if (i < 1 || i > 2) - info->tty->termios->c_cflag &= ~CBAUDEX; + port->tty->termios->c_cflag &= ~CBAUDEX; else i += 15; } @@ -1040,20 +1047,20 @@ isdn_tty_change_speed(modem_info *info) /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { - info->flags |= ISDN_ASYNC_CTS_FLOW; + port->flags |= ASYNC_CTS_FLOW; } else - info->flags &= ~ISDN_ASYNC_CTS_FLOW; + port->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) - info->flags &= ~ISDN_ASYNC_CHECK_CD; + port->flags &= ~ASYNC_CHECK_CD; else { - info->flags |= ISDN_ASYNC_CHECK_CD; + port->flags |= ASYNC_CHECK_CD; } } static int isdn_tty_startup(modem_info *info) { - if (info->flags & ISDN_ASYNC_INITIALIZED) + if (info->port.flags & ASYNC_INITIALIZED) return 0; isdn_lock_drivers(); #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1063,14 +1070,14 @@ isdn_tty_startup(modem_info *info) * Now, initialize the UART */ info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); /* * and set the speed of the serial port */ isdn_tty_change_speed(info); - info->flags |= ISDN_ASYNC_INITIALIZED; + info->port.flags |= ASYNC_INITIALIZED; info->msr |= (UART_MSR_DSR | UART_MSR_CTS); info->send_outstanding = 0; return 0; @@ -1083,14 +1090,14 @@ isdn_tty_startup(modem_info *info) static void isdn_tty_shutdown(modem_info *info) { - if (!(info->flags & ISDN_ASYNC_INITIALIZED)) + if (!(info->port.flags & ASYNC_INITIALIZED)) return; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line); #endif isdn_unlock_drivers(); info->msr &= ~UART_MSR_RI; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { isdn_tty_modem_reset_regs(info, 0); @@ -1100,10 +1107,10 @@ isdn_tty_shutdown(modem_info *info) isdn_tty_modem_hup(info, 1); } } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); - info->flags &= ~ISDN_ASYNC_INITIALIZED; + info->port.flags &= ~ASYNC_INITIALIZED; } /* isdn_tty_write() is the main send-routine. It is called from the upper @@ -1146,7 +1153,7 @@ isdn_tty_write(struct tty_struct *tty, const u_char *buf, int count) isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, &(m->pluscount), &(m->lastplus)); - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); + memcpy(&info->port.xmit_buf[info->xmit_count], buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1478,107 +1485,6 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * isdn_tty_open() and friends * ------------------------------------------------------------ */ -static int -isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info *info) -{ - DECLARE_WAITQUEUE(wait, NULL); - int do_clocal = 0; - int retval; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ISDN_ASYNC_CLOSING)) { - if (info->flags & ISDN_ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; -#else - return -EAGAIN; -#endif - } - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; - return 0; - } - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) { - if (info->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * isdn_tty_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n", - info->line, info->count); -#endif - if (!(tty_hung_up_p(filp))) - info->count--; - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ISDN_ASYNC_INITIALIZED)) { -#ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ISDN_ASYNC_CLOSING) && - (do_clocal || (info->msr & UART_MSR_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n", - info->line, info->count); -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n", - info->line, info->count); -#endif - if (retval) - return retval; - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; - return 0; -} /* * This routine is called whenever a serial port is opened. It @@ -1589,23 +1495,22 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * static int isdn_tty_open(struct tty_struct *tty, struct file *filp) { + struct tty_port *port; modem_info *info; int retval; info = &dev->mdm.info[tty->index]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; - if (!try_module_get(info->owner)) { - printk(KERN_WARNING "%s: cannot reserve module\n", __func__); - return -ENODEV; - } + port = &info->port; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, - info->count); + port->count); #endif - info->count++; + port->count++; tty->driver_data = info; - info->tty = tty; + port->tty = tty; + tty->port = port; /* * Start up serial port */ @@ -1614,15 +1519,13 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after startup\n"); #endif - module_put(info->owner); return retval; } - retval = isdn_tty_block_til_ready(tty, filp, info); + retval = tty_port_block_til_ready(port, tty, filp); if (retval) { #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n"); #endif - module_put(info->owner); return retval; } #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1639,6 +1542,7 @@ static void isdn_tty_close(struct tty_struct *tty, struct file *filp) { modem_info *info = (modem_info *) tty->driver_data; + struct tty_port *port = &info->port; ulong timeout; if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) @@ -1649,7 +1553,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - if ((tty->count == 1) && (info->count != 1)) { + if ((tty->count == 1) && (port->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always @@ -1658,30 +1562,21 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * serial port won't be shutdown. */ printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; + "info->count is %d\n", port->count); + port->count = 1; } - if (--info->count < 0) { + if (--port->count < 0) { printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n", - info->line, info->count); - info->count = 0; + info->line, port->count); + port->count = 0; } - if (info->count) { + if (port->count) { #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif - module_put(info->owner); return; } - info->flags |= ISDN_ASYNC_CLOSING; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - info->callout_termios = *tty->termios; + port->flags |= ASYNC_CLOSING; tty->closing = 1; /* @@ -1690,7 +1585,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * interrupt driver to stop checking the data ready bit in the * line status register. */ - if (info->flags & ISDN_ASYNC_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter @@ -1708,16 +1603,10 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) isdn_tty_shutdown(info); isdn_tty_flush_buffer(tty); tty_ldisc_flush(tty); - info->tty = NULL; + port->tty = NULL; info->ncarrier = 0; - tty->closing = 0; - module_put(info->owner); - if (info->blocked_open) { - msleep_interruptible(500); - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + + tty_port_close_end(port, tty); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -1730,14 +1619,15 @@ static void isdn_tty_hangup(struct tty_struct *tty) { modem_info *info = (modem_info *) tty->driver_data; + struct tty_port *port = &info->port; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup")) return; isdn_tty_shutdown(info); - info->count = 0; - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE); - info->tty = NULL; - wake_up_interruptible(&info->open_wait); + port->count = 0; + port->flags &= ~ASYNC_NORMAL_ACTIVE; + port->tty = NULL; + wake_up_interruptible(&port->open_wait); } /* This routine initializes all emulator-data. @@ -1864,6 +1754,16 @@ static const struct tty_operations modem_ops = { .tiocmset = isdn_tty_tiocmset, }; +static int isdn_tty_carrier_raised(struct tty_port *port) +{ + modem_info *info = container_of(port, modem_info, port); + return info->msr & UART_MSR_DCD; +} + +static const struct tty_port_operations isdn_tty_port_ops = { + .carrier_raised = isdn_tty_carrier_raised, +}; + int isdn_tty_modem_init(void) { @@ -1899,9 +1799,8 @@ isdn_tty_modem_init(void) goto err_unregister; } #endif -#ifdef MODULE - info->owner = THIS_MODULE; -#endif + tty_port_init(&info->port); + info->port.ops = &isdn_tty_port_ops; spin_lock_init(&info->readlock); sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); @@ -1913,12 +1812,7 @@ isdn_tty_modem_init(void) isdn_tty_modem_reset_regs(info, 1); info->magic = ISDN_ASYNC_MAGIC; info->line = i; - info->tty = NULL; info->x_char = 0; - info->count = 0; - info->blocked_open = 0; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); info->isdn_driver = -1; info->isdn_channel = -1; info->drv_index = -1; @@ -1930,13 +1824,15 @@ isdn_tty_modem_init(void) #ifdef CONFIG_ISDN_AUDIO skb_queue_head_init(&info->dtmf_queue); #endif - if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) { + info->port.xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, + GFP_KERNEL); + if (!info->port.xmit_buf) { printk(KERN_ERR "Could not allocate modem xmit-buffer\n"); retval = -ENOMEM; goto err_unregister; } /* Make room for T.70 header */ - info->xmit_buf += 4; + info->port.xmit_buf += 4; } return 0; err_unregister: @@ -1945,7 +1841,7 @@ err_unregister: #ifdef CONFIG_ISDN_TTY_FAX kfree(info->fax); #endif - kfree(info->xmit_buf - 4); + kfree(info->port.xmit_buf - 4); } tty_unregister_driver(m->tty_modem); err: @@ -1966,7 +1862,7 @@ isdn_tty_exit(void) #ifdef CONFIG_ISDN_TTY_FAX kfree(info->fax); #endif - kfree(info->xmit_buf - 4); + kfree(info->port.xmit_buf - 4); } tty_unregister_driver(dev->mdm.tty_modem); put_tty_driver(dev->mdm.tty_modem); @@ -2068,7 +1964,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; - if (info->count == 0) + if (info->port.count == 0) continue; if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ @@ -2076,12 +1972,12 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx, - info->flags, info->isdn_driver, info->isdn_channel, - dev->usage[idx]); + info->port.flags, info->isdn_driver, + info->isdn_channel, dev->usage[idx]); #endif if ( #ifndef FIX_FILE_TRANSFER - (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && + (info->port.flags & ASYNC_NORMAL_ACTIVE) && #endif (info->isdn_driver == -1) && (info->isdn_channel == -1) && @@ -2120,8 +2016,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) return (wret == 2) ? 3 : 0; } -#define TTY_IS_ACTIVE(info) \ - (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE)) +#define TTY_IS_ACTIVE(info) (info->port.flags & ASYNC_NORMAL_ACTIVE) int isdn_tty_stat_callback(int i, isdn_ctrl *c) @@ -2212,9 +2107,9 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) * for incoming call of this device when * DCD follow the state of incoming carrier */ - if (info->blocked_open && + if (info->port.blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD)) { - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } /* Schedule CONNECT-Message to any tty @@ -2222,7 +2117,8 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) * set DCD-bit of its modem-status. */ if (TTY_IS_ACTIVE(info) || - (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) { + (info->port.blocked_open && + (info->emu.mdmreg[REG_DCD] & BIT_DCD))) { info->msr |= UART_MSR_DCD; info->emu.charge = 0; if (info->dialing & 0xf) @@ -2339,8 +2235,8 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - tty = info->tty; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) { + tty = info->port.tty; + if ((info->port.flags & ASYNC_CLOSING) || (!tty)) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2490,15 +2386,15 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->flags & ISDN_ASYNC_CLOSING), - (!info->tty)); + (info->port.flags & ASYNC_CLOSING), + (!info->port.tty)); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { + if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) return; - } + #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 1) { #ifdef ISDN_DEBUG_MODEM_VOICE @@ -2629,14 +2525,11 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { + if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) return; - } - if ((info->flags & ISDN_ASYNC_CHECK_CD) && - (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { - tty_hangup(info->tty); - } + + if (info->port.flags & ASYNC_CHECK_CD) + tty_hangup(info->port.tty); } } @@ -3803,19 +3696,19 @@ isdn_tty_modem_escape(void) int midx; for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (USG_MODEM(dev->usage[i])) - if ((midx = dev->m_idx[i]) >= 0) { - modem_info *info = &dev->mdm.info[midx]; - if (info->online) { - ton = 1; - if ((info->emu.pluscount == 3) && - time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) { - info->emu.pluscount = 0; - info->online = 0; - isdn_tty_modem_result(RESULT_OK, info); - } + if (USG_MODEM(dev->usage[i]) && (midx = dev->m_idx[i]) >= 0) { + modem_info *info = &dev->mdm.info[midx]; + if (info->online) { + ton = 1; + if ((info->emu.pluscount == 3) && + time_after(jiffies, + info->emu.lastplus + PLUSWAIT2)) { + info->emu.pluscount = 0; + info->online = 0; + isdn_tty_modem_result(RESULT_OK, info); } } + } isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton); } @@ -3873,15 +3766,14 @@ isdn_tty_carrier_timeout(void) for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; - if (info->dialing) { - if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) { - info->dialing = 0; - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - isdn_tty_modem_hup(info, 1); - } - else - ton = 1; - } + if (!info->dialing) + continue; + if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) { + info->dialing = 0; + isdn_tty_modem_result(RESULT_NO_CARRIER, info); + isdn_tty_modem_hup(info, 1); + } else + ton = 1; } isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton); } |