clk_prepare() and clk_prepare_enable

Problem introduction

[ 7898.374645] ------------[ cut here ]------------
[ 7898.374837] WARNING: CPU: 2 PID: 1517 at drivers/clk/clk.c:730 clk_core_enable+0x94/0x)
[ 7898.375021] Modules linked in: timer(O+) [last unloaded: timer]
[ 7898.375285] CPU: 2 PID: 1517 Comm: insmod Tainted: G        W  O    4.4.0 #3
[ 7898.380949] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 7898.387084] [<c00160ec>] (unwind_backtrace) from [<c0012e08>] (show_stack+0x10/0x14)
[ 7898.394786] [<c0012e08>] (show_stack) from [<c01f6bd8>] (dump_stack+0x80/0xc0)
[ 7898.401947] [<c01f6bd8>] (dump_stack) from [<c00235c8>] (warn_slowpath_common+0x80/0xb)
[ 7898.410016] [<c00235c8>] (warn_slowpath_common) from [<c0023694>] (warn_slowpath_null+)
[ 7898.418781] [<c0023694>] (warn_slowpath_null) from [<c04092c4>] (clk_core_enable+0x94/)
[ 7898.427116] [<c04092c4>] (clk_core_enable) from [<c04095e0>] (clk_enable+0x1c/0x38)
[ 7898.434760] [<c04095e0>] (clk_enable) from [<bf02c07c>] (timer3_probe+0x5c/0x15c [time)
[ 7898.442921] [<bf02c07c>] (timer3_probe [timer]) from [<c02c58c4>] (platform_drv_probe+)
[ 7898.451680] [<c02c58c4>] (platform_drv_probe) from [<c02c3f54>] (driver_probe_device+0)
[ 7898.460532] [<c02c3f54>] (driver_probe_device) from [<c02c40a0>] (__driver_attach+0x8c)
[ 7898.468959] [<c02c40a0>] (__driver_attach) from [<c02c247c>] (bus_for_each_dev+0x60/0x)
[ 7898.477115] [<c02c247c>] (bus_for_each_dev) from [<c02c366c>] (bus_add_driver+0x1a0/0x)
[ 7898.485358] [<c02c366c>] (bus_add_driver) from [<c02c4874>] (driver_register+0x78/0xf8)
[ 7898.493346] [<c02c4874>] (driver_register) from [<bf02c18c>] (timer_init+0x10/0x3c [ti)
[ 7898.501681] [<bf02c18c>] (timer_init [timer]) from [<c0009774>] (do_one_initcall+0x90/)
[ 7898.510100] [<c0009774>] (do_one_initcall) from [<c0098050>] (do_init_module+0x60/0x34)
[ 7898.518172] [<c0098050>] (do_init_module) from [<c008bef0>] (load_module+0x1b3c/0x1d68)
[ 7898.526153] [<c008bef0>] (load_module) from [<c008c1f0>] (SyS_init_module+0xd4/0x144)
[ 7898.533967] [<c008c1f0>] (SyS_init_module) from [<c000f600>] (ret_fast_syscall+0x0/0x3)
[ 7898.542031] ---[ end trace 655de26992d22f14 ]---
[ 7898.546682] ret:-108

Recent write driver ret=clk_enable(clk) error, traceable reasons:
http://blog.csdn.net/qq_33160790/article/details/79354855
108 corresponds to ESHUTDOWN, so the error is due to

Later, refer to the information, call clk_prepare before using clk_enable, or use clk_prepare_enable API.

clk_prepare()and clk_prepare_enable

/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
static inline int clk_prepare_enable(struct clk *clk)
{
        int ret;

        ret = clk_prepare(clk);
        if (ret)
                return ret;
        ret = clk_enable(clk);
        if (ret)        
                clk_unprepare(clk);

        return ret;
}

Clearly, clk_prepare_enable encapsulates clk_prepare and clk_enable together.
There was no clk_prepare API in the early drivers, and all the prepares were new.

It's worth mentioning that API s with prepared and unprepare strings in their names were added by the kernel later, in the past.
Only clk_enable and clk_disable. Only clk_enable and clk_disable cause problems.
Sometimes, enable/disable clk on some hardware may cause sleep so that enable/disable cannot be in the atom.
Context proceeds.
After adding prepare s, the old clk_enable is decomposed into non-callable in atomic context
 clk_prepare (this function may sleep) and clk_enable that can be called in the atomic context.
And clk_prepare_enable is done at the same time.
prepare and enable work, of course, can only call the API in the context of possible sleep.

How to understand the above paragraph? I think the key point is why clk_prepare s may sleep.

Posted by wiseoleweazel on Tue, 12 Feb 2019 02:51:18 -0800