TTY/Serial fixes for 6.5-rc7
Here are some small tty and serial core fixes for 6.5-rc7 that resolve a lot of reported issues. Primarily in here is the fixes for the serial bus code from Tony that came in -rc1, as it hit wider testing with the huge number of different types of systems and serial ports. All of the reported issues with duplicate names and other issues with this code are now resolved. Other than that included in here is: - n_gsm fix for a previous fix - 8250 lockdep annotation fix - fsl_lpuart serial driver fix - TIOCSTI documentation update for previous CAP_SYS_ADMIN change All of these have been in linux-next for a while with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZOEjmg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykpSgCfajOM7BUzL1kOrfKNvHQuPmOYlIUAnAot+4M+ HkvS58Xs2+PM14y/KG1j =6DRj -----END PGP SIGNATURE----- Merge tag 'tty-6.5-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial fixes from Greg KH: "Here are some small tty and serial core fixes for 6.5-rc7 that resolve a lot of reported issues. Primarily in here are the fixes for the serial bus code from Tony that came in -rc1, as it hit wider testing with the huge number of different types of systems and serial ports. All of the reported issues with duplicate names and other issues with this code are now resolved. Other than that included in here is: - n_gsm fix for a previous fix - 8250 lockdep annotation fix - fsl_lpuart serial driver fix - TIOCSTI documentation update for previous CAP_SYS_ADMIN change All of these have been in linux-next for a while with no reported problems" * tag 'tty-6.5-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: core: Fix serial core port id, including multiport devices serial: 8250: drop lockdep annotation from serial8250_clear_IER() tty: n_gsm: fix the UAF caused by race condition in gsm_cleanup_mux serial: core: Revert port_id use TIOCSTI: Document CAP_SYS_ADMIN behaviour in Kconfig serial: 8250: Fix oops for port->pm on uart_change_pm() serial: 8250: Reinit port_id when adding back serial8250_isa_devs serial: core: Fix kmemleak issue for serial core device remove MAINTAINERS: Merge TTY layer and serial drivers serial: core: Fix serial_base_match() after fixing controller port name serial: core: Fix serial core controller port name to show controller id serial: core: Fix serial core port id to not use port->line serial: core: Controller id cannot be negative tty: serial: fsl_lpuart: Clear the error flags by writing 1 for lpuart32 platforms
This commit is contained in:
commit
b320441c04
15
MAINTAINERS
15
MAINTAINERS
@ -19224,13 +19224,6 @@ F: Documentation/devicetree/bindings/serial/serial.yaml
|
|||||||
F: drivers/tty/serdev/
|
F: drivers/tty/serdev/
|
||||||
F: include/linux/serdev.h
|
F: include/linux/serdev.h
|
||||||
|
|
||||||
SERIAL DRIVERS
|
|
||||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
||||||
L: linux-serial@vger.kernel.org
|
|
||||||
S: Maintained
|
|
||||||
F: Documentation/devicetree/bindings/serial/
|
|
||||||
F: drivers/tty/serial/
|
|
||||||
|
|
||||||
SERIAL IR RECEIVER
|
SERIAL IR RECEIVER
|
||||||
M: Sean Young <sean@mess.org>
|
M: Sean Young <sean@mess.org>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
@ -21635,20 +21628,16 @@ W: https://github.com/srcres258/linux-doc
|
|||||||
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
|
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
|
||||||
F: Documentation/translations/zh_TW/
|
F: Documentation/translations/zh_TW/
|
||||||
|
|
||||||
TTY LAYER
|
TTY LAYER AND SERIAL DRIVERS
|
||||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
M: Jiri Slaby <jirislaby@kernel.org>
|
M: Jiri Slaby <jirislaby@kernel.org>
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
L: linux-serial@vger.kernel.org
|
L: linux-serial@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
|
||||||
|
F: Documentation/devicetree/bindings/serial/
|
||||||
F: Documentation/driver-api/serial/
|
F: Documentation/driver-api/serial/
|
||||||
F: drivers/tty/
|
F: drivers/tty/
|
||||||
F: drivers/tty/serial/serial_base.h
|
|
||||||
F: drivers/tty/serial/serial_base_bus.c
|
|
||||||
F: drivers/tty/serial/serial_core.c
|
|
||||||
F: drivers/tty/serial/serial_ctrl.c
|
|
||||||
F: drivers/tty/serial/serial_port.c
|
|
||||||
F: include/linux/selection.h
|
F: include/linux/selection.h
|
||||||
F: include/linux/serial.h
|
F: include/linux/serial.h
|
||||||
F: include/linux/serial_core.h
|
F: include/linux/serial_core.h
|
||||||
|
@ -164,6 +164,9 @@ config LEGACY_TIOCSTI
|
|||||||
userspace depends on this functionality to continue operating
|
userspace depends on this functionality to continue operating
|
||||||
normally.
|
normally.
|
||||||
|
|
||||||
|
Processes which run with CAP_SYS_ADMIN, such as BRLTTY, can
|
||||||
|
use TIOCSTI even when this is set to N.
|
||||||
|
|
||||||
This functionality can be changed at runtime with the
|
This functionality can be changed at runtime with the
|
||||||
dev.tty.legacy_tiocsti sysctl. This configuration option sets
|
dev.tty.legacy_tiocsti sysctl. This configuration option sets
|
||||||
the default value of the sysctl.
|
the default value of the sysctl.
|
||||||
|
@ -3042,12 +3042,13 @@ static void gsm_error(struct gsm_mux *gsm)
|
|||||||
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
|
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct gsm_dlci *dlci = gsm->dlci[0];
|
struct gsm_dlci *dlci;
|
||||||
struct gsm_msg *txq, *ntxq;
|
struct gsm_msg *txq, *ntxq;
|
||||||
|
|
||||||
gsm->dead = true;
|
gsm->dead = true;
|
||||||
mutex_lock(&gsm->mutex);
|
mutex_lock(&gsm->mutex);
|
||||||
|
|
||||||
|
dlci = gsm->dlci[0];
|
||||||
if (dlci) {
|
if (dlci) {
|
||||||
if (disc && dlci->state != DLCI_CLOSED) {
|
if (disc && dlci->state != DLCI_CLOSED) {
|
||||||
gsm_dlci_begin_close(dlci);
|
gsm_dlci_begin_close(dlci);
|
||||||
|
@ -497,6 +497,7 @@ static struct uart_8250_port *serial8250_setup_port(int index)
|
|||||||
|
|
||||||
up = &serial8250_ports[index];
|
up = &serial8250_ports[index];
|
||||||
up->port.line = index;
|
up->port.line = index;
|
||||||
|
up->port.port_id = index;
|
||||||
|
|
||||||
serial8250_init_port(up);
|
serial8250_init_port(up);
|
||||||
if (!base_ops)
|
if (!base_ops)
|
||||||
@ -1040,6 +1041,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
|
|||||||
uart_remove_one_port(&serial8250_reg, &uart->port);
|
uart_remove_one_port(&serial8250_reg, &uart->port);
|
||||||
|
|
||||||
uart->port.ctrl_id = up->port.ctrl_id;
|
uart->port.ctrl_id = up->port.ctrl_id;
|
||||||
|
uart->port.port_id = up->port.port_id;
|
||||||
uart->port.iobase = up->port.iobase;
|
uart->port.iobase = up->port.iobase;
|
||||||
uart->port.membase = up->port.membase;
|
uart->port.membase = up->port.membase;
|
||||||
uart->port.irq = up->port.irq;
|
uart->port.irq = up->port.irq;
|
||||||
@ -1202,6 +1204,7 @@ void serial8250_unregister_port(int line)
|
|||||||
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
|
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
|
||||||
uart->port.type = PORT_UNKNOWN;
|
uart->port.type = PORT_UNKNOWN;
|
||||||
uart->port.dev = &serial8250_isa_devs->dev;
|
uart->port.dev = &serial8250_isa_devs->dev;
|
||||||
|
uart->port.port_id = line;
|
||||||
uart->capabilities = 0;
|
uart->capabilities = 0;
|
||||||
serial8250_init_port(uart);
|
serial8250_init_port(uart);
|
||||||
serial8250_apply_quirks(uart);
|
serial8250_apply_quirks(uart);
|
||||||
|
@ -703,9 +703,6 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
|
|||||||
|
|
||||||
static void serial8250_clear_IER(struct uart_8250_port *up)
|
static void serial8250_clear_IER(struct uart_8250_port *up)
|
||||||
{
|
{
|
||||||
/* Port locked to synchronize UART_IER access against the console. */
|
|
||||||
lockdep_assert_held_once(&up->port.lock);
|
|
||||||
|
|
||||||
if (up->capabilities & UART_CAP_UUE)
|
if (up->capabilities & UART_CAP_UUE)
|
||||||
serial_out(up, UART_IER, UART_IER_UUE);
|
serial_out(up, UART_IER, UART_IER_UUE);
|
||||||
else
|
else
|
||||||
@ -3278,6 +3275,7 @@ void serial8250_init_port(struct uart_8250_port *up)
|
|||||||
|
|
||||||
spin_lock_init(&port->lock);
|
spin_lock_init(&port->lock);
|
||||||
port->ctrl_id = 0;
|
port->ctrl_id = 0;
|
||||||
|
port->pm = NULL;
|
||||||
port->ops = &serial8250_pops;
|
port->ops = &serial8250_pops;
|
||||||
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
|
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
|
||||||
|
|
||||||
|
@ -1139,8 +1139,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
|
|||||||
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
|
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);
|
||||||
|
|
||||||
if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
|
if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
|
||||||
/* Read DR to clear the error flags */
|
/* Clear the error flags */
|
||||||
lpuart32_read(&sport->port, UARTDATA);
|
lpuart32_write(&sport->port, sr, UARTSTAT);
|
||||||
|
|
||||||
if (sr & UARTSTAT_PE)
|
if (sr & UARTSTAT_PE)
|
||||||
sport->port.icount.parity++;
|
sport->port.icount.parity++;
|
||||||
|
@ -16,6 +16,7 @@ struct device;
|
|||||||
|
|
||||||
struct serial_ctrl_device {
|
struct serial_ctrl_device {
|
||||||
struct device dev;
|
struct device dev;
|
||||||
|
struct ida port_ida;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct serial_port_device {
|
struct serial_port_device {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <linux/container_of.h>
|
#include <linux/container_of.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/idr.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -19,11 +20,25 @@
|
|||||||
|
|
||||||
static bool serial_base_initialized;
|
static bool serial_base_initialized;
|
||||||
|
|
||||||
|
static const struct device_type serial_ctrl_type = {
|
||||||
|
.name = "ctrl",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct device_type serial_port_type = {
|
||||||
|
.name = "port",
|
||||||
|
};
|
||||||
|
|
||||||
static int serial_base_match(struct device *dev, struct device_driver *drv)
|
static int serial_base_match(struct device *dev, struct device_driver *drv)
|
||||||
{
|
{
|
||||||
int len = strlen(drv->name);
|
if (dev->type == &serial_ctrl_type &&
|
||||||
|
str_has_prefix(drv->name, serial_ctrl_type.name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
return !strncmp(dev_name(dev), drv->name, len);
|
if (dev->type == &serial_port_type &&
|
||||||
|
str_has_prefix(drv->name, serial_port_type.name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bus_type serial_base_bus_type = {
|
static struct bus_type serial_base_bus_type = {
|
||||||
@ -48,7 +63,8 @@ static int serial_base_device_init(struct uart_port *port,
|
|||||||
struct device *parent_dev,
|
struct device *parent_dev,
|
||||||
const struct device_type *type,
|
const struct device_type *type,
|
||||||
void (*release)(struct device *dev),
|
void (*release)(struct device *dev),
|
||||||
int id)
|
unsigned int ctrl_id,
|
||||||
|
unsigned int port_id)
|
||||||
{
|
{
|
||||||
device_initialize(dev);
|
device_initialize(dev);
|
||||||
dev->type = type;
|
dev->type = type;
|
||||||
@ -61,12 +77,15 @@ static int serial_base_device_init(struct uart_port *port,
|
|||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev_set_name(dev, "%s.%s.%d", type->name, dev_name(port->dev), id);
|
if (type == &serial_ctrl_type)
|
||||||
}
|
return dev_set_name(dev, "%s:%d", dev_name(port->dev), ctrl_id);
|
||||||
|
|
||||||
static const struct device_type serial_ctrl_type = {
|
if (type == &serial_port_type)
|
||||||
.name = "ctrl",
|
return dev_set_name(dev, "%s:%d.%d", dev_name(port->dev),
|
||||||
};
|
ctrl_id, port_id);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static void serial_base_ctrl_release(struct device *dev)
|
static void serial_base_ctrl_release(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -81,6 +100,7 @@ void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
device_del(&ctrl_dev->dev);
|
device_del(&ctrl_dev->dev);
|
||||||
|
put_device(&ctrl_dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
|
struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
|
||||||
@ -93,10 +113,12 @@ struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
|
|||||||
if (!ctrl_dev)
|
if (!ctrl_dev)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
ida_init(&ctrl_dev->port_ida);
|
||||||
|
|
||||||
err = serial_base_device_init(port, &ctrl_dev->dev,
|
err = serial_base_device_init(port, &ctrl_dev->dev,
|
||||||
parent, &serial_ctrl_type,
|
parent, &serial_ctrl_type,
|
||||||
serial_base_ctrl_release,
|
serial_base_ctrl_release,
|
||||||
port->ctrl_id);
|
port->ctrl_id, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_put_device;
|
goto err_put_device;
|
||||||
|
|
||||||
@ -112,10 +134,6 @@ err_put_device:
|
|||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct device_type serial_port_type = {
|
|
||||||
.name = "port",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void serial_base_port_release(struct device *dev)
|
static void serial_base_port_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
|
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
|
||||||
@ -127,16 +145,31 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,
|
|||||||
struct serial_ctrl_device *ctrl_dev)
|
struct serial_ctrl_device *ctrl_dev)
|
||||||
{
|
{
|
||||||
struct serial_port_device *port_dev;
|
struct serial_port_device *port_dev;
|
||||||
|
int min = 0, max = -1; /* Use -1 for max to apply IDA defaults */
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
|
port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
|
||||||
if (!port_dev)
|
if (!port_dev)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/* Device driver specified port_id vs automatic assignment? */
|
||||||
|
if (port->port_id) {
|
||||||
|
min = port->port_id;
|
||||||
|
max = port->port_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ida_alloc_range(&ctrl_dev->port_ida, min, max, GFP_KERNEL);
|
||||||
|
if (err < 0) {
|
||||||
|
kfree(port_dev);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
port->port_id = err;
|
||||||
|
|
||||||
err = serial_base_device_init(port, &port_dev->dev,
|
err = serial_base_device_init(port, &port_dev->dev,
|
||||||
&ctrl_dev->dev, &serial_port_type,
|
&ctrl_dev->dev, &serial_port_type,
|
||||||
serial_base_port_release,
|
serial_base_port_release,
|
||||||
port->line);
|
port->ctrl_id, port->port_id);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_put_device;
|
goto err_put_device;
|
||||||
|
|
||||||
@ -150,16 +183,25 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,
|
|||||||
|
|
||||||
err_put_device:
|
err_put_device:
|
||||||
put_device(&port_dev->dev);
|
put_device(&port_dev->dev);
|
||||||
|
ida_free(&ctrl_dev->port_ida, port->port_id);
|
||||||
|
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_base_port_device_remove(struct serial_port_device *port_dev)
|
void serial_base_port_device_remove(struct serial_port_device *port_dev)
|
||||||
{
|
{
|
||||||
|
struct serial_ctrl_device *ctrl_dev;
|
||||||
|
struct device *parent;
|
||||||
|
|
||||||
if (!port_dev)
|
if (!port_dev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
parent = port_dev->dev.parent;
|
||||||
|
ctrl_dev = to_serial_base_ctrl_device(parent);
|
||||||
|
|
||||||
device_del(&port_dev->dev);
|
device_del(&port_dev->dev);
|
||||||
|
ida_free(&ctrl_dev->port_ida, port_dev->port->port_id);
|
||||||
|
put_device(&port_dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_base_init(void)
|
static int serial_base_init(void)
|
||||||
|
@ -459,7 +459,8 @@ struct uart_port {
|
|||||||
struct serial_rs485 *rs485);
|
struct serial_rs485 *rs485);
|
||||||
int (*iso7816_config)(struct uart_port *,
|
int (*iso7816_config)(struct uart_port *,
|
||||||
struct serial_iso7816 *iso7816);
|
struct serial_iso7816 *iso7816);
|
||||||
int ctrl_id; /* optional serial core controller id */
|
unsigned int ctrl_id; /* optional serial core controller id */
|
||||||
|
unsigned int port_id; /* optional serial core port id */
|
||||||
unsigned int irq; /* irq number */
|
unsigned int irq; /* irq number */
|
||||||
unsigned long irqflags; /* irq flags */
|
unsigned long irqflags; /* irq flags */
|
||||||
unsigned int uartclk; /* base uart clock */
|
unsigned int uartclk; /* base uart clock */
|
||||||
|
Loading…
Reference in New Issue
Block a user