From patchwork Wed Feb 27 10:46:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= X-Patchwork-Id: 10831535 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 36596180E for ; Wed, 27 Feb 2019 10:47:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22F992C6EE for ; Wed, 27 Feb 2019 10:47:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 170572C70F; Wed, 27 Feb 2019 10:47:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C12CA2C73A for ; Wed, 27 Feb 2019 10:47:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726931AbfB0Kq7 (ORCPT ); Wed, 27 Feb 2019 05:46:59 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:31949 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726397AbfB0Kq7 (ORCPT ); Wed, 27 Feb 2019 05:46:59 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448XQY3zQJzJX; Wed, 27 Feb 2019 11:45:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551264341; bh=q3dmSavRAaTLVOyB3bYchJD0/kxWEL01eNi0BB2jO7w=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=XnQ1G7CsjVGjdVp7vv3njLtV6+N2gRsctLyUVyacm+uYxxD54IcYlRSUtnlqr0pK/ qx2Xzoakz541MIHhv2+ML3uu9RFpOcdcN8XV8xZic1thIxJuAaTsvEzDzflfYSiYyO FRHg3PHQ+0Yr/rqshyEdntdARksLYoQsZ4xcFHjQAZxRPdLwf0hCLX/iNdp7tNlLeJ PxuYfqRvX3tUewXMSRJ2/LDflKR+e1x0ZOTFEjzTqXGq+dtn4ynrYjWuEMwvAZRiw6 vRkhkNlY949bBmZsA9fJCgsBCmssVjtcZ4KJuVDe/h2+zeSDX87SF5Kldpjfv2Yc9M CPadvo/rMm1UQ== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 11:46:57 +0100 Message-Id: <7e94cf9d80899fe76537b455bb5668cc7ed0fa08.1551264094.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH v3 1/5] usb: gadget: u_serial: add missing port entry locking MIME-Version: 1.0 To: linux-usb@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP gserial_alloc_line() misses locking (for a release barrier) while resetting port entry on TTY allocation failure. Fix this. Cc: stable@vger.kernel.org Signed-off-by: Michał Mirosław Reviewed-by: Greg Kroah-Hartman --- v3: added cc-stable v2: no changes --- drivers/usb/gadget/function/u_serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 65f634ec7fc2..bb1e2e1d0076 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1239,8 +1239,10 @@ int gserial_alloc_line(unsigned char *line_num) __func__, port_num, PTR_ERR(tty_dev)); ret = PTR_ERR(tty_dev); + mutex_lock(&ports[port_num].lock); port = ports[port_num].port; ports[port_num].port = NULL; + mutex_unlock(&ports[port_num].lock); gserial_free_port(port); goto err; } From patchwork Wed Feb 27 10:46:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= X-Patchwork-Id: 10831543 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FB4F1575 for ; Wed, 27 Feb 2019 10:47:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78E802C6EE for ; Wed, 27 Feb 2019 10:47:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D3472C73A; Wed, 27 Feb 2019 10:47:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 858922C6EE for ; Wed, 27 Feb 2019 10:47:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726894AbfB0KrE (ORCPT ); Wed, 27 Feb 2019 05:47:04 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:4322 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726590AbfB0KrD (ORCPT ); Wed, 27 Feb 2019 05:47:03 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448XQZ09NYzL0; Wed, 27 Feb 2019 11:45:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551264342; bh=zHZKJXD121oHuZwqy1jn0ipYIBZXpggj3EQxborCxcg=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=YArunbHxdUnWvU6SAKcfHalHttDlGPK/+p9cxDY51jP5iPJdfB3cHDWgxmNMjZdK+ BV9zc7KpJjOiqjpZTTviSn/8VWDysMCrmiGgK8dPROOQWgKMFcxPECTVzRyX48U4T3 9GD0jot2Iwm9RbaNpWM4lSaOh6V/ib17vxkaHuF52t7qmofpI3C91TpqnT/hfBo1ud qD/Bgt9GTa+UaxvJxXluLhl1DJ58x2arWpkAcKI4LzKs8i7dxri3UgNAoT4665W8N6 s4d2vkgxaZCe525ssJK0Z/DfTlrG+M07vP2wUjLgki3x4e35KljKfLAHOKM95foqJI w1kZaiuCpOLnQ== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 11:46:57 +0100 Message-Id: <82350b03df1df2f85b1bd76970ba88bcf155ec5f.1551264094.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH v3 2/5] usb: gadget: u_serial: reimplement console support MIME-Version: 1.0 To: linux-usb@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Rewrite console support to fix a few shortcomings of the old code preventing its use with multiple ports. This removes some duplicated code and replaces a custom kthread with simpler workqueue item. Only port ttyGS0 gets to be a console for now. Signed-off-by: Michał Mirosław Reviewed-by: Greg Kroah-Hartman --- v3: no changes v2: no changes --- drivers/usb/gadget/function/u_serial.c | 352 ++++++++++++------------- 1 file changed, 164 insertions(+), 188 deletions(-) diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index bb1e2e1d0076..8d2d861e1543 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -82,14 +82,12 @@ #define GS_CONSOLE_BUF_SIZE 8192 /* console info */ -struct gscons_info { - struct gs_port *port; - struct task_struct *console_thread; - struct kfifo con_buf; - /* protect the buf and busy flag */ - spinlock_t con_lock; - int req_busy; - struct usb_request *console_req; +struct gs_console { + struct console console; + struct work_struct work; + spinlock_t lock; + struct usb_request *req; + struct kfifo buf; }; /* @@ -101,6 +99,9 @@ struct gs_port { spinlock_t port_lock; /* guard port_* access */ struct gserial *port_usb; +#ifdef CONFIG_U_SERIAL_CONSOLE + struct gs_console *console; +#endif bool openclose; /* open/close in progress */ u8 port_num; @@ -889,36 +890,9 @@ static struct tty_driver *gs_tty_driver; #ifdef CONFIG_U_SERIAL_CONSOLE -static struct gscons_info gscons_info; -static struct console gserial_cons; - -static struct usb_request *gs_request_new(struct usb_ep *ep) +static void gs_console_complete_out(struct usb_ep *ep, struct usb_request *req) { - struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (!req) - return NULL; - - req->buf = kmalloc(ep->maxpacket, GFP_ATOMIC); - if (!req->buf) { - usb_ep_free_request(ep, req); - return NULL; - } - - return req; -} - -static void gs_request_free(struct usb_request *req, struct usb_ep *ep) -{ - if (!req) - return; - - kfree(req->buf); - usb_ep_free_request(ep, req); -} - -static void gs_complete_out(struct usb_ep *ep, struct usb_request *req) -{ - struct gscons_info *info = &gscons_info; + struct gs_console *cons = req->context; switch (req->status) { default: @@ -927,12 +901,12 @@ static void gs_complete_out(struct usb_ep *ep, struct usb_request *req) /* fall through */ case 0: /* normal completion */ - spin_lock(&info->con_lock); - info->req_busy = 0; - spin_unlock(&info->con_lock); - - wake_up_process(info->console_thread); + spin_lock(&cons->lock); + req->length = 0; + schedule_work(&cons->work); + spin_unlock(&cons->lock); break; + case -ECONNRESET: case -ESHUTDOWN: /* disconnect */ pr_vdebug("%s: %s shutdown\n", __func__, ep->name); @@ -940,190 +914,189 @@ static void gs_complete_out(struct usb_ep *ep, struct usb_request *req) } } -static int gs_console_connect(int port_num) +static void __gs_console_push(struct gs_console *cons) { - struct gscons_info *info = &gscons_info; - struct gs_port *port; - struct usb_ep *ep; + struct usb_request *req = cons->req; + struct usb_ep *ep = cons->console.data; + size_t size = 0; - if (port_num != gserial_cons.index) { - pr_err("%s: port num [%d] is not support console\n", - __func__, port_num); - return -ENXIO; - } + if (!req) + return; /* disconnected */ - port = ports[port_num].port; - ep = port->port_usb->in; - if (!info->console_req) { - info->console_req = gs_request_new(ep); - if (!info->console_req) - return -ENOMEM; - info->console_req->complete = gs_complete_out; - } + if (req->length) + return; /* busy */ - info->port = port; - spin_lock(&info->con_lock); - info->req_busy = 0; - spin_unlock(&info->con_lock); - pr_vdebug("port[%d] console connect!\n", port_num); - return 0; -} - -static void gs_console_disconnect(struct usb_ep *ep) -{ - struct gscons_info *info = &gscons_info; - struct usb_request *req = info->console_req; + size = kfifo_out(&cons->buf, req->buf, ep->maxpacket); + if (!size) + return; - gs_request_free(req, ep); - info->console_req = NULL; + req->length = size; + if (usb_ep_queue(ep, req, GFP_ATOMIC)) + req->length = 0; } -static int gs_console_thread(void *data) +static void gs_console_work(struct work_struct *work) { - struct gscons_info *info = &gscons_info; - struct gs_port *port; - struct usb_request *req; - struct usb_ep *ep; - int xfer, ret, count, size; - - do { - port = info->port; - set_current_state(TASK_INTERRUPTIBLE); - if (!port || !port->port_usb - || !port->port_usb->in || !info->console_req) - goto sched; - - req = info->console_req; - ep = port->port_usb->in; - - 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; - - spin_unlock_irq(&info->con_lock); - } else { - spin_unlock_irq(&info->con_lock); -sched: - if (kthread_should_stop()) { - set_current_state(TASK_RUNNING); - break; - } - schedule(); - } - } while (1); - - return 0; -} - -static int gs_console_setup(struct console *co, char *options) -{ - struct gscons_info *info = &gscons_info; - int status; - - info->port = NULL; - info->console_req = NULL; - info->req_busy = 0; - spin_lock_init(&info->con_lock); + struct gs_console *cons = container_of(work, struct gs_console, work); - status = kfifo_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL); - if (status) { - pr_err("%s: allocate console buffer failed\n", __func__); - return status; - } + spin_lock_irq(&cons->lock); - info->console_thread = kthread_create(gs_console_thread, - co, "gs_console"); - if (IS_ERR(info->console_thread)) { - pr_err("%s: cannot create console thread\n", __func__); - kfifo_free(&info->con_buf); - return PTR_ERR(info->console_thread); - } - wake_up_process(info->console_thread); + __gs_console_push(cons); - return 0; + spin_unlock_irq(&cons->lock); } static void gs_console_write(struct console *co, const char *buf, unsigned count) { - struct gscons_info *info = &gscons_info; + struct gs_console *cons = container_of(co, struct gs_console, console); unsigned long flags; - spin_lock_irqsave(&info->con_lock, flags); - kfifo_in(&info->con_buf, buf, count); - spin_unlock_irqrestore(&info->con_lock, flags); + spin_lock_irqsave(&cons->lock, flags); - wake_up_process(info->console_thread); + kfifo_in(&cons->buf, buf, count); + + if (cons->req && !cons->req->length) + schedule_work(&cons->work); + + spin_unlock_irqrestore(&cons->lock, flags); } static struct tty_driver *gs_console_device(struct console *co, int *index) { - struct tty_driver **p = (struct tty_driver **)co->data; - - if (!*p) - return NULL; - *index = co->index; - return *p; + return gs_tty_driver; } -static struct console gserial_cons = { - .name = "ttyGS", - .write = gs_console_write, - .device = gs_console_device, - .setup = gs_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &gs_tty_driver, -}; - -static void gserial_console_init(void) +static int gs_console_connect(struct gs_port *port) { - register_console(&gserial_cons); + struct gs_console *cons = port->console; + struct usb_request *req; + struct usb_ep *ep; + + if (!cons) + return 0; + + ep = port->port_usb->in; + req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); + if (!req) + return -ENOMEM; + req->complete = gs_console_complete_out; + req->context = cons; + req->length = 0; + + spin_lock(&cons->lock); + cons->req = req; + cons->console.data = ep; + spin_unlock(&cons->lock); + + pr_debug("ttyGS%d: console connected!\n", port->port_num); + + schedule_work(&cons->work); + + return 0; +} + +static void gs_console_disconnect(struct gs_port *port) +{ + struct gs_console *cons = port->console; + struct usb_request *req; + struct usb_ep *ep; + + if (!cons) + return; + + spin_lock(&cons->lock); + + req = cons->req; + ep = cons->console.data; + cons->req = NULL; + + spin_unlock(&cons->lock); + + if (!req) + return; + + usb_ep_dequeue(ep, req); + gs_free_req(ep, req); } -static void gserial_console_exit(void) +static int gs_console_init(struct gs_port *port) { - struct gscons_info *info = &gscons_info; + struct gs_console *cons; + int err; + + if (port->console) + return 0; + + cons = kzalloc(sizeof(*port->console), GFP_KERNEL); + if (!cons) + return -ENOMEM; + + strcpy(cons->console.name, "ttyGS"); + cons->console.write = gs_console_write; + cons->console.device = gs_console_device; + cons->console.flags = CON_PRINTBUFFER; + cons->console.index = port->port_num; + + INIT_WORK(&cons->work, gs_console_work); + spin_lock_init(&cons->lock); + + err = kfifo_alloc(&cons->buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL); + if (err) { + pr_err("ttyGS%d: allocate console buffer failed\n", port->port_num); + kfree(cons); + return err; + } + + port->console = cons; + register_console(&cons->console); + + spin_lock_irq(&port->port_lock); + if (port->port_usb) + gs_console_connect(port); + spin_unlock_irq(&port->port_lock); + + return 0; +} + +static void gs_console_exit(struct gs_port *port) +{ + struct gs_console *cons = port->console; + + if (!cons) + return; + + unregister_console(&cons->console); + + spin_lock_irq(&port->port_lock); + if (cons->req) + gs_console_disconnect(port); + spin_unlock_irq(&port->port_lock); - unregister_console(&gserial_cons); - if (!IS_ERR_OR_NULL(info->console_thread)) - kthread_stop(info->console_thread); - kfifo_free(&info->con_buf); + cancel_work_sync(&cons->work); + kfifo_free(&cons->buf); + kfree(cons); + port->console = NULL; } #else -static int gs_console_connect(int port_num) +static int gs_console_connect(struct gs_port *port) { return 0; } -static void gs_console_disconnect(struct usb_ep *ep) +static void gs_console_disconnect(struct gs_port *port) { } -static void gserial_console_init(void) +static int gs_console_init(struct gs_port *port) { + return -ENOSYS; } -static void gserial_console_exit(void) +static void gs_console_exit(struct gs_port *port) { } @@ -1197,18 +1170,19 @@ void gserial_free_line(unsigned char port_num) return; } port = ports[port_num].port; + gs_console_exit(port); ports[port_num].port = NULL; mutex_unlock(&ports[port_num].lock); gserial_free_port(port); tty_unregister_device(gs_tty_driver, port_num); - gserial_console_exit(); } EXPORT_SYMBOL_GPL(gserial_free_line); int gserial_alloc_line(unsigned char *line_num) { struct usb_cdc_line_coding coding; + struct gs_port *port; struct device *tty_dev; int ret; int port_num; @@ -1231,23 +1205,24 @@ int gserial_alloc_line(unsigned char *line_num) /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ - tty_dev = tty_port_register_device(&ports[port_num].port->port, + port = ports[port_num].port; + tty_dev = tty_port_register_device(&port->port, gs_tty_driver, port_num, NULL); if (IS_ERR(tty_dev)) { - struct gs_port *port; pr_err("%s: failed to register tty for port %d, err %ld\n", __func__, port_num, PTR_ERR(tty_dev)); ret = PTR_ERR(tty_dev); mutex_lock(&ports[port_num].lock); - port = ports[port_num].port; ports[port_num].port = NULL; mutex_unlock(&ports[port_num].lock); gserial_free_port(port); goto err; } *line_num = port_num; - gserial_console_init(); + + if (!port_num) + gs_console_init(port); err: return ret; } @@ -1329,7 +1304,7 @@ int gserial_connect(struct gserial *gser, u8 port_num) gser->disconnect(gser); } - status = gs_console_connect(port_num); + status = gs_console_connect(port); spin_unlock_irqrestore(&port->port_lock, flags); return status; @@ -1361,6 +1336,8 @@ void gserial_disconnect(struct gserial *gser) /* tell the TTY glue not to do I/O here any more */ spin_lock_irqsave(&port->port_lock, flags); + gs_console_disconnect(port); + /* REVISIT as above: how best to track this? */ port->port_line_coding = gser->port_line_coding; @@ -1388,7 +1365,6 @@ void gserial_disconnect(struct gserial *gser) port->read_allocated = port->read_started = port->write_allocated = port->write_started = 0; - gs_console_disconnect(gser->in); spin_unlock_irqrestore(&port->port_lock, flags); } EXPORT_SYMBOL_GPL(gserial_disconnect); From patchwork Wed Feb 27 10:46:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= X-Patchwork-Id: 10831537 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E15D715AC for ; Wed, 27 Feb 2019 10:47:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CBDEB2C6EE for ; Wed, 27 Feb 2019 10:47:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C03112C73A; Wed, 27 Feb 2019 10:47:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 62F6D2C6EE for ; Wed, 27 Feb 2019 10:47:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726944AbfB0KrB (ORCPT ); Wed, 27 Feb 2019 05:47:01 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:48847 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726356AbfB0KrB (ORCPT ); Wed, 27 Feb 2019 05:47:01 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448XQZ3fQczQ4; Wed, 27 Feb 2019 11:45:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551264342; bh=inIh7ePlWMtnVDQm/GavBGMQjRZkXtpdDrYRbKUGWFM=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=ZodRW2LLkLqxcJVCm8OAxJSjNS3HTqhGKjEdMQ3iibkQji6JN42rUIginXv9cIjPA OyUOPcRNyT/FfpU1eNHq++l57P6GqtuSnDN9VKypuR54VDHYKFLO83lf4QLzt/BmT2 BXwTjtZCzpFarVUV7dzJHP7lSeg+CN3lBr0a6tv5vcCD/3dWx5LXvUcpHZsWJyUZ/5 HoIiLocNEl/rbZlMtfUeU7m8BBsCdBIVoV3d5Bt+5is3Yk0ACC3THm6ico/t2+TzRQ oJXTryzgSTLkG3GaaKtvWMzx299poARwooqFvdTgPxAY0mjGvfnQhkyNFoSAdj2nOA ed/8SUPA2/uhw== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 11:46:58 +0100 Message-Id: In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH v3 3/5] usb: gadget: u_serial: make OBEX port not a console MIME-Version: 1.0 To: linux-usb@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Prevent OBEX serial port from ever becoming a console. Console messages will definitely break the protocol, and since you have to instantiate the port making it explicitly for OBEX, there is no point in allowing console to break it by mistake. Signed-off-by: Michał Mirosław Reviewed-by: Greg Kroah-Hartman --- v3: rename gserial_alloc_line_raw() -> gserial_alloc_line_no_console() v2: change of API + commit message massage --- drivers/usb/gadget/function/f_obex.c | 2 +- drivers/usb/gadget/function/u_serial.c | 16 ++++++++++++---- drivers/usb/gadget/function/u_serial.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index 55b7f57d2dc7..ab26d84ed95e 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -432,7 +432,7 @@ static struct usb_function_instance *obex_alloc_inst(void) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = obex_free_inst; - ret = gserial_alloc_line(&opts->port_num); + ret = gserial_alloc_line_no_console(&opts->port_num); if (ret) { kfree(opts); return ERR_PTR(ret); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 8d2d861e1543..18f5a2e9abd3 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1179,7 +1179,7 @@ void gserial_free_line(unsigned char port_num) } EXPORT_SYMBOL_GPL(gserial_free_line); -int gserial_alloc_line(unsigned char *line_num) +int gserial_alloc_line_no_console(unsigned char *line_num) { struct usb_cdc_line_coding coding; struct gs_port *port; @@ -1220,12 +1220,20 @@ int gserial_alloc_line(unsigned char *line_num) goto err; } *line_num = port_num; - - if (!port_num) - gs_console_init(port); err: return ret; } +EXPORT_SYMBOL_GPL(gserial_alloc_line_no_console); + +int gserial_alloc_line(unsigned char *line_num) +{ + int ret = gserial_alloc_line_no_console(line_num); + + if (!ret && !*line_num) + gs_console_init(ports[*line_num].port); + + return ret; +} EXPORT_SYMBOL_GPL(gserial_alloc_line); /** diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index 9acaac1cbb75..8b472b0c8cb4 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -54,6 +54,7 @@ struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags); void gs_free_req(struct usb_ep *, struct usb_request *req); /* management of individual TTY ports */ +int gserial_alloc_line_no_console(unsigned char *port_line); int gserial_alloc_line(unsigned char *port_line); void gserial_free_line(unsigned char port_line); From patchwork Wed Feb 27 10:46:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= X-Patchwork-Id: 10831541 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 57E0A1575 for ; Wed, 27 Feb 2019 10:47:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 43A832C6EE for ; Wed, 27 Feb 2019 10:47:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 37C4A2C73A; Wed, 27 Feb 2019 10:47:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 131B42C6EE for ; Wed, 27 Feb 2019 10:47:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727053AbfB0KrD (ORCPT ); Wed, 27 Feb 2019 05:47:03 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:58009 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726894AbfB0KrC (ORCPT ); Wed, 27 Feb 2019 05:47:02 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448XQb03shzTV; Wed, 27 Feb 2019 11:45:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551264343; bh=O9n3Bz/yuJiQkHifW7p61f9vUHck9F8GXMaT7or9KkE=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=kMgSVWZJ+DO913D52kGvf1BKXGtPfIvyruetg2O3p7+UOHFnvqdxzRbYjswJebkVS SxMRfXwusalmym9qsktEU3v63DY+cLxnrQs23jtQSzhicrtEUKy1Jv63WXtUHa1Njb RfRQb6P2dz9Ow8eOTz30XjYBJCsW03K+xRCCus3uECIKN0pOCBoIGvOBwxxLWKngX2 yojfUXyNBZ6bt3rArvRK8x3vrisiZJqiC8FdjwUaPz7lL/+ZWop6FNXmZ+YcENQV2O PtH0q4exj1nbTTTKHdCXV1VZhAkgbWOj3BhoWPXrAubI/U+8ZgTXpnYoAVhT55hkWT 7bR8Oo5B2Q7hQ== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 11:46:58 +0100 Message-Id: <186c619dd1443c5c124ca9f1b9844cc92e843be1.1551264094.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH v3 4/5] usb: gadget: u_serial: allow more console gadget ports MIME-Version: 1.0 To: linux-usb@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Allow configuring more than one console using USB serial or ACM gadget. By default, only first (ttyGS0) is a console, but this may be changed using function's new "console" attribute. Signed-off-by: Michał Mirosław Reviewed-by: Greg Kroah-Hartman --- v3: no changes v2: no changes --- drivers/usb/gadget/function/f_acm.c | 21 ++++++++++++ drivers/usb/gadget/function/f_serial.c | 21 ++++++++++++ drivers/usb/gadget/function/u_serial.c | 46 ++++++++++++++++++++++++++ drivers/usb/gadget/function/u_serial.h | 7 ++++ 4 files changed, 95 insertions(+) diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 9fc98de83624..7c152c28b26c 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -771,6 +771,24 @@ static struct configfs_item_operations acm_item_ops = { .release = acm_attr_release, }; +#ifdef CONFIG_U_SERIAL_CONSOLE + +static ssize_t f_acm_console_store(struct config_item *item, + const char *page, size_t count) +{ + return gserial_set_console(to_f_serial_opts(item)->port_num, + page, count); +} + +static ssize_t f_acm_console_show(struct config_item *item, char *page) +{ + return gserial_get_console(to_f_serial_opts(item)->port_num, page); +} + +CONFIGFS_ATTR(f_acm_, console); + +#endif /* CONFIG_U_SERIAL_CONSOLE */ + static ssize_t f_acm_port_num_show(struct config_item *item, char *page) { return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num); @@ -779,6 +797,9 @@ static ssize_t f_acm_port_num_show(struct config_item *item, char *page) CONFIGFS_ATTR_RO(f_acm_, port_num); static struct configfs_attribute *acm_attrs[] = { +#ifdef CONFIG_U_SERIAL_CONSOLE + &f_acm_attr_console, +#endif &f_acm_attr_port_num, NULL, }; diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index c860f30a0ea2..1406255d0865 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -266,6 +266,24 @@ static struct configfs_item_operations serial_item_ops = { .release = serial_attr_release, }; +#ifdef CONFIG_U_SERIAL_CONSOLE + +static ssize_t f_serial_console_store(struct config_item *item, + const char *page, size_t count) +{ + return gserial_set_console(to_f_serial_opts(item)->port_num, + page, count); +} + +static ssize_t f_serial_console_show(struct config_item *item, char *page) +{ + return gserial_get_console(to_f_serial_opts(item)->port_num, page); +} + +CONFIGFS_ATTR(f_serial_, console); + +#endif /* CONFIG_U_SERIAL_CONSOLE */ + static ssize_t f_serial_port_num_show(struct config_item *item, char *page) { return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num); @@ -274,6 +292,9 @@ static ssize_t f_serial_port_num_show(struct config_item *item, char *page) CONFIGFS_ATTR_RO(f_serial_, port_num); static struct configfs_attribute *acm_attrs[] = { +#ifdef CONFIG_U_SERIAL_CONSOLE + &f_serial_attr_console, +#endif &f_serial_attr_port_num, NULL, }; diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 18f5a2e9abd3..994882861db7 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1080,6 +1080,52 @@ static void gs_console_exit(struct gs_port *port) port->console = NULL; } +ssize_t gserial_set_console(unsigned char port_num, const char *page, size_t count) +{ + struct gs_port *port; + bool enable; + int ret = -ENXIO; + + mutex_lock(&ports[port_num].lock); + port = ports[port_num].port; + + if (WARN_ON(port == NULL)) + goto out; + + ret = strtobool(page, &enable); + if (ret) + goto out; + + if (enable) + ret = gs_console_init(port); + else + gs_console_exit(port); + + mutex_unlock(&ports[port_num].lock); +out: + return ret < 0 ? ret : count; +} +EXPORT_SYMBOL_GPL(gserial_set_console); + +ssize_t gserial_get_console(unsigned char port_num, char *page) +{ + struct gs_port *port; + ssize_t ret = -ENXIO; + + mutex_lock(&ports[port_num].lock); + port = ports[port_num].port; + + if (WARN_ON(port == NULL)) + goto out; + + ret = sprintf(page, "%u\n", !!port->console); + + mutex_unlock(&ports[port_num].lock); +out: + return ret; +} +EXPORT_SYMBOL_GPL(gserial_get_console); + #else static int gs_console_connect(struct gs_port *port) diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index 8b472b0c8cb4..e5b08ab8cf7a 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -58,6 +58,13 @@ int gserial_alloc_line_no_console(unsigned char *port_line); int gserial_alloc_line(unsigned char *port_line); void gserial_free_line(unsigned char port_line); +#ifdef CONFIG_U_SERIAL_CONSOLE + +ssize_t gserial_set_console(unsigned char port_num, const char *page, size_t count); +ssize_t gserial_get_console(unsigned char port_num, char *page); + +#endif /* CONFIG_U_SERIAL_CONSOLE */ + /* connect/disconnect is handled by individual functions */ int gserial_connect(struct gserial *, u8 port_num); void gserial_disconnect(struct gserial *); From patchwork Wed Feb 27 10:46:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= X-Patchwork-Id: 10831539 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F1C381575 for ; Wed, 27 Feb 2019 10:47:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DD3B02C6EE for ; Wed, 27 Feb 2019 10:47:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D15122C73A; Wed, 27 Feb 2019 10:47:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7CB3D2C6EE for ; Wed, 27 Feb 2019 10:47:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726950AbfB0KrC (ORCPT ); Wed, 27 Feb 2019 05:47:02 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:30664 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726397AbfB0KrB (ORCPT ); Wed, 27 Feb 2019 05:47:01 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448XQb3Wb6zTr; Wed, 27 Feb 2019 11:45:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551264343; bh=yGf5HQKRyEAHsASBNai+0+c3qB6zzeMzRjzeZ24Y11Y=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=b+y7TFTrocMSmRvmo6hiPPFv3x9hM3NEsUD9bAjX/t4GEa4zT8AGhCdAJqLBIODl9 Din4pym2iO/h0kDOWx1BxcNogeUZdeTIgyxs6Uows+TzlZ7k0YfsHXpnFgn9eowTg8 V8+tmdrNn/N81IlrExyXEqk0I2+3huq82kB4MKyb6GipjYsdrU+nosbfoODEVH88Ul eBiqCWG4xML03NLTui5ZWpREs8tuI7j4ZR6guwqP9WTHymrA7XuBpylqN7fwglGzjS PLss2e5xXIiwnsm4PP+zdrXZlZYWrfqH8XQYco52OQleDdvirTrpqUYIaH7iJatWZ5 sIReIMxtUVxgQ== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 11:46:59 +0100 Message-Id: <3702f809d397892d91479f80e5f74d6d30345208.1551264094.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH v3 5/5] usb: gadget: u_serial: diagnose missed console messages MIME-Version: 1.0 To: linux-usb@vger.kernel.org Cc: Felipe Balbi , Greg Kroah-Hartman Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Greg Kroah-Hartman --- v3: added example output + lowecase 'missed' v2: commit message massage --- drivers/usb/gadget/function/u_serial.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 994882861db7..9e143bd081b6 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -88,6 +88,7 @@ struct gs_console { spinlock_t lock; struct usb_request *req; struct kfifo buf; + size_t missed; }; /* @@ -930,6 +931,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; @@ -951,10 +961,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);