mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-03 00:54:09 +08:00
serial: core: Move tty and serdev to be children of serial core port device
Let's move tty and serdev controller to be children of the serial core port device. This way the runtime PM usage count of a child device propagates to the serial hardware device. The tty and serdev devices are associated with a specific serial port of a serial hardware controller device, and we now have serial core hierarchy of controllers and ports. The tty device moves happily with just a change of the parent device and update of device_find_child() handling. The serdev device init needs some changes to separate the serial hardware controller device from the parent device. With this change the tty devices move under sysfs similar to this x86_64 qemu example of a diff of "find /sys -name ttyS*": /sys/class/tty/ttyS0 /sys/class/tty/ttyS3 /sys/class/tty/ttyS1 -/sys/devices/pnp0/00:04/tty/ttyS0 -/sys/devices/platform/serial8250/tty/ttyS2 -/sys/devices/platform/serial8250/tty/ttyS3 -/sys/devices/platform/serial8250/tty/ttyS1 +/sys/devices/pnp0/00:04/00:04:0/00:04:0.0/tty/ttyS0 +/sys/devices/platform/serial8250/serial8250:0/serial8250:0.3/tty/ttyS3 +/sys/devices/platform/serial8250/serial8250:0/serial8250:0.1/tty/ttyS1 +/sys/devices/platform/serial8250/serial8250:0/serial8250:0.2/tty/ttyS2 If a serdev device is used instead of a tty, it moves in a similar way. Suggested-by: Johan Hovold <johan@kernel.org> Cc: Maximilian Luz <luzmaximilian@gmail.com> Cc: Rob Herring <robh@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Link: https://lore.kernel.org/r/20231113080758.30346-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
39ff20f5fd
commit
b286f4e87e
@ -468,6 +468,7 @@ EXPORT_SYMBOL_GPL(serdev_device_alloc);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* serdev_controller_alloc() - Allocate a new serdev controller
|
* serdev_controller_alloc() - Allocate a new serdev controller
|
||||||
|
* @host: serial port hardware controller device
|
||||||
* @parent: parent device
|
* @parent: parent device
|
||||||
* @size: size of private data
|
* @size: size of private data
|
||||||
*
|
*
|
||||||
@ -476,8 +477,9 @@ EXPORT_SYMBOL_GPL(serdev_device_alloc);
|
|||||||
* The allocated private data region may be accessed via
|
* The allocated private data region may be accessed via
|
||||||
* serdev_controller_get_drvdata()
|
* serdev_controller_get_drvdata()
|
||||||
*/
|
*/
|
||||||
struct serdev_controller *serdev_controller_alloc(struct device *parent,
|
struct serdev_controller *serdev_controller_alloc(struct device *host,
|
||||||
size_t size)
|
struct device *parent,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
struct serdev_controller *ctrl;
|
struct serdev_controller *ctrl;
|
||||||
int id;
|
int id;
|
||||||
@ -502,7 +504,8 @@ struct serdev_controller *serdev_controller_alloc(struct device *parent,
|
|||||||
ctrl->dev.type = &serdev_ctrl_type;
|
ctrl->dev.type = &serdev_ctrl_type;
|
||||||
ctrl->dev.bus = &serdev_bus_type;
|
ctrl->dev.bus = &serdev_bus_type;
|
||||||
ctrl->dev.parent = parent;
|
ctrl->dev.parent = parent;
|
||||||
device_set_node(&ctrl->dev, dev_fwnode(parent));
|
ctrl->host = host;
|
||||||
|
device_set_node(&ctrl->dev, dev_fwnode(host));
|
||||||
serdev_controller_set_drvdata(ctrl, &ctrl[1]);
|
serdev_controller_set_drvdata(ctrl, &ctrl[1]);
|
||||||
|
|
||||||
dev_set_name(&ctrl->dev, "serial%d", id);
|
dev_set_name(&ctrl->dev, "serial%d", id);
|
||||||
@ -665,7 +668,7 @@ static int acpi_serdev_check_resources(struct serdev_controller *ctrl,
|
|||||||
acpi_get_parent(adev->handle, &lookup.controller_handle);
|
acpi_get_parent(adev->handle, &lookup.controller_handle);
|
||||||
|
|
||||||
/* Make sure controller and ResourceSource handle match */
|
/* Make sure controller and ResourceSource handle match */
|
||||||
if (!device_match_acpi_handle(ctrl->dev.parent, lookup.controller_handle))
|
if (!device_match_acpi_handle(ctrl->host, lookup.controller_handle))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -730,7 +733,7 @@ static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
|||||||
bool skip;
|
bool skip;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!has_acpi_companion(ctrl->dev.parent))
|
if (!has_acpi_companion(ctrl->host))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -739,7 +742,7 @@ static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
|||||||
* succeed in this case, so that the proper serdev devices can be
|
* succeed in this case, so that the proper serdev devices can be
|
||||||
* added "manually" later.
|
* added "manually" later.
|
||||||
*/
|
*/
|
||||||
ret = acpi_quirk_skip_serdev_enumeration(ctrl->dev.parent, &skip);
|
ret = acpi_quirk_skip_serdev_enumeration(ctrl->host, &skip);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (skip)
|
if (skip)
|
||||||
|
@ -274,6 +274,7 @@ static const struct serdev_controller_ops ctrl_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct device *serdev_tty_port_register(struct tty_port *port,
|
struct device *serdev_tty_port_register(struct tty_port *port,
|
||||||
|
struct device *host,
|
||||||
struct device *parent,
|
struct device *parent,
|
||||||
struct tty_driver *drv, int idx)
|
struct tty_driver *drv, int idx)
|
||||||
{
|
{
|
||||||
@ -284,7 +285,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
|
|||||||
if (!port || !drv || !parent)
|
if (!port || !drv || !parent)
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
ctrl = serdev_controller_alloc(parent, sizeof(struct serport));
|
ctrl = serdev_controller_alloc(host, parent, sizeof(struct serport));
|
||||||
if (!ctrl)
|
if (!ctrl)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
serport = serdev_controller_get_drvdata(ctrl);
|
serport = serdev_controller_get_drvdata(ctrl);
|
||||||
|
@ -2342,7 +2342,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
|||||||
|
|
||||||
mutex_lock(&port->mutex);
|
mutex_lock(&port->mutex);
|
||||||
|
|
||||||
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
|
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
|
||||||
if (tty_dev && device_may_wakeup(tty_dev)) {
|
if (tty_dev && device_may_wakeup(tty_dev)) {
|
||||||
enable_irq_wake(uport->irq);
|
enable_irq_wake(uport->irq);
|
||||||
put_device(tty_dev);
|
put_device(tty_dev);
|
||||||
@ -2423,7 +2423,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
|||||||
|
|
||||||
mutex_lock(&port->mutex);
|
mutex_lock(&port->mutex);
|
||||||
|
|
||||||
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
|
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
|
||||||
if (!uport->suspended && device_may_wakeup(tty_dev)) {
|
if (!uport->suspended && device_may_wakeup(tty_dev)) {
|
||||||
if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq))))
|
if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq))))
|
||||||
disable_irq_wake(uport->irq);
|
disable_irq_wake(uport->irq);
|
||||||
@ -3153,7 +3153,8 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u
|
|||||||
* setserial to be used to alter this port's parameters.
|
* setserial to be used to alter this port's parameters.
|
||||||
*/
|
*/
|
||||||
tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
|
tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
|
||||||
uport->line, uport->dev, port, uport->tty_groups);
|
uport->line, uport->dev, &uport->port_dev->dev, port,
|
||||||
|
uport->tty_groups);
|
||||||
if (!IS_ERR(tty_dev)) {
|
if (!IS_ERR(tty_dev)) {
|
||||||
device_set_wakeup_capable(tty_dev, 1);
|
device_set_wakeup_capable(tty_dev, 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,7 +171,8 @@ EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
|
|||||||
* @port: tty_port of the device
|
* @port: tty_port of the device
|
||||||
* @driver: tty_driver for this device
|
* @driver: tty_driver for this device
|
||||||
* @index: index of the tty
|
* @index: index of the tty
|
||||||
* @device: parent if exists, otherwise NULL
|
* @host: serial port hardware device
|
||||||
|
* @parent: parent if exists, otherwise NULL
|
||||||
* @drvdata: driver data for the device
|
* @drvdata: driver data for the device
|
||||||
* @attr_grp: attribute group for the device
|
* @attr_grp: attribute group for the device
|
||||||
*
|
*
|
||||||
@ -180,20 +181,20 @@ EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
|
|||||||
*/
|
*/
|
||||||
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
||||||
struct tty_driver *driver, unsigned index,
|
struct tty_driver *driver, unsigned index,
|
||||||
struct device *device, void *drvdata,
|
struct device *host, struct device *parent, void *drvdata,
|
||||||
const struct attribute_group **attr_grp)
|
const struct attribute_group **attr_grp)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
tty_port_link_device(port, driver, index);
|
tty_port_link_device(port, driver, index);
|
||||||
|
|
||||||
dev = serdev_tty_port_register(port, device, driver, index);
|
dev = serdev_tty_port_register(port, host, parent, driver, index);
|
||||||
if (PTR_ERR(dev) != -ENODEV) {
|
if (PTR_ERR(dev) != -ENODEV) {
|
||||||
/* Skip creating cdev if we registered a serdev device */
|
/* Skip creating cdev if we registered a serdev device */
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tty_register_device_attr(driver, index, device, drvdata,
|
return tty_register_device_attr(driver, index, parent, drvdata,
|
||||||
attr_grp);
|
attr_grp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
|
EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
|
||||||
@ -203,17 +204,18 @@ EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
|
|||||||
* @port: tty_port of the device
|
* @port: tty_port of the device
|
||||||
* @driver: tty_driver for this device
|
* @driver: tty_driver for this device
|
||||||
* @index: index of the tty
|
* @index: index of the tty
|
||||||
* @device: parent if exists, otherwise NULL
|
* @host: serial port hardware controller device
|
||||||
|
* @parent: parent if exists, otherwise NULL
|
||||||
*
|
*
|
||||||
* Register a serdev or tty device depending on if the parent device has any
|
* Register a serdev or tty device depending on if the parent device has any
|
||||||
* defined serdev clients or not.
|
* defined serdev clients or not.
|
||||||
*/
|
*/
|
||||||
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
||||||
struct tty_driver *driver, unsigned index,
|
struct tty_driver *driver, unsigned index,
|
||||||
struct device *device)
|
struct device *host, struct device *parent)
|
||||||
{
|
{
|
||||||
return tty_port_register_device_attr_serdev(port, driver, index,
|
return tty_port_register_device_attr_serdev(port, driver, index,
|
||||||
device, NULL, NULL);
|
host, parent, NULL, NULL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
|
EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
|
||||||
|
|
||||||
|
@ -99,12 +99,14 @@ struct serdev_controller_ops {
|
|||||||
/**
|
/**
|
||||||
* struct serdev_controller - interface to the serdev controller
|
* struct serdev_controller - interface to the serdev controller
|
||||||
* @dev: Driver model representation of the device.
|
* @dev: Driver model representation of the device.
|
||||||
|
* @host: Serial port hardware controller device
|
||||||
* @nr: number identifier for this controller/bus.
|
* @nr: number identifier for this controller/bus.
|
||||||
* @serdev: Pointer to slave device for this controller.
|
* @serdev: Pointer to slave device for this controller.
|
||||||
* @ops: Controller operations.
|
* @ops: Controller operations.
|
||||||
*/
|
*/
|
||||||
struct serdev_controller {
|
struct serdev_controller {
|
||||||
struct device dev;
|
struct device dev;
|
||||||
|
struct device *host;
|
||||||
unsigned int nr;
|
unsigned int nr;
|
||||||
struct serdev_device *serdev;
|
struct serdev_device *serdev;
|
||||||
const struct serdev_controller_ops *ops;
|
const struct serdev_controller_ops *ops;
|
||||||
@ -167,7 +169,9 @@ struct serdev_device *serdev_device_alloc(struct serdev_controller *);
|
|||||||
int serdev_device_add(struct serdev_device *);
|
int serdev_device_add(struct serdev_device *);
|
||||||
void serdev_device_remove(struct serdev_device *);
|
void serdev_device_remove(struct serdev_device *);
|
||||||
|
|
||||||
struct serdev_controller *serdev_controller_alloc(struct device *, size_t);
|
struct serdev_controller *serdev_controller_alloc(struct device *host,
|
||||||
|
struct device *parent,
|
||||||
|
size_t size);
|
||||||
int serdev_controller_add(struct serdev_controller *);
|
int serdev_controller_add(struct serdev_controller *);
|
||||||
void serdev_controller_remove(struct serdev_controller *);
|
void serdev_controller_remove(struct serdev_controller *);
|
||||||
|
|
||||||
@ -311,11 +315,13 @@ struct tty_driver;
|
|||||||
|
|
||||||
#ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT
|
#ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT
|
||||||
struct device *serdev_tty_port_register(struct tty_port *port,
|
struct device *serdev_tty_port_register(struct tty_port *port,
|
||||||
|
struct device *host,
|
||||||
struct device *parent,
|
struct device *parent,
|
||||||
struct tty_driver *drv, int idx);
|
struct tty_driver *drv, int idx);
|
||||||
int serdev_tty_port_unregister(struct tty_port *port);
|
int serdev_tty_port_unregister(struct tty_port *port);
|
||||||
#else
|
#else
|
||||||
static inline struct device *serdev_tty_port_register(struct tty_port *port,
|
static inline struct device *serdev_tty_port_register(struct tty_port *port,
|
||||||
|
struct device *host,
|
||||||
struct device *parent,
|
struct device *parent,
|
||||||
struct tty_driver *drv, int idx)
|
struct tty_driver *drv, int idx)
|
||||||
{
|
{
|
||||||
|
@ -149,10 +149,10 @@ struct device *tty_port_register_device_attr(struct tty_port *port,
|
|||||||
const struct attribute_group **attr_grp);
|
const struct attribute_group **attr_grp);
|
||||||
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
||||||
struct tty_driver *driver, unsigned index,
|
struct tty_driver *driver, unsigned index,
|
||||||
struct device *device);
|
struct device *host, struct device *parent);
|
||||||
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
|
||||||
struct tty_driver *driver, unsigned index,
|
struct tty_driver *driver, unsigned index,
|
||||||
struct device *device, void *drvdata,
|
struct device *host, struct device *parent, void *drvdata,
|
||||||
const struct attribute_group **attr_grp);
|
const struct attribute_group **attr_grp);
|
||||||
void tty_port_unregister_device(struct tty_port *port,
|
void tty_port_unregister_device(struct tty_port *port,
|
||||||
struct tty_driver *driver, unsigned index);
|
struct tty_driver *driver, unsigned index);
|
||||||
|
Loading…
Reference in New Issue
Block a user