Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When executing clk_disable_unprepare() in __fclk_set_enable(), the warning “pl0_ref already disabled” occurs. #3

Closed
ikwzm opened this issue Mar 6, 2025 · 2 comments

Comments

@ikwzm
Copy link
Owner

ikwzm commented Mar 6, 2025

The following warning appears when loading fclkcfg.

[ 1544.942268] fclkcfg: loading out-of-tree module taints kernel.
[ 1544.949984] ------------[ cut here ]------------
[ 1544.954625] pl0_ref already disabled
[ 1544.958243] WARNING: CPU: 3 PID: 558 at drivers/clk/clk.c:1181 clk_core_disable+0xb0/0xb8
[ 1544.966435] Modules linked in: fclkcfg(O+) fuse ip_tables x_tables
[ 1544.975829] CPU: 3 PID: 558 Comm: systemd-udevd Tainted: G           O       6.6.40-zynqmp-fpga-generic #1
[ 1544.985477] Hardware name: Avnet Ultra96-V2 Rev1 (DT)
[ 1544.990513] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 1545.002143] pc : clk_core_disable+0xb0/0xb8
[ 1545.006317] lr : clk_core_disable+0xb0/0xb8
[ 1545.010493] sp : ffffffc081f1b600
[ 1545.013791] x29: ffffffc081f1b600 x28: 0000000000000000 x27: ffffffc081f1bcd8
[ 1545.020917] x26: ffffffc081f1bcd8 x25: ffffffc081f1b6f8 x24: 0000000000000001
[ 1545.028043] x23: ffffffc081f1b6f8 x22: ffffff8003f53de0 x21: ffffff8004906ba8
[ 1545.035170] x20: ffffff8001e45e00 x19: ffffff8001e45e00 x18: 0000000000000010
[ 1545.042296] x17: 0000000000000124 x16: ffffffc079648638 x15: ffffff80025b4a10
[ 1545.049422] x14: 00000000000001b9 x13: ffffff80025b4a10 x12: 00000000ffffffea
[ 1545.056549] x11: 00000000fffff7ff x10: 00000000fffff7ff x9 : ffffffc0814ec360
[ 1545.063675] x8 : 000000000000bfe8 x7 : c0000000fffff7ff x6 : 0000000000000001
[ 1545.070801] x5 : ffffff807fb9fac8 x4 : 0000000000000000 x3 : 0000000000000027
[ 1545.077927] x2 : ffffff807fb9fad0 x1 : 0000000000000000 x0 : 0000000000000000
[ 1545.085055] Call trace:
[ 1545.087486]  clk_core_disable+0xb0/0xb8
[ 1545.091312]  clk_core_disable_lock+0x24/0x3c
[ 1545.095574]  clk_disable+0x20/0x30
[ 1545.098968]  __fclk_change_state+0x1f8/0x2c0 [fclkcfg]
[ 1545.104115]  fclk_device_setup+0x10c/0x358 [fclkcfg]
[ 1545.109080]  fclkcfg_platform_driver_probe+0x108/0x4bc [fclkcfg]
[ 1545.115087]  platform_probe+0x68/0xd8
[ 1545.118741]  really_probe+0x110/0x280
[ 1545.122395]  __driver_probe_device+0x78/0x12c
[ 1545.126744]  driver_probe_device+0x3c/0x118
[ 1545.130919]  __driver_attach+0x74/0x124
[ 1545.134747]  bus_for_each_dev+0x78/0xdc
[ 1545.138575]  driver_attach+0x24/0x30
[ 1545.142142]  bus_add_driver+0xe4/0x208
[ 1545.145883]  driver_register+0x60/0x128
[ 1545.149711]  __platform_driver_register+0x28/0x34
[ 1545.154407]  fclkcfg_module_init+0x84/0x1000 [fclkcfg]
[ 1545.159545]  do_one_initcall+0x70/0x1b8
[ 1545.163373]  do_init_module+0x58/0x1e4
[ 1545.167115]  load_module+0x1984/0x1a4c
[ 1545.170856]  init_module_from_file+0x88/0xc8
[ 1545.175117]  __arm64_sys_finit_module+0x1ec/0x320
[ 1545.179813]  invoke_syscall+0x50/0x118
[ 1545.183555]  el0_svc_common.constprop.0+0xc0/0xe0
[ 1545.188251]  do_el0_svc+0x1c/0x28
[ 1545.191557]  el0_svc+0x40/0xe8
[ 1545.194604]  el0t_64_sync_handler+0xc0/0xc4
[ 1545.198779]  el0t_64_sync+0x190/0x194
[ 1545.202435] ---[ end trace 0000000000000000 ]---
[ 1545.207121] ------------[ cut here ]------------
[ 1545.211916] pl0_ref already unprepared
[ 1545.215805] WARNING: CPU: 3 PID: 558 at drivers/clk/clk.c:1040 clk_core_unprepare+0xf0/0x110
[ 1545.224266] Modules linked in: u_dma_buf(O+) fclkcfg(O+) fuse ip_tables x_tables
[ 1545.231671] CPU: 3 PID: 558 Comm: systemd-udevd Tainted: G        W  O       6.6.40-zynqmp-fpga-generic #1
[ 1545.241320] Hardware name: Avnet Ultra96-V2 Rev1 (DT)
[ 1545.246357] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 1545.256857] pc : clk_core_unprepare+0xf0/0x110
[ 1545.261301] lr : clk_core_unprepare+0xf0/0x110
[ 1545.265737] sp : ffffffc081f1b610
[ 1545.269035] x29: ffffffc081f1b610 x28: 0000000000000000 x27: ffffffc081f1bcd8
[ 1545.276170] x26: ffffffc081f1bcd8 x25: ffffffc081f1b6f8 x24: 0000000000000001
[ 1545.283296] x23: ffffffc081f1b6f8 x22: ffffff8003f53de0 x21: ffffff8004906ba8
[ 1545.290422] x20: ffffff8004906b80 x19: ffffff8001e45e00 x18: 0000000000000010
[ 1545.297549] x17: 0000000000000124 x16: ffffffc079648638 x15: ffffff80025b4a10
[ 1545.304675] x14: 00000000000001eb x13: ffffff80025b4a10 x12: 00000000ffffffea
[ 1545.311801] x11: 00000000fffff7ff x10: 00000000fffff7ff x9 : ffffffc0814ec360
[ 1545.318928] x8 : 000000000000bfe8 x7 : c0000000fffff7ff x6 : 0000000000000001
[ 1545.326054] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
[ 1545.333180] x2 : ffffff807fba2c98 x1 : 0000000000000000 x0 : 0000000000000000
[ 1545.340307] Call trace:
[ 1545.342738]  clk_core_unprepare+0xf0/0x110
[ 1545.346825]  clk_unprepare+0x2c/0x44
[ 1545.350392]  __fclk_change_state+0x200/0x2c0 [fclkcfg]
[ 1545.355540]  fclk_device_setup+0x10c/0x358 [fclkcfg]
[ 1545.360505]  fclkcfg_platform_driver_probe+0x108/0x4bc [fclkcfg]
[ 1545.366512]  platform_probe+0x68/0xd8
[ 1545.370166]  really_probe+0x110/0x280
[ 1545.373820]  __driver_probe_device+0x78/0x12c
[ 1545.378169]  driver_probe_device+0x3c/0x118
[ 1545.382344]  __driver_attach+0x74/0x124
[ 1545.386172]  bus_for_each_dev+0x78/0xdc
[ 1545.389999]  driver_attach+0x24/0x30
[ 1545.393567]  bus_add_driver+0xe4/0x208
[ 1545.397308]  driver_register+0x60/0x128
[ 1545.401136]  __platform_driver_register+0x28/0x34
[ 1545.405832]  fclkcfg_module_init+0x84/0x1000 [fclkcfg]
[ 1545.410970]  do_one_initcall+0x70/0x1b8
[ 1545.414798]  do_init_module+0x58/0x1e4
[ 1545.418540]  load_module+0x1984/0x1a4c
[ 1545.422281]  init_module_from_file+0x88/0xc8
[ 1545.426542]  __arm64_sys_finit_module+0x1ec/0x320
[ 1545.431238]  invoke_syscall+0x50/0x118
[ 1545.434980]  el0_svc_common.constprop.0+0xc0/0xe0
[ 1545.439675]  do_el0_svc+0x1c/0x28
[ 1545.442982]  el0_svc+0x40/0xe8
[ 1545.446038]  el0t_64_sync_handler+0xc0/0xc4
[ 1545.450212]  el0t_64_sync+0x190/0x194
[ 1545.453868] ---[ end trace 0000000000000000 ]---
[ 1545.458883] fclkcfg amba_pl@0:fclk0: driver version : 1.8.0
[ 1545.464478] fclkcfg amba_pl@0:fclk0: device name    : amba_pl@0:fclk0
[ 1545.470931] fclkcfg amba_pl@0:fclk0: clock  name    : pl0_ref
[ 1545.476680] fclkcfg amba_pl@0:fclk0: clock  rate    : 249999998
[ 1545.482622] fclkcfg amba_pl@0:fclk0: clock  enabled : 1
[ 1545.487841] fclkcfg amba_pl@0:fclk0: remove rate    : 1000000
[ 1545.493587] fclkcfg amba_pl@0:fclk0: remove enable  : 0
[ 1545.498813] fclkcfg amba_pl@0:fclk0: driver installed.
@ikwzm
Copy link
Owner Author

