diff options
author | Johan Hovold <johan@kernel.org> | 2020-01-14 12:01:46 +0100 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2020-01-17 11:28:05 +0100 |
commit | e6421583953fd92eba1785f90b228d70345125d6 (patch) | |
tree | 48429fcda8143c067c8dd0c2ade6bdef8140691b /drivers/usb | |
parent | a00e7182308f41cac1aa071912ff7a16797dade9 (diff) | |
download | linux-e6421583953fd92eba1785f90b228d70345125d6.tar.gz linux-e6421583953fd92eba1785f90b228d70345125d6.tar.bz2 linux-e6421583953fd92eba1785f90b228d70345125d6.zip |
USB: serial: opticon: stop all I/O on close()
Make sure to stop any submitted write URBs on close().
Note that the tty layer will wait up to 30 seconds for the buffers to
drain before close() is called.
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/opticon.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 05ea21ed967c..9fd9caab397b 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -42,6 +42,8 @@ struct opticon_private { bool cts; int outstanding_urbs; int outstanding_bytes; + + struct usb_anchor anchor; }; @@ -150,6 +152,15 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) return res; } +static void opticon_close(struct usb_serial_port *port) +{ + struct opticon_private *priv = usb_get_serial_port_data(port); + + usb_kill_anchored_urbs(&priv->anchor); + + usb_serial_generic_close(port); +} + static void opticon_write_control_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -226,10 +237,13 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, (unsigned char *)dr, buffer, count, opticon_write_control_callback, port); + usb_anchor_urb(urb, &priv->anchor); + /* send it down the pipe */ ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { dev_err(&port->dev, "failed to submit write urb: %d\n", ret); + usb_unanchor_urb(urb); goto error; } @@ -364,6 +378,7 @@ static int opticon_port_probe(struct usb_serial_port *port) return -ENOMEM; spin_lock_init(&priv->lock); + init_usb_anchor(&priv->anchor); usb_set_serial_port_data(port, priv); @@ -391,6 +406,7 @@ static struct usb_serial_driver opticon_device = { .port_probe = opticon_port_probe, .port_remove = opticon_port_remove, .open = opticon_open, + .close = opticon_close, .write = opticon_write, .write_room = opticon_write_room, .chars_in_buffer = opticon_chars_in_buffer, |