summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2023-08-11 13:36:45 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-08-11 21:19:22 +0200
commit04c7f60ca477ffbf7b7910320482335050f0d23a (patch)
treea3e6f4dfb824714970e71c25b6d1f864033b0c97
parent3d9e6f556e235ddcdc9f73600fdd46fe1736b090 (diff)
serial: core: Fix serial core port id, including multiport devices
We want to fix the serial core port DEVNAME to use a port id of the hardware specific controller port instance instead of the port->line. For example, the 8250 driver sets up a number of serial8250 ports initially that can be inherited by the hardware specific driver. At that the port->line no longer decribes the port's relation to the serial core controller instance. Let's fix the issue by assigning port->port_id for each serial core controller port instance. Fixes: 7d695d83767c ("serial: core: Fix serial_base_match() after fixing controller port name") Tested-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Dhruva Gole <d-gole@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20230811103648.2826-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/serial_base.h1
-rw-r--r--drivers/tty/serial/serial_base_bus.c28
2 files changed, 28 insertions, 1 deletions
diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h
index 9faac0ff6b89..c74c548f0db6 100644
--- a/drivers/tty/serial/serial_base.h
+++ b/drivers/tty/serial/serial_base.h
@@ -16,6 +16,7 @@ struct device;
struct serial_ctrl_device {
struct device dev;
+ struct ida port_ida;
};
struct serial_port_device {
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
index e446c57e845a..3dfcf20c4eb6 100644
--- a/drivers/tty/serial/serial_base_bus.c
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -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>
@@ -112,6 +113,8 @@ 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,
@@ -142,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->ctrl_id, port->line);
+ port->ctrl_id, port->port_id);
if (err)
goto err_put_device;
@@ -165,16 +183,24 @@ 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);
}