From 53366a9f917a8601dcad0fd9768d5956cd2f99a6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 30 Mar 2021 16:38:17 +0200 Subject: USB: serial: drop unused suspending flag The suspending flag was added back in 2009 but no users ever followed. Remove it. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- include/linux/usb/serial.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux/usb/serial.h') diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 952272002e48..7efba6caaadc 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -146,7 +146,6 @@ struct usb_serial { struct usb_serial_driver *type; struct usb_interface *interface; unsigned char disconnected:1; - unsigned char suspending:1; unsigned char attached:1; unsigned char minors_reserved:1; unsigned char num_ports; -- cgit v1.2.3 From 5de03c99691d5b0b6253fda1d1d3bbc8239aadb8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 30 Mar 2021 16:38:19 +0200 Subject: USB: serial: add support for multi-interface functions A single USB function can be implemented using a group of interfaces and this is for example commonly used for Communication Class devices. Add support for multi-interface functions to USB serial core and export an interface that allows drivers to claim a second sibling interface. The interface could easily be extended to allow claiming further interfaces if ever needed. When a driver claims a sibling interface in probe(), core allocates resources for any bulk in, bulk out, interrupt in and interrupt out endpoints found also on the sibling interface. Disconnect is implemented so that unbinding either interface will release the other interface while disconnect() is called precisely once. Similarly, suspend() is called when the first sibling interface is suspended and resume() is called when the last sibling interface is resumed by USB core. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- drivers/usb/serial/usb-serial.c | 84 +++++++++++++++++++++++++++++++++++------ include/linux/usb/serial.h | 7 ++++ 2 files changed, 80 insertions(+), 11 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d981809c4ed3..aaae71a0bbff 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -121,6 +121,44 @@ static void release_minors(struct usb_serial *serial) serial->minors_reserved = 0; } +int usb_serial_claim_interface(struct usb_serial *serial, struct usb_interface *intf) +{ + struct usb_driver *driver = serial->type->usb_driver; + int ret; + + if (serial->sibling) + return -EBUSY; + + ret = usb_driver_claim_interface(driver, intf, serial); + if (ret) { + dev_err(&serial->interface->dev, + "failed to claim sibling interface: %d\n", ret); + return ret; + } + + serial->sibling = intf; + + return 0; +} +EXPORT_SYMBOL_GPL(usb_serial_claim_interface); + +static void release_sibling(struct usb_serial *serial, struct usb_interface *intf) +{ + struct usb_driver *driver = serial->type->usb_driver; + struct usb_interface *sibling; + + if (!serial->sibling) + return; + + if (intf == serial->sibling) + sibling = serial->interface; + else + sibling = serial->sibling; + + usb_set_intfdata(sibling, NULL); + usb_driver_release_interface(driver, sibling); +} + static void destroy_serial(struct kref *kref) { struct usb_serial *serial; @@ -742,13 +780,14 @@ static void store_endpoint(struct usb_serial *serial, } static void find_endpoints(struct usb_serial *serial, - struct usb_serial_endpoints *epds) + struct usb_serial_endpoints *epds, + struct usb_interface *intf) { struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *epd; unsigned int i; - iface_desc = serial->interface->cur_altsetting; + iface_desc = intf->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { epd = &iface_desc->endpoint[i].desc; store_endpoint(serial, epds, epd); @@ -917,7 +956,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (retval) { dev_dbg(ddev, "sub driver rejected device\n"); - goto err_put_serial; + goto err_release_sibling; } } @@ -925,10 +964,12 @@ static int usb_serial_probe(struct usb_interface *interface, epds = kzalloc(sizeof(*epds), GFP_KERNEL); if (!epds) { retval = -ENOMEM; - goto err_put_serial; + goto err_release_sibling; } - find_endpoints(serial, epds); + find_endpoints(serial, epds, interface); + if (serial->sibling) + find_endpoints(serial, epds, serial->sibling); if (epds->num_bulk_in < type->num_bulk_in || epds->num_bulk_out < type->num_bulk_out || @@ -1076,7 +1117,8 @@ exit: err_free_epds: kfree(epds); -err_put_serial: +err_release_sibling: + release_sibling(serial, interface); usb_serial_put(serial); err_put_module: module_put(type->driver.owner); @@ -1092,6 +1134,10 @@ static void usb_serial_disconnect(struct usb_interface *interface) struct usb_serial_port *port; struct tty_struct *tty; + /* sibling interface is cleaning up */ + if (!serial) + return; + usb_serial_console_disconnect(serial); mutex_lock(&serial->disc_mutex); @@ -1115,6 +1161,8 @@ static void usb_serial_disconnect(struct usb_interface *interface) if (serial->type->disconnect) serial->type->disconnect(serial); + release_sibling(serial, interface); + /* let the last holder of this object cause it to be cleaned up */ usb_serial_put(serial); dev_info(dev, "device disconnected\n"); @@ -1123,7 +1171,11 @@ static void usb_serial_disconnect(struct usb_interface *interface) int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) { struct usb_serial *serial = usb_get_intfdata(intf); - int i, r = 0; + int i, r; + + /* suspend when called for first sibling interface */ + if (serial->suspend_count++) + return 0; /* * serial->type->suspend() MUST return 0 in system sleep context, @@ -1132,14 +1184,16 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) */ if (serial->type->suspend) { r = serial->type->suspend(serial, message); - if (r < 0) - goto err_out; + if (r < 0) { + serial->suspend_count--; + return r; + } } for (i = 0; i < serial->num_ports; ++i) usb_serial_port_poison_urbs(serial->port[i]); -err_out: - return r; + + return 0; } EXPORT_SYMBOL(usb_serial_suspend); @@ -1156,6 +1210,10 @@ int usb_serial_resume(struct usb_interface *intf) struct usb_serial *serial = usb_get_intfdata(intf); int rv; + /* resume when called for last sibling interface */ + if (--serial->suspend_count) + return 0; + usb_serial_unpoison_port_urbs(serial); if (serial->type->resume) @@ -1172,6 +1230,10 @@ static int usb_serial_reset_resume(struct usb_interface *intf) struct usb_serial *serial = usb_get_intfdata(intf); int rv; + /* resume when called for last sibling interface */ + if (--serial->suspend_count) + return 0; + usb_serial_unpoison_port_urbs(serial); if (serial->type->reset_resume) { diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 7efba6caaadc..e9b90577f50b 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -130,6 +130,8 @@ static inline void usb_set_serial_port_data(struct usb_serial_port *port, * @dev: pointer to the struct usb_device for this device * @type: pointer to the struct usb_serial_driver for this device * @interface: pointer to the struct usb_interface for this device + * @sibling: pointer to the struct usb_interface of any sibling interface + * @suspend_count: number of suspended (sibling) interfaces * @num_ports: the number of ports this device has * @num_interrupt_in: number of interrupt in endpoints we have * @num_interrupt_out: number of interrupt out endpoints we have @@ -145,6 +147,8 @@ struct usb_serial { struct usb_device *dev; struct usb_serial_driver *type; struct usb_interface *interface; + struct usb_interface *sibling; + unsigned int suspend_count; unsigned char disconnected:1; unsigned char attached:1; unsigned char minors_reserved:1; @@ -334,6 +338,9 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} /* Functions needed by other parts of the usbserial core */ struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor); void usb_serial_put(struct usb_serial *serial); + +int usb_serial_claim_interface(struct usb_serial *serial, struct usb_interface *intf); + int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port); int usb_serial_generic_write_start(struct usb_serial_port *port, gfp_t mem_flags); int usb_serial_generic_write(struct tty_struct *tty, struct usb_serial_port *port, -- cgit v1.2.3 From 01fd45f676f1b3785b7cdd5d815f9c31ddcd9dd1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 7 Apr 2021 12:39:21 +0200 Subject: USB: serial: add generic support for TIOCSSERIAL TIOCSSERIAL is a horrid, underspecified, legacy interface which for most serial devices is only useful for setting the close_delay and closing_wait parameters. The closing_wait parameter determines how long to wait for the transfer buffers to drain during close and the default timeout of 30 seconds may not be sufficient at low line speeds. In other cases, when for example flow is stopped, the default timeout may instead be too long. Add generic support for TIOCSSERIAL and TIOCGSERIAL with handling of the three common parameters close_delay, closing_wait and line for the benefit of all USB serial drivers while still allowing drivers to implement further functionality through the existing callbacks. This currently includes a few drivers that report their base baud clock rate even if that is really only of interest when setting custom divisors through the deprecated ASYNC_SPD_CUST interface; an interface which only the FTDI driver actually implements. Some drivers have also been reporting back a fake UART type, something which should no longer be needed and will be dropped by a follow-on patch. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- drivers/usb/serial/ark3116.c | 9 +----- drivers/usb/serial/f81232.c | 12 ++------ drivers/usb/serial/f81534.c | 8 +----- drivers/usb/serial/ftdi_sio.c | 11 ++------ drivers/usb/serial/io_edgeport.c | 12 ++------ drivers/usb/serial/io_ti.c | 17 ++--------- drivers/usb/serial/mos7720.c | 12 ++------ drivers/usb/serial/mos7840.c | 10 +------ drivers/usb/serial/opticon.c | 12 ++------ drivers/usb/serial/option.c | 2 -- drivers/usb/serial/pl2303.c | 10 +------ drivers/usb/serial/quatech2.c | 13 --------- drivers/usb/serial/ssu100.c | 13 --------- drivers/usb/serial/ti_usb_3410_5052.c | 42 ++------------------------- drivers/usb/serial/usb-serial.c | 53 +++++++++++++++++++++++++++++++---- drivers/usb/serial/usb-wwan.h | 4 --- drivers/usb/serial/usb_wwan.c | 42 --------------------------- drivers/usb/serial/whiteheat.c | 12 ++------ include/linux/usb/serial.h | 2 +- 19 files changed, 70 insertions(+), 226 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 957cdd694b1f..c0cf60e9273d 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -385,17 +385,10 @@ err_free: return result; } -static int ark3116_get_serial_info(struct tty_struct *tty, +static void ark3116_get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - ss->type = PORT_16654; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } static int ark3116_tiocmget(struct tty_struct *tty) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index af0fe2a82eb2..5e34b364d94d 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -820,19 +820,13 @@ static int f81232_carrier_raised(struct usb_serial_port *port) return 0; } -static int f81232_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void f81232_get_serial(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; struct f81232_private *priv = usb_get_serial_port_data(port); ss->type = PORT_16550A; - ss->line = port->minor; ss->baud_base = priv->baud_base; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } static void f81232_interrupt_work(struct work_struct *work) @@ -1023,7 +1017,7 @@ static struct usb_serial_driver f81232_device = { .close = f81232_close, .dtr_rts = f81232_dtr_rts, .carrier_raised = f81232_carrier_raised, - .get_serial = f81232_get_serial_info, + .get_serial = f81232_get_serial, .break_ctl = f81232_break_ctl, .set_termios = f81232_set_termios, .tiocmget = f81232_tiocmget, @@ -1048,7 +1042,7 @@ static struct usb_serial_driver f81534a_device = { .close = f81232_close, .dtr_rts = f81232_dtr_rts, .carrier_raised = f81232_carrier_raised, - .get_serial = f81232_get_serial_info, + .get_serial = f81232_get_serial, .break_ctl = f81232_break_ctl, .set_termios = f81232_set_termios, .tiocmget = f81232_tiocmget, diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c index c9f90d437e3a..633de52feaad 100644 --- a/drivers/usb/serial/f81534.c +++ b/drivers/usb/serial/f81534.c @@ -1140,8 +1140,7 @@ static void f81534_close(struct usb_serial_port *port) mutex_unlock(&serial_priv->urb_mutex); } -static int f81534_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void f81534_get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; struct f81534_port_private *port_priv; @@ -1149,12 +1148,7 @@ static int f81534_get_serial_info(struct tty_struct *tty, port_priv = usb_get_serial_port_data(port); ss->type = PORT_16550A; - ss->line = port->minor; ss->baud_base = port_priv->baud_base; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } static void f81534_process_per_serial_block(struct usb_serial_port *port, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f8a0911f90ea..16d3e50487e6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1082,8 +1082,7 @@ static int ftdi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss); +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss); static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss); static void ftdi_break_ctl(struct tty_struct *tty, int break_state); @@ -1477,20 +1476,14 @@ static int read_latency_timer(struct usb_serial_port *port) return 0; } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); - ss->line = port->minor; ss->flags = priv->flags; ss->baud_base = priv->baud_base; ss->custom_divisor = priv->custom_divisor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } static int set_serial_info(struct tty_struct *tty, diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 3b4809875a71..6b86e68ee2e8 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1594,17 +1594,9 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - - ss->type = PORT_16550A; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; + ss->type = PORT_16550A; } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index f5aab570fd05..dce994c29afe 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2433,22 +2433,9 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - unsigned cwait; - - cwait = port->port.closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = jiffies_to_msecs(cwait) / 10; - - ss->type = PORT_16550A; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = cwait; - - return 0; + ss->type = PORT_16550A; } static void edge_break(struct tty_struct *tty, int break_state) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 7289d46c3164..4012b448388a 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1634,17 +1634,9 @@ static int mos7720_tiocmset(struct tty_struct *tty, return 0; } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - - ss->type = PORT_16550A; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; + ss->type = PORT_16550A; } static int mos7720_ioctl(struct tty_struct *tty, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 77cbe18a1629..d20fb0a678dc 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1388,17 +1388,9 @@ static int mos7840_get_lsr_info(struct tty_struct *tty, * function to get information about serial port *****************************************************************************/ -static int mos7840_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void mos7840_get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - ss->type = PORT_16550A; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } /***************************************************************************** diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 1c7e5dc2c272..db84afcf7f1a 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -352,18 +352,10 @@ static int opticon_tiocmset(struct tty_struct *tty, return 0; } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - /* fake emulate a 16550 uart to make userspace code happy */ - ss->type = PORT_16550A; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; + ss->type = PORT_16550A; } static int opticon_port_probe(struct usb_serial_port *port) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c6969ca72839..3e79a543d3e7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2095,8 +2095,6 @@ static struct usb_serial_driver option_1port_device = { .chars_in_buffer = usb_wwan_chars_in_buffer, .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, - .get_serial = usb_wwan_get_serial_info, - .set_serial = usb_wwan_set_serial_info, .attach = option_attach, .release = option_release, .port_probe = usb_wwan_port_probe, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1bb870ca7044..64f08a45eb46 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -1048,17 +1048,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port) return 0; } -static int pl2303_get_serial(struct tty_struct *tty, - struct serial_struct *ss) +static void pl2303_get_serial(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - ss->type = PORT_16654; - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } static void pl2303_set_break(struct usb_serial_port *port, bool enable) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 0d23e565e0d2..5f2e7f668e68 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -453,18 +453,6 @@ static void qt2_disconnect(struct usb_serial *serial) usb_kill_urb(serial_priv->read_urb); } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) -{ - struct usb_serial_port *port = tty->driver_data; - - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; -} - static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch) { switch (*ch) { @@ -975,7 +963,6 @@ static struct usb_serial_driver qt2_device = { .tiocmset = qt2_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, - .get_serial = get_serial_info, .set_termios = qt2_set_termios, }; diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index c4616c37f33f..3baf7c0f5a98 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -331,18 +331,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) return usb_serial_generic_open(tty, port); } -static int get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) -{ - struct usb_serial_port *port = tty->driver_data; - - ss->line = port->minor; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; -} - static int ssu100_attach(struct usb_serial *serial) { return ssu100_initdevice(serial->dev); @@ -542,7 +530,6 @@ static struct usb_serial_driver ssu100_device = { .tiocmset = ssu100_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, - .get_serial = get_serial_info, .set_termios = ssu100_set_termios, }; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index bb50098a0ce6..6df316bdb40f 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -328,10 +328,7 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data, static void ti_send(struct ti_port *tport); static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); static int ti_get_lsr(struct ti_port *tport, u8 *lsr); -static int ti_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss); -static int ti_set_serial_info(struct tty_struct *tty, - struct serial_struct *ss); +static void ti_get_serial_info(struct tty_struct *tty, struct serial_struct *ss); static void ti_handle_new_msr(struct ti_port *tport, u8 msr); static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty); @@ -435,7 +432,6 @@ static struct usb_serial_driver ti_1port_device = { .throttle = ti_throttle, .unthrottle = ti_unthrottle, .get_serial = ti_get_serial_info, - .set_serial = ti_set_serial_info, .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, @@ -469,7 +465,6 @@ static struct usb_serial_driver ti_2port_device = { .throttle = ti_throttle, .unthrottle = ti_unthrottle, .get_serial = ti_get_serial_info, - .set_serial = ti_set_serial_info, .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, @@ -1393,46 +1388,13 @@ free_data: } -static int ti_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) +static void ti_get_serial_info(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - unsigned cwait; - - cwait = port->port.closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = jiffies_to_msecs(cwait) / 10; ss->type = PORT_16550A; - ss->line = port->minor; ss->baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; - ss->close_delay = 50; - ss->closing_wait = cwait; - - return 0; -} - - -static int ti_set_serial_info(struct tty_struct *tty, - struct serial_struct *ss) -{ - struct usb_serial_port *port = tty->driver_data; - struct tty_port *tport = &port->port; - unsigned cwait; - - cwait = ss->closing_wait; - if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = msecs_to_jiffies(10 * ss->closing_wait); - - if (!capable(CAP_SYS_ADMIN)) { - if (cwait != tport->closing_wait) - return -EPERM; - } - - tport->closing_wait = cwait; - - return 0; } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index f53a830f4094..255f562ef1a0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -437,19 +437,62 @@ static void serial_unthrottle(struct tty_struct *tty) static int serial_get_serial(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; + struct tty_port *tport = &port->port; + unsigned int close_delay, closing_wait; + + mutex_lock(&tport->mutex); + + close_delay = jiffies_to_msecs(tport->close_delay) / 10; + closing_wait = tport->closing_wait; + if (closing_wait != ASYNC_CLOSING_WAIT_NONE) + closing_wait = jiffies_to_msecs(closing_wait) / 10; + + ss->line = port->minor; + ss->close_delay = close_delay; + ss->closing_wait = closing_wait; if (port->serial->type->get_serial) - return port->serial->type->get_serial(tty, ss); - return -ENOTTY; + port->serial->type->get_serial(tty, ss); + + mutex_unlock(&tport->mutex); + + return 0; } static int serial_set_serial(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; + struct tty_port *tport = &port->port; + unsigned int close_delay, closing_wait; + int ret = 0; + + close_delay = msecs_to_jiffies(ss->close_delay * 10); + closing_wait = ss->closing_wait; + if (closing_wait != ASYNC_CLOSING_WAIT_NONE) + closing_wait = msecs_to_jiffies(closing_wait * 10); + + mutex_lock(&tport->mutex); + + if (!capable(CAP_SYS_ADMIN)) { + if (close_delay != tport->close_delay || + closing_wait != tport->closing_wait) { + ret = -EPERM; + goto out_unlock; + } + } - if (port->serial->type->set_serial) - return port->serial->type->set_serial(tty, ss); - return -ENOTTY; + if (port->serial->type->set_serial) { + ret = port->serial->type->set_serial(tty, ss); + if (ret) + goto out_unlock; + } + + tport->close_delay = close_delay; + tport->closing_wait = closing_wait; +out_unlock: + mutex_unlock(&tport->mutex); + + return ret; } static int serial_ioctl(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 79dafd98e0a1..b5331d03092f 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -15,10 +15,6 @@ extern int usb_wwan_write_room(struct tty_struct *tty); extern int usb_wwan_tiocmget(struct tty_struct *tty); extern int usb_wwan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -extern int usb_wwan_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss); -extern int usb_wwan_set_serial_info(struct tty_struct *tty, - struct serial_struct *ss); extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); extern int usb_wwan_chars_in_buffer(struct tty_struct *tty); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 4ea315e5e69b..3eb72c59ede6 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -132,48 +132,6 @@ int usb_wwan_tiocmset(struct tty_struct *tty, } EXPORT_SYMBOL(usb_wwan_tiocmset); -int usb_wwan_get_serial_info(struct tty_struct *tty, - struct serial_struct *ss) -{ - struct usb_serial_port *port = tty->driver_data; - - ss->line = port->minor; - ss->close_delay = jiffies_to_msecs(port->port.close_delay) / 10; - ss->closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : - jiffies_to_msecs(port->port.closing_wait) / 10; - return 0; -} -EXPORT_SYMBOL(usb_wwan_get_serial_info); - -int usb_wwan_set_serial_info(struct tty_struct *tty, - struct serial_struct *ss) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int closing_wait, close_delay; - int retval = 0; - - close_delay = msecs_to_jiffies(ss->close_delay * 10); - closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : - msecs_to_jiffies(ss->closing_wait * 10); - - mutex_lock(&port->port.mutex); - - if (!capable(CAP_SYS_ADMIN)) { - if ((close_delay != port->port.close_delay) || - (closing_wait != port->port.closing_wait)) - retval = -EPERM; - } else { - port->port.close_delay = close_delay; - port->port.closing_wait = closing_wait; - } - - mutex_unlock(&port->port.mutex); - return retval; -} -EXPORT_SYMBOL(usb_wwan_set_serial_info); - int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index c8b10faa2ff8..6a95c5a0056f 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,7 +83,7 @@ static void whiteheat_port_remove(struct usb_serial_port *port); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); -static int whiteheat_get_serial(struct tty_struct *tty, +static void whiteheat_get_serial(struct tty_struct *tty, struct serial_struct *ss); static void whiteheat_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); @@ -439,18 +439,10 @@ static int whiteheat_tiocmset(struct tty_struct *tty, } -static int whiteheat_get_serial(struct tty_struct *tty, - struct serial_struct *ss) +static void whiteheat_get_serial(struct tty_struct *tty, struct serial_struct *ss) { - struct usb_serial_port *port = tty->driver_data; - ss->type = PORT_16654; - ss->line = port->minor; ss->baud_base = 460800; - ss->close_delay = 50; - ss->closing_wait = 3000; - - return 0; } diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index e9b90577f50b..8c63fa9bfc74 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -279,7 +279,7 @@ struct usb_serial_driver { int (*write_room)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg); - int (*get_serial)(struct tty_struct *tty, struct serial_struct *ss); + void (*get_serial)(struct tty_struct *tty, struct serial_struct *ss); int (*set_serial)(struct tty_struct *tty, struct serial_struct *ss); void (*set_termios)(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); -- cgit v1.2.3