Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+16
+16
drivers/usb/serial/opticon.c
··· 42 42 bool cts; 43 43 int outstanding_urbs; 44 44 int outstanding_bytes; 45 + 46 + struct usb_anchor anchor; 45 47 }; 46 48 47 49 ··· 152 150 return res; 153 151 } 154 152 153 + static void opticon_close(struct usb_serial_port *port) 154 + { 155 + struct opticon_private *priv = usb_get_serial_port_data(port); 156 + 157 + usb_kill_anchored_urbs(&priv->anchor); 158 + 159 + usb_serial_generic_close(port); 160 + } 161 + 155 162 static void opticon_write_control_callback(struct urb *urb) 156 163 { 157 164 struct usb_serial_port *port = urb->context; ··· 237 226 (unsigned char *)dr, buffer, count, 238 227 opticon_write_control_callback, port); 239 228 229 + usb_anchor_urb(urb, &priv->anchor); 230 + 240 231 /* send it down the pipe */ 241 232 ret = usb_submit_urb(urb, GFP_ATOMIC); 242 233 if (ret) { 243 234 dev_err(&port->dev, "failed to submit write urb: %d\n", ret); 235 + usb_unanchor_urb(urb); 244 236 goto error; 245 237 } 246 238 ··· 378 364 return -ENOMEM; 379 365 380 366 spin_lock_init(&priv->lock); 367 + init_usb_anchor(&priv->anchor); 381 368 382 369 usb_set_serial_port_data(port, priv); 383 370 ··· 406 391 .port_probe = opticon_port_probe, 407 392 .port_remove = opticon_port_remove, 408 393 .open = opticon_open, 394 + .close = opticon_close, 409 395 .write = opticon_write, 410 396 .write_room = opticon_write_room, 411 397 .chars_in_buffer = opticon_chars_in_buffer,