diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/console.c | 13 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 9 | ||||
-rw-r--r-- | drivers/usb/serial/kl5kusb105.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/mct_u232.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/mos7840.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/sierra.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 26 |
7 files changed, 42 insertions, 14 deletions
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5b95009d2fb..19e24045b13 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -241,12 +241,25 @@ static void usb_console_write(struct console *co, } } +static struct tty_driver *usb_console_device(struct console *co, int *index) +{ + struct tty_driver **p = (struct tty_driver **)co->data; + + if (!*p) + return NULL; + + *index = co->index; + return *p; +} + static struct console usbcons = { .name = "ttyUSB", .write = usb_console_write, + .device = usb_console_device, .setup = usb_console_setup, .flags = CON_PRINTBUFFER, .index = -1, + .data = &usb_serial_tty_driver, }; void usb_serial_console_disconnect(struct usb_serial *serial) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fb6f2933b01..ef6cfa5a447 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1054,6 +1054,8 @@ static int set_serial_info(struct tty_struct *tty, if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) return -EFAULT; + + lock_kernel(); old_priv = *priv; /* Do error checking and permission checking */ @@ -1069,8 +1071,10 @@ static int set_serial_info(struct tty_struct *tty, } if ((new_serial.baud_base != priv->baud_base) && - (new_serial.baud_base < 9600)) + (new_serial.baud_base < 9600)) { + unlock_kernel(); return -EINVAL; + } /* Make the changes - these are privileged changes! */ @@ -1098,8 +1102,11 @@ check_and_exit: (priv->flags & ASYNC_SPD_MASK)) || (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (old_priv.custom_divisor != priv->custom_divisor))) { + unlock_kernel(); change_speed(tty, port); } + else + unlock_kernel(); return 0; } /* set_serial_info */ diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index dc36a052766..fcd9082f3e7 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -878,6 +878,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) dbg("%sstate=%d", __func__, break_state); + /* LOCKING */ if (break_state) lcr |= MCT_U232_SET_BREAK; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 07710cf31d0..82930a7d509 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -721,10 +721,10 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) spin_lock_irqsave(&priv->lock, flags); lcr = priv->last_lcr; - spin_unlock_irqrestore(&priv->lock, flags); if (break_state) lcr |= MCT_U232_SET_BREAK; + spin_unlock_irqrestore(&priv->lock, flags); mct_u232_set_line_ctrl(serial, lcr); } /* mct_u232_break_ctl */ diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index fda4a6421c4..96a8c771321 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1343,6 +1343,7 @@ static void mos7840_break(struct tty_struct *tty, int break_state) else data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; + /* FIXME: no locking on shadowLCR anywhere in driver */ mos7840_port->shadowLCR = data; dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", mos7840_port->shadowLCR); @@ -2214,10 +2215,12 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port, break; } + lock_kernel(); mos7840_port->shadowMCR = mcr; Data = mos7840_port->shadowMCR; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + unlock_kernel(); if (status < 0) { dbg("setting MODEM_CONTROL_REGISTER Failed\n"); return -1; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0f2b67244af..d9bf9a5c20e 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -442,7 +442,7 @@ static void sierra_indat_callback(struct urb *urb) " endpoint %02x.", __func__, status, endpoint); } else { if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); + tty = tty_port_tty_get(&port->port); tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 794b5ffe439..080ade223d5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -269,15 +269,19 @@ static void serial_close(struct tty_struct *tty, struct file *filp) return; } - --port->port.count; - if (port->port.count == 0) + if (port->port.count == 1) /* only call the device specific close if this - * port is being closed by the last owner */ + * port is being closed by the last owner. Ensure we do + * this before we drop the port count. The call is protected + * by the port mutex + */ port->serial->type->close(tty, port, filp); - if (port->port.count == (port->console? 1 : 0)) { + if (port->port.count == (port->console ? 2 : 1)) { struct tty_struct *tty = tty_port_tty_get(&port->port); if (tty) { + /* We must do this before we drop the port count to + zero. */ if (tty->driver_data) tty->driver_data = NULL; tty_port_tty_set(&port->port, NULL); @@ -285,13 +289,14 @@ static void serial_close(struct tty_struct *tty, struct file *filp) } } - if (port->port.count == 0) { + if (port->port.count == 1) { mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) usb_autopm_put_interface(port->serial->interface); mutex_unlock(&port->serial->disc_mutex); module_put(port->serial->type->driver.owner); } + --port->port.count; mutex_unlock(&port->mutex); usb_serial_put(port->serial); @@ -334,6 +339,10 @@ static int serial_chars_in_buffer(struct tty_struct *tty) dbg("%s = port %d", __func__, port->number); WARN_ON(!port->port.count); + /* if the device was unplugged then any remaining characters + fell out of the connector ;) */ + if (port->serial->disconnected) + return 0; /* pass on to the driver specific version of this function */ return port->serial->type->chars_in_buffer(tty); } @@ -373,9 +382,7 @@ static int serial_ioctl(struct tty_struct *tty, struct file *file, /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->ioctl) { - lock_kernel(); retval = port->serial->type->ioctl(tty, file, cmd, arg); - unlock_kernel(); } else retval = -ENOIOCTLCMD; return retval; @@ -404,11 +411,8 @@ static int serial_break(struct tty_struct *tty, int break_state) WARN_ON(!port->port.count); /* pass on to the driver specific version of this function if it is available */ - if (port->serial->type->break_ctl) { - lock_kernel(); + if (port->serial->type->break_ctl) port->serial->type->break_ctl(tty, break_state); - unlock_kernel(); - } return 0; } |