This patch tries to solve the problem that printk data is dropped because there are too many outstanding transmit urb's while trying to execute printk's to a console. You can observe this by booting a kernel with a serial console and cross checking the dmesg output with what you received on the console or doing something like "echo t > /proc/sysrq-trigger". This patch takes the route of forcibly polling the hcd device to drain the urb queue in order to initiate the bulk write call backs. A few millisecond penalty will get incurred to allow the hcd controller to complete a write urb, else the console data is thrown away. Even with any kind of delay, the latency is still lower than using a traditional serial port uart due to the fact that there are bigger buffer for use with the USB serial console kfifo implementation. Signed-off-by: Jason Wessel <jason.wessel@xxxxxxxxxxxxx> CC: Greg Kroah-Hartman <gregkh@xxxxxxx> CC: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/serial/console.c | 42 +++++++++++++++++++++++++++--------------- 1 files changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 1ee6b2a..b09832f 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -197,13 +197,37 @@ static int usb_console_setup(struct console *co, char *options) return retval; } +static void usb_do_console_write(struct usb_serial *serial, + struct usb_serial_port *port, + const char *buf, unsigned count) +{ + int retval; + int loops = 100; +try_again: + /* pass on to the driver specific version of this function if + it is available */ + if (serial->type->write) + retval = serial->type->write(NULL, port, buf, count); + else + retval = usb_serial_generic_write(NULL, port, buf, count); + if (retval < count && retval >= 0 && loops--) { + /* poll the hcd device because the queue is full */ + count -= retval; + buf += retval; + udelay(100); + usb_poll_irq(serial->dev); + usb_poll_irq_schedule_flush(); + goto try_again; + } + dbg("%s - return value : %d", __func__, retval); +} + static void usb_console_write(struct console *co, const char *buf, unsigned count) { static struct usbcons_info *info = &usbcons_info; struct usb_serial_port *port = info->port; struct usb_serial *serial; - int retval = -ENODEV; if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) return; @@ -230,23 +254,11 @@ static void usb_console_write(struct console *co, break; } } - /* pass on to the driver specific version of this function if - it is available */ - if (serial->type->write) - retval = serial->type->write(NULL, port, buf, i); - else - retval = usb_serial_generic_write(NULL, port, buf, i); - dbg("%s - return value : %d", __func__, retval); + usb_do_console_write(serial, port, buf, i); if (lf) { /* append CR after LF */ unsigned char cr = 13; - if (serial->type->write) - retval = serial->type->write(NULL, - port, &cr, 1); - else - retval = usb_serial_generic_write(NULL, - port, &cr, 1); - dbg("%s - return value : %d", __func__, retval); + usb_do_console_write(serial, port, &cr, 1); } buf += i; count -= i; -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html