summaryrefslogtreecommitdiffstats
path: root/drivers/char/mxser.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 14:45:05 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 19:19:38 +0100
commit31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch)
tree39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/mxser.c
parenttty: Fix PPP hang under load (diff)
downloadlinux-31f35939d1d9bcfb3099b32c67b896d2792603f9.tar.xz
linux-31f35939d1d9bcfb3099b32c67b896d2792603f9.zip
tty_port: Add a port level carrier detect operation
This is the first step to generalising the various pieces of waiting logic duplicated in all sorts of serial drivers. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r--drivers/char/mxser.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 047766915411..eafbbcf355e7 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -541,13 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
return status;
}
+static int mxser_carrier_raised(struct tty_port *port)
+{
+ struct mxser_port *mp = container_of(port, struct mxser_port, port);
+ return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
+}
+
static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
- struct mxser_port *port)
+ struct mxser_port *mp)
{
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0;
unsigned long flags;
+ int cd;
+ struct tty_port *port = &mp->port;
/*
* If non-blocking mode is set, or the port is not enabled,
@@ -555,7 +563,7 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
*/
if ((filp->f_flags & O_NONBLOCK) ||
test_bit(TTY_IO_ERROR, &tty->flags)) {
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -565,34 +573,33 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
/*
* 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, port->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* mxser_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&port->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
- spin_lock_irqsave(&port->slock, flags);
+ spin_lock_irqsave(&mp->slock, flags);
if (!tty_hung_up_p(filp))
- port->port.count--;
- spin_unlock_irqrestore(&port->slock, flags);
- port->port.blocked_open++;
+ port->count--;
+ spin_unlock_irqrestore(&mp->slock, flags);
+ port->blocked_open++;
while (1) {
- spin_lock_irqsave(&port->slock, flags);
- outb(inb(port->ioaddr + UART_MCR) |
- UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
- spin_unlock_irqrestore(&port->slock, flags);
+ spin_lock_irqsave(&mp->slock, flags);
+ outb(inb(mp->ioaddr + UART_MCR) |
+ UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&mp->slock, flags);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) {
- if (port->port.flags & ASYNC_HUP_NOTIFY)
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
}
- if (!(port->port.flags & ASYNC_CLOSING) &&
- (do_clocal ||
- (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
+ cd = tty_port_carrier_raised(port);
+ if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -601,13 +608,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
schedule();
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp))
- port->port.count++;
- port->port.blocked_open--;
+ port->count++;
+ port->blocked_open--;
if (retval)
return retval;
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -2449,6 +2456,10 @@ static const struct tty_operations mxser_ops = {
.tiocmset = mxser_tiocmset,
};
+struct tty_port_operations mxser_port_ops = {
+ .carrier_raised = mxser_carrier_raised,
+};
+
/*
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
@@ -2482,6 +2493,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
for (i = 0; i < brd->info->nports; i++) {
info = &brd->ports[i];
tty_port_init(&info->port);
+ info->port.ops = &mxser_port_ops;
info->board = brd;
info->stop_rx = 0;
info->ldisc_stop_rx = 0;