From patchwork Wed Nov 23 10:01:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sascha Hauer X-Patchwork-Id: 9442847 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 088C4600BA for ; Wed, 23 Nov 2016 10:04:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E15DE203C0 for ; Wed, 23 Nov 2016 10:04:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D5BC823D5E; Wed, 23 Nov 2016 10:04:16 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 84C9A203C0 for ; Wed, 23 Nov 2016 10:04:16 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1c9UO0-0008Eu-7w; Wed, 23 Nov 2016 10:02:40 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1c9UMy-0007iC-A2 for linux-arm-kernel@lists.infradead.org; Wed, 23 Nov 2016 10:01:38 +0000 Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1c9UMW-0000zE-0o; Wed, 23 Nov 2016 11:01:08 +0100 Received: from sha by dude.hi.pengutronix.de with local (Exim 4.87) (envelope-from ) id 1c9UMV-0007QU-A1; Wed, 23 Nov 2016 11:01:07 +0100 From: Sascha Hauer To: linux-serial@vger.kernel.org Subject: [PATCH 1/4] serial: core: Add LED trigger support Date: Wed, 23 Nov 2016 11:01:03 +0100 Message-Id: <20161123100106.15969-2-s.hauer@pengutronix.de> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161123100106.15969-1-s.hauer@pengutronix.de> References: <20161123100106.15969-1-s.hauer@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: sha@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161123_020136_606152_0F9B9FB6 X-CRM114-Status: GOOD ( 18.86 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kernel@pengutronix.de, Greg Kroah-Hartman , Sascha Hauer , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP With this patch the serial core provides LED triggers for RX and TX. As the serial core layer does not know when the hardware actually sends or receives characters, this needs help from the UART drivers. The LED triggers are registered in uart_add_led_triggers() called from the UART drivers which want to support LED triggers. All the driver has to do then is to call uart_led_trigger_[tx|rx] to indicate activity. Signed-off-by: Sascha Hauer --- drivers/tty/serial/serial_core.c | 73 ++++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 10 ++++++ 2 files changed, 83 insertions(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f2303f3..3e8afb7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -2703,6 +2704,77 @@ static const struct attribute_group tty_dev_attr_group = { .attrs = tty_dev_attrs, }; +void uart_led_trigger_tx(struct uart_port *uport) +{ + unsigned long delay = 50; + + led_trigger_blink_oneshot(uport->led_trigger_tx, &delay, &delay, 0); +} + +void uart_led_trigger_rx(struct uart_port *uport) +{ + unsigned long delay = 50; + + led_trigger_blink_oneshot(uport->led_trigger_rx, &delay, &delay, 0); +} + +/** + * uart_add_led_triggers - register LED triggers for a UART + * @drv: pointer to the uart low level driver structure for this port + * @uport: uart port structure to use for this port. + * + * Called by the driver to register LED triggers for a UART. It's the + * drivers responsibility to call uart_led_trigger_rx/tx on received + * and transmitted chars then. + */ +int uart_add_led_triggers(struct uart_driver *drv, struct uart_port *uport) +{ + int ret; + + if (!IS_ENABLED(CONFIG_LEDS_TRIGGERS)) + return 0; + + uport->led_trigger_tx_name = kasprintf(GFP_KERNEL, "%s%d-tx", + drv->dev_name, uport->line); + uport->led_trigger_rx_name = kasprintf(GFP_KERNEL, "%s%d-rx", + drv->dev_name, uport->line); + if (!uport->led_trigger_tx_name || !uport->led_trigger_rx_name) { + ret = -ENOMEM; + goto err_alloc; + } + + led_trigger_register_simple(uport->led_trigger_tx_name, + &uport->led_trigger_tx); + led_trigger_register_simple(uport->led_trigger_rx_name, + &uport->led_trigger_rx); + + return 0; + +err_alloc: + kfree(uport->led_trigger_tx_name); + kfree(uport->led_trigger_rx_name); + + return ret; +} + +/** + * uart_remove_led_triggers - remove LED triggers + * @drv: pointer to the uart low level driver structure for this port + * @uport: uart port structure to use for this port. + * + * Remove LED triggers previously registered with uart_add_led_triggers + */ +void uart_remove_led_triggers(struct uart_port *uport) +{ + if (uport->led_trigger_rx) + led_trigger_unregister_simple(uport->led_trigger_rx); + kfree(uport->led_trigger_rx_name); + + if (uport->led_trigger_tx) + led_trigger_unregister_simple(uport->led_trigger_tx); + kfree(uport->led_trigger_tx_name); +} + /** * uart_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port @@ -2872,6 +2944,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) WARN_ON(atomic_dec_return(&state->refcount) < 0); wait_event(state->remove_wait, !atomic_read(&state->refcount)); state->uart_port = NULL; + mutex_unlock(&port->mutex); out: mutex_unlock(&port_mutex); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3442014..1b0a169 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef CONFIG_SERIAL_CORE_CONSOLE @@ -249,6 +250,10 @@ struct uart_port { const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ struct serial_rs485 rs485; void *private_data; /* generic platform data pointer */ + struct led_trigger *led_trigger_rx; + char *led_trigger_rx_name; + struct led_trigger *led_trigger_tx; + char *led_trigger_tx_name; }; static inline int serial_port_in(struct uart_port *up, int offset) @@ -392,6 +397,11 @@ void uart_console_write(struct uart_port *port, const char *s, unsigned int count, void (*putchar)(struct uart_port *, int)); +int uart_add_led_triggers(struct uart_driver *drv, struct uart_port *uport); +void uart_remove_led_triggers(struct uart_port *uport); +void uart_led_trigger_tx(struct uart_port *port); +void uart_led_trigger_rx(struct uart_port *port); + /* * Port/driver registration/removal */