Maxime Ripard cb1b1dd962 clk: Set req_rate on reparenting
If a non-rate clock started by default with a parent that never
registered, core->req_rate will be 0. The expectation is that whenever
the parent will be registered, req_rate will be updated with the new
value that has just been computed.

However, if that clock is a mux, clk_set_parent() can also make that
clock no longer orphan. In this case however, we never update req_rate.

The natural solution to this would be to update core->rate and
core->req_rate in clk_reparent() by calling clk_recalc().

However, this doesn't work in all cases. Indeed, clk_recalc() is called
by __clk_set_parent_before(), __clk_set_parent() and
clk_core_reparent(). Both __clk_set_parent_before() and __clk_set_parent
will call clk_recalc() with the enable_lock taken through a call to
clk_enable_lock(), the underlying locking primitive being a spinlock.

clk_recalc() calls the backing driver .recalc_rate hook, and that
implementation might sleep if the underlying device uses a bus with
accesses that might sleep, such as i2c.

In such a situation, we would end up sleeping while holding a spinlock,
and thus in an atomic section.

In order to work around this, we can move the core->rate and
core->req_rate update to the clk_recalc() calling sites, after the
enable_lock has been released if it was taken.

The only situation that could still be problematic is the
clk_core_reparent() -> clk_reparent() case that doesn't have any
locking. clk_core_reparent() is itself called by clk_hw_reparent(),
which is then called by 4 drivers:

  * clk-stm32mp1.c, stm32/clk-stm32-core.c and tegra/clk-tegra210-emc.c
    use it in their set_parent implementation. The set_parent hook is
    only called by __clk_set_parent() and clk_change_rate(), both of
    them calling it without the enable_lock taken.

  * clk/tegra/clk-tegra124-emc.c calls it as part of its set_rate
    implementation. set_rate is only called by clk_change_rate(), again
    without the enable_lock taken.

In both cases we can't end up in a situation where the clk_hw_reparent()
caller would hold a spinlock, so it seems like this is a good
workaround.

Let's also add some unit tests to make sure we cover the original bug.

Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # imx8mp
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> # exynos4210, meson g12b
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220816112530.1837489-14-maxime@cerno.tech
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Tested-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
2022-09-15 09:31:09 -07:00
2022-09-15 09:31:09 -07:00
2022-08-12 09:07:33 -07:00
2022-08-14 15:50:18 -07:00

Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``.  The formatted documentation can also be read online at:

    https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.
Description
No description provided
Readme 3.4 GiB
Languages
C 97%
Assembly 1%
Shell 0.6%
Rust 0.5%
Python 0.4%
Other 0.3%