From 0a15f43b92ddaa2fdb476891a12ac2e207c7fcd2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 Jan 2026 13:58:21 +0100 Subject: [PATCH] Revert "tty: tty_port: add workqueue to flip TTY buffer" This reverts commit d000422a46aad32217cf1be747eb61d641baae2f. It is reported by many to cause boot failures, so must be reverted. Cc: Xin Zhao Cc: Jiri Slaby Link: https://lore.kernel.org/r/d1942304-ee30-478d-90fb-279519f3ae81@samsung.com Reported-by: Marek Szyprowski Reported-by: Tommaso Merciai Reported-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 14 ++++---------- drivers/tty/tty_buffer.c | 8 ++++---- drivers/tty/tty_io.c | 21 +-------------------- drivers/tty/tty_port.c | 23 ----------------------- include/linux/tty_buffer.h | 1 - include/linux/tty_driver.h | 7 ------- include/linux/tty_port.h | 13 ------------- 7 files changed, 9 insertions(+), 78 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 1f17575f8fe0c..6120d827a7977 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -403,8 +403,6 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, o_tty->link = tty; tty_port_init(ports[0]); tty_port_init(ports[1]); - tty_port_link_wq(ports[0], system_dfl_wq); - tty_port_link_wq(ports[1], system_dfl_wq); tty_buffer_set_limit(ports[0], 8192); tty_buffer_set_limit(ports[1], 8192); o_tty->port = ports[0]; @@ -534,16 +532,14 @@ static void __init legacy_pty_init(void) pty_driver = tty_alloc_driver(legacy_count, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_ALLOC | - TTY_DRIVER_CUSTOM_WORKQUEUE); + TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pty_driver)) panic("Couldn't allocate pty driver"); pty_slave_driver = tty_alloc_driver(legacy_count, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_ALLOC | - TTY_DRIVER_CUSTOM_WORKQUEUE); + TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pty_slave_driver)) panic("Couldn't allocate pty slave driver"); @@ -853,8 +849,7 @@ static void __init unix98_pty_init(void) TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM | - TTY_DRIVER_DYNAMIC_ALLOC | - TTY_DRIVER_CUSTOM_WORKQUEUE); + TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(ptm_driver)) panic("Couldn't allocate Unix98 ptm driver"); pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX, @@ -862,8 +857,7 @@ static void __init unix98_pty_init(void) TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM | - TTY_DRIVER_DYNAMIC_ALLOC | - TTY_DRIVER_CUSTOM_WORKQUEUE); + TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pts_driver)) panic("Couldn't allocate Unix98 pts driver"); diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 86e1e7178e900..1a5673acd9b10 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -76,7 +76,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) mutex_unlock(&buf->lock); if (restart) - queue_work(buf->flip_wq, &buf->work); + queue_work(system_dfl_wq, &buf->work); } EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive); @@ -530,7 +530,7 @@ void tty_flip_buffer_push(struct tty_port *port) struct tty_bufhead *buf = &port->buf; tty_flip_buffer_commit(buf->tail); - queue_work(buf->flip_wq, &buf->work); + queue_work(system_dfl_wq, &buf->work); } EXPORT_SYMBOL(tty_flip_buffer_push); @@ -560,7 +560,7 @@ int tty_insert_flip_string_and_push_buffer(struct tty_port *port, tty_flip_buffer_commit(buf->tail); spin_unlock_irqrestore(&port->lock, flags); - queue_work(buf->flip_wq, &buf->work); + queue_work(system_dfl_wq, &buf->work); return size; } @@ -613,7 +613,7 @@ void tty_buffer_set_lock_subclass(struct tty_port *port) bool tty_buffer_restart_work(struct tty_port *port) { - return queue_work(port->buf.flip_wq, &port->buf.work); + return queue_work(system_dfl_wq, &port->buf.work); } bool tty_buffer_cancel_work(struct tty_port *port) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d64fb08baa179..e2d92cf70eb78 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3446,23 +3446,10 @@ int tty_register_driver(struct tty_driver *driver) if (error < 0) goto err; - if (!(driver->flags & TTY_DRIVER_CUSTOM_WORKQUEUE)) { - driver->flip_wq = alloc_workqueue("%s-flip-wq", WQ_UNBOUND | WQ_SYSFS, - 0, driver->name); - if (!driver->flip_wq) { - error = -ENOMEM; - goto err_unreg_char; - } - for (i = 0; i < driver->num; i++) { - if (driver->ports[i]) - tty_port_link_driver_wq(driver->ports[i], driver); - } - } - if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) { error = tty_cdev_add(driver, dev, 0, driver->num); if (error) - goto err_destroy_wq; + goto err_unreg_char; } scoped_guard(mutex, &tty_mutex) @@ -3488,10 +3475,6 @@ err_unreg_devs: scoped_guard(mutex, &tty_mutex) list_del(&driver->tty_drivers); -err_destroy_wq: - if (!(driver->flags & TTY_DRIVER_CUSTOM_WORKQUEUE)) - destroy_workqueue(driver->flip_wq); - err_unreg_char: unregister_chrdev_region(dev, driver->num); err: @@ -3511,8 +3494,6 @@ void tty_unregister_driver(struct tty_driver *driver) driver->num); scoped_guard(mutex, &tty_mutex) list_del(&driver->tty_drivers); - if (!(driver->flags & TTY_DRIVER_CUSTOM_WORKQUEUE)) - destroy_workqueue(driver->flip_wq); } EXPORT_SYMBOL(tty_unregister_driver); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 611f878149f8a..fe67c5cb0a3f0 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -99,26 +99,6 @@ void tty_port_init(struct tty_port *port) } EXPORT_SYMBOL(tty_port_init); -/** - * tty_port_link_wq - link tty_port and flip workqueue - * @port: tty_port of the device - * @flip_wq: workqueue to queue flip buffer work on - * - * When %TTY_DRIVER_CUSTOM_WORKQUEUE is used, every tty_port shall be linked to - * a workqueue manually by this function, otherwise tty_flip_buffer_push() will - * see %NULL flip_wq pointer on queue_work. - * When %TTY_DRIVER_CUSTOM_WORKQUEUE is NOT used, the function can be used to - * link a certain port to a specific workqueue, instead of using the workqueue - * allocated in tty_register_driver(). - * - * Note that TTY port API will NOT destroy the workqueue. - */ -void tty_port_link_wq(struct tty_port *port, struct workqueue_struct *flip_wq) -{ - port->buf.flip_wq = flip_wq; -} -EXPORT_SYMBOL_GPL(tty_port_link_wq); - /** * tty_port_link_device - link tty and tty_port * @port: tty_port of the device @@ -177,7 +157,6 @@ struct device *tty_port_register_device_attr(struct tty_port *port, const struct attribute_group **attr_grp) { tty_port_link_device(port, driver, index); - tty_port_link_driver_wq(port, driver); return tty_register_device_attr(driver, index, device, drvdata, attr_grp); } @@ -204,7 +183,6 @@ struct device *tty_port_register_device_attr_serdev(struct tty_port *port, struct device *dev; tty_port_link_device(port, driver, index); - tty_port_link_driver_wq(port, driver); dev = serdev_tty_port_register(port, host, parent, driver, index); if (PTR_ERR(dev) != -ENODEV) { @@ -725,7 +703,6 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver, struct tty_struct *tty) { tty->port = port; - tty_port_link_driver_wq(port, driver); return tty_standard_install(driver, tty); } EXPORT_SYMBOL_GPL(tty_port_install); diff --git a/include/linux/tty_buffer.h b/include/linux/tty_buffer.h index 48adcb0e8ff39..31125e3be3c55 100644 --- a/include/linux/tty_buffer.h +++ b/include/linux/tty_buffer.h @@ -34,7 +34,6 @@ static inline u8 *flag_buf_ptr(struct tty_buffer *b, unsigned int ofs) struct tty_bufhead { struct tty_buffer *head; /* Queue head */ - struct workqueue_struct *flip_wq; struct work_struct work; struct mutex lock; atomic_t priority; diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 9c65854f7d94e..188ee9b768eb6 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -69,10 +69,6 @@ struct serial_struct; * Do not create numbered ``/dev`` nodes. For example, create * ``/dev/ttyprintk`` and not ``/dev/ttyprintk0``. Applicable only when a * driver for a single tty device is being allocated. - * - * @TTY_DRIVER_CUSTOM_WORKQUEUE: - * Do not create workqueue when tty_register_driver(). When set, flip - * buffer workqueue shall be set by tty_port_link_wq() for every port. */ enum tty_driver_flag { TTY_DRIVER_INSTALLED = BIT(0), @@ -83,7 +79,6 @@ enum tty_driver_flag { TTY_DRIVER_HARDWARE_BREAK = BIT(5), TTY_DRIVER_DYNAMIC_ALLOC = BIT(6), TTY_DRIVER_UNNUMBERED_NODE = BIT(7), - TTY_DRIVER_CUSTOM_WORKQUEUE = BIT(8), }; enum tty_driver_type { @@ -511,7 +506,6 @@ struct tty_operations { * @flags: tty driver flags (%TTY_DRIVER_) * @proc_entry: proc fs entry, used internally * @other: driver of the linked tty; only used for the PTY driver - * @flip_wq: workqueue to queue flip buffer work on * @ttys: array of active &struct tty_struct, set by tty_standard_install() * @ports: array of &struct tty_port; can be set during initialization by * tty_port_link_device() and similar @@ -545,7 +539,6 @@ struct tty_driver { unsigned long flags; struct proc_dir_entry *proc_entry; struct tty_driver *other; - struct workqueue_struct *flip_wq; /* * Pointer to the tty data structures diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h index c1b87f3c56034..660c254f1efe5 100644 --- a/include/linux/tty_port.h +++ b/include/linux/tty_port.h @@ -138,7 +138,6 @@ struct tty_port { kernel */ void tty_port_init(struct tty_port *port); -void tty_port_link_wq(struct tty_port *port, struct workqueue_struct *flip_wq); void tty_port_link_device(struct tty_port *port, struct tty_driver *driver, unsigned index); struct device *tty_port_register_device(struct tty_port *port, @@ -166,18 +165,6 @@ static inline struct tty_port *tty_port_get(struct tty_port *port) return NULL; } -/* - * Never overwrite the workqueue set by tty_port_link_wq(). - * No effect when %TTY_DRIVER_CUSTOM_WORKQUEUE is set, as driver->flip_wq is - * %NULL. - */ -static inline void tty_port_link_driver_wq(struct tty_port *port, - struct tty_driver *driver) -{ - if (!port->buf.flip_wq) - port->buf.flip_wq = driver->flip_wq; -} - /* If the cts flow control is enabled, return true. */ static inline bool tty_port_cts_enabled(const struct tty_port *port) { -- 2.47.3