From patchwork Wed Feb 27 07:48:56 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: 10831365 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 E08901669 for ; Wed, 27 Feb 2019 07:49:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CFC2A29B9A for ; Wed, 27 Feb 2019 07:49:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C43882B5E8; Wed, 27 Feb 2019 07:49: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 EB03C2A356 for ; Wed, 27 Feb 2019 07:48:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729582AbfB0Hs7 (ORCPT ); Wed, 27 Feb 2019 02:48:59 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:21003 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726702AbfB0Hs6 (ORCPT ); Wed, 27 Feb 2019 02:48:58 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448ST86bWbzJX; Wed, 27 Feb 2019 08:47:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551253661; bh=9RtTC/x97iJT7E9jhPBjHjTZM3xVnkiFvfHbp5E2RUc=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=F6rA0vY+tBvqABiFPYR8+k39OPzYx6SCbJRmVoq4qbRjhWzanj9JXK5a5fEx1BG33 HYR8K8zSsF3DZ4Z0GdSYu04HAuAMjXIeIJ9bmdtMMTcTQTuDCcLzNqFpZwweuOQYye odDyk299n3cF70TaqednQklF7cEHcGYImB3yRY5/pHSSef23qjmMa12cvzeeYThHtr w7uk1jQWwdTlwhNKF+bO1YC3hs929fqjTDHbmFlol6+btMLhy50C7d0QFOmHrtBJy0 pD3GWWuVzEWyD68K5QhuCE9Z/gPo3IYdwkV7bMgDtQ8+JLTxKryNr5JYhvstbNkVYp UNas35evClI5w== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 08:48:56 +0100 Message-Id: <1437fea1a8e1ca2c00870451197611df29c1a7ac.1551253561.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH 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. Signed-off-by: Michał Mirosław --- 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 07:48: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: 10831369 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 4E4FF1880 for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 38E5629B9A for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2C8C22B5E8; Wed, 27 Feb 2019 07:49: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 418EC29B9A for ; Wed, 27 Feb 2019 07:49:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729611AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:22570 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729541AbfB0HtA (ORCPT ); Wed, 27 Feb 2019 02:49:00 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448ST93Rr2zL0; Wed, 27 Feb 2019 08:47:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551253661; bh=CwixGgpjC8SXIis0uzb0HYBG/Bi9cUbg96cBh7t+4L0=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=Mox3gBZBHzREhNy0tz/FwZTrIvneaxrYmJ3POdwsYHuEdGsx5JFH2arbLQ8PbSU3J yVw22CbzxAOPibAbkH3A6IRaNQzGvIxSiY+aXX6xqtkmAzQNQ8Wt5GyDfRVXbOlSsy iYMVcdKPyKpctbXD9Y2717vMMZeGvEWskAzM+5bu2yz5bMgl3MgcRKPrDCD92T5MuR WksG8LIXo8CxKumLpTha4uw1naxEwO3zDpr4se5pWo9J+rrNP/LAeD7W+KlMzFzq0N Z2QJ2Qh6X79H1gdmJ5QR4ZP0+k9i2GI70NRinCum0v3ho0YRSHT3JRI4qAz1q9QK/U 4BYxOXD8xz72A== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 08:48:57 +0100 Message-Id: In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH 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 --- 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 07:48: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: 10831371 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 C56721669 for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B1C2F29B9A for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A3B452A356; Wed, 27 Feb 2019 07:49: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 3C2072B69D for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729614AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:8655 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729542AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448ST96xDPzQ4; Wed, 27 Feb 2019 08:47:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551253662; bh=+yM36rKNlN+7bQ+MvrsF3rCLf4rqVdFTR/+JjOh0AcY=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=hOqq/fRVWMeOiVMtNWqDD+scetPCt44Qiee9Ctb5NTwniWXylS0fJKix/Ut2esxNj F1rsWrfuC2M02B5+btkaejwgQnN/Xvaxj7ABEOQq5fIsUA2PuIEN68ZmQx5hbAHJQ8 9eGUJjN3nOmeFBuBjtO7iTs1KF2OYPOUl9ySaAQ+C2VQ+BXbAVCBQBXjodlHrk+Xo8 jozBhK8vmUQ1JEHyRdfmdOX8jR9r31QqFpafPTlakdp3KKqtZFigXb10m4VBbnn10I uuwVFs72Grk7+YGygjNl0OITANYqOlriCcRGrk/nv6TlYD431+VOrEDjsxY5WLINfe kLfImcKKEpnCQ== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 08:48:57 +0100 Message-Id: <3a0a3ebfe65b7cc5b413ecc11af7aa9b0c97a532.1551253561.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH 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. Signed-off-by: Michał Mirosław --- drivers/usb/gadget/function/f_acm.c | 2 +- drivers/usb/gadget/function/f_obex.c | 2 +- drivers/usb/gadget/function/f_serial.c | 2 +- drivers/usb/gadget/function/u_serial.c | 4 ++-- drivers/usb/gadget/function/u_serial.h | 2 +- drivers/usb/gadget/legacy/dbgp.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 9fc98de83624..60d18c7dcef3 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -807,7 +807,7 @@ static struct usb_function_instance *acm_alloc_instance(void) if (!opts) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = acm_free_instance; - ret = gserial_alloc_line(&opts->port_num); + ret = gserial_alloc_line(&opts->port_num, true); if (ret) { kfree(opts); return ERR_PTR(ret); diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index 55b7f57d2dc7..8242ba76dc1e 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(&opts->port_num, false); if (ret) { kfree(opts); return ERR_PTR(ret); diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index c860f30a0ea2..788179a9a23c 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -303,7 +303,7 @@ static struct usb_function_instance *gser_alloc_inst(void) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = gser_free_inst; - ret = gserial_alloc_line(&opts->port_num); + ret = gserial_alloc_line(&opts->port_num, true); 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..dd138d372940 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(unsigned char *line_num, bool maybe_console) { struct usb_cdc_line_coding coding; struct gs_port *port; @@ -1221,7 +1221,7 @@ int gserial_alloc_line(unsigned char *line_num) } *line_num = port_num; - if (!port_num) + if (maybe_console && !port_num) gs_console_init(port); err: return ret; diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index 9acaac1cbb75..40e89ddfe90e 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -54,7 +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(unsigned char *port_line); +int gserial_alloc_line(unsigned char *port_line, bool maybe_console); void gserial_free_line(unsigned char port_line); /* connect/disconnect is handled by individual functions */ diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index e1d566c9918a..a6785a4a1ac6 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -305,7 +305,7 @@ static int dbgp_bind(struct usb_gadget *gadget, goto fail; } - if (gserial_alloc_line(&tty_line)) { + if (gserial_alloc_line(&tty_line, true)) { stp = 4; err = -ENODEV; goto fail; From patchwork Wed Feb 27 07:48: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: 10831373 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 3364A1399 for ; Wed, 27 Feb 2019 07:49:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2078729B9A for ; Wed, 27 Feb 2019 07:49:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1138E2B5E8; Wed, 27 Feb 2019 07:49: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 8D64829B9A for ; Wed, 27 Feb 2019 07:49:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729249AbfB0HtD (ORCPT ); Wed, 27 Feb 2019 02:49:03 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:41520 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726925AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448STB4fWYzTV; Wed, 27 Feb 2019 08:47:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551253662; bh=JxXS00mRUI0h7tZjMwbpHm2qbCVZT/eeplyyXPWhB3s=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=kTE6zXF6gry7fB2TU3/l6qU0Ny0hF+ZkpdwXR1seXXVeZ7vJ4sarOtNZkfczpq4bN iPoFTjlOAd1RJJNjega+EYjMR8zvL96PIzPr68JGXjbnb+RsxseZ4jtHiubFJMAYmt Ei7djSI+irTqaUiY5Q0w5oz++ASQ7C+bqwMarajrVcf9y8EUb1VIlUUPXiB8fWDRAU ZEZ7rjKHqsLEIq3yFIL9r9JkT+wz5g4Kbk4yxMH5cRJMrwJn3tRQe1xw6q7CdluqlH DBcBVPzcs9pWrxKgGNRKMkeoXmDGC7evrDrk9dy0FrGzIZ5O8RdzgP6hi5+QHVsWnR cmrl9LcQhpV9g== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 08:48:58 +0100 Message-Id: In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH 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 --- 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 60d18c7dcef3..edd6dba1a024 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 788179a9a23c..4aab32e12665 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 dd138d372940..7b719c166517 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 40e89ddfe90e..2fa5fb8548ba 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -57,6 +57,13 @@ void gs_free_req(struct usb_ep *, struct usb_request *req); int gserial_alloc_line(unsigned char *port_line, bool maybe_console); 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 07:48: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: 10831367 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 174B51399 for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 059A42A356 for ; Wed, 27 Feb 2019 07:49:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EE3732B69D; Wed, 27 Feb 2019 07:49: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 9441E2A356 for ; Wed, 27 Feb 2019 07:49:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729617AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from rere.qmqm.pl ([91.227.64.183]:14433 "EHLO rere.qmqm.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729604AbfB0HtB (ORCPT ); Wed, 27 Feb 2019 02:49:01 -0500 Received: from remote.user (localhost [127.0.0.1]) by rere.qmqm.pl (Postfix) with ESMTPSA id 448STC2322zXN; Wed, 27 Feb 2019 08:47:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rere.qmqm.pl; s=1; t=1551253663; bh=jfnixvYi/8kJFn56+3WvroUDhhzp0/AeB5LXPLwz44o=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=PyaWIudhiZiN4BKxU5am+9YLe0OmrRfyajPuCDIUuSz+wOw+P9Jox5Wyb4N+0/Al4 nUNyAqW9J2uCtBrhYuAjbaDoBoTJH7lhpSTwAJfXGFQ97Byae91JhrMUW40uqSKEFY ZGyb8i52XOPFDCJBmzJ5ptfNauqrWptqkZBQx0YxQ6w8BIm+Nqo6uPkf49TB+Fi7vP hOHTVc7BA2kFBpmN4gh8k8cpM13BO+LwZsC//24yBygTT8TfhQbU3nBfj93I+rnz/W M8ASW6eJJcUSU/nOYFc++xzPb8dq3qh9d8jCxtYDmPuN7BHDnXlhZmXvmWjndzw1/5 ZHWDWNrRHECBw== X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.100.2 at mail Date: Wed, 27 Feb 2019 08:48:58 +0100 Message-Id: <78e9b2c9313dea8a35f5b6f2a2c285c5f2f5ecbb.1551253561.git.mirq-linux@rere.qmqm.pl> In-Reply-To: References: From: =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= Subject: [PATCH 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 instead of making console output glued together when drops happen. Signed-off-by: Michał Mirosław --- 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 7b719c166517..f025cb958362 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);