]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
serial: 8250_dw: remove clock-notifier infrastructure
authorStepan Ionichev <sozdayvek@gmail.com>
Thu, 14 May 2026 14:37:46 +0000 (19:37 +0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 May 2026 09:46:18 +0000 (11:46 +0200)
The clock notifier and matching work_struct in dw8250_data were added
in 2020 for the Baikal-T1 SoC, whose multiple UART ports share a
single reference clock and need to be informed when another consumer
re-rates that clock.

Baikal SoC support has since been removed from the kernel (see e.g.
commit 5d6c477687ae ("clk: baikal-t1: Remove not-going-to-be-supported
code for Baikal SoC") and the matching removals across bus/, mtd/,
PCI/, hwmon/, memory/). No remaining in-tree user needs the
cross-device baudclk rate-change notification path: the only
configuration that wired up the notifier was Baikal-T1's shared
reference clock topology.

Drop the now-unused clock-notifier and its deferred-update worker:

  - struct dw8250_data fields clk_notifier and clk_work,
  - the clk_to_dw8250_data() and work_to_dw8250_data() helpers,
  - the dw8250_clk_work_cb() and dw8250_clk_notifier_cb() callbacks,
  - the INIT_WORK / notifier_call setup in dw8250_probe(),
  - the clk_notifier_register() / queue_work() in dw8250_probe(),
  - the matching clk_notifier_unregister() / flush_work() in
    dw8250_remove(),
  - the stale comment in dw8250_set_termios() about the worker
    blocking,
  - the linux/notifier.h and linux/workqueue.h includes that are
    no longer used.

dw8250_set_termios() keeps calling clk_set_rate() directly, which is
all the remaining single-UART configurations require.

Signed-off-by: Stepan Ionichev <sozdayvek@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260514143746.23671-3-sozdayvek@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250_dw.c

index 2d30a164eeae0aaba644fafa247161a6a8fd8146..7920e2cb5307354c6b7c0f65fecb1fe1f7b14924 100644 (file)
 #include <linux/lockdep.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
-#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 
@@ -75,8 +73,6 @@ struct dw8250_data {
        u32                     msr_mask_off;
        struct clk              *clk;
        struct clk              *pclk;
-       struct notifier_block   clk_notifier;
-       struct work_struct      clk_work;
        struct reset_control    *rst;
 
        unsigned int            skip_autocfg:1;
@@ -91,16 +87,6 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
        return container_of(data, struct dw8250_data, data);
 }
 
-static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
-{
-       return container_of(nb, struct dw8250_data, clk_notifier);
-}
-
-static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work)
-{
-       return container_of(work, struct dw8250_data, clk_work);
-}
-
 static inline u32 dw8250_modify_msr(struct uart_port *p, unsigned int offset, u32 value)
 {
        struct dw8250_data *d = to_dw8250_data(p->private_data);
@@ -473,46 +459,6 @@ static int dw8250_handle_irq(struct uart_port *p)
        return 1;
 }
 
-static void dw8250_clk_work_cb(struct work_struct *work)
-{
-       struct dw8250_data *d = work_to_dw8250_data(work);
-       struct uart_8250_port *up;
-       unsigned long rate;
-
-       rate = clk_get_rate(d->clk);
-       if (rate <= 0)
-               return;
-
-       up = serial8250_get_port(d->data.line);
-
-       serial8250_update_uartclk(&up->port, rate);
-}
-
-static int dw8250_clk_notifier_cb(struct notifier_block *nb,
-                                 unsigned long event, void *data)
-{
-       struct dw8250_data *d = clk_to_dw8250_data(nb);
-
-       /*
-        * We have no choice but to defer the uartclk update due to two
-        * deadlocks. First one is caused by a recursive mutex lock which
-        * happens when clk_set_rate() is called from dw8250_set_termios().
-        * Second deadlock is more tricky and is caused by an inverted order of
-        * the clk and tty-port mutexes lock. It happens if clock rate change
-        * is requested asynchronously while set_termios() is executed between
-        * tty-port mutex lock and clk_set_rate() function invocation and
-        * vise-versa. Anyway if we didn't have the reference clock alteration
-        * in the dw8250_set_termios() method we wouldn't have needed this
-        * deferred event handling complication.
-        */
-       if (event == POST_RATE_CHANGE) {
-               queue_work(system_dfl_wq, &d->clk_work);
-               return NOTIFY_OK;
-       }
-
-       return NOTIFY_DONE;
-}
-
 static void
 dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 {
@@ -536,10 +482,6 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
        clk_disable_unprepare(d->clk);
        rate = clk_round_rate(d->clk, newrate);
        if (rate > 0) {
-               /*
-                * Note that any clock-notifier worker will block in
-                * serial8250_update_uartclk() until we are done.
-                */
                ret = clk_set_rate(d->clk, newrate);
                if (!ret)
                        p->uartclk = rate;
@@ -772,9 +714,6 @@ static int dw8250_probe(struct platform_device *pdev)
                return dev_err_probe(dev, PTR_ERR(data->clk),
                                     "failed to get baudclk\n");
 
-       INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
-       data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
-
        if (data->clk)
                p->uartclk = clk_get_rate(data->clk);
 
@@ -832,20 +771,6 @@ static int dw8250_probe(struct platform_device *pdev)
        if (data->data.line < 0)
                return data->data.line;
 
-       /*
-        * Some platforms may provide a reference clock shared between several
-        * devices. In this case any clock state change must be known to the
-        * UART port at least post factum.
-        */
-       if (data->clk) {
-               err = clk_notifier_register(data->clk, &data->clk_notifier);
-               if (err) {
-                       serial8250_unregister_port(data->data.line);
-                       return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
-               }
-               queue_work(system_dfl_wq, &data->clk_work);
-       }
-
        platform_set_drvdata(pdev, data);
 
        pm_runtime_enable(dev);
@@ -860,12 +785,6 @@ static void dw8250_remove(struct platform_device *pdev)
 
        pm_runtime_get_sync(dev);
 
-       if (data->clk) {
-               clk_notifier_unregister(data->clk, &data->clk_notifier);
-
-               flush_work(&data->clk_work);
-       }
-
        serial8250_unregister_port(data->data.line);
 
        pm_runtime_disable(dev);