mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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 ...
This commit is contained in:
6
Documentation/ABI/testing/sysfs-class-led-trigger-tty
Normal file
6
Documentation/ABI/testing/sysfs-class-led-trigger-tty
Normal file
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
183
drivers/leds/trigger/ledtrig-tty.c
Normal file
183
drivers/leds/trigger/ledtrig-tty.c
Normal file
@@ -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");
|
||||
@@ -89,8 +89,7 @@ static inline void update_tty_status(struct ser_device *ser)
|
||||
ser->tty_status =
|
||||
ser->tty->stopped << 5 |
|
||||
ser->tty->flow_stopped << 3 |
|
||||
ser->tty->packet << 2 |
|
||||
ser->tty->port->low_latency << 1;
|
||||
ser->tty->packet << 2;
|
||||
}
|
||||
static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty)
|
||||
{
|
||||
|
||||
@@ -259,7 +259,8 @@ static int ppp_asynctty_hangup(struct tty_struct *tty)
|
||||
*/
|
||||
static ssize_t
|
||||
ppp_asynctty_read(struct tty_struct *tty, struct file *file,
|
||||
unsigned char __user *buf, size_t count)
|
||||
unsigned char *buf, size_t count,
|
||||
void **cookie, unsigned long offset)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,8 @@ static int ppp_sync_hangup(struct tty_struct *tty)
|
||||
*/
|
||||
static ssize_t
|
||||
ppp_sync_read(struct tty_struct *tty, struct file *file,
|
||||
unsigned char __user *buf, size_t count)
|
||||
unsigned char *buf, size_t count,
|
||||
void **cookie, unsigned long offset)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -914,7 +914,6 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp)
|
||||
|
||||
tty_port_tty_set(&raw->port, tty);
|
||||
|
||||
raw->port.low_latency = 0; /* don't use bottom half for pushing chars */
|
||||
/*
|
||||
* Start up 3215 device
|
||||
*/
|
||||
|
||||
@@ -65,7 +65,6 @@ sclp_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
tty_port_tty_set(&sclp_port, tty);
|
||||
tty->driver_data = NULL;
|
||||
sclp_port.low_latency = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -560,7 +560,6 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (tty->count == 1) {
|
||||
tty_port_tty_set(&sclp_vt220_port, tty);
|
||||
sclp_vt220_port.low_latency = 0;
|
||||
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
|
||||
tty->winsize.ws_row = 24;
|
||||
tty->winsize.ws_col = 80;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user