@@ -984,47 +984,40 @@ static int gs_console_thread(void *data)
struct gs_port *port;
struct usb_request *req;
struct usb_ep *ep;
- int xfer, ret, count, size;
+ int len, size, status;
+ spin_lock_irq(&info->con_lock);
do {
port = info->port;
- set_current_state(TASK_INTERRUPTIBLE);
- if (!port || !port->port_usb
- || !port->port_usb->in || !info->console_req)
+ if (!port || !port->port_usb || !info->console_req)
goto sched;
req = info->console_req;
ep = port->port_usb->in;
+ len = kfifo_len(&info->con_buf);
+ if (len > 0 && !info->req_busy) {
+ size = ep->maxpacket;
+ if (len < size)
+ size = len;
- spin_lock_irq(&info->con_lock);
- count = kfifo_len(&info->con_buf);
- size = ep->maxpacket;
-
- if (count > 0 && !info->req_busy) {
- set_current_state(TASK_RUNNING);
- if (count < size)
- size = count;
-
- xfer = kfifo_out(&info->con_buf, req->buf, size);
- req->length = xfer;
-
- spin_unlock(&info->con_lock);
- ret = usb_ep_queue(ep, req, GFP_ATOMIC);
- spin_lock(&info->con_lock);
- if (ret < 0)
- info->req_busy = 0;
- else
- info->req_busy = 1;
+ req->length = kfifo_out(&info->con_buf, req->buf, size);
+ info->req_busy = 1;
spin_unlock_irq(&info->con_lock);
+ status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ spin_lock_irq(&info->con_lock);
+ if (status < 0)
+ info->req_busy = 0;
} else {
- spin_unlock_irq(&info->con_lock);
sched:
+ spin_unlock_irq(&info->con_lock);
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
break;
}
schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_lock_irq(&info->con_lock);
}
} while (1);
gs_complete_out might be called before con_lock following usb_ep_queue is locked, which prevents any future output on the console. Fix that by resetting req_busy only if usb_ep_queue fails. While there also put variable access we are racing with connection/disconnection events under con_lock as well. Fixes: a5beaaf39455 ("usb: gadget: Add the console support for usb-to-serial port") Signed-off-by: Ladislav Michl <ladis@linux-mips.org> --- Changes: - v2: None drivers/usb/gadget/function/u_serial.c | 41 +++++++++++--------------- 1 file changed, 17 insertions(+), 24 deletions(-)