ikwzm commented Mar 6, 2025

fclkcfg stops the clock once when changing the clock frequency.
When stopping the clock, in fclkcfg.c, it calls clk_disable_prepare() to stop the clock if it is enabled, as follows

static int __fclk_set_enable(struct fclk_device_data* this, bool enable)
{
    int status = 0;

    if (enable == true) {
        if (__clk_is_enabled(this->clk) == false) {
            status = clk_prepare_enable(this->clk);
            if (status) 
                dev_err(this->device, "enable failed.");
            else 
                DEV_DBG(this->device, "enable success.");
        }
    } else {
        if (__clk_is_enabled(this->clk) == true) {
            clk_disable_unprepare(this->clk);
            DEV_DBG(this->device, "disable done.");
        }
    }
    return status;
}

Then, clk_disable_prepare() in linux kernel driver (drivers/clk/clk.c) checks enable_count and issues a warning if enable_count is 0 as follows

static void clk_core_disable(struct clk_core *core)
{
	lockdep_assert_held(&enable_lock);

	if (!core)
		return;

	if (WARN(core->enable_count == 0, "%s already disabled\n", core->name))
		return;

	if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL,
	    "Disabling critical %s\n", core->name))
		return;

	if (--core->enable_count > 0)
		return;

	trace_clk_disable(core);

	if (core->ops->disable)
		core->ops->disable(core->hw);

	trace_clk_disable_complete(core);

	clk_core_disable(core->parent);
}

On the other hand, zynqmp_clk_gate_is_enabled() in drivers/clk/zynqmp/clk-gate-zynqmp.c, the clock driver for ZynqMP on Linux Kernel, asks firmware as follows.

static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw)
{
	struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
	const char *clk_name = clk_hw_get_name(hw);
	u32 clk_id = gate->clk_id;
	int state, ret;

	ret = zynqmp_pm_clock_getstate(clk_id, &state);
	if (ret) {
		pr_debug("%s() clock get state failed for %s, ret = %d\n",
			 __func__, clk_name, ret);
		return -EIO;
	}

	return state ? 1 : 0;
}

These things lead to a situation where __clk_is_enabled() is true but enable_count is 0 if the clock was previously enabled by firmware when ZynqMP was started up.
This is why the warning occurs.

@ikwzm
Copy link
Owner Author

ikwzm commented Mar 6, 2025

In such a case, an inconsistency with the clock driver may occur, resulting in warning such as issue #3 when the clock is stopped.

The enable-sync property forces the clock state to be synchronized at dirver load time to suppress the occurrence of this warning.

        fclk0 {
            compatible    = "ikwzm,fclkcfg";
            device-name   = "fpga-clk0";
            clocks        = <&clkc 15>, <&clkc 2>;
            enable-sync;
            insert-enable = <0>;
        };

@ikwzm ikwzm closed this as completed Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant