usb: gadget: u_serial: diagnose missed console messages
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>
Sat, 10 Aug 2019 08:42:52 +0000 (10:42 +0200)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 22 Oct 2019 07:27:17 +0000 (10:27 +0300)
Insert markers in console stream marking places where data
is missing. This makes the hole in the data stand out clearly
instead of glueing together unrelated messages.

Example output as seen from USB host side:

[    0.064078] pinctrl core: registered pin 16 (UART3_RTS_N PC0) on 70000868.pinmux
[    0.064130] pinctrl
[missed 114987 bytes]
[    4.302299] udevd[134]: starting version 3.2.5
[    4.306845] random: udevd: uninitialized urandom read (16 bytes read)

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/function/u_serial.c

index 0da0054..a248ed0 100644 (file)
@@ -88,6 +88,7 @@ struct gs_console {
        spinlock_t              lock;
        struct usb_request      *req;
        struct kfifo            buf;
+       size_t                  missed;
 };
 
 /*
@@ -931,6 +932,15 @@ static void __gs_console_push(struct gs_console *cons)
        if (!size)
                return;
 
+       if (cons->missed && ep->maxpacket >= 64) {
+               char buf[64];
+               size_t len;
+
+               len = sprintf(buf, "\n[missed %zu bytes]\n", cons->missed);
+               kfifo_in(&cons->buf, buf, len);
+               cons->missed = 0;
+       }
+
        req->length = size;
        if (usb_ep_queue(ep, req, GFP_ATOMIC))
                req->length = 0;
@@ -952,10 +962,13 @@ static void gs_console_write(struct console *co,
 {
        struct gs_console *cons = container_of(co, struct gs_console, console);
        unsigned long flags;
+       size_t n;
 
        spin_lock_irqsave(&cons->lock, flags);
 
-       kfifo_in(&cons->buf, buf, count);
+       n = kfifo_in(&cons->buf, buf, count);
+       if (n < count)
+               cons->missed += count - n;
 
        if (cons->req && !cons->req->length)
                schedule_work(&cons->work);