@@ -124,6 +124,7 @@ struct gs_port {
struct kfifo port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */
bool write_busy;
+ bool read_busy;
wait_queue_head_t close_wait;
bool suspended; /* port suspended */
bool start_delayed; /* delay start when suspended */
@@ -331,9 +332,11 @@ __acquires(&port->port_lock)
/* drop lock while we call out; the controller driver
* may need to call us back (e.g. for disconnect)
*/
+ port->read_busy = true;
spin_unlock(&port->port_lock);
status = usb_ep_queue(out, req, GFP_ATOMIC);
spin_lock(&port->port_lock);
+ port->read_busy = false;
if (status) {
pr_debug("%s: %s %s err %d\n",
@@ -1412,19 +1415,21 @@ void gserial_disconnect(struct gserial *gser)
/* tell the TTY glue not to do I/O here any more */
spin_lock(&port->port_lock);
- gs_console_disconnect(port);
+ if (!port->read_busy) {
+ gs_console_disconnect(port);
- /* REVISIT as above: how best to track this? */
- port->port_line_coding = gser->port_line_coding;
+ /* REVISIT as above: how best to track this? */
+ port->port_line_coding = gser->port_line_coding;
- port->port_usb = NULL;
- gser->ioport = NULL;
- if (port->port.count > 0) {
- wake_up_interruptible(&port->drain_wait);
- if (port->port.tty)
- tty_hangup(port->port.tty);
+ port->port_usb = NULL;
+ gser->ioport = NULL;
+ if (port->port.count > 0) {
+ wake_up_interruptible(&port->drain_wait);
+ if (port->port.tty)
+ tty_hangup(port->port.tty);
+ }
+ port->suspended = false;
}
- port->suspended = false;
spin_unlock(&port->port_lock);
spin_unlock_irqrestore(&serial_port_lock, flags);