From fc60a8b675bd9499c71716d21c238eed5092ddfc Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sun, 9 Jul 2017 22:29:42 +0200 Subject: tty: serial: owl: Implement console driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement serial console driver to complement earlycon. Based on LeMaker linux-actions tree. Signed-off-by: Andreas Färber Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/serial_core.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index c34a2a3eeff5..38bea3217ead 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -70,6 +70,7 @@ #define PORT_CLPS711X 33 #define PORT_SA1100 34 #define PORT_UART00 35 +#define PORT_OWL 36 #define PORT_21285 37 /* Sparc type numbers. */ -- cgit v1.2.3 From c7ac15ce89242e3c25fcc49fa4d00028285fab05 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 Jul 2017 20:39:58 +0300 Subject: serial: core: move UPF_NO_TXEN_TEST to quirks and rename First 16 bits in the flags field are user-visible except UPF_NO_TXEN_TEST. To keep it clean we introduce internal quirks and move UPF_NO_TXEN_TEST to them. Rename the constant to UPQ_NO_TXEN_TEST to distinguish with port flags. Users are converted accordingly. The quirks field might be extended later to hold the additional ones. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 16 ++++++++-------- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/8250/8250_port.c | 2 +- include/linux/serial_core.h | 9 +++++---- 4 files changed, 15 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b5def356af63..3db9d6e19660 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -497,6 +497,11 @@ static void univ8250_rsa_support(struct uart_ops *ops) #define univ8250_rsa_support(x) do { } while (0) #endif /* CONFIG_SERIAL_8250_RSA */ +static inline void serial8250_apply_quirks(struct uart_8250_port *up) +{ + up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; +} + static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; @@ -577,9 +582,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) up->port.dev = dev; - if (skip_txen_test) - up->port.flags |= UPF_NO_TXEN_TEST; - + serial8250_apply_quirks(up); uart_add_one_port(drv, &up->port); } } @@ -1006,9 +1009,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->port.dev) uart->port.dev = up->port.dev; - if (skip_txen_test) - uart->port.flags |= UPF_NO_TXEN_TEST; - if (up->port.flags & UPF_FIXED_TYPE) uart->port.type = up->port.type; @@ -1047,6 +1047,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) serial8250_isa_config(0, &uart->port, &uart->capabilities); + serial8250_apply_quirks(uart); ret = uart_add_one_port(&serial8250_reg, &uart->port); if (ret == 0) ret = uart->port.line; @@ -1081,11 +1082,10 @@ void serial8250_unregister_port(int line) uart_remove_one_port(&serial8250_reg, &uart->port); if (serial8250_isa_devs) { uart->port.flags &= ~UPF_BOOT_AUTOCONF; - if (skip_txen_test) - uart->port.flags |= UPF_NO_TXEN_TEST; uart->port.type = PORT_UNKNOWN; uart->port.dev = &serial8250_isa_devs->dev; uart->capabilities = 0; + serial8250_apply_quirks(uart); uart_add_one_port(&serial8250_reg, &uart->port); } else { uart->port.dev = NULL; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 553823c12c2f..e82d7d521010 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1548,7 +1548,7 @@ static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) { - port->port.flags |= UPF_NO_TXEN_TEST; + port->port.quirks |= UPQ_NO_TXEN_TEST; dev_dbg(&priv->dev->dev, "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n", priv->dev->vendor, priv->dev->device, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a5fe0e66c607..25aae660cb9e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2304,7 +2304,7 @@ int serial8250_do_startup(struct uart_port *port) * test if we receive TX irq. This way, we'll never enable * UART_BUG_TXEN. */ - if (up->port.flags & UPF_NO_TXEN_TEST) + if (up->port.quirks & UPQ_NO_TXEN_TEST) goto dont_test_tx_en; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 1775500294bb..8dc24c855a70 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -20,7 +20,7 @@ #ifndef LINUX_SERIAL_CORE_H #define LINUX_SERIAL_CORE_H - +#include #include #include #include @@ -144,7 +144,7 @@ struct uart_port { unsigned char x_char; /* xon/xoff char */ unsigned char regshift; /* reg offset shift */ unsigned char iotype; /* io access style */ - unsigned char unused1; + unsigned char quirks; /* internal quirks */ #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ @@ -155,6 +155,9 @@ struct uart_port { #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ #define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ + /* quirks must be updated while holding port mutex */ +#define UPQ_NO_TXEN_TEST BIT(0) + unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ struct uart_state *state; /* pointer to parent state */ @@ -175,7 +178,6 @@ struct uart_port { * [for bit definitions in the UPF_CHANGE_MASK] * * Bits [0..UPF_LAST_USER] are userspace defined/visible/changeable - * except bit 15 (UPF_NO_TXEN_TEST) which is masked off. * The remaining bits are serial-core specific and not modifiable by * userspace. */ @@ -192,7 +194,6 @@ struct uart_port { #define UPF_SPD_SHI ((__force upf_t) ASYNC_SPD_SHI /* 12 */ ) #define UPF_LOW_LATENCY ((__force upf_t) ASYNC_LOW_LATENCY /* 13 */ ) #define UPF_BUGGY_UART ((__force upf_t) ASYNC_BUGGY_UART /* 14 */ ) -#define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) #define UPF_MAGIC_MULTIPLIER ((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ ) #define UPF_NO_THRE_TEST ((__force upf_t) (1 << 19)) -- cgit v1.2.3 From 979990c6284814617d8f2179d197f72ff62b5d85 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 20 Jun 2017 23:10:41 +0200 Subject: tty: improve tty_insert_flip_char() fast path kernelci.org reports a crazy stack usage for the VT code when CONFIG_KASAN is enabled: drivers/tty/vt/keyboard.c: In function 'kbd_keycode': drivers/tty/vt/keyboard.c:1452:1: error: the frame size of 2240 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] The problem is that tty_insert_flip_char() gets inlined many times into kbd_keycode(), and also into other functions, and each copy requires 128 bytes for stack redzone to check for a possible out-of-bounds access on the 'ch' and 'flags' arguments that are passed into tty_insert_flip_string_flags as a variable-length string. This introduces a new __tty_insert_flip_char() function for the slow path, which receives the two arguments by value. This completely avoids the problem and the stack usage goes back down to around 100 bytes. Without KASAN, this is also slightly better, as we don't have to spill the arguments to the stack but can simply pass 'ch' and 'flag' in registers, saving a few bytes in .text for each call site. This should be backported to linux-4.0 or later, which first introduced the stack sanitizer in the kernel. Cc: stable@vger.kernel.org Fixes: c420f167db8c ("kasan: enable stack instrumentation") Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 24 ++++++++++++++++++++++++ include/linux/tty_flip.h | 3 ++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 4e7a4e9dcf4d..2da05fa37aec 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -361,6 +361,30 @@ int tty_insert_flip_string_flags(struct tty_port *port, } EXPORT_SYMBOL(tty_insert_flip_string_flags); +/** + * __tty_insert_flip_char - Add one character to the tty buffer + * @port: tty port + * @ch: character + * @flag: flag byte + * + * Queue a single byte to the tty buffering, with an optional flag. + * This is the slow path of tty_insert_flip_char. + */ +int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) +{ + struct tty_buffer *tb = port->buf.tail; + int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0; + + if (!tty_buffer_request_room(port, 1)) + return 0; + + *flag_buf_ptr(tb, tb->used) = flag; + *char_buf_ptr(tb, tb->used++) = ch; + + return 1; +} +EXPORT_SYMBOL(__tty_insert_flip_char); + /** * tty_schedule_flip - push characters to ldisc * @port: tty port to push from diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index c28dd523f96e..d43837f2ce3a 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -12,6 +12,7 @@ extern int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size); extern void tty_flip_buffer_push(struct tty_port *port); void tty_schedule_flip(struct tty_port *port); +int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag); static inline int tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) @@ -26,7 +27,7 @@ static inline int tty_insert_flip_char(struct tty_port *port, *char_buf_ptr(tb, tb->used++) = ch; return 1; } - return tty_insert_flip_string_flags(port, &ch, &flag, 1); + return __tty_insert_flip_char(port, ch, flag); } static inline int tty_insert_flip_string(struct tty_port *port, -- cgit v1.2.3 From aef3ad103a686f21b746977d4ed21cc1af36f589 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 13 Aug 2017 17:47:42 +0300 Subject: serial: core: remove unneeded irq_wake flag There is no need to duplicate a flag which IRQ core takes care of. Replace custom flag by IRQ core API that retrieves its state. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 9 +++------ include/linux/serial_core.h | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 73ce4e2f7a93..220e1d088c9b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include /* @@ -2083,8 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (tty_dev && device_may_wakeup(tty_dev)) { - if (!enable_irq_wake(uport->irq)) - uport->irq_wake = 1; + enable_irq_wake(uport->irq); put_device(tty_dev); mutex_unlock(&port->mutex); return 0; @@ -2147,10 +2146,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (!uport->suspended && device_may_wakeup(tty_dev)) { - if (uport->irq_wake) { + if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq)))) disable_irq_wake(uport->irq); - uport->irq_wake = 0; - } put_device(tty_dev); mutex_unlock(&port->mutex); return 0; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 8dc24c855a70..5553e04e59c9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -247,7 +247,6 @@ struct uart_port { struct device *dev; /* parent device */ unsigned char hub6; /* this should be in the 8250 driver */ unsigned char suspended; - unsigned char irq_wake; unsigned char unused[2]; const char *name; /* port name */ struct attribute_group *attr_group; /* port specific attributes */ -- cgit v1.2.3 From 63e8d4394a2d226803f47abd7287dbb6d21bf8e4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 22 Aug 2017 16:58:20 +0300 Subject: serial: pch_uart: Make port type explicit It used to be a gap in port definitions after PORT_MAX_8250. Since the new drivers are coming the gap become shorter and shorter until the commit a2d6a987bfe4 ("serial: 8250: Add new port type for TI DA8xx/66AK2x") completely removed it. So, while type here is just a formality, make things a little bit more explicit for this driver and move port types to UAPI header. Note, it uses two types for now. Fixes: fddceb8b5399 ("tty: 8250: Add 64byte UART support for FSL platforms") Cc: Priyanka Jain Cc: Poonam Aggrwal Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 35 +++++++++++++++-------------------- include/uapi/linux/serial_core.h | 5 ++++- 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 3788198f105b..ae8cfc81ffc5 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -46,11 +46,6 @@ enum { PCH_UART_HANDLED_LS_INT_SHIFT, }; -enum { - PCH_UART_8LINE, - PCH_UART_2LINE, -}; - #define PCH_UART_DRIVER_DEVICE "ttyPCH" /* Set the max number of UART port @@ -267,7 +262,7 @@ struct eg20t_port { /** * struct pch_uart_driver_data - private data structure for UART-DMA - * @port_type: The number of DMA channel + * @port_type: The type of UART port * @line_no: UART port line number (0, 1, 2...) */ struct pch_uart_driver_data { @@ -290,17 +285,17 @@ enum pch_uart_num_t { }; static struct pch_uart_driver_data drv_dat[] = { - [pch_et20t_uart0] = {PCH_UART_8LINE, 0}, - [pch_et20t_uart1] = {PCH_UART_2LINE, 1}, - [pch_et20t_uart2] = {PCH_UART_2LINE, 2}, - [pch_et20t_uart3] = {PCH_UART_2LINE, 3}, - [pch_ml7213_uart0] = {PCH_UART_8LINE, 0}, - [pch_ml7213_uart1] = {PCH_UART_2LINE, 1}, - [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, - [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, - [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, - [pch_ml7831_uart0] = {PCH_UART_8LINE, 0}, - [pch_ml7831_uart1] = {PCH_UART_2LINE, 1}, + [pch_et20t_uart0] = {PORT_PCH_8LINE, 0}, + [pch_et20t_uart1] = {PORT_PCH_2LINE, 1}, + [pch_et20t_uart2] = {PORT_PCH_2LINE, 2}, + [pch_et20t_uart3] = {PORT_PCH_2LINE, 3}, + [pch_ml7213_uart0] = {PORT_PCH_8LINE, 0}, + [pch_ml7213_uart1] = {PORT_PCH_2LINE, 1}, + [pch_ml7213_uart2] = {PORT_PCH_2LINE, 2}, + [pch_ml7223_uart0] = {PORT_PCH_8LINE, 0}, + [pch_ml7223_uart1] = {PORT_PCH_2LINE, 1}, + [pch_ml7831_uart0] = {PORT_PCH_8LINE, 0}, + [pch_ml7831_uart1] = {PORT_PCH_2LINE, 1}, }; #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE @@ -1777,10 +1772,10 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, goto init_port_free_txbuf; switch (port_type) { - case PORT_UNKNOWN: + case PORT_PCH_8LINE: fifosize = 256; /* EG20T/ML7213: UART0 */ break; - case PORT_8250: + case PORT_PCH_2LINE: fifosize = 64; /* EG20T:UART1~3 ML7213: UART1~2*/ break; default: @@ -1804,7 +1799,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, priv->fifo_size = fifosize; priv->uartclk = pch_uart_get_uartclk(); - priv->port_type = PORT_MAX_8250 + port_type + 1; + priv->port_type = port_type; priv->port.dev = &pdev->dev; priv->port.iobase = iobase; priv->port.membase = NULL; diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 38bea3217ead..502aa23c7e15 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -57,7 +57,6 @@ #define PORT_RT2880 29 /* Ralink RT2880 internal UART */ #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */ #define PORT_DA830 31 /* TI DA8xx/66AK2x */ -#define PORT_MAX_8250 31 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed @@ -77,6 +76,10 @@ #define PORT_SUNZILOG 38 #define PORT_SUNSAB 39 +/* Intel EG20 */ +#define PORT_PCH_8LINE 44 +#define PORT_PCH_2LINE 45 + /* DEC */ #define PORT_DZ 46 #define PORT_ZS 47 -- cgit v1.2.3 From 3f3dac7e4d815cb7f929c0ed98c3a45a86852e53 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 22 Aug 2017 16:58:21 +0300 Subject: serial: Remove unused port type PORT_MFD is not in use since commit 1bd187de5364 ("x86, intel-mid: remove Intel MID specific serial support") Remove leftover. Fixes: 1bd187de5364 ("x86, intel-mid: remove Intel MID specific serial support") Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/serial_core.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 502aa23c7e15..00d335634271 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -209,9 +209,6 @@ /* MAX310X */ #define PORT_MAX310X 94 -/* High Speed UART for Medfield */ -#define PORT_MFD 95 - /* TI OMAP-UART */ #define PORT_OMAP 96 -- cgit v1.2.3 From ee1c90cc2cea80638f559c552371ee6893ca9d9e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 22 Aug 2017 16:58:22 +0300 Subject: serial: Fix port type numbering for TI DA8xx The UAPI has a global list of unique numbers for different port types. The commit a2d6a987bfe4 ("serial: 8250: Add new port type for TI DA8xx/66AK2x") introduced a new port type and brought the collision with two other port types. Reuse 95 for it instead. Fixes: a2d6a987bfe4 ("serial: 8250: Add new port type for TI DA8xx/66AK2x") Cc: David Lechner Cc: Sekhar Nori Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/serial_core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 00d335634271..dc2d7cb766ab 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -56,7 +56,6 @@ #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ #define PORT_RT2880 29 /* Ralink RT2880 internal UART */ #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */ -#define PORT_DA830 31 /* TI DA8xx/66AK2x */ /* * ARM specific type numbers. These are not currently guaranteed @@ -209,6 +208,9 @@ /* MAX310X */ #define PORT_MAX310X 94 +/* TI DA8xx/66AK2x */ +#define PORT_DA830 95 + /* TI OMAP-UART */ #define PORT_OMAP 96 -- cgit v1.2.3 From 6e0a5de2136b26bd0b3501f2f362abfffeb47d1e Mon Sep 17 00:00:00 2001 From: Rafael Gago Date: Mon, 31 Jul 2017 10:46:43 +0200 Subject: serial: 8250: Use hrtimers for rs485 delays Previously the timers where based on the classic timers, giving a too coarse resolution on systems with configs of less than 1000 HZ. This patch changes the rs485 timers to hrtimers. Signed-off-by: Rafael Gago Castano Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 63 +++++++++++++++++++++++-------------- include/linux/serial_8250.h | 7 +++-- 2 files changed, 44 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 25aae660cb9e..6b745e440b81 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -553,8 +553,8 @@ static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) serial8250_out_MCR(p, mcr); } -static void serial8250_em485_handle_start_tx(unsigned long arg); -static void serial8250_em485_handle_stop_tx(unsigned long arg); +static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); +static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t); void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) { @@ -609,12 +609,14 @@ int serial8250_em485_init(struct uart_8250_port *p) if (!p->em485) return -ENOMEM; - setup_timer(&p->em485->stop_tx_timer, - serial8250_em485_handle_stop_tx, (unsigned long)p); - setup_timer(&p->em485->start_tx_timer, - serial8250_em485_handle_start_tx, (unsigned long)p); + hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx; + p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx; + p->em485->port = p; p->em485->active_timer = NULL; - serial8250_em485_rts_after_send(p); return 0; @@ -639,8 +641,8 @@ void serial8250_em485_destroy(struct uart_8250_port *p) if (!p->em485) return; - del_timer(&p->em485->start_tx_timer); - del_timer(&p->em485->stop_tx_timer); + hrtimer_cancel(&p->em485->start_tx_timer); + hrtimer_cancel(&p->em485->stop_tx_timer); kfree(p->em485); p->em485 = NULL; @@ -1435,12 +1437,13 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p) serial_port_out(&p->port, UART_IER, p->ier); } } - -static void serial8250_em485_handle_stop_tx(unsigned long arg) +static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) { - struct uart_8250_port *p = (struct uart_8250_port *)arg; - struct uart_8250_em485 *em485 = p->em485; + struct uart_8250_em485 *em485; + struct uart_8250_port *p; unsigned long flags; + em485 = container_of(t, struct uart_8250_em485, stop_tx_timer); + p = em485->port; serial8250_rpm_get(p); spin_lock_irqsave(&p->port.lock, flags); @@ -1451,6 +1454,16 @@ static void serial8250_em485_handle_stop_tx(unsigned long arg) } spin_unlock_irqrestore(&p->port.lock, flags); serial8250_rpm_put(p); + return HRTIMER_NORESTART; +} + +static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) +{ + long sec = msec / 1000; + long nsec = (msec % 1000) * 1000000; + ktime_t t = ktime_set(sec, nsec); + + hrtimer_start(hrt, t, HRTIMER_MODE_REL); } static void __stop_tx_rs485(struct uart_8250_port *p) @@ -1463,8 +1476,8 @@ static void __stop_tx_rs485(struct uart_8250_port *p) */ if (p->port.rs485.delay_rts_after_send > 0) { em485->active_timer = &em485->stop_tx_timer; - mod_timer(&em485->stop_tx_timer, jiffies + - p->port.rs485.delay_rts_after_send * HZ / 1000); + start_hrtimer_ms(&em485->stop_tx_timer, + p->port.rs485.delay_rts_after_send); } else { __do_stop_tx_rs485(p); } @@ -1494,8 +1507,8 @@ static inline void __stop_tx(struct uart_8250_port *p) if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) return; - del_timer(&em485->start_tx_timer); em485->active_timer = NULL; + hrtimer_cancel(&em485->start_tx_timer); __stop_tx_rs485(p); } @@ -1558,8 +1571,9 @@ static inline void start_tx_rs485(struct uart_port *port) if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) serial8250_stop_rx(&up->port); - del_timer(&em485->stop_tx_timer); em485->active_timer = NULL; + if (hrtimer_is_queued(&em485->stop_tx_timer)) + hrtimer_cancel(&em485->stop_tx_timer); mcr = serial8250_in_MCR(up); if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != @@ -1572,8 +1586,8 @@ static inline void start_tx_rs485(struct uart_port *port) if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; - mod_timer(&em485->start_tx_timer, jiffies + - up->port.rs485.delay_rts_before_send * HZ / 1000); + start_hrtimer_ms(&em485->start_tx_timer, + up->port.rs485.delay_rts_before_send); return; } } @@ -1581,11 +1595,13 @@ static inline void start_tx_rs485(struct uart_port *port) __start_tx(port); } -static void serial8250_em485_handle_start_tx(unsigned long arg) +static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t) { - struct uart_8250_port *p = (struct uart_8250_port *)arg; - struct uart_8250_em485 *em485 = p->em485; + struct uart_8250_em485 *em485; + struct uart_8250_port *p; unsigned long flags; + em485 = container_of(t, struct uart_8250_em485, start_tx_timer); + p = em485->port; spin_lock_irqsave(&p->port.lock, flags); if (em485 && @@ -1594,6 +1610,7 @@ static void serial8250_em485_handle_start_tx(unsigned long arg) em485->active_timer = NULL; } spin_unlock_irqrestore(&p->port.lock, flags); + return HRTIMER_NORESTART; } static void serial8250_start_tx(struct uart_port *port) diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 61fbb440449c..a27ef5f56431 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -80,9 +80,10 @@ struct uart_8250_ops { }; struct uart_8250_em485 { - struct timer_list start_tx_timer; /* "rs485 start tx" timer */ - struct timer_list stop_tx_timer; /* "rs485 stop tx" timer */ - struct timer_list *active_timer; /* pointer to active timer */ + struct hrtimer start_tx_timer; /* "rs485 start tx" timer */ + struct hrtimer stop_tx_timer; /* "rs485 stop tx" timer */ + struct hrtimer *active_timer; /* pointer to active timer */ + struct uart_8250_port *port; /* for hrtimer callbacks */ }; /* -- cgit v1.2.3 From 1c16ae65e2502da05310b2ec56b3a1fd3efe6f4d Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 21 Aug 2017 01:17:56 +0800 Subject: serial: 8250: of: Add new port type for MediaTek BTIF controller on MT7622/23 SoC MediaTek BTIF controller is the serial interface similar to UART but it works only as the digital device which is mainly used to communicate with the connectivity module called CONNSYS inside the SoC which could be mostly found on those MediaTek SoCs with Bluetooth feature such as MT7622 and MT7623 SoCs. And the controller is made as being compatible with the 8250 register layout with extra registers such as DMA enablement so it tends to be integrated with reusing 8250 OF driver. However, DMA mode is not being supported yet in the current driver. Signed-off-by: Sean Wang Suggested-by: Andy Shevchenko Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_of.c | 2 ++ drivers/tty/serial/8250/8250_port.c | 8 ++++++++ include/uapi/linux/serial_core.h | 3 +++ 3 files changed, 13 insertions(+) (limited to 'include') diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 30eacbffaa51..1222c005fb98 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -313,6 +313,8 @@ static const struct of_device_id of_platform_serial_table[] = { .data = (void *)PORT_ALTR_16550_F64, }, { .compatible = "altr,16550-FIFO128", .data = (void *)PORT_ALTR_16550_F128, }, + { .compatible = "mediatek,mtk-btif", + .data = (void *)PORT_MTK_BTIF, }, { .compatible = "mrvl,mmp-uart", .data = (void *)PORT_XSCALE, }, { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 6b745e440b81..4726aa276968 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -289,6 +289,14 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 4, 8, 14}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + [PORT_MTK_BTIF] = { + .name = "MediaTek BTIF", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + .flags = UART_CAP_FIFO, + }, }; /* Uart divisor latch read */ diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index dc2d7cb766ab..50d71c436323 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -274,4 +274,7 @@ /* MPS2 UART */ #define PORT_MPS2UART 116 +/* MediaTek BTIF */ +#define PORT_MTK_BTIF 117 + #endif /* _UAPILINUX_SERIAL_CORE_H */ -- cgit v1.2.3 From 2ce8008711e4837c11e99a94df55406085d0d098 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 2 Aug 2017 09:58:52 +0200 Subject: mcb: introduce mcb_get_resource() Introduce mcb_get_resource() as a common accessor to a mcb device's memory or IRQ resources. Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/mcb/mcb-core.c | 20 +++++++++++++++++++- include/linux/mcb.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c index 921a5d2a802b..bb5c5692dedc 100644 --- a/drivers/mcb/mcb-core.c +++ b/drivers/mcb/mcb-core.c @@ -417,6 +417,22 @@ void mcb_bus_add_devices(const struct mcb_bus *bus) } EXPORT_SYMBOL_GPL(mcb_bus_add_devices); +/** + * mcb_get_resource() - get a resource for a mcb device + * @dev: the mcb device + * @type: the type of resource + */ +struct resource *mcb_get_resource(struct mcb_device *dev, unsigned int type) +{ + if (type == IORESOURCE_MEM) + return &dev->mem; + else if (type == IORESOURCE_IRQ) + return &dev->irq; + else + return NULL; +} +EXPORT_SYMBOL_GPL(mcb_get_resource); + /** * mcb_request_mem() - Request memory * @dev: The @mcb_device the memory is for @@ -460,7 +476,9 @@ EXPORT_SYMBOL_GPL(mcb_release_mem); static int __mcb_get_irq(struct mcb_device *dev) { - struct resource *irq = &dev->irq; + struct resource *irq; + + irq = mcb_get_resource(dev, IORESOURCE_IRQ); return irq->start; } diff --git a/include/linux/mcb.h b/include/linux/mcb.h index 4097ac9ea13a..b1a0ad9d23b3 100644 --- a/include/linux/mcb.h +++ b/include/linux/mcb.h @@ -136,5 +136,7 @@ extern struct resource *mcb_request_mem(struct mcb_device *dev, const char *name); extern void mcb_release_mem(struct resource *mem); extern int mcb_get_irq(struct mcb_device *dev); +extern struct resource *mcb_get_resource(struct mcb_device *dev, + unsigned int type); #endif /* _LINUX_MCB_H */ -- cgit v1.2.3 From d01c3289e7d68162e32bc08c2b65dd1a216a7ef8 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Tue, 18 Jul 2017 06:27:59 +0900 Subject: pty: show associative slave of ptmx in fdinfo This patch adds "tty-index" field to /proc/PID/fdinfo/N if N specifies /dev/ptmx. The field shows the index of associative slave pts. Though a minor number is given for each pts instance, ptmx is not. It means there is no way in user-space to know the association between file descriptors for pts/n and ptmx. (n = 0, 1, ...) This is different from pipe. About pipe such association can be solved by inode of pipefs. Providing the way to know the association between pts/n and ptmx helps users understand the status of running system. lsof can utilize this field. Signed-off-by: Masatake YAMATO Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 8 +++++++- drivers/tty/tty_io.c | 9 +++++++++ include/linux/tty_driver.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 284749fb0f6b..bb672ace562f 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -741,6 +741,11 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) } } +static void pty_show_fdinfo(struct tty_struct *tty, struct seq_file *m) +{ + seq_printf(m, "tty-index:\t%d\n", tty->index); +} + static const struct tty_operations ptm_unix98_ops = { .lookup = ptm_unix98_lookup, .install = pty_unix98_install, @@ -755,7 +760,8 @@ static const struct tty_operations ptm_unix98_ops = { .ioctl = pty_unix98_ioctl, .compat_ioctl = pty_unix98_compat_ioctl, .resize = pty_resize, - .cleanup = pty_cleanup + .cleanup = pty_cleanup, + .show_fdinfo = pty_show_fdinfo, }; static const struct tty_operations pty_unix98_ops = { diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 974b13d24401..c3c8fd0ed535 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -462,6 +462,14 @@ static int hung_up_tty_fasync(int fd, struct file *file, int on) return -ENOTTY; } +static void tty_show_fdinfo(struct seq_file *m, struct file *file) +{ + struct tty_struct *tty = file_tty(file); + + if (tty && tty->ops && tty->ops->show_fdinfo) + tty->ops->show_fdinfo(tty, m); +} + static const struct file_operations tty_fops = { .llseek = no_llseek, .read = tty_read, @@ -472,6 +480,7 @@ static const struct file_operations tty_fops = { .open = tty_open, .release = tty_release, .fasync = tty_fasync, + .show_fdinfo = tty_show_fdinfo, }; static const struct file_operations console_fops = { diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 00b2213f6a35..fcdc0f5d9098 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -243,6 +243,7 @@ #include #include #include +#include struct tty_struct; struct tty_driver; @@ -285,6 +286,7 @@ struct tty_operations { int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount); + void (*show_fdinfo)(struct tty_struct *tty, struct seq_file *m); #ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); -- cgit v1.2.3