summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-02-20 21:28:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2021-02-20 21:28:04 -0800
commite4286926abbbaab9b047c8bc25cae78ec990928f (patch)
tree02d3c80e581476d93253df5c16dbf9f907494e1c
parent3342ff2698e9720f4040cc458a2744b2b32f5c3a (diff)
parenta157270fbf37f822e1fa9e9faa8ed8c81da1eb28 (diff)
downloadlinux-e4286926abbbaab9b047c8bc25cae78ec990928f.tar.gz
linux-e4286926abbbaab9b047c8bc25cae78ec990928f.tar.bz2
linux-e4286926abbbaab9b047c8bc25cae78ec990928f.zip
Merge tag 'tty-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big set of tty/serial driver changes for 5.12-rc1. Nothing huge, just lots of good cleanups and additions: - n_tty line discipline cleanups - vt core cleanups and reworks to make the code more "modern" - stm32 driver additions - tty led support added to the tty core and led layer - minor serial driver fixups and additions All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (54 commits) serial: core: Remove BUG_ON(in_interrupt()) check vt_ioctl: Remove in_interrupt() check dt-bindings: serial: imx: Switch to my personal address vt: keyboard, use new API for keyboard_tasklet serial: stm32: improve platform_get_irq condition handling in init_port serial: ifx6x60: Remove driver for deprecated platform tty: fix up iterate_tty_read() EOVERFLOW handling tty: fix up hung_up_tty_read() conversion tty: fix up hung_up_tty_write() conversion tty: teach the n_tty ICANON case about the new "cookie continuations" too tty: teach n_tty line discipline about the new "cookie continuations" tty: clean up legacy leftovers from n_tty line discipline tty: implement read_iter tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer serial: remove sirf prima/atlas driver serial: mxs-auart: Remove <asm/cacheflush.h> serial: mxs-auart: Remove serial_mxs_probe_dt() serial: fsl_lpuart: Use of_device_get_match_data() dt-bindings: serial: renesas,hscif: Add r8a779a0 support tty: serial: Drop unused efm32 serial driver ...
-rw-r--r--Documentation/ABI/testing/sysfs-class-led-trigger-tty6
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,hscif.yaml1
-rw-r--r--Documentation/devicetree/bindings/serial/sirf-uart.txt34
-rw-r--r--Documentation/devicetree/bindings/serial/st,stm32-uart.yaml13
-rw-r--r--Documentation/networking/caif/caif.rst1
-rw-r--r--drivers/accessibility/speakup/spk_ttyio.c2
-rw-r--r--drivers/bluetooth/hci_ldisc.c34
-rw-r--r--drivers/char/pcmcia/synclink_cs.c2
-rw-r--r--drivers/input/serio/serport.c4
-rw-r--r--drivers/leds/trigger/Kconfig9
-rw-r--r--drivers/leds/trigger/Makefile1
-rw-r--r--drivers/leds/trigger/ledtrig-tty.c183
-rw-r--r--drivers/net/caif/caif_serial.c3
-rw-r--r--drivers/net/ppp/ppp_async.c3
-rw-r--r--drivers/net/ppp/ppp_synctty.c3
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/char/sclp_tty.c1
-rw-r--r--drivers/s390/char/sclp_vt220.c1
-rw-r--r--drivers/s390/char/tty3270.c2
-rw-r--r--drivers/tty/amiserial.c3
-rw-r--r--drivers/tty/hvc/hvcs.c5
-rw-r--r--drivers/tty/ipwireless/tty.c1
-rw-r--r--drivers/tty/mxser.c1
-rw-r--r--drivers/tty/n_gsm.c3
-rw-r--r--drivers/tty/n_hdlc.c60
-rw-r--r--drivers/tty/n_null.c3
-rw-r--r--drivers/tty/n_r3964.c10
-rw-r--r--drivers/tty/n_tracerouter.c4
-rw-r--r--drivers/tty/n_tracesink.c4
-rw-r--r--drivers/tty/n_tty.c153
-rw-r--r--drivers/tty/pty.c16
-rw-r--r--drivers/tty/serial/8250/8250_tegra.c11
-rw-r--r--drivers/tty/serial/Kconfig42
-rw-r--r--drivers/tty/serial/Makefile3
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c43
-rw-r--r--drivers/tty/serial/efm32-uart.c852
-rw-r--r--drivers/tty/serial/fsl_lpuart.c4
-rw-r--r--drivers/tty/serial/icom.c4
-rw-r--r--drivers/tty/serial/ifx6x60.c1390
-rw-r--r--drivers/tty/serial/ifx6x60.h118
-rw-r--r--drivers/tty/serial/imx.c2
-rw-r--r--drivers/tty/serial/lantiq.c2
-rw-r--r--drivers/tty/serial/max3100.c3
-rw-r--r--drivers/tty/serial/mxs-auart.c45
-rw-r--r--drivers/tty/serial/owl-uart.c38
-rw-r--r--drivers/tty/serial/serial_core.c11
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c1503
-rw-r--r--drivers/tty/serial/sirfsoc_uart.h447
-rw-r--r--drivers/tty/serial/stm32-usart.c419
-rw-r--r--drivers/tty/synclink_gt.c1
-rw-r--r--drivers/tty/tty_io.c210
-rw-r--r--drivers/tty/vcc.c10
-rw-r--r--drivers/tty/vt/consolemap.c2
-rw-r--r--drivers/tty/vt/defkeymap.c_shipped82
-rw-r--r--drivers/tty/vt/keyboard.c18
-rw-r--r--drivers/tty/vt/vt.c42
-rw-r--r--drivers/tty/vt/vt_ioctl.c154
-rw-r--r--drivers/video/console/vgacon.c19
-rw-r--r--include/linux/kbd_kern.h10
-rw-r--r--include/linux/kd.h8
-rw-r--r--include/linux/platform_data/efm32-uart.h19
-rw-r--r--include/linux/spi/ifx_modem.h15
-rw-r--r--include/linux/tty.h11
-rw-r--r--include/linux/tty_ldisc.h3
-rw-r--r--include/linux/vt_kern.h12
-rw-r--r--include/uapi/linux/serial_core.h3
-rw-r--r--include/uapi/linux/termios.h15
-rw-r--r--net/nfc/nci/uart.c3
70 files changed, 958 insertions, 5187 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-tty b/Documentation/ABI/testing/sysfs-class-led-trigger-tty
new file mode 100644
index 000000000000..2bf6b24e781b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-tty
@@ -0,0 +1,6 @@
+What: /sys/class/leds/<led>/ttyname
+Date: Dec 2020
+KernelVersion: 5.10
+Contact: linux-leds@vger.kernel.org
+Description:
+ Specifies the tty device name of the triggering tty
diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
index 9702c07a6b6c..2b06c6ce4a75 100644
--- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
maintainers:
- - Fabio Estevam <fabio.estevam@nxp.com>
+ - Fabio Estevam <festevam@gmail.com>
allOf:
- $ref: "serial.yaml"
diff --git a/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml b/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
index ce1d89496342..14c7594c88c6 100644
--- a/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-mxs-auart.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale MXS Application UART (AUART)
maintainers:
- - Fabio Estevam <fabio.estevam@nxp.com>
+ - Fabio Estevam <festevam@gmail.com>
allOf:
- $ref: "serial.yaml"
diff --git a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
index c139c5edb93e..512a84942f78 100644
--- a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml
@@ -51,6 +51,7 @@ properties:
- renesas,hscif-r8a77980 # R-Car V3H
- renesas,hscif-r8a77990 # R-Car E3
- renesas,hscif-r8a77995 # R-Car D3
+ - renesas,hscif-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2
- const: renesas,hscif # generic HSCIF compatible UART
diff --git a/Documentation/devicetree/bindings/serial/sirf-uart.txt b/Documentation/devicetree/bindings/serial/sirf-uart.txt
deleted file mode 100644
index 1e48bbbeecc6..000000000000
--- a/Documentation/devicetree/bindings/serial/sirf-uart.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-* CSR SiRFprimaII/atlasVI Universal Synchronous Asynchronous Receiver/Transmitter *
-
-Required properties:
-- compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart",
- "sirf,atlas7-uart" or "sirf,atlas7-usp-uart".
-- reg : Offset and length of the register set for the device
-- interrupts : Should contain uart interrupt
-- fifosize : Should define hardware rx/tx fifo size
-- clocks : Should contain uart clock number
-
-Optional properties:
-- uart-has-rtscts: we have hardware flow controller pins in hardware
-- rts-gpios: RTS pin for USP-based UART if uart-has-rtscts is true
-- cts-gpios: CTS pin for USP-based UART if uart-has-rtscts is true
-
-Example:
-
-uart0: uart@b0050000 {
- cell-index = <0>;
- compatible = "sirf,prima2-uart";
- reg = <0xb0050000 0x1000>;
- interrupts = <17>;
- fifosize = <128>;
- clocks = <&clks 13>;
-};
-
-On the board-specific dts, we can put rts-gpios and cts-gpios like
-
-usp@b0090000 {
- compatible = "sirf,prima2-usp-uart";
- uart-has-rtscts;
- rts-gpios = <&gpio 15 0>;
- cts-gpios = <&gpio 46 0>;
-};
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
index 06d5f251ec88..8631678283f9 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
@@ -50,11 +50,14 @@ properties:
minItems: 1
maxItems: 2
- cts-gpios:
- maxItems: 1
-
- rts-gpios:
- maxItems: 1
+# cts-gpios and rts-gpios properties can be used instead of 'uart-has-rtscts'
+# or 'st,hw-flow-ctrl' (deprecated) for making use of any gpio pins for flow
+# control instead of dedicated pins.
+#
+# It should be noted that both cts-gpios/rts-gpios and 'uart-has-rtscts' or
+# 'st,hw-flow-ctrl' (deprecated) properties cannot co-exist in a design.
+ cts-gpios: true
+ rts-gpios: true
wakeup-source: true
diff --git a/Documentation/networking/caif/caif.rst b/Documentation/networking/caif/caif.rst
index a07213030ccf..81a14373d780 100644
--- a/Documentation/networking/caif/caif.rst
+++ b/Documentation/networking/caif/caif.rst
@@ -68,7 +68,6 @@ There are debugfs parameters provided for serial communication.
* tty_status: Prints the bit-mask tty status information
- 0x01 - tty->warned is on.
- - 0x02 - tty->low_latency is on.
- 0x04 - tty->packed is on.
- 0x08 - tty->flow_stopped is on.
- 0x10 - tty->hw_stopped is on.
diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c
index 6284aff434a1..835d17455fcd 100644
--- a/drivers/accessibility/speakup/spk_ttyio.c
+++ b/drivers/accessibility/speakup/spk_ttyio.c
@@ -152,7 +152,7 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
if (ret)
return ret;
- tty = tty_kopen(dev);
+ tty = tty_kopen_exclusive(dev);
if (IS_ERR(tty))
return PTR_ERR(tty);
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 8be4d807d137..637c5b8c2aa1 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -801,7 +801,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
* We don't provide read/write/poll interface for user space.
*/
static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
- unsigned char __user *buf, size_t nr)
+ unsigned char *buf, size_t nr,
+ void **cookie, unsigned long offset)
{
return 0;
}
@@ -818,29 +819,28 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty,
return 0;
}
+static struct tty_ldisc_ops hci_uart_ldisc = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "n_hci",
+ .open = hci_uart_tty_open,
+ .close = hci_uart_tty_close,
+ .read = hci_uart_tty_read,
+ .write = hci_uart_tty_write,
+ .ioctl = hci_uart_tty_ioctl,
+ .compat_ioctl = hci_uart_tty_ioctl,
+ .poll = hci_uart_tty_poll,
+ .receive_buf = hci_uart_tty_receive,
+ .write_wakeup = hci_uart_tty_wakeup,
+};
+
static int __init hci_uart_init(void)
{
- static struct tty_ldisc_ops hci_uart_ldisc;
int err;
BT_INFO("HCI UART driver ver %s", VERSION);
/* Register the tty discipline */
-
- memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc));
- hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
- hci_uart_ldisc.name = "n_hci";
- hci_uart_ldisc.open = hci_uart_tty_open;
- hci_uart_ldisc.close = hci_uart_tty_close;
- hci_uart_ldisc.read = hci_uart_tty_read;
- hci_uart_ldisc.write = hci_uart_tty_write;
- hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
- hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl;
- hci_uart_ldisc.poll = hci_uart_tty_poll;
- hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
- hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
- hci_uart_ldisc.owner = THIS_MODULE;
-
err = tty_register_ldisc(N_HCI, &hci_uart_ldisc);
if (err) {
BT_ERR("HCI line discipline registration failed. (%d)", err);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e342daa73d1b..2be8d9a8eec5 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2494,8 +2494,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
__FILE__, __LINE__, tty->driver->name, port->count);
- port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
spin_lock_irqsave(&info->netlock, flags);
if (info->netcount) {
retval = -EBUSY;
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 8ac970a423de..33e9d9bfd036 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -156,7 +156,9 @@ out:
* returning 0 characters.
*/
-static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
+static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file,
+ unsigned char *kbuf, size_t nr,
+ void **cookie, unsigned long offset)
{
struct serport *serport = (struct serport*) tty->disc_data;
struct serio *serio;
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index ce9429ca6dde..b77a01bd27f4 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -144,4 +144,13 @@ config LEDS_TRIGGER_AUDIO
the audio mute and mic-mute changes.
If unsure, say N
+config LEDS_TRIGGER_TTY
+ tristate "LED Trigger for TTY devices"
+ depends on TTY
+ help
+ This allows LEDs to be controlled by activity on ttys which includes
+ serial devices like /dev/ttyS0.
+
+ When build as a module this driver will be called ledtrig-tty.
+
endif # LEDS_TRIGGERS
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 733a83e2a718..25c4db97cdd4 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o
obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o
+obj-$(CONFIG_LEDS_TRIGGER_TTY) += ledtrig-tty.o
diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c
new file mode 100644
index 000000000000..d2ab6ab080ac
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-tty.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <uapi/linux/serial.h>
+
+struct ledtrig_tty_data {
+ struct led_classdev *led_cdev;
+ struct delayed_work dwork;
+ struct mutex mutex;
+ const char *ttyname;
+ struct tty_struct *tty;
+ int rx, tx;
+};
+
+static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data)
+{
+ schedule_delayed_work(&trigger_data->dwork, 0);
+}
+
+static ssize_t ttyname_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
+ ssize_t len = 0;
+
+ mutex_lock(&trigger_data->mutex);
+
+ if (trigger_data->ttyname)
+ len = sprintf(buf, "%s\n", trigger_data->ttyname);
+
+ mutex_unlock(&trigger_data->mutex);
+
+ return len;
+}
+
+static ssize_t ttyname_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
+ char *ttyname;
+ ssize_t ret = size;
+ bool running;
+
+ if (size > 0 && buf[size - 1] == '\n')
+ size -= 1;
+
+ if (size) {
+ ttyname = kmemdup_nul(buf, size, GFP_KERNEL);
+ if (!ttyname) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+ } else {
+ ttyname = NULL;
+ }
+
+ mutex_lock(&trigger_data->mutex);
+
+ running = trigger_data->ttyname != NULL;
+
+ kfree(trigger_data->ttyname);
+ tty_kref_put(trigger_data->tty);
+ trigger_data->tty = NULL;
+
+ trigger_data->ttyname = ttyname;
+
+out_unlock:
+ mutex_unlock(&trigger_data->mutex);
+
+ if (ttyname && !running)
+ ledtrig_tty_restart(trigger_data);
+
+ return ret;
+}
+static DEVICE_ATTR_RW(ttyname);
+
+static void ledtrig_tty_work(struct work_struct *work)
+{
+ struct ledtrig_tty_data *trigger_data =
+ container_of(work, struct ledtrig_tty_data, dwork.work);
+ struct serial_icounter_struct icount;
+ int ret;
+
+ mutex_lock(&trigger_data->mutex);
+
+ if (!trigger_data->ttyname) {
+ /* exit without rescheduling */
+ mutex_unlock(&trigger_data->mutex);
+ return;
+ }
+
+ /* try to get the tty corresponding to $ttyname */
+ if (!trigger_data->tty) {
+ dev_t devno;
+ struct tty_struct *tty;
+ int ret;
+
+ ret = tty_dev_name_to_number(trigger_data->ttyname, &devno);
+ if (ret < 0)
+ /*
+ * A device with this name might appear later, so keep
+ * retrying.
+ */
+ goto out;
+
+ tty = tty_kopen_shared(devno);
+ if (IS_ERR(tty) || !tty)
+ /* What to do? retry or abort */
+ goto out;
+
+ trigger_data->tty = tty;
+ }
+
+ ret = tty_get_icount(trigger_data->tty, &icount);
+ if (ret) {
+ dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n");
+ mutex_unlock(&trigger_data->mutex);
+ return;
+ }
+
+ if (icount.rx != trigger_data->rx ||
+ icount.tx != trigger_data->tx) {
+ led_set_brightness(trigger_data->led_cdev, LED_ON);
+
+ trigger_data->rx = icount.rx;
+ trigger_data->tx = icount.tx;
+ } else {
+ led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ }
+
+out:
+ mutex_unlock(&trigger_data->mutex);
+ schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(100));
+}
+
+static struct attribute *ledtrig_tty_attrs[] = {
+ &dev_attr_ttyname.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(ledtrig_tty);
+
+static int ledtrig_tty_activate(struct led_classdev *led_cdev)
+{
+ struct ledtrig_tty_data *trigger_data;
+
+ trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL);
+ if (!trigger_data)
+ return -ENOMEM;
+
+ led_set_trigger_data(led_cdev, trigger_data);
+
+ INIT_DELAYED_WORK(&trigger_data->dwork, ledtrig_tty_work);
+ trigger_data->led_cdev = led_cdev;
+ mutex_init(&trigger_data->mutex);
+
+ return 0;
+}
+
+static void ledtrig_tty_deactivate(struct led_classdev *led_cdev)
+{
+ struct ledtrig_tty_data *trigger_data = led_get_trigger_data(led_cdev);
+
+ cancel_delayed_work_sync(&trigger_data->dwork);
+
+ kfree(trigger_data);
+}
+
+static struct led_trigger ledtrig_tty = {
+ .name = "tty",
+ .activate = ledtrig_tty_activate,
+ .deactivate = ledtrig_tty_deactivate,
+ .groups = ledtrig_tty_groups,
+};
+module_led_trigger(ledtrig_tty);
+
+MODULE_AUTHOR("Uwe Kleine-König <u.kleine-koenig@pengutronix.de>");
+MODULE_DESCRIPTION("UART LED trigger");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index bcc14c5875bf..8215cd77301f 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drive