On Mon, Dec 23, 2019 at 07:06:51AM -0500, Greg KH wrote: > On Fri, Dec 20, 2019 at 10:08:03AM -0800, Linus Torvalds wrote: > > On Thu, Dec 19, 2019 at 11:07 PM Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx> wrote: > > > > > > The last tty core fix should resolve a long-standing bug with a race > > > at port creation time that some people would see, and Sudip finally > > > tracked down. > > > > Hmm, looks good. But it makes me wonder if we should now try to remove > > the second call to tty_port_link_device()? > > > > Now we have a number of helpers that do that tty_port_link_device() > > call for the driver (eg tty_port_register_device_attr_serdev(), > > tty_port_register_device_attr(), and the just added > > uart_add_one_port()). > > > > But we also have drivers doing it by hand, and presumably we now have > > drivers that do it through multiple paths? I guess it's harmless, but > > it feels a bit odd. No? > > It does. I'll try to look at this after the holidays unless Sudip beats > me to it. The second call to tty_port_link_device() is in tty_port_register_device_attr_serdev() and tty_port_register_device_attr() is being called from many other places apart from uart_add_one_port(). The attached patch should be safe. I will test and send it properly unless someone objects to it. -- Regards Sudip
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 7c2782785736..09df885442ae 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2858,7 +2858,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) * setserial to be used to alter this port's parameters. */ tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver, - uport->line, uport->dev, port, uport->tty_groups); + uport->line, uport->dev, port, uport->tty_groups, + false); if (!IS_ERR(tty_dev)) { device_set_wakeup_capable(tty_dev, 1); } else { diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 5023c85ebc6e..dc66543fa2c3 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -152,11 +152,12 @@ EXPORT_SYMBOL_GPL(tty_port_register_device_attr); struct device *tty_port_register_device_attr_serdev(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device, void *drvdata, - const struct attribute_group **attr_grp) + const struct attribute_group **attr_grp, bool link) { struct device *dev; - tty_port_link_device(port, driver, index); + if (link) + tty_port_link_device(port, driver, index); dev = serdev_tty_port_register(port, device, driver, index); if (PTR_ERR(dev) != -ENODEV) { @@ -184,7 +185,7 @@ struct device *tty_port_register_device_serdev(struct tty_port *port, struct device *device) { return tty_port_register_device_attr_serdev(port, driver, index, - device, NULL, NULL); + device, NULL, NULL, true); } EXPORT_SYMBOL_GPL(tty_port_register_device_serdev); diff --git a/include/linux/tty.h b/include/linux/tty.h index bfa4e2ee94a9..7f2ad47ecf88 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -587,7 +587,7 @@ extern struct device *tty_port_register_device_serdev(struct tty_port *port, extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device, void *drvdata, - const struct attribute_group **attr_grp); + const struct attribute_group **attr_grp, bool link); extern void tty_port_unregister_device(struct tty_port *port, struct tty_driver *driver, unsigned index); extern int tty_port_alloc_xmit_buf(struct tty_port *port);