Skip to content

Commit

Permalink
Merge tag 'tty-6.5-rc7' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Aug 20, 2023
2 parents ec27a63 + 04c7f60 commit b320441
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 34 deletions.
15 changes: 2 additions & 13 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -19224,13 +19224,6 @@ F: Documentation/devicetree/bindings/serial/serial.yaml
F: drivers/tty/serdev/
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
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
Expand Down Expand Up @@ -21635,20 +21628,16 @@ W: https://github.com/srcres258/linux-doc
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
F: Documentation/translations/zh_TW/

TTY LAYER
TTY LAYER AND SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M: Jiri Slaby <jirislaby@kernel.org>
L: linux-kernel@vger.kernel.org
L: linux-serial@vger.kernel.org
S: Supported
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: 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/serial.h
F: include/linux/serial_core.h
Expand Down
3 changes: 3 additions & 0 deletions drivers/tty/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ config LEGACY_TIOCSTI
userspace depends on this functionality to continue operating
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
dev.tty.legacy_tiocsti sysctl. This configuration option sets
the default value of the sysctl.
Expand Down
3 changes: 2 additions & 1 deletion drivers/tty/n_gsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3042,12 +3042,13 @@ static void gsm_error(struct gsm_mux *gsm)
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
int i;
struct gsm_dlci *dlci = gsm->dlci[0];
struct gsm_dlci *dlci;
struct gsm_msg *txq, *ntxq;

gsm->dead = true;
mutex_lock(&gsm->mutex);

dlci = gsm->dlci[0];
if (dlci) {
if (disc && dlci->state != DLCI_CLOSED) {
gsm_dlci_begin_close(dlci);
Expand Down
3 changes: 3 additions & 0 deletions drivers/tty/serial/8250/8250_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ static struct uart_8250_port *serial8250_setup_port(int index)

up = &serial8250_ports[index];
up->port.line = index;
up->port.port_id = index;

serial8250_init_port(up);
if (!base_ops)
Expand Down Expand Up @@ -1040,6 +1041,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
uart_remove_one_port(&serial8250_reg, &uart->port);

uart->port.ctrl_id = up->port.ctrl_id;
uart->port.port_id = up->port.port_id;
uart->port.iobase = up->port.iobase;
uart->port.membase = up->port.membase;
uart->port.irq = up->port.irq;
Expand Down Expand Up @@ -1202,6 +1204,7 @@ void serial8250_unregister_port(int line)
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
uart->port.type = PORT_UNKNOWN;
uart->port.dev = &serial8250_isa_devs->dev;
uart->port.port_id = line;
uart->capabilities = 0;
serial8250_init_port(uart);
serial8250_apply_quirks(uart);
Expand Down
4 changes: 1 addition & 3 deletions drivers/tty/serial/8250/8250_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
/* Port locked to synchronize UART_IER access against the console. */
lockdep_assert_held_once(&up->port.lock);

if (up->capabilities & UART_CAP_UUE)
serial_out(up, UART_IER, UART_IER_UUE);
else
Expand Down Expand Up @@ -3278,6 +3275,7 @@ void serial8250_init_port(struct uart_8250_port *up)

spin_lock_init(&port->lock);
port->ctrl_id = 0;
port->pm = NULL;
port->ops = &serial8250_pops;
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);

Expand Down
4 changes: 2 additions & 2 deletions drivers/tty/serial/fsl_lpuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,8 +1139,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
unsigned long sr = lpuart32_read(&sport->port, UARTSTAT);

if (sr & (UARTSTAT_PE | UARTSTAT_FE)) {
/* Read DR to clear the error flags */
lpuart32_read(&sport->port, UARTDATA);
/* Clear the error flags */
lpuart32_write(&sport->port, sr, UARTSTAT);

if (sr & UARTSTAT_PE)
sport->port.icount.parity++;
Expand Down
1 change: 1 addition & 0 deletions drivers/tty/serial/serial_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct device;

struct serial_ctrl_device {
struct device dev;
struct ida port_ida;
};

struct serial_port_device {
Expand Down
70 changes: 56 additions & 14 deletions drivers/tty/serial/serial_base_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <linux/container_of.h>
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
Expand All @@ -19,11 +20,25 @@

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)
{
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 = {
Expand All @@ -48,7 +63,8 @@ static int serial_base_device_init(struct uart_port *port,
struct device *parent_dev,
const struct device_type *type,
void (*release)(struct device *dev),
int id)
unsigned int ctrl_id,
unsigned int port_id)
{
device_initialize(dev);
dev->type = type;
Expand All @@ -61,12 +77,15 @@ static int serial_base_device_init(struct uart_port *port,
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 = {
.name = "ctrl",
};
if (type == &serial_port_type)
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)
{
Expand All @@ -81,6 +100,7 @@ void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev)
return;

device_del(&ctrl_dev->dev);
put_device(&ctrl_dev->dev);
}

struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
Expand All @@ -93,10 +113,12 @@ struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
if (!ctrl_dev)
return ERR_PTR(-ENOMEM);

ida_init(&ctrl_dev->port_ida);

err = serial_base_device_init(port, &ctrl_dev->dev,
parent, &serial_ctrl_type,
serial_base_ctrl_release,
port->ctrl_id);
port->ctrl_id, 0);
if (err)
goto err_put_device;

Expand All @@ -112,10 +134,6 @@ struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
return ERR_PTR(err);
}

static const struct device_type serial_port_type = {
.name = "port",
};

static void serial_base_port_release(struct device *dev)
{
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
Expand All @@ -127,16 +145,31 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,
struct serial_ctrl_device *ctrl_dev)
{
struct serial_port_device *port_dev;
int min = 0, max = -1; /* Use -1 for max to apply IDA defaults */
int err;

port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
if (!port_dev)
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,
&ctrl_dev->dev, &serial_port_type,
serial_base_port_release,
port->line);
port->ctrl_id, port->port_id);
if (err)
goto err_put_device;

Expand All @@ -150,16 +183,25 @@ struct serial_port_device *serial_base_port_add(struct uart_port *port,

err_put_device:
put_device(&port_dev->dev);
ida_free(&ctrl_dev->port_ida, port->port_id);

return ERR_PTR(err);
}

void serial_base_port_device_remove(struct serial_port_device *port_dev)
{
struct serial_ctrl_device *ctrl_dev;
struct device *parent;

if (!port_dev)
return;

parent = port_dev->dev.parent;
ctrl_dev = to_serial_base_ctrl_device(parent);

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)
Expand Down
3 changes: 2 additions & 1 deletion include/linux/serial_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ struct uart_port {
struct serial_rs485 *rs485);
int (*iso7816_config)(struct uart_port *,
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 long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */
Expand Down

0 comments on commit b320441

Please sign in to comment.