On Wed, 7 Dec 2022, Tony Lindgren wrote: > We want to enable runtime PM for serial port device drivers in a generic > way. To do this, we want to have the serial core layer manage the > registered physical serial controller devices. > > To do this, let's set up a struct device for the serial core controller > as suggested by Greg and Jiri. The serial core controller devices are > children of the physical serial port device. The serial core controller > device is needed to support multiple different kind of ports connected > to single physical serial port device. > > Let's also set up a struct device for the serial core port. The serial > core port instances are children of the serial core controller device. > With the serial core port device we can now flush pending TX on the > runtime PM resume as suggested by Johan. > > Suggested-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > Suggested-by: Jiri Slaby <jirislaby@xxxxxxxxxx> > Suggested-by: Johan Hovold <johan@xxxxxxxxxx> > Signed-off-by: Tony Lindgren <tony@xxxxxxxxxxx> > --- > > Changes since v3: > > - Simplify things by adding a serial core control device as the child of > the physical serial port as suggested by Jiri > > - Drop the tinkering of the physical serial port device for runtime PM. > Serial core just needs to manage port->port_dev with the addition of > the serial core control device and the device hierarchy will keep the > pysical serial port device enabled as needed > > - Simplify patch description with all the runtime PM tinkering gone > > - Coding style improvments as noted by Andy > > - Post as a single RFC patch as we're close to the merge window > > Changes since v2: > > - Make each serial port a proper device as suggested by Greg. This is > a separate patch that flushes the TX on runtime PM resume > > Changes since v1: > > - Use kref as suggested by Andy > > - Fix memory leak on error as noted by Andy > > - Use use unsigned char for supports_autosuspend as suggested by Andy > > - Coding style improvments as suggested by Andy > > --- > + ret = serial_core_add_one_port(drv, port); > + if (ret) > + return ret; > + > + mutex_lock(&port_mutex); > + > + /* Inititalize a serial core controller device if needed */ > + ctrl_dev = serial_core_ctrl_find(drv, port->dev, port->ctrl_id); > + if (!ctrl_dev) { > + ctrl_dev = serial_core_ctrl_device_add(port); > + if (!ctrl_dev) > + goto err_remove_port; > + allocated = true; > + } > + > + /* Initialize a serial core port device */ > + ret = serial_core_port_device_add(ctrl_dev, port); How is ->port_dev supposed to work here? ->port_dev is not set until in serial_core_port_device_add() but you made serial_core_add_one_port() call before that. -- i. > + if (ret) > + goto err_del_ctrl_dev; > + > + mutex_unlock(&port_mutex); > + > + return 0; > + > +err_del_ctrl_dev: > + if (allocated) > + platform_device_del(to_platform_device(ctrl_dev)); > + > +err_remove_port: > + mutex_unlock(&port_mutex); > + > + return serial_core_remove_one_port(drv, port); > +} > +EXPORT_SYMBOL_NS(serial_core_register_port, SERIAL_CORE);