ARM: smp_twd: reprogram twd based on clk notifier
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
From: Mike Turquette <[email protected]>
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269
<snip>
stack backtrace: Backtrace: [<80011d64>] (dump_backtrace+0x0/0x10c) from [<803fc164>] (dump_stack+0x18/0x1c) r6:bf8142e0 r5:bf814000 r4:806ac794 r3:bf814000 [<803fc14c>] (dump_stack+0x0/0x1c) from [<803fd444>] (print_usage_bug+0x250/0x2b
8)
[<803fd1f4>] (print_usage_bug+0x0/0x2b8) from [<80060f90>] (mark_lock+0x56c/0x67
0)
[<80060a24>] (mark_lock+0x0/0x670) from [<80061a20>] (__lock_acquire+0x98c/0x19b
4)
[<80061094>] (__lock_acquire+0x0/0x19b4) from [<80062f14>] (lock_acquire+0x68/0x 7c)
[<80062eac>] (lock_acquire+0x0/0x7c) from [<80400f28>] (mutex_lock_nested+0x78/0 x344)
r7:00000000 r6:bf872000 r5:805cc858 r4:805c2a04
[<80400eb0>] (mutex_lock_nested+0x0/0x344) from [<803089ac>] (clk_get_rate+0x1c/ 0x58)
[<80308990>] (clk_get_rate+0x0/0x58) from [<80013c48>] (twd_update_frequency+0x1 8/0x50)
r5:bf253d04 r4:805cadf4
[<80013c30>] (twd_update_frequency+0x0/0x50) from [<80068e20>] (generic_smp_call
_function_single_interrupt+0xd4/0x13c) r4:bf873ee0 r3:80013c30 [<80068d4c>] (generic_smp_call_function_single_interrupt+0x0/0x13c) from [<80013 34c>] (handle_IPI+0xc0/0x194) r8:00000001 r7:00000000 r6:80574e48 r5:bf872000 r4:80593958 [<8001328c>] (handle_IPI+0x0/0x194) from [<800084e8>] (gic_handle_irq+0x58/0x60) r8:00000000 r7:bf873f8c r6:bf873f58 r5:80593070 r4:f4000100 r3:00000005 [<80008490>] (gic_handle_irq+0x0/0x60) from [<8000e124>] (__irq_svc+0x44/0x60) Exception stack(0xbf873f58 to 0xbf873fa0)
3f40: 00000001 00000001
3f60: 00000000 bf814000 bf872000 805cab48 80405aa4 80597648 00000000 412fc09a 3f80: bf872000 bf873fac bf873f70 bf873fa0 80063844 8000f1f8 20000013 ffffffff
r6:ffffffff r5:20000013 r4:8000f1f8 r3:bf814000
[<8000f1b8>] (default_idle+0x0/0x4c) from [<8000f428>] (cpu_idle+0x98/0x114) [<8000f390>] (cpu_idle+0x0/0x114) from [<803f9834>] (secondary_start_kernel+0x11 c/0x140)
[<803f9718>] (secondary_start_kernel+0x0/0x140) from [<103f9234>] (0x103f9234)
r6:10c03c7d r5:0000001f r4:4f86806a r3:803f921c
It looks that the warning is caused by that twd_update_frequency() gets called from an atomic context while it calls clk_get_rate() where a mutex gets held.
To fix the warning, let's convert the existing code to use clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
--- arch/arm/kernel/smp_twd.c | 32 +++++++++++++------------------- 1 files changed, 13 insertions(+), 19 deletions(-)
arch/arm/kernel/smp_twd.c +13 -19
@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h>
@@ -96,51 +95,46 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ -/* * Updates clockevent frequency when the cpu frequency changes. * Called on the cpu that is changing frequency with interrupts disabled. */ -static void twd_update_frequency (void *data) +static void twd_update_frequency (void *new_rate) { - twd_timer_rate =clk_get_rate (twd_clk); + twd_timer_rate = *((unsigned long *) new_rate);clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); } -static int twd_cpufreq_transition (struct notifier_block *nb, -unsigned long state,void *data) +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) { -struct cpufreq_freqs *freqs = data; +struct clk_notifier_data *cnd = data;/* * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. */ -if (state ==CPUFREQ_POSTCHANGE || state ==CPUFREQ_RESUMECHANGE ) -smp_call_function_single (freqs->cpu, twd_update_frequency, -NULL ,1 ); +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 );return NOTIFY_OK ; } -static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, }; -static int twd_cpufreq_init (void ) +static int twd_clk_init (void ) {if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) -return cpufreq_register_notifier (&twd_cpufreq_nb, -CPUFREQ_TRANSITION_NOTIFIER ); +return clk_notifier_register (twd_clk, &twd_clk_nb);return 0 ; } -core_initcall (twd_cpufreq_init); - -#endif +core_initcall (twd_clk_init);static void __cpuinit twd_calibrate_rate (void ) {
Signature · 1 line
1.7.5.4
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates for smp_twd clock is supported from within the cpufreq driver I suppose.
In other words the cpufreq drivers needs to do clk_get of "smp_twd" clock and then do a set_rate on it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?
Kind regards
Ulf Hansson
Quoted 148 lines · Shawn Guo
From: Mike Turquette <[email protected]>
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269<snip>
stack backtrace: Backtrace: [<80011d64>] (dump_backtrace+0x0/0x10c) from [<803fc164>] (dump_stack+0x18/0x1c) r6:bf8142e0 r5:bf814000 r4:806ac794 r3:bf814000 [<803fc14c>] (dump_stack+0x0/0x1c) from [<803fd444>] (print_usage_bug+0x250/0x2b8)
[<803fd1f4>] (print_usage_bug+0x0/0x2b8) from [<80060f90>] (mark_lock+0x56c/0x67
0)
[<80060a24>] (mark_lock+0x0/0x670) from [<80061a20>] (__lock_acquire+0x98c/0x19b
4)
[<80061094>] (__lock_acquire+0x0/0x19b4) from [<80062f14>] (lock_acquire+0x68/0x 7c)
[<80062eac>] (lock_acquire+0x0/0x7c) from [<80400f28>] (mutex_lock_nested+0x78/0 x344)
r7:00000000 r6:bf872000 r5:805cc858 r4:805c2a04
[<80400eb0>] (mutex_lock_nested+0x0/0x344) from [<803089ac>] (clk_get_rate+0x1c/0x58)
[<80308990>] (clk_get_rate+0x0/0x58) from [<80013c48>] (twd_update_frequency+0x18/0x50)
r5:bf253d04 r4:805cadf4
[<80013c30>] (twd_update_frequency+0x0/0x50) from [<80068e20>] (generic_smp_call_function_single_interrupt+0xd4/0x13c) r4:bf873ee0 r3:80013c30 [<80068d4c>] (generic_smp_call_function_single_interrupt+0x0/0x13c) from [<80013 34c>] (handle_IPI+0xc0/0x194) r8:00000001 r7:00000000 r6:80574e48 r5:bf872000 r4:80593958 [<8001328c>] (handle_IPI+0x0/0x194) from [<800084e8>] (gic_handle_irq+0x58/0x60) r8:00000000 r7:bf873f8c r6:bf873f58 r5:80593070 r4:f4000100 r3:00000005 [<80008490>] (gic_handle_irq+0x0/0x60) from [<8000e124>] (__irq_svc+0x44/0x60) Exception stack(0xbf873f58 to 0xbf873fa0)3f40: 00000001 00000001
3f60: 00000000bf814000bf872000805cab4880405aa480597648 00000000412fc09a3f80:bf872000bf873facbf873f70bf873fa0800638448000f1f820000013 ffffffff
r6:ffffffff r5:20000013 r4:8000f1f8 r3:bf814000
[<8000f1b8>] (default_idle+0x0/0x4c) from [<8000f428>] (cpu_idle+0x98/0x114) [<8000f390>] (cpu_idle+0x0/0x114) from [<803f9834>] (secondary_start_kernel+0x11c/0x140)
[<803f9718>] (secondary_start_kernel+0x0/0x140) from [<103f9234>] (0x103f9234)
r6:10c03c7d r5:0000001f r4:4f86806a r3:803f921cIt looks that the warning is caused by that
twd_update_frequency()gets called from an atomic context while it callsclk_get_rate()where a mutex gets held.To fix the warning, let's convert the existing code to use clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>--- arch/arm/kernel/smp_twd.c | 32 +++++++++++++------------------- 1 files changed, 13 insertions(+), 19 deletions(-)arch/arm/kernel/smp_twd.c +13
-20@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> @@ -96,51 +95,46 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ -/* * Updates clockevent frequency when the cpu frequency changes. * Called on the cpu that is changing frequency with interrupts disabled. */ -static void twd_update_frequency (void *data) +static void twd_update_frequency (void *new_rate) { - twd_timer_rate =clk_get_rate (twd_clk); + twd_timer_rate = *((unsigned long *) new_rate);clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); } -static int twd_cpufreq_transition (struct notifier_block *nb, -unsigned long state,void *data) +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) { -struct cpufreq_freqs *freqs = data; +struct clk_notifier_data *cnd = data;/* * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. */ -if (state ==CPUFREQ_POSTCHANGE || state ==CPUFREQ_RESUMECHANGE ) -smp_call_function_single (freqs->cpu, twd_update_frequency, -NULL ,1 ); +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 );return NOTIFY_OK ; } -static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, }; -static int twd_cpufreq_init (void ) +static int twd_clk_init (void ) {if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) -return cpufreq_register_notifier (&twd_cpufreq_nb, -CPUFREQ_TRANSITION_NOTIFIER ); +return clk_notifier_register (twd_clk, &twd_clk_nb);return 0 ; } -core_initcall (twd_cpufreq_init); - -#endif +core_initcall (twd_clk_init);static void __cpuinit twd_calibrate_rate (void ) { --1.7.5.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 10 lines · Ulf Hansson
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "
cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates forsmp_twdclock is supported from within the cpufreq driver I suppose.
Quoted 5 lines
In other words the cpufreq drivers needs to do
clk_getof "smp_twd" clock and then do aset_rateon it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?
Here is how it works on imx6q.
1) There are clks arm and twd defined in imx6q clock tree. And twd is registered to clock framework as one child of arm clk with a fixed divider 2.
/* name parent_name mult div */
clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);2) Register lookup "cpu0" and "smp_twd" for cpufreq and smp_twd drivers respectively.
clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[arm], NULL, "cpu0");
That's it. The clock framework will just handle all the work nicely. When cpufreq driver scales arm clk, the framework will propagate the rate change to twd clk automatically. And once twd clk rate changes, smp_twd will get the notification.
Signature · 2 lines
Regards, Shawn
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 28 lines · Shawn Guo
Quoted 10 lines · Ulf Hansson
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "
cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates forsmp_twdclock is supported from within the cpufreq driver I suppose.Quoted 5 lines
In other words the cpufreq drivers needs to do
clk_getof "smp_twd" clock and then do aset_rateon it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?Here is how it works on imx6q.
1) There are clks arm and twd defined in imx6q clock tree. And twd is registered to clock framework as one child of arm clk with a fixed divider 2.
/* name parent_name mult div */ clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);2) Register lookup "cpu0" and "
smp_twd" for cpufreq andsmp_twddrivers respectively.
Quoted 8 lines
clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[arm], NULL, "cpu0");That's it. The clock framework will just handle all the work nicely. When cpufreq driver scales arm clk, the framework will propagate the rate change to twd clk automatically. And once twd clk rate changes,
smp_twdwill get the notification.
That's a nice solution!
This won't work for ux500 that simple though. Maybe I might be able to use some kind of clock "parent" thing though, let's see. Thanks for the information!
Kind regards
Ulf Hansson
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoting Ulf Hansson (2012-09-07 06:26:21)
Quoted 38 lines · Shawn Guo
Quoted 28 lines · Ulf Hansson
Quoted 10 lines
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "
cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates forsmp_twdclock is supported from within the cpufreq driver I suppose.Quoted 5 lines
In other words the cpufreq drivers needs to do
clk_getof "smp_twd" clock and then do aset_rateon it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?Here is how it works on imx6q.
1) There are clks arm and twd defined in imx6q clock tree. And twd is registered to clock framework as one child of arm clk with a fixed divider 2.
/* name parent_name mult div */ clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);2) Register lookup "cpu0" and "
smp_twd" for cpufreq andsmp_twddrivers respectively.Quoted 8 lines
clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[arm], NULL, "cpu0");That's it. The clock framework will just handle all the work nicely. When cpufreq driver scales arm clk, the framework will propagate the rate change to twd clk automatically. And once twd clk rate changes,
smp_twdwill get the notification.
Quoted 4 lines
That's a nice solution!
This won't work for ux500 that simple though. Maybe I might be able to use some kind of clock "parent" thing though, let's see. Thanks for the information!
Hi Ulf,
Why won't this work for ux500?
Thanks,
Mike
Quoted 8 lines
Kind regards
Ulf Hansson_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 39 lines · Mike Turquette
Quoting Ulf Hansson (2012-09-07 06:26:21)
Quoted 38 lines · Shawn Guo
Quoted 36 lines · Ulf Hansson
Quoted 10 lines
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "
cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates forsmp_twdclock is supported from within the cpufreq driver I suppose.Quoted 5 lines
In other words the cpufreq drivers needs to do
clk_getof "smp_twd" clock and then do aset_rateon it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?Here is how it works on imx6q.
1) There are clks arm and twd defined in imx6q clock tree. And twd is registered to clock framework as one child of arm clk with a fixed divider 2.
/* name parent_name mult div */ clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);2) Register lookup "cpu0" and "
smp_twd" for cpufreq andsmp_twddrivers respectively.clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[arm], NULL, "cpu0");That's it. The clock framework will just handle all the work nicely. When cpufreq driver scales arm clk, the framework will propagate the rate change to twd clk automatically. And once twd clk rate changes,
smp_twdwill get the notification.
Quoted 9 lines
Quoted 4 lines
That's a nice solution!
This won't work for ux500 that simple though. Maybe I might be able to use some kind of clock "parent" thing though, let's see. Thanks for the information!Hi Ulf,
Why won't this work for ux500?
The value for smp_twd clock freq is not directly connected to the CPU freq clock, I believe. I will dig into the details to see what we can do to make the most easiest solution.
Using a "parent" solution is definitely to prefer, so let's see.
Kind regards
Ulf Hansson
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 47 lines · Ulf Hansson
Quoted 46 lines · Mike Turquette
Quoting Ulf Hansson (2012-09-07 06:26:21)
Quoted 38 lines · Shawn Guo
Quoted 28 lines · Ulf Hansson
Quoted 10 lines
Hi Shawn and Mike,
In general I am in favor of this patch, but I also see some corresponding problems to resolve. Please correct me if I am wrong.
I suppose most machines is relying on that it enough to only take care of the notification by using "
cpufreq_notify_transition" from their cpufreq drivers. Thus those have to make sure the updates forsmp_twdclock is supported from within the cpufreq driver I suppose.Quoted 5 lines
In other words the cpufreq drivers needs to do
clk_getof "smp_twd" clock and then do aset_rateon it when it's has changed, to trigger a rate change notification. Is this what you also have in mind or do you have any other idea of how this should work?Here is how it works on imx6q.
1) There are clks arm and twd defined in imx6q clock tree. And twd is registered to clock framework as one child of arm clk with a fixed divider 2.
/* name parent_name mult div */ clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);2) Register lookup "cpu0" and "
smp_twd" for cpufreq andsmp_twddrivers respectively.Quoted 8 lines
clk_register_clkdev(clk[twd], NULL, "smp_twd"); clk_register_clkdev(clk[arm], NULL, "cpu0");That's it. The clock framework will just handle all the work nicely. When cpufreq driver scales arm clk, the framework will propagate the rate change to twd clk automatically. And once twd clk rate changes,
smp_twdwill get the notification.Quoted 4 lines
That's a nice solution!
This won't work for ux500 that simple though. Maybe I might be able to use some kind of clock "parent" thing though, let's see. Thanks for the information!Hi Ulf,
Quoted 8 lines
Quoted 2 lines
Why won't this work for ux500?
The value for
smp_twdclock freq is not directly connected to the CPU freq clock, I believe. I will dig into the details to see what we can do to make the most easiest solution.
Using a "parent" solution is definitely to prefer, so let's see.
It is connected to the CPU clock wih a fixed divider in between on A9 based SoCs. This divider is different across SoC's as seen from various patches done for the CPUFREQ TWD update.
if you look at OMAP TWD clock node, it's parent is CPU clock node with fixed divider of 2.
Regards
Santosh
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
In reply to Shawn GuoAny comment? Otherwise, I will submit it to patch tracker system tomorrow.
Regards,
Shawn
Quoted 143 lines · Shawn Guo
From: Mike Turquette <[email protected]>
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269<snip>
stack backtrace: Backtrace: [<80011d64>] (dump_backtrace+0x0/0x10c) from [<803fc164>] (dump_stack+0x18/0x1c) r6:bf8142e0 r5:bf814000 r4:806ac794 r3:bf814000 [<803fc14c>] (dump_stack+0x0/0x1c) from [<803fd444>] (print_usage_bug+0x250/0x2b8)
[<803fd1f4>] (print_usage_bug+0x0/0x2b8) from [<80060f90>] (mark_lock+0x56c/0x67
0)
[<80060a24>] (mark_lock+0x0/0x670) from [<80061a20>] (__lock_acquire+0x98c/0x19b
4)
[<80061094>] (__lock_acquire+0x0/0x19b4) from [<80062f14>] (lock_acquire+0x68/0x 7c)
[<80062eac>] (lock_acquire+0x0/0x7c) from [<80400f28>] (mutex_lock_nested+0x78/0 x344)
r7:00000000 r6:bf872000 r5:805cc858 r4:805c2a04
[<80400eb0>] (mutex_lock_nested+0x0/0x344) from [<803089ac>] (clk_get_rate+0x1c/0x58)
[<80308990>] (clk_get_rate+0x0/0x58) from [<80013c48>] (twd_update_frequency+0x18/0x50)
r5:bf253d04 r4:805cadf4
[<80013c30>] (twd_update_frequency+0x0/0x50) from [<80068e20>] (generic_smp_call_function_single_interrupt+0xd4/0x13c) r4:bf873ee0 r3:80013c30 [<80068d4c>] (generic_smp_call_function_single_interrupt+0x0/0x13c) from [<80013 34c>] (handle_IPI+0xc0/0x194) r8:00000001 r7:00000000 r6:80574e48 r5:bf872000 r4:80593958 [<8001328c>] (handle_IPI+0x0/0x194) from [<800084e8>] (gic_handle_irq+0x58/0x60) r8:00000000 r7:bf873f8c r6:bf873f58 r5:80593070 r4:f4000100 r3:00000005 [<80008490>] (gic_handle_irq+0x0/0x60) from [<8000e124>] (__irq_svc+0x44/0x60) Exception stack(0xbf873f58 to 0xbf873fa0)3f40: 00000001 00000001
3f60: 00000000bf814000bf872000805cab4880405aa480597648 00000000412fc09a3f80:bf872000bf873facbf873f70bf873fa0800638448000f1f820000013 ffffffff
r6:ffffffff r5:20000013 r4:8000f1f8 r3:bf814000
[<8000f1b8>] (default_idle+0x0/0x4c) from [<8000f428>] (cpu_idle+0x98/0x114) [<8000f390>] (cpu_idle+0x0/0x114) from [<803f9834>] (secondary_start_kernel+0x11c/0x140)
[<803f9718>] (secondary_start_kernel+0x0/0x140) from [<103f9234>] (0x103f9234)
r6:10c03c7d r5:0000001f r4:4f86806a r3:803f921cIt looks that the warning is caused by that
twd_update_frequency()gets called from an atomic context while it callsclk_get_rate()where a mutex gets held.To fix the warning, let's convert the existing code to use clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>--- arch/arm/kernel/smp_twd.c | 32 +++++++++++++------------------- 1 files changed, 13 insertions(+), 19 deletions(-)arch/arm/kernel/smp_twd.c +13
-19@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> @@ -96,51 +95,46 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ -/* * Updates clockevent frequency when the cpu frequency changes. * Called on the cpu that is changing frequency with interrupts disabled. */ -static void twd_update_frequency (void *data) +static void twd_update_frequency (void *new_rate) { - twd_timer_rate =clk_get_rate (twd_clk); + twd_timer_rate = *((unsigned long *) new_rate);clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); } -static int twd_cpufreq_transition (struct notifier_block *nb, -unsigned long state,void *data) +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) { -struct cpufreq_freqs *freqs = data; +struct clk_notifier_data *cnd = data;/* * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. */ -if (state ==CPUFREQ_POSTCHANGE || state ==CPUFREQ_RESUMECHANGE ) -smp_call_function_single (freqs->cpu, twd_update_frequency, -NULL ,1 ); +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 );return NOTIFY_OK ; } -static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, }; -static int twd_cpufreq_init (void ) +static int twd_clk_init (void ) {if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) -return cpufreq_register_notifier (&twd_cpufreq_nb, -CPUFREQ_TRANSITION_NOTIFIER ); +return clk_notifier_register (twd_clk, &twd_clk_nb);return 0 ; } -core_initcall (twd_cpufreq_init); - -#endif +core_initcall (twd_clk_init);static void __cpuinit twd_calibrate_rate (void ) {Signature · 1 line
1.7.5.4
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
In reply to Shawn Guoarch/arm/kernel/smp_twd.c static void twd_timer_stop(struct clock_event_device *clk) · line 127
Quoted 4 lines · Shawn Guo
arch/arm/kernel/smp_twd.c +2
-2-static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change,
But what happens if there is a platform which is now using this through cpufreq and has not yet switched to the common clock? It regresses right, because no notifications arrive anymore? Does it even compile?
These in linux-next look like they could be in trouble:
cd arch/arm
grep -r smp_twd ../arch/arm/mach-imx/clk-imx6q.c: clk_register_clkdev(clk[twd], NULL, "smp_twd");./arch/arm/mach-tegra/tegra30_clocks_data.c: CLK_DUPLICATE("twd",
"smp_twd", NULL),
Tegra seems to be a common clk implementation, but imx6 looks like it's in trouble right?
Yours,
Linus Walleij
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 10 lines · Linus Walleij
arch/arm/kernel/smp_twd.c static void twd_timer_stop(struct clock_event_device *clk) · line 127
Quoted 4 lines · Shawn Guo
arch/arm/kernel/smp_twd.c +2
-2-static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change,But what happens if there is a platform which is now using this through cpufreq and has not yet switched to the common clock? It regresses right, because no notifications arrive anymore? Does it even compile?
Bah too late in the afternoon :-(
So the real question is - are we sure that imx6 is the last platform migrated to common clock of all those using the CPUfreq scaling (this seems to be the last piece) such that
we don't break anything....
Yours,
Linus Walleij
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoting Linus Walleij (2012-09-12 09:07:51)
Quoted 12 lines · Linus Walleij
Quoted 10 lines · Shawn Guo
arch/arm/kernel/smp_twd.c static void twd_timer_stop(struct clock_event_device *clk) · line 127
Quoted 5 lines
arch/arm/kernel/smp_twd.c +2
-2-static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change,But what happens if there is a platform which is now using this through cpufreq and has not yet switched to the common clock? It regresses right, because no notifications arrive anymore? Does it even compile?
Quoted 7 lines
Bah too late in the afternoon :-(
So the real question is - are we sure that imx6 is the last platform migrated to common clock of all those using the CPUfreq scaling (this seems to be the last piece) such that
we don't break anything....
OMAP will break. My original version of this patch had "HACK:" in the $subject since it was just a demo of the notifiers.
I'll submit a new version with some #ifdef CONFIG_COMMON_CLK bits ASAP.
Regards,
Mike
Quoted 7 lines
Yours,
Linus Walleij_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH v2 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269
<snip>
stack backtrace: Backtrace: [<80011d64>] (dump_backtrace+0x0/0x10c) from [<803fc164>] (dump_stack+0x18/0x1c) r6:bf8142e0 r5:bf814000 r4:806ac794 r3:bf814000 [<803fc14c>] (dump_stack+0x0/0x1c) from [<803fd444>] (print_usage_bug+0x250/0x2b
8)
[<803fd1f4>] (print_usage_bug+0x0/0x2b8) from [<80060f90>] (mark_lock+0x56c/0x67
0)
[<80060a24>] (mark_lock+0x0/0x670) from [<80061a20>] (__lock_acquire+0x98c/0x19b
4)
[<80061094>] (__lock_acquire+0x0/0x19b4) from [<80062f14>] (lock_acquire+0x68/0x 7c)
[<80062eac>] (lock_acquire+0x0/0x7c) from [<80400f28>] (mutex_lock_nested+0x78/0 x344)
r7:00000000 r6:bf872000 r5:805cc858 r4:805c2a04
[<80400eb0>] (mutex_lock_nested+0x0/0x344) from [<803089ac>] (clk_get_rate+0x1c/ 0x58)
[<80308990>] (clk_get_rate+0x0/0x58) from [<80013c48>] (twd_update_frequency+0x1 8/0x50)
r5:bf253d04 r4:805cadf4
[<80013c30>] (twd_update_frequency+0x0/0x50) from [<80068e20>] (generic_smp_call
_function_single_interrupt+0xd4/0x13c) r4:bf873ee0 r3:80013c30 [<80068d4c>] (generic_smp_call_function_single_interrupt+0x0/0x13c) from [<80013 34c>] (handle_IPI+0xc0/0x194) r8:00000001 r7:00000000 r6:80574e48 r5:bf872000 r4:80593958 [<8001328c>] (handle_IPI+0x0/0x194) from [<800084e8>] (gic_handle_irq+0x58/0x60) r8:00000000 r7:bf873f8c r6:bf873f58 r5:80593070 r4:f4000100 r3:00000005 [<80008490>] (gic_handle_irq+0x0/0x60) from [<8000e124>] (__irq_svc+0x44/0x60) Exception stack(0xbf873f58 to 0xbf873fa0)
3f40: 00000001 00000001
3f60: 00000000 bf814000 bf872000 805cab48 80405aa4 80597648 00000000 412fc09a 3f80: bf872000 bf873fac bf873f70 bf873fa0 80063844 8000f1f8 20000013 ffffffff
r6:ffffffff r5:20000013 r4:8000f1f8 r3:bf814000
[<8000f1b8>] (default_idle+0x0/0x4c) from [<8000f428>] (cpu_idle+0x98/0x114) [<8000f390>] (cpu_idle+0x0/0x114) from [<803f9834>] (secondary_start_kernel+0x11 c/0x140)
[<803f9718>] (secondary_start_kernel+0x0/0x140) from [<103f9234>] (0x103f9234)
r6:10c03c7d r5:0000001f r4:4f86806a r3:803f921c
It looks that the warning is caused by that twd_update_frequency() gets called from an atomic context while it calls clk_get_rate() where a mutex gets held.
To fix the warning, let's convert common clk users over to clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
Platforms that have not been converted to the common clk framework and support CPUfreq will rely on the old mechanism. Once these platforms are converted over fully then we can remove the CPUfreq-specific bits for good.
---
Changes in v2:
* Kept the original CPUfreq notifier scheme in place for platforms that have not adapted to the common clk framework yet
Testing notes:
* Tested on OMAP4430 Panda against v3.6-rc5 with legacy clk framework and with local common clk patches, thus both code paths are validated
* CPUfreq userspace governor @ 300MHz, 600MHz and 1008MHz
* Ran "date; sleep 30; date" and compared with a stopwatch to verify correct timekeeping
arch/arm/kernel/smp_twd.c | 48 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-)
arch/arm/kernel/smp_twd.c +46 -2
@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h>
@@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ +#ifdef CONFIG_COMMON_CLK + +/* +* Updates clockevent frequency when the cpu frequency changes. +* Called on the cpu that is changing frequency with interrupts disabled. +*/ +static void twd_update_frequency (void *new_rate) +{ + twd_timer_rate = *((unsigned long *) new_rate); + +clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); +} + +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) +{ +struct clk_notifier_data *cnd = data; + +/* +* The twd clock events must be reprogrammed to account for the new +* frequency. The timer is local to a cpu, so cross-call to the +* changing cpu. +*/ +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 ); + +return NOTIFY_OK ; +} + +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, +}; + +static int twd_clk_init (void ) +{ +if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) +return clk_notifier_register (twd_clk, &twd_clk_nb); + +return 0 ; +} +core_initcall (twd_clk_init); + +#elif defined (CONFIG_CPU_FREQ ) + +#include <linux/cpufreq.h> /* * Updates clockevent frequency when the cpu frequency changes.
Signature · 1 line
1.7.9.5
PATCH v2 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoted 6 lines · Mike Turquette
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>---
Changes in v2:
* Kept the original CPUfreq notifier scheme in place for platforms that have not adapted to the common clk framework yet
This looks good. We can always delete the cpufreq part (which is a kinda hack anyway) once all OMAPs have notifiers.
Yours,
Linus Walleij
PATCH v2 1/1 ARM: smp_twd: reprogram twd based on clk notifier
Quoting Linus Walleij (2012-09-13 05:51:52)
Quoted 9 lines · Mike Turquette
Quoted 7 lines
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>---
Changes in v2:
* Kept the original CPUfreq notifier scheme in place for platforms that have not adapted to the common clk framework yet
Quoted 5 lines
This looks good. We can always delete the cpufreq part (which is a kinda hack anyway) once all OMAPs have notifiers.
Reviewed-by Linus Walleij <[email protected]>
Thanks Linus. I've added v2 of this patch to Russell's patch tracker with your and Ulf's Reviewed-by's.
Regards,
Mike
Quoted 2 lines
Yours,
Linus Walleij
PATCH v2 1/1 ARM: smp_twd: reprogram twd based on clk notifier
In reply to Mike TurquetteQuoted 147 lines · Mike Turquette
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269<snip>
stack backtrace: Backtrace: [<80011d64>] (dump_backtrace+0x0/0x10c) from [<803fc164>] (dump_stack+0x18/0x1c) r6:bf8142e0 r5:bf814000 r4:806ac794 r3:bf814000 [<803fc14c>] (dump_stack+0x0/0x1c) from [<803fd444>] (print_usage_bug+0x250/0x2b8)
[<803fd1f4>] (print_usage_bug+0x0/0x2b8) from [<80060f90>] (mark_lock+0x56c/0x67
0)
[<80060a24>] (mark_lock+0x0/0x670) from [<80061a20>] (__lock_acquire+0x98c/0x19b
4)
[<80061094>] (__lock_acquire+0x0/0x19b4) from [<80062f14>] (lock_acquire+0x68/0x 7c)
[<80062eac>] (lock_acquire+0x0/0x7c) from [<80400f28>] (mutex_lock_nested+0x78/0 x344)
r7:00000000 r6:bf872000 r5:805cc858 r4:805c2a04
[<80400eb0>] (mutex_lock_nested+0x0/0x344) from [<803089ac>] (clk_get_rate+0x1c/0x58)
[<80308990>] (clk_get_rate+0x0/0x58) from [<80013c48>] (twd_update_frequency+0x18/0x50)
r5:bf253d04 r4:805cadf4
[<80013c30>] (twd_update_frequency+0x0/0x50) from [<80068e20>] (generic_smp_call_function_single_interrupt+0xd4/0x13c) r4:bf873ee0 r3:80013c30 [<80068d4c>] (generic_smp_call_function_single_interrupt+0x0/0x13c) from [<80013 34c>] (handle_IPI+0xc0/0x194) r8:00000001 r7:00000000 r6:80574e48 r5:bf872000 r4:80593958 [<8001328c>] (handle_IPI+0x0/0x194) from [<800084e8>] (gic_handle_irq+0x58/0x60) r8:00000000 r7:bf873f8c r6:bf873f58 r5:80593070 r4:f4000100 r3:00000005 [<80008490>] (gic_handle_irq+0x0/0x60) from [<8000e124>] (__irq_svc+0x44/0x60) Exception stack(0xbf873f58 to 0xbf873fa0)3f40: 00000001 00000001
3f60: 00000000bf814000bf872000805cab4880405aa480597648 00000000412fc09a3f80:bf872000bf873facbf873f70bf873fa0800638448000f1f820000013 ffffffff
r6:ffffffff r5:20000013 r4:8000f1f8 r3:bf814000
[<8000f1b8>] (default_idle+0x0/0x4c) from [<8000f428>] (cpu_idle+0x98/0x114) [<8000f390>] (cpu_idle+0x0/0x114) from [<803f9834>] (secondary_start_kernel+0x11c/0x140)
[<803f9718>] (secondary_start_kernel+0x0/0x140) from [<103f9234>] (0x103f9234)
r6:10c03c7d r5:0000001f r4:4f86806a r3:803f921cIt looks that the warning is caused by that
twd_update_frequency()gets called from an atomic context while it callsclk_get_rate()where a mutex gets held.To fix the warning, let's convert common clk users over to clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
Platforms that have not been converted to the common clk framework and support CPUfreq will rely on the old mechanism. Once these platforms are converted over fully then we can remove the CPUfreq-specific bits for good.
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>---
Changes in v2:
* Kept the original CPUfreq notifier scheme in place for platforms that have not adapted to the common clk framework yetTesting notes:
* Tested on OMAP4430 Panda against v3.6-rc5 with legacy clk framework and with local common clk patches, thus both code paths are validated
* CPUfreq userspace governor @ 300MHz, 600MHz and 1008MHz
* Ran "date; sleep 30; date" and compared with a stopwatch to verify correct timekeepingarch/arm/kernel/smp_twd.c | 48 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-)arch/arm/kernel/smp_twd.c +46
-3@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> @@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ +#ifdef CONFIG_COMMON_CLK + +/* +* Updates clockevent frequency when the cpu frequency changes. +* Called on the cpu that is changing frequency with interrupts disabled. +*/ +static void twd_update_frequency (void *new_rate) +{ + twd_timer_rate = *((unsigned long *) new_rate); + +clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); +} + +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) +{ +struct clk_notifier_data *cnd = data; + +/* +* The twd clock events must be reprogrammed to account for the new +* frequency. The timer is local to a cpu, so cross-call to the +* changing cpu. +*/ +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 ); + +return NOTIFY_OK ; +} + +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, +}; + +static int twd_clk_init (void ) +{ +if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) +return clk_notifier_register (twd_clk, &twd_clk_nb); + +return 0 ; +} +core_initcall (twd_clk_init); + +#elif defined (CONFIG_CPU_FREQ ) + +#include <linux/cpufreq.h> /* * Updates clockevent frequency when the cpu frequency changes. -- 1.7.9.5
Quoted 4 lines
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
I think this makes good sense! I will adapt ux500 smp_twd clock handling accordingly.
Kind regards
Ulf Hansson
PATCH 1/1 ARM: smp_twd: reprogram twd based on clk notifier
In reply to Shawn GuoQuoted 5 lines · Shawn Guo
From: Mike Turquette <[email protected]>
Running cpufreq driver on imx6q, the following warning is seen.
$ BUG: sleeping function called from invalid context at kernel/mutex.c:269
...
Quoted 10 lines
It looks that the warning is caused by that
twd_update_frequency()gets called from an atomic context while it callsclk_get_rate()where a mutex gets held.To fix the warning, let's convert the existing code to use clk notifiers in place of CPUfreq notifiers. This works out nicely for Cortex-A9 MPcore designs that scale all CPUs at the same frequency.
Signed-off-by Mike Turquette <[email protected]>Signed-off-by Shawn Guo <[email protected]>
At least in next-20120912, this doesn't appear to cause any issue on either Tegra20 or Tegra30. I'm copying Prashant to verify this is OK for Tegra.
For reference, the situation for Tegra is:
Pre-3.7:
Tegra20: Does not use common clock, and there is NO "smp_twd" clock defined.
Tegra30: Does not use common clock, and there IS a "smp_twd" clock defined.
In 3.7 will be:
Tegra20: Supports common clock, but there is NO "smp_twd" clock defined.
Tegra30: Supports common clock, and there IS a "smp_twd" clock defined.
I believe Prashant will be sending a patch very soon to define an "smp_twd" clock for Tegra20.
The Tegra cpufreq driver currently only initializes on Tegra20 and not Tegra30 right now due to some clock-naming differences. I don't expect this to change in 3.7, but who knows, someone might send a patch in the next 2 days or so...
Quoted 82 lines
--- arch/arm/kernel/smp_twd.c | 32 +++++++++++++------------------- 1 files changed, 13 insertions(+), 19 deletions(-)arch/arm/kernel/smp_twd.c +13
-19@@ -11,7 +11,6 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> -#include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> @@ -96,51 +95,46 @@ static void twd_timer_stop(struct clock_event_device *clk)disable_percpu_irq (clk->irq); } -#ifdef CONFIG_CPU_FREQ -/* * Updates clockevent frequency when the cpu frequency changes. * Called on the cpu that is changing frequency with interrupts disabled. */ -static void twd_update_frequency (void *data) +static void twd_update_frequency (void *new_rate) { - twd_timer_rate =clk_get_rate (twd_clk); + twd_timer_rate = *((unsigned long *) new_rate);clockevents_update_freq (*__this_cpu_ptr (twd_evt), twd_timer_rate); } -static int twd_cpufreq_transition (struct notifier_block *nb, -unsigned long state,void *data) +static int twd_rate_change (struct notifier_block *nb, +unsigned long flags,void *data) { -struct cpufreq_freqs *freqs = data; +struct clk_notifier_data *cnd = data;/* * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. */ -if (state ==CPUFREQ_POSTCHANGE || state ==CPUFREQ_RESUMECHANGE ) -smp_call_function_single (freqs->cpu, twd_update_frequency, -NULL ,1 ); +if (flags ==POST_RATE_CHANGE ) +smp_call_function (twd_update_frequency, + (void *)&cnd->new_rate,1 );return NOTIFY_OK ; } -static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, +static struct notifier_block twd_clk_nb = { + .notifier_call = twd_rate_change, }; -static int twd_cpufreq_init (void ) +static int twd_clk_init (void ) {if (twd_evt && *__this_cpu_ptr (twd_evt) && !IS_ERR (twd_clk)) -return cpufreq_register_notifier (&twd_cpufreq_nb, -CPUFREQ_TRANSITION_NOTIFIER ); +return clk_notifier_register (twd_clk, &twd_clk_nb);return 0 ; } -core_initcall (twd_cpufreq_init); - -#endif +core_initcall (twd_clk_init);static void __cpuinit twd_calibrate_rate (void ) {