Remove ARM local timer API
Subsystems (14)
v7 cover Remove ARM local timer API
In light of Mark Rutland's recent work on divorcing the ARM architected timers from the ARM local timer API and introducing a generic arch hook for broadcast it seems that we should remove the local timer API entirely. Doing so will reduce the architecture dependencies of our timer drivers, reduce code in ARM core, and simplify timer drivers because they no longer go through an architecture layer that is essentially a hotplug notifier.
Previous attempts have been made[1] unsuccessfully. I'm hoping this can be accepted now so that we can clean up the timer drivers that are used in both UP and SMP situations. Right now these drivers have to ignore the timer setup callback on the boot CPU to avoid registering clockevents twice. This is not very symmetric and causes convuluted code that does the same thing in two places.
Patches based on v3.10-rc1
I'm still looking for Acks/Tested-by on PRIMA2.
[1] http://article.gmane.org/gmane.linux.ports.arm.kernel/145705
Note: A hotplug notifier is used by both x86 for the apb_timer (see apbt_cpuhp_notify) and by metag (see arch_timer_cpu_notify in metag_generic.c) so this is not new.
Changes since v6:
* Picked up acks and resent
Changes since v5:
* Rebased onto v3.10-rc1
* Rebase caused minor updates to mct patch
Changes since v4:
* Rebased onto next-20130418
* Rebase caused minor updates to mct patch and twd Kconfig
Changes since v3:
* New patch to fix SMP with dummy timers registered after a global timer
* Push this_cpu_ptr lower to avoid preemptible false positive warnings
* Collected acks/tested-bys
Changes since v2:
* Bug fixes in smp_twd from Tony Lindgren's testing
* Move smp_twd to use late_time_init hook
* Collected Acks
Changes since v1:
* Picked up Mark's generic dummy timer driver
* Split out omap changes into new patch
Mark Rutland (1):
clocksource: add generic dummy timer driver
Stephen Boyd (10):
clockevents: Prefer CPU local devices over global devices
ARM: smp: Remove duplicate dummy timer implementation
ARM: smp_twd: Divorce smp_twd from local timer API
ARM: OMAP2+: Divorce from local timer API
ARM: EXYNOS4: Divorce mct from local timer API
ARM: PRIMA2: Divorce timer-marco from local timer API
ARM: msm: Divorce msm_timer from local timer API
clocksource: time-armada-370-xp: Fix sparse warning
clocksource: time-armada-370-xp: Divorce from local timer API
ARM: smp: Remove local timer API
arch/arm/Kconfig | 12 +-- arch/arm/include/asm/localtimer.h | 34 --------- arch/arm/kernel/smp.c | 87 --------------------- arch/arm/kernel/smp_twd.c | 64 ++++++++++------ arch/arm/mach-highbank/Kconfig | 2 +- arch/arm/mach-imx/Kconfig | 2 +- arch/arm/mach-msm/timer.c | 126 +++++++++++++++++-------------- arch/arm/mach-omap2/Kconfig | 3 +- arch/arm/mach-omap2/timer.c | 7 -- arch/arm/mach-realview/Kconfig | 8 +- arch/arm/mach-spear/Kconfig | 2 +- arch/arm/mach-tegra/Kconfig | 2 +- arch/arm/mach-ux500/Kconfig | 2 +- arch/arm/mach-vexpress/Kconfig | 2 +- arch/arm/mach-zynq/Kconfig | 2 +- drivers/clocksource/Makefile | 1 + drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++ drivers/clocksource/exynos_mct.c | 60 ++++++++++----- drivers/clocksource/time-armada-370-xp.c | 92 +++++++++++----------- drivers/clocksource/timer-marco.c | 100 +++++++++++++----------- include/linux/time-armada-370-xp.h | 4 +- kernel/time/tick-common.c | 5 +- 22 files changed, 340 insertions(+), 346 deletions(-) delete mode 100644 arch/arm/include/asm/localtimer.h create mode 100644 drivers/clocksource/dummy_timer.c
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 1/11 clockevents: Prefer CPU local devices over global devices
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
--- kernel/time/tick-common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/time/tick-common.c +3 -2
@@ -254,9 +254,10 @@ static int tick_check_new_device(struct clock_event_device *newdev) !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) goto out_bc;/* -* Check the rating +* Check the rating, but prefer CPU local devices */ -if (curdev->rating >= newdev->rating) +if (curdev->rating >= newdev->rating && +cpumask_equal (curdev->cpumask, newdev->cpumask)) goto out_bc; }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
Thanks
-- Daniel
Quoted 30 lines
Reported-by Mark Rutland <[email protected]>Tested-by Mark Rutland <[email protected]>Tested-by S?ren Brinkmann <[email protected]>Acked-by Marc Zyngier <[email protected]>,Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Daniel Lezcano <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- kernel/time/tick-common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)kernel/time/tick-common.c +3
-2@@ -254,9 +254,10 @@ static int tick_check_new_device(struct clock_event_device *newdev) !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) goto out_bc;/* -* Check the rating +* Check the rating, but prefer CPU local devices */ -if (curdev->rating >= newdev->rating) +if (curdev->rating >= newdev->rating && +cpumask_equal (curdev->cpumask, newdev->cpumask)) goto out_bc; }
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 21 lines · Daniel Lezcano
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 3 lines
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
There is one tick device per-cpu and one broadcast device. The broadcast device can only be a global clockevent, whereas the per-cpu tick device can be a global clockevent or a per-cpu clockevent. The code tries hard to keep per-cpu clockevents in the tick device slots but it has an ordering/rating requirement that doesn't work when there are only dummy per-cpu devices and one global device.
Perhaps an example will help. Let's say you only have one global clockevent such as the sp804, and you have SMP enabled. To support SMP we have to register dummy clockevents on each CPU so that the sp804 can go into broadcast mode. If we don't do this, only the CPU that registered the sp804 will get interrupts while the other CPUs will be left with no tick device and thus no scheduling. To fix this we register dummy clockevents on all the CPUs _before_ we register the sp804 to force the sp804 into the broadcast slot. Or we give the dummy clockevents a higher rating than the sp804 so that when we register them after the sp804 the sp804 is bumped out to broadcast duty.
If the dummy devices are registered before the sp804 we can give the dummies a low rating and the sp804 will still go into the broadcast slot due to this code:
/* * If we have a cpu local device already, do not replace it * by a non cpu local device */ if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) goto out_bc;
If we register the sp804 before the dummies we're also fine as long as the rating of the dummy is more than the sp804. Playing games with the dummy rating is not very nice so this patch fixes it by allowing the per-cpu device to replace the global device no matter what the rating of the global device is.
This fixes the sp804 case when the dummy is rated lower than sp804 and it removes any ordering requirement from the registration of clockevents. It also completes the logic above where we prefer cpu local devices over non cpu local devices.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 63 lines · Stephen Boyd
Quoted 21 lines · Daniel Lezcano
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 3 lines
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
There is one tick device per-cpu and one broadcast device. The broadcast device can only be a global clockevent, whereas the per-cpu tick device can be a global clockevent or a per-cpu clockevent. The code tries hard to keep per-cpu clockevents in the tick device slots but it has an ordering/rating requirement that doesn't work when there are only dummy per-cpu devices and one global device.
Perhaps an example will help. Let's say you only have one global clockevent such as the sp804, and you have SMP enabled. To support SMP we have to register dummy clockevents on each CPU so that the sp804 can go into broadcast mode. If we don't do this, only the CPU that registered the sp804 will get interrupts while the other CPUs will be left with no tick device and thus no scheduling. To fix this we register dummy clockevents on all the CPUs _before_ we register the sp804 to force the sp804 into the broadcast slot. Or we give the dummy clockevents a higher rating than the sp804 so that when we register them after the sp804 the sp804 is bumped out to broadcast duty.
If the dummy devices are registered before the sp804 we can give the dummies a low rating and the sp804 will still go into the broadcast slot due to this code:
/* * If we have a cpu local device already, do not replace it * by a non cpu local device */ if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) goto out_bc;If we register the sp804 before the dummies we're also fine as long as the rating of the dummy is more than the sp804. Playing games with the dummy rating is not very nice so this patch fixes it by allowing the per-cpu device to replace the global device no matter what the rating of the global device is.
Quoted 4 lines
This fixes the sp804 case when the dummy is rated lower than sp804 and it removes any ordering requirement from the registration of clockevents. It also completes the logic above where we prefer cpu local devices over non cpu local devices.
Thanks for the detailed explanation.
Did Thomas reacted to this patch ?
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 64 lines · Daniel Lezcano
Quoted 63 lines · Stephen Boyd
Quoted 21 lines · Daniel Lezcano
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 3 lines
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
There is one tick device per-cpu and one broadcast device. The broadcast device can only be a global clockevent, whereas the per-cpu tick device can be a global clockevent or a per-cpu clockevent. The code tries hard to keep per-cpu clockevents in the tick device slots but it has an ordering/rating requirement that doesn't work when there are only dummy per-cpu devices and one global device.
Perhaps an example will help. Let's say you only have one global clockevent such as the sp804, and you have SMP enabled. To support SMP we have to register dummy clockevents on each CPU so that the sp804 can go into broadcast mode. If we don't do this, only the CPU that registered the sp804 will get interrupts while the other CPUs will be left with no tick device and thus no scheduling. To fix this we register dummy clockevents on all the CPUs _before_ we register the sp804 to force the sp804 into the broadcast slot. Or we give the dummy clockevents a higher rating than the sp804 so that when we register them after the sp804 the sp804 is bumped out to broadcast duty.
If the dummy devices are registered before the sp804 we can give the dummies a low rating and the sp804 will still go into the broadcast slot due to this code:
/* * If we have a cpu local device already, do not replace it * by a non cpu local device */ if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) goto out_bc;If we register the sp804 before the dummies we're also fine as long as the rating of the dummy is more than the sp804. Playing games with the dummy rating is not very nice so this patch fixes it by allowing the per-cpu device to replace the global device no matter what the rating of the global device is.
Quoted 9 lines
Quoted 4 lines
This fixes the sp804 case when the dummy is rated lower than sp804 and it removes any ordering requirement from the registration of clockevents. It also completes the logic above where we prefer cpu local devices over non cpu local devices.
Thanks for the detailed explanation.
Did Thomas reacted to this patch ?
So far there has been no response from Thomas.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 70 lines · Stephen Boyd
Quoted 69 lines · Daniel Lezcano
Quoted 67 lines · Stephen Boyd
Quoted 21 lines · Daniel Lezcano
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 3 lines
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
There is one tick device per-cpu and one broadcast device. The broadcast device can only be a global clockevent, whereas the per-cpu tick device can be a global clockevent or a per-cpu clockevent. The code tries hard to keep per-cpu clockevents in the tick device slots but it has an ordering/rating requirement that doesn't work when there are only dummy per-cpu devices and one global device.
Perhaps an example will help. Let's say you only have one global clockevent such as the sp804, and you have SMP enabled. To support SMP we have to register dummy clockevents on each CPU so that the sp804 can go into broadcast mode. If we don't do this, only the CPU that registered the sp804 will get interrupts while the other CPUs will be left with no tick device and thus no scheduling. To fix this we register dummy clockevents on all the CPUs _before_ we register the sp804 to force the sp804 into the broadcast slot. Or we give the dummy clockevents a higher rating than the sp804 so that when we register them after the sp804 the sp804 is bumped out to broadcast duty.
If the dummy devices are registered before the sp804 we can give the dummies a low rating and the sp804 will still go into the broadcast slot due to this code:
/* * If we have a cpu local device already, do not replace it * by a non cpu local device */ if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) goto out_bc;If we register the sp804 before the dummies we're also fine as long as the rating of the dummy is more than the sp804. Playing games with the dummy rating is not very nice so this patch fixes it by allowing the per-cpu device to replace the global device no matter what the rating of the global device is.
This fixes the sp804 case when the dummy is rated lower than sp804 and it removes any ordering requirement from the registration of clockevents. It also completes the logic above where we prefer cpu local devices over non cpu local devices.
Quoted 7 lines
Quoted 4 lines
Thanks for the detailed explanation.
Did Thomas reacted to this patch ?
So far there has been no response from Thomas.
Will you ack this patch anyway? Or do we need Thomas to review this patch? It seems that this patch series has stalled again.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 73 lines · Stephen Boyd
Quoted 72 lines · Stephen Boyd
Quoted 71 lines · Daniel Lezcano
Quoted 63 lines · Stephen Boyd
Quoted 21 lines · Daniel Lezcano
Quoted 12 lines · Stephen Boyd
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
Quoted 7 lines
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 3 lines
It is not clear the connection between the changelog, the patch and the comment. Could you clarify a bit ?
There is one tick device per-cpu and one broadcast device. The broadcast device can only be a global clockevent, whereas the per-cpu tick device can be a global clockevent or a per-cpu clockevent. The code tries hard to keep per-cpu clockevents in the tick device slots but it has an ordering/rating requirement that doesn't work when there are only dummy per-cpu devices and one global device.
Perhaps an example will help. Let's say you only have one global clockevent such as the sp804, and you have SMP enabled. To support SMP we have to register dummy clockevents on each CPU so that the sp804 can go into broadcast mode. If we don't do this, only the CPU that registered the sp804 will get interrupts while the other CPUs will be left with no tick device and thus no scheduling. To fix this we register dummy clockevents on all the CPUs _before_ we register the sp804 to force the sp804 into the broadcast slot. Or we give the dummy clockevents a higher rating than the sp804 so that when we register them after the sp804 the sp804 is bumped out to broadcast duty.
If the dummy devices are registered before the sp804 we can give the dummies a low rating and the sp804 will still go into the broadcast slot due to this code:
/* * If we have a cpu local device already, do not replace it * by a non cpu local device */ if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) goto out_bc;If we register the sp804 before the dummies we're also fine as long as the rating of the dummy is more than the sp804. Playing games with the dummy rating is not very nice so this patch fixes it by allowing the per-cpu device to replace the global device no matter what the rating of the global device is.
Quoted 4 lines
This fixes the sp804 case when the dummy is rated lower than sp804 and it removes any ordering requirement from the registration of clockevents. It also completes the logic above where we prefer cpu local devices over non cpu local devices.
Thanks for the detailed explanation.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Did Thomas reacted to this patch ?
So far there has been no response from Thomas.
Will you ack this patch anyway? Or do we need Thomas to review this patch? It seems that this patch series has stalled again.
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
Thanks
-- Daniel
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 2 lines · Daniel Lezcano
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
The patch does not apply on tip timers/core. The code has been reworked a month ago. Please work against tip timers/core. That's where this stuff ends up.
Thanks,
tglx
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 8 lines · Thomas Gleixner
Quoted 2 lines · Daniel Lezcano
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
The patch does not apply on tip timers/core. The code has been reworked a month ago. Please work against tip timers/core. That's where this stuff ends up.
Ah, I thought your patch series had stalled. Here is a refreshed patch. Every other patch in this series applies cleanly to tip timers/core so I don't want to resend them again unless absolutely necessary.
-----8<-----
Subject: [PATCH v8] clockevents: Prefer CPU local devices over global devices
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
--- kernel/time/tick-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/time/tick-common.c +7 -2
@@ -243,8 +243,13 @@ static bool tick_check_preferred(struct clock_event_device *curdev,return false; } -/* Use the higher rated one */ -return !curdev || newdev->rating > curdev->rating; +/* +* Use the higher rated one, but prefer a CPU local device with a lower +* rating than a non-CPU local device +*/ +return !curdev || + newdev->rating > curdev->rating || + !cpumask_equal (curdev->cpumask, newdev->cpumask); }/*
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Sören Brinkmann
Tested-byRe: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 38 lines · Stephen Boyd
Quoted 8 lines · Thomas Gleixner
Quoted 2 lines · Daniel Lezcano
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
The patch does not apply on tip timers/core. The code has been reworked a month ago. Please work against tip timers/core. That's where this stuff ends up.
Ah, I thought your patch series had stalled. Here is a refreshed patch. Every other patch in this series applies cleanly to tip timers/core so I don't want to resend them again unless absolutely necessary.
-----8<-----
Subject: [PATCH v8] clockevents: Prefer CPU local devices over global devicesOn an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 5 lines
Reported-by Mark Rutland <[email protected]>Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Daniel Lezcano <[email protected]>Signed-off-by Stephen Boyd <[email protected]>
I retested my case on tip/timers/core with the same results.
S?ren
Mark Rutland
Tested-byRe: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
In reply to Stephen BoydQuoted 38 lines · Stephen Boyd
Quoted 8 lines · Thomas Gleixner
Quoted 2 lines · Daniel Lezcano
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
The patch does not apply on tip timers/core. The code has been reworked a month ago. Please work against tip timers/core. That's where this stuff ends up.
Ah, I thought your patch series had stalled. Here is a refreshed patch. Every other patch in this series applies cleanly to tip timers/core so I don't want to resend them again unless absolutely necessary.
-----8<-----
Subject: [PATCH v8] clockevents: Prefer CPU local devices over global devicesOn an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 5 lines
Reported-by Mark Rutland <[email protected]>Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Daniel Lezcano <[email protected]>Signed-off-by Stephen Boyd <[email protected]>
I've just tested this atop of tip/timers/core on a tc2, using only the sp804. As previously, without the patch boot hangs, and with the patch I'm able to reach userspace and do useful things.
Thanks for working on this, Stephen.
Mark.
Quoted 29 lines
--- kernel/time/tick-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)kernel/time/tick-common.c +7
-2@@ -243,8 +243,13 @@ static bool tick_check_preferred(struct clock_event_device *curdev,return false; } -/* Use the higher rated one */ -return !curdev || newdev->rating > curdev->rating; +/* +* Use the higher rated one, but prefer a CPU local device with a lower +* rating than a non-CPU local device +*/ +return !curdev || + newdev->rating > curdev->rating || + !cpumask_equal (curdev->cpumask, newdev->cpumask); }/* Signature · 3 lines
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Thomas,
Quoted 45 lines · Mark Rutland
Quoted 38 lines · Stephen Boyd
Quoted 8 lines · Thomas Gleixner
Quoted 2 lines · Daniel Lezcano
I prefer Thomas to have a look at it and ack it. I changed Cc to To for Thomas.
The patch does not apply on tip timers/core. The code has been reworked a month ago. Please work against tip timers/core. That's where this stuff ends up.
Ah, I thought your patch series had stalled. Here is a refreshed patch. Every other patch in this series applies cleanly to tip timers/core so I don't want to resend them again unless absolutely necessary.
-----8<-----
Subject: [PATCH v8] clockevents: Prefer CPU local devices over global devicesOn an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
Quoted 5 lines
Reported-by Mark Rutland <[email protected]>Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Daniel Lezcano <[email protected]>Signed-off-by Stephen Boyd <[email protected]>
Quoted 7 lines
I've just tested this atop of tip/timers/core on a tc2, using only the sp804. As previously, without the patch boot hangs, and with the patch I'm able to reach userspace and do useful things.
Tested-by Mark Rutland <[email protected]>Thanks for working on this, Stephen.
Can you pick up the first two patches in this series please? And preferably make a stable branch that can be pulled into arm-soc? Then I can send the rest through the arm-soc tree.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 5 lines · Stephen Boyd
Can you pick up the first two patches in this series please? And preferably make a stable branch that can be pulled into arm-soc? Then I can send the rest through the arm-soc tree.
ping?
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
Quoted 7 lines · Stephen Boyd
Quoted 4 lines · Stephen Boyd
Can you pick up the first two patches in this series please? And preferably make a stable branch that can be pulled into arm-soc? Then I can send the rest through the arm-soc tree.
ping?
Thomas, please apply these first two patches.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
tip-bot for Stephen Boyd
merge bot[tip:timers/core] clockevents: Prefer CPU local devices over global devices
In reply to Stephen Boydclockevents: Prefer CPU local devices over global devices
Commit-ID: 70e5975d3a04be5479a28eec4a2fb10f98ad2785 Gitweb: http://git.kernel.org/tip/70e5975d3a04be5479a28eec4a2fb10f98ad2785 Author: Stephen Boyd <[email protected]> AuthorDate: Thu, 13 Jun 2013 11:39:50 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Mon, 24 Jun 2013 22:27:36 +0200
clockevents: Prefer CPU local devices over global devices
On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices.
If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above.
--- kernel/time/tick-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/time/tick-common.c +7 -2
@@ -243,8 +243,13 @@ static bool tick_check_preferred(struct clock_event_device *curdev,return false; } -/* Use the higher rated one */ -return !curdev || newdev->rating > curdev->rating; +/* +* Use the higher rated one, but prefer a CPU local device with a lower +* rating than a non-CPU local device +*/ +return !curdev || + newdev->rating > curdev->rating || + !cpumask_equal (curdev->cpumask, newdev->cpumask); }/*
PATCH v7 2/11 clocksource: add generic dummy timer driver
In reply to Stephen BoydFrom: Mark Rutland <[email protected]>
Several architectures have a dummy timer driver tightly coupled with their broadcast code to support machines without cpu-local timers (or where there is a lack of driver support).
Since 12ad100046: "clockevents: Add generic timer broadcast function" it's been possible to write broadcast-capable timer drivers decoupled from the broadcast mechanism. We can use this functionality to implement a generic dummy timer driver that can be shared by all architectures with generic tick broadcast (ARCH_HAS_TICK_BROADCAST).
This patch implements a generic dummy timer using this facility.
[sboyd: Make percpu data static, use __this_cpu_ptr(), move to
early_initcall to properly register on each CPU, only register if more than one CPU possible]
--- drivers/clocksource/Makefile | 1 + drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 drivers/clocksource/dummy_timer.c
drivers/clocksource/Makefile +1 -0
@@ -29,3 +29,4 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o +obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
drivers/clocksource/dummy_timer.c new file +69 -0
69 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 02/11] clocksource: add generic dummy timer driver
Quoted 19 lines · Stephen Boyd
From: Mark Rutland <[email protected]>
Several architectures have a dummy timer driver tightly coupled with their broadcast code to support machines without cpu-local timers (or where there is a lack of driver support).
Since
12ad100046: "clockevents: Add generic timer broadcast function" it's been possible to write broadcast-capable timer drivers decoupled from the broadcast mechanism. We can use this functionality to implement a generic dummy timer driver that can be shared by all architectures with generic tick broadcast (ARCH_HAS_TICK_BROADCAST).This patch implements a generic dummy timer using this facility.
Signed-off-by Mark Rutland <[email protected]>Acked-by Marc Zyngier <[email protected]>,Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Daniel Lezcano <[email protected]>
Quoted 5 lines
[sboyd: Make percpu data static, use
__this_cpu_ptr(), move to
early_initcallto properly register on each CPU, only register if more than one CPU possible]Signed-off-by Stephen Boyd <[email protected]>---
Except the missing first letter capitalization, in the patch description 'add' => 'Add'.
Quoted 90 lines
drivers/clocksource/Makefile | 1 + drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 drivers/clocksource/dummy_timer.cdrivers/clocksource/Makefile +1
-0@@ -29,3 +29,4 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o +obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.odrivers/clocksource/dummy_timer.c new file +69
-0@@ -0,0 +1,69 @@ +/* +* linux/drivers/clocksource/dummy_timer.c +* +* Copyright (C) 2013 ARM Ltd. +* All Rights Reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/clockchips.h> +#include <linux/cpu.h> +#include <linux/init.h> +#include <linux/percpu.h> +#include <linux/cpumask.h> + +static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt); + +static void dummy_timer_set_mode (enum clock_event_mode mode, +struct clock_event_device *evt) +{ +/* +* Core clockevents code will call this when exchanging timer devices. +* We don't need to do anything here. +*/ +} + +static void __cpuinit dummy_timer_setup (void ) +{ +int cpu =smp_processor_id (); +struct clock_event_device *evt =__this_cpu_ptr (&dummy_timer_evt); + + evt->name ="dummy_timer" ; + evt->features =CLOCK_EVT_FEAT_PERIODIC | +CLOCK_EVT_FEAT_ONESHOT | +CLOCK_EVT_FEAT_DUMMY ; + evt->rating =100 ; + evt->set_mode = dummy_timer_set_mode; + evt->cpumask =cpumask_of (cpu); + +clockevents_register_device (evt); +} + +static int __cpuinit dummy_timer_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +if ((action & ~CPU_TASKS_FROZEN ) ==CPU_STARTING ) +dummy_timer_setup (); + +return NOTIFY_OK ; +} + +static struct notifier_block dummy_timer_cpu_nb__cpuinitdata = { + .notifier_call = dummy_timer_cpu_notify, +}; + +static int __init dummy_timer_register (void ) +{ +int err =register_cpu_notifier (&dummy_timer_cpu_nb); +if (err) +return err; + +/* We won't get a call on the boot CPU, so register immediately */ +if (num_possible_cpus () >1 ) +dummy_timer_setup (); + +return 0 ; +} +early_initcall (dummy_timer_register);
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
tip-bot for Mark Rutland
merge bot[tip:timers/core] clocksource: Add generic dummy timer driver
In reply to Stephen Boydclocksource: Add generic dummy timer driver
Commit-ID: 064706514ec3fea740c2656e03c4f01f6a551ac4 Gitweb: http://git.kernel.org/tip/064706514ec3fea740c2656e03c4f01f6a551ac4 Author: Mark Rutland <[email protected]> AuthorDate: Mon, 3 Jun 2013 13:33:53 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Mon, 24 Jun 2013 22:27:37 +0200
clocksource: Add generic dummy timer driver
Several architectures have a dummy timer driver tightly coupled with their broadcast code to support machines without cpu-local timers (or where there is a lack of driver support).
Since 12ad100046: "clockevents: Add generic timer broadcast function" it's been possible to write broadcast-capable timer drivers decoupled from the broadcast mechanism. We can use this functionality to implement a generic dummy timer driver that can be shared by all architectures with generic tick broadcast (ARCH_HAS_TICK_BROADCAST).
This patch implements a generic dummy timer using this facility.
[sboyd: Make percpu data static, use __this_cpu_ptr(), move to
early_initcall to properly register on each CPU, only register if more than one CPU possible]
--- drivers/clocksource/Makefile | 1 + drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+)
drivers/clocksource/Makefile +1 -0
@@ -31,3 +31,4 @@ obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o +obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
drivers/clocksource/dummy_timer.c new file +69 -0
69 lines not on this page · raw message
PATCH v7 3/11 ARM: smp: Remove duplicate dummy timer implementation
In reply to Stephen BoydDrop ARM's version of the dummy timer now that we have a generic implementation in drivers/clocksource.
--- arch/arm/kernel/smp.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-)
arch/arm/kernel/smp.c +2 -20
@@ -503,24 +503,6 @@ void tick_broadcast(const struct cpumask *mask) }#endif -static void broadcast_timer_set_mode (enum clock_event_mode mode, -struct clock_event_device *evt) -{ -} - -static void __cpuinit broadcast_timer_setup (struct clock_event_device *evt) -{ - evt->name ="dummy_timer" ; - evt->features =CLOCK_EVT_FEAT_ONESHOT | -CLOCK_EVT_FEAT_PERIODIC | -CLOCK_EVT_FEAT_DUMMY ; - evt->rating =100 ; - evt->mult =1 ; - evt->set_mode = broadcast_timer_set_mode; - -clockevents_register_device (evt); -} -static struct local_timer_ops *lt_ops;#ifdef CONFIG_LOCAL_TIMERS
@@ -544,8 +526,8 @@ static void __cpuinit percpu_timer_setup(void) evt->cpumask =cpumask_of (cpu); -if (!lt_ops || lt_ops->setup (evt)) -broadcast_timer_setup (evt); +if (lt_ops) + lt_ops->setup (evt); }#ifdef CONFIG_HOTPLUG_CPU
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 4/11 ARM: smp_twd: Divorce smp_twd from local timer API
In reply to Stephen BoydSeparate the smp_twd timers from the local timer API. This will allow us to remove ARM local timer support in the near future and gets us closer to moving this driver to drivers/clocksource.
--- arch/arm/Kconfig | 2 +- arch/arm/kernel/smp_twd.c | 64 ++++++++++++++++++++++++++++-------------- arch/arm/mach-highbank/Kconfig | 2 +- arch/arm/mach-imx/Kconfig | 2 +- arch/arm/mach-omap2/Kconfig | 2 +- arch/arm/mach-realview/Kconfig | 8 +++--- arch/arm/mach-spear/Kconfig | 2 +- arch/arm/mach-tegra/Kconfig | 2 +- arch/arm/mach-ux500/Kconfig | 2 +- arch/arm/mach-vexpress/Kconfig | 2 +- arch/arm/mach-zynq/Kconfig | 2 +- 11 files changed, 56 insertions(+), 34 deletions(-)
arch/arm/Kconfig +1 -1
@@ -636,7 +636,7 @@ config ARCH_SHMOBILE select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_CLK select HAVE_MACH_CLKDEV select HAVE_SMP
arch/arm/kernel/smp_twd.c +43 -21
163 lines not on this page · raw message
arch/arm/mach-highbank/Kconfig +1 -1
@@ -12,7 +12,7 @@ config ARCH_HIGHBANK select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select MAILBOX select PL320_MBOX
arch/arm/mach-imx/Kconfig +1 -1
@@ -798,7 +798,7 @@ config SOC_IMX6Q select COMMON_CLK select CPU_V7 select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_CAN_FLEXCAN if CAN select HAVE_IMX_ANATOP select HAVE_IMX_GPC
arch/arm/mach-omap2/Kconfig +1 -1
@@ -90,7 +90,7 @@ config ARCH_OMAP4 select CACHE_L2X0 select CPU_V7 select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select LOCAL_TIMERS if SMP select OMAP_INTERCONNECT
arch/arm/mach-realview/Kconfig +4 -4
@@ -13,7 +13,7 @@ config REALVIEW_EB_A9MP depends on MACH_REALVIEW_EB select CPU_V7 select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 help
@@ -26,7 +26,7 @@ config REALVIEW_EB_ARM11MP select ARCH_HAS_BARRIERS if SMP select CPU_V6K select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 help
@@ -48,7 +48,7 @@ config MACH_REALVIEW_PB11MP select ARM_GIC select CPU_V6K select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_PATA_PLATFORM select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0
@@ -92,7 +92,7 @@ config MACH_REALVIEW_PBX select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET select ARM_GIC select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_PATA_PLATFORM select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0
arch/arm/mach-spear/Kconfig +1 -1
@@ -23,7 +23,7 @@ config ARCH_SPEAR13XX select CPU_V7 select GPIO_SPEAR_SPICS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 select PINCTRL
arch/arm/mach-tegra/Kconfig +1 -1
@@ -8,7 +8,7 @@ config ARCH_TEGRA select COMMON_CLK select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_CLK select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0
arch/arm/mach-ux500/Kconfig +1 -1
@@ -8,7 +8,7 @@ config ARCH_U8500 select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 help
arch/arm/mach-vexpress/Kconfig +1 -1
@@ -10,7 +10,7 @@ config ARCH_VEXPRESS select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_CLK select HAVE_PATA_PLATFORM select HAVE_SMP
arch/arm/mach-zynq/Kconfig +1 -1
@@ -6,7 +6,7 @@ config ARCH_ZYNQ select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select ICST select MIGHT_HAVE_CACHE_L2X0 select USE_OF
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 5/11 ARM: OMAP2+: Divorce from local timer API
In reply to Stephen BoydNow that the TWD doesn't rely on the local timer API, OMAP can stop selecting it in Kconfig and relying on the config option to decide if it should call smp_twd functions.
--- arch/arm/mach-omap2/Kconfig | 1 - arch/arm/mach-omap2/timer.c | 7 ------- 2 files changed, 8 deletions(-)
arch/arm/mach-omap2/Kconfig +0 -1
@@ -92,7 +92,6 @@ config ARCH_OMAP4 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select HAVE_SMP - select LOCAL_TIMERS if SMP select OMAP_INTERCONNECT select PL310_ERRATA_588369 select PL310_ERRATA_727915
arch/arm/mach-omap2/timer.c +0 -7
@@ -600,7 +600,6 @@ static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",#endif #ifdef CONFIG_ARCH_OMAP4 -#ifdef CONFIG_LOCAL_TIMERS static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);void __init omap4_local_timer_init (void ) {
@@ -619,12 +618,6 @@ void __init omap4_local_timer_init(void) pr_err("twd_local_timer_register failed %d\n", err); } } -#else /* CONFIG_LOCAL_TIMERS */ -void __init omap4_local_timer_init (void ) -{ -omap4_sync32k_timer_init (); -} -#endif /* CONFIG_LOCAL_TIMERS */ #endif /* CONFIG_ARCH_OMAP4 */ #ifdef CONFIG_SOC_OMAP5
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 6/11 ARM: EXYNOS4: Divorce mct from local timer API
In reply to Stephen BoydSeparate the mct local timers from the local timer API. This will allow us to remove ARM local timer support in the near future and gets us closer to moving this driver to drivers/clocksource.
--- drivers/clocksource/exynos_mct.c | 60 ++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 17 deletions(-)
drivers/clocksource/exynos_mct.c +43 -17
@@ -16,6 +16,7 @@#include <linux/err.h> #include <linux/clk.h> #include <linux/clockchips.h> +#include <linux/cpu.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/percpu.h>
@@ -24,7 +25,6 @@#include <linux/of_address.h> #include <linux/clocksource.h> -#include <asm/localtimer.h> #include <asm/mach/time.h> #define EXYNOS4_MCTREG (x) (x)
@@ -80,7 +80,7 @@ static unsigned int mct_int_type;static int mct_irqs[MCT_NR_IRQS ];struct mct_clock_event_device { -struct clock_event_device *evt; +struct clock_event_device evt;unsigned long base;char name[10 ]; };
@@ -295,8 +295,6 @@ static void exynos4_clockevent_init(void)setup_irq (mct_irqs[MCT_G0_IRQ ], &mct_comp_event_irq); } -#ifdef CONFIG_LOCAL_TIMERS - static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);/* Clock event handling */
@@ -369,7 +367,7 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,static int exynos4_mct_tick_clear (struct mct_clock_event_device *mevt) { -struct clock_event_device *evt = mevt->evt; +struct clock_event_device *evt = &mevt->evt;/* * This is for supporting oneshot mode.
@@ -391,7 +389,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)static irqreturn_t exynos4_mct_tick_isr (int irq,void *dev_id) {struct mct_clock_event_device *mevt = dev_id; -struct clock_event_device *evt = mevt->evt; +struct clock_event_device *evt = &mevt->evt;exynos4_mct_tick_clear (mevt);
@@ -417,8 +415,7 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)struct mct_clock_event_device *mevt;unsigned int cpu =smp_processor_id (); - mevt =this_cpu_ptr (&percpu_mct_tick); - mevt->evt = evt; + mevt = container_of(evt, struct mct_clock_event_device, evt); mevt->base =EXYNOS4_MCT_L_BASE (cpu);sprintf (mevt->name,"mct_tick%d" , cpu);
@@ -452,7 +449,7 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)return 0 ; } -static void exynos4_local_timer_stop (struct clock_event_device *evt) +static void __cpuinit exynos4_local_timer_stop (struct clock_event_device *evt) {unsigned int cpu =smp_processor_id (); evt->set_mode (CLOCK_EVT_MODE_UNUSED , evt);
@@ -465,14 +462,37 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)disable_percpu_irq (mct_irqs[MCT_L0_IRQ ]); } -static struct local_timer_ops exynos4_mct_tick_ops__cpuinitdata = { - .setup = exynos4_local_timer_setup, - .stop = exynos4_local_timer_stop, +static int __cpuinit exynos4_mct_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +struct mct_clock_event_device *mevt; + +/* +* Grab cpu pointer in each case to avoid spurious +* preemptible warnings +*/ +switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_STARTING : + mevt =this_cpu_ptr (&percpu_mct_tick); +exynos4_local_timer_setup (&mevt->evt); +break ; +case CPU_DYING : + mevt =this_cpu_ptr (&percpu_mct_tick); +exynos4_local_timer_stop (&mevt->evt); +break ; + } + +return NOTIFY_OK ; +} + +static struct notifier_block exynos4_mct_cpu_nb__cpuinitdata = { + .notifier_call = exynos4_mct_cpu_notify, }; -#endif /* CONFIG_LOCAL_TIMERS */ static void __init exynos4_timer_resources (struct device_node *np,void __iomem *base) { +int err; +struct mct_clock_event_device *mevt =this_cpu_ptr (&percpu_mct_tick);struct clk *mct_clk, *tick_clk; tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
@@ -490,9 +510,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomemif (!reg_base)panic ("%s: unable to ioremap mct address space\n" , __func__); -#ifdef CONFIG_LOCAL_TIMERS if (mct_int_type ==MCT_INT_PPI ) { -int err; err = request_percpu_irq(mct_irqs[MCT_L0_IRQ], exynos4_mct_tick_isr, "MCT",
@@ -501,8 +519,16 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem mct_irqs[MCT_L0_IRQ], err); } -local_timer_register (&exynos4_mct_tick_ops); -#endif /* CONFIG_LOCAL_TIMERS */ + err =register_cpu_notifier (&exynos4_mct_cpu_nb); +if (err) + goto out_irq; + +/* Immediately configure the timer on the boot CPU */ +exynos4_local_timer_setup (&mevt->evt); +return ; + +out_irq: +free_percpu_irq (mct_irqs[MCT_L0_IRQ ], &percpu_mct_tick); }void __init mct_init (void __iomem *base,int irq_g0,int irq_l0,int irq_l1)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 7/11 ARM: PRIMA2: Divorce timer-marco from local timer API
In reply to Stephen BoydSeparate the marco local timers from the local timer API. This will allow us to remove ARM local timer support in the near future and gets us closer to moving this driver to drivers/clocksource.
--- drivers/clocksource/timer-marco.c | 100 ++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 46 deletions(-)
drivers/clocksource/timer-marco.c +54 -46
@@ -10,6 +10,7 @@#include <linux/interrupt.h> #include <linux/clockchips.h> #include <linux/clocksource.h> +#include <linux/cpu.h> #include <linux/bitops.h> #include <linux/irq.h> #include <linux/clk.h>
@@ -18,7 +19,6 @@#include <linux/of_irq.h> #include <linux/of_address.h> #include <asm/sched_clock.h> -#include <asm/localtimer.h> #include <asm/mach/time.h> #define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
@@ -151,13 +151,7 @@ static void sirfsoc_clocksource_resume(struct clocksource *cs) BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); } -static struct clock_event_device sirfsoc_clockevent = { - .name ="sirfsoc_clockevent" , - .rating =200 , - .features =CLOCK_EVT_FEAT_ONESHOT , - .set_mode = sirfsoc_timer_set_mode, - .set_next_event = sirfsoc_timer_set_next_event, -}; +static struct clock_event_device __percpu *sirfsoc_clockevent;static struct clocksource sirfsoc_clocksource = { .name ="sirfsoc_clocksource" ,
@@ -173,11 +167,8 @@ static struct irqaction sirfsoc_timer_irq = { .name = "sirfsoc_timer0", .flags = IRQF_TIMER | IRQF_NOBALANCING, .handler = sirfsoc_timer_interrupt, - .dev_id = &sirfsoc_clockevent, }; -#ifdef CONFIG_LOCAL_TIMERS -static struct irqaction sirfsoc_timer1_irq = { .name ="sirfsoc_timer1" , .flags =IRQF_TIMER |IRQF_NOBALANCING ,
@@ -186,56 +177,77 @@ static struct irqaction sirfsoc_timer1_irq = {static int __cpuinit sirfsoc_local_timer_setup (struct clock_event_device *ce) { -/* Use existing clock_event for cpu 0 */ -if (!smp_processor_id ()) -return 0 ; +int cpu =smp_processor_id (); +struct irqaction *action; + +if (cpu ==0 ) + action = &sirfsoc_timer_irq; +else + action = &sirfsoc_timer1_irq; - ce->irq = sirfsoc_timer1_irq.irq; + ce->irq = action->irq; ce->name ="local_timer" ; - ce->features = sirfsoc_clockevent.features; - ce->rating = sirfsoc_clockevent.rating; + ce->features =CLOCK_EVT_FEAT_ONESHOT ; + ce->rating =200 ; ce->set_mode = sirfsoc_timer_set_mode; ce->set_next_event = sirfsoc_timer_set_next_event; - ce->shift = sirfsoc_clockevent.shift; - ce->mult = sirfsoc_clockevent.mult; - ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns; - ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns; +clockevents_calc_mult_shift (ce,CLOCK_TICK_RATE ,60 ); + ce->max_delta_ns =clockevent_delta2ns (-2 , ce); + ce->min_delta_ns =clockevent_delta2ns (2 , ce); + ce->cpumask =cpumask_of (cpu); - sirfsoc_timer1_irq.dev_id = ce; -BUG_ON (setup_irq (ce->irq, &sirfsoc_timer1_irq)); -irq_set_affinity (sirfsoc_timer1_irq.irq,cpumask_of (1 )); + action->dev_id = ce; +BUG_ON (setup_irq (ce->irq, action)); +irq_set_affinity (action->irq,cpumask_of (cpu));clockevents_register_device (ce);return 0 ; } -static void sirfsoc_local_timer_stop (struct clock_event_device *ce) +static void __cpuinit sirfsoc_local_timer_stop (struct clock_event_device *ce) { +int cpu =smp_processor_id (); +sirfsoc_timer_count_disable (1 ); -remove_irq (sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); +if (cpu ==0 ) +remove_irq (sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); +else +remove_irq (sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); } -static struct local_timer_ops sirfsoc_local_timer_ops__cpuinitdata = { - .setup = sirfsoc_local_timer_setup, - .stop = sirfsoc_local_timer_stop, +static int __cpuinit sirfsoc_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +/* +* Grab cpu pointer in each case to avoid spurious +* preemptible warnings +*/ +switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_STARTING : +sirfsoc_local_timer_setup (this_cpu_ptr (sirfsoc_clockevent)); +break ; +case CPU_DYING : +sirfsoc_local_timer_stop (this_cpu_ptr (sirfsoc_clockevent)); +break ; + } + +return NOTIFY_OK ; +} + +static struct notifier_block sirfsoc_cpu_nb__cpuinitdata = { + .notifier_call = sirfsoc_cpu_notify, }; -#endif /* CONFIG_LOCAL_TIMERS */ static void __init sirfsoc_clockevent_init (void ) { -clockevents_calc_mult_shift (&sirfsoc_clockevent,CLOCK_TICK_RATE ,60 ); - - sirfsoc_clockevent.max_delta_ns = -clockevent_delta2ns (-2 , &sirfsoc_clockevent); - sirfsoc_clockevent.min_delta_ns = -clockevent_delta2ns (2 , &sirfsoc_clockevent); - - sirfsoc_clockevent.cpumask =cpumask_of (0 ); -clockevents_register_device (&sirfsoc_clockevent); -#ifdef CONFIG_LOCAL_TIMERS -local_timer_register (&sirfsoc_local_timer_ops); -#endif + sirfsoc_clockevent = alloc_percpu(struct clock_event_device); +BUG_ON (!sirfsoc_clockevent); + +BUG_ON (register_cpu_notifier (&sirfsoc_cpu_nb)); + +/* Immediately configure the timer on the boot CPU */ +sirfsoc_local_timer_setup (this_cpu_ptr (sirfsoc_clockevent)); }/* initialize the kernel jiffy timer source */
@@ -273,8 +285,6 @@ static void __init sirfsoc_marco_timer_init(void)BUG_ON (clocksource_register_hz (&sirfsoc_clocksource,CLOCK_TICK_RATE )); -BUG_ON (setup_irq (sirfsoc_timer_irq.irq, &sirfsoc_timer_irq)); -sirfsoc_clockevent_init (); }
@@ -288,11 +298,9 @@ static void __init sirfsoc_of_timer_init(struct device_node *np)if (!sirfsoc_timer_irq.irq)panic ("No irq passed for timer0 via DT\n" ); -#ifdef CONFIG_LOCAL_TIMERS sirfsoc_timer1_irq.irq =irq_of_parse_and_map (np,1 );if (!sirfsoc_timer1_irq.irq)panic ("No irq passed for timer1 via DT\n" ); -#endif sirfsoc_marco_timer_init (); }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 8/11 ARM: msm: Divorce msm_timer from local timer API
In reply to Stephen BoydSeparate the msm_timer from the local timer API. This will allow us to remove ARM local timer support in the near future and gets us closer to moving this driver to drivers/clocksource.
--- arch/arm/mach-msm/timer.c | 126 +++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 56 deletions(-)
arch/arm/mach-msm/timer.c +70 -56
@@ -16,6 +16,7 @@#include <linux/clocksource.h> #include <linux/clockchips.h> +#include <linux/cpu.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h>
@@ -25,7 +26,6 @@#include <linux/of_irq.h> #include <asm/mach/time.h> -#include <asm/localtimer.h> #include <asm/sched_clock.h> #include "common.h"
@@ -49,7 +49,7 @@ static void __iomem *sts_base;static irqreturn_t msm_timer_interrupt (int irq,void *dev_id) { -struct clock_event_device *evt = *(struct clock_event_device **)dev_id; +struct clock_event_device *evt = dev_id;/* Stop the timer tick */ if (evt->mode ==CLOCK_EVT_MODE_ONESHOT ) {u32 ctrl =readl_relaxed (event_base +TIMER_ENABLE );
@@ -101,18 +101,7 @@ static void msm_timer_set_mode(enum clock_event_mode mode,writel_relaxed (ctrl, event_base +TIMER_ENABLE ); } -static struct clock_event_device msm_clockevent = { - .name ="gp_timer" , - .features =CLOCK_EVT_FEAT_ONESHOT , - .rating =200 , - .set_next_event = msm_timer_set_next_event, - .set_mode = msm_timer_set_mode, -}; - -static union { -struct clock_event_device *evt; -struct clock_event_device *__percpu *percpu_evt; -} msm_evt; +static struct clock_event_device __percpu *msm_evt;static void __iomem *source_base;
@@ -138,37 +127,65 @@ static struct clocksource msm_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -#ifdef CONFIG_LOCAL_TIMERS +static int msm_timer_irq; +static int msm_timer_has_ppi; +static int __cpuinit msm_local_timer_setup (struct clock_event_device *evt) { -/* Use existing clock_event for cpu 0 */ -if (!smp_processor_id ()) -return 0 ; - - evt->irq = msm_clockevent.irq; - evt->name ="local_timer" ; - evt->features = msm_clockevent.features; - evt->rating = msm_clockevent.rating; +int cpu =smp_processor_id (); +int err; + + evt->irq = msm_timer_irq; + evt->name ="msm_timer" ; + evt->features =CLOCK_EVT_FEAT_ONESHOT ; + evt->rating =200 ; evt->set_mode = msm_timer_set_mode; evt->set_next_event = msm_timer_set_next_event; + evt->cpumask =cpumask_of (cpu); + +clockevents_config_and_register (evt,GPT_HZ ,4 ,0xffffffff ); + +if (msm_timer_has_ppi) { +enable_percpu_irq (evt->irq,IRQ_TYPE_EDGE_RISING ); + }else { + err =request_irq (evt->irq, msm_timer_interrupt, +IRQF_TIMER |IRQF_NOBALANCING | +IRQF_TRIGGER_RISING ,"gp_timer" , evt); +if (err) +pr_err ("request_irq failed\n" ); + } - *__this_cpu_ptr (msm_evt.percpu_evt) = evt; -clockevents_config_and_register (evt,GPT_HZ ,4 ,0xf0000000 ); -enable_percpu_irq (evt->irq,IRQ_TYPE_EDGE_RISING );return 0 ; } -static void msm_local_timer_stop (struct clock_event_device *evt) +static void __cpuinit msm_local_timer_stop (struct clock_event_device *evt) { evt->set_mode (CLOCK_EVT_MODE_UNUSED , evt);disable_percpu_irq (evt->irq); } -static struct local_timer_ops msm_local_timer_ops__cpuinitdata = { - .setup = msm_local_timer_setup, - .stop = msm_local_timer_stop, +static int __cpuinit msm_timer_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +/* +* Grab cpu pointer in each case to avoid spurious +* preemptible warnings +*/ +switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_STARTING : +msm_local_timer_setup (this_cpu_ptr (msm_evt)); +break ; +case CPU_DYING : +msm_local_timer_stop (this_cpu_ptr (msm_evt)); +break ; + } + +return NOTIFY_OK ; +} + +static struct notifier_block msm_timer_cpu_nb__cpuinitdata = { + .notifier_call = msm_timer_cpu_notify, }; -#endif /* CONFIG_LOCAL_TIMERS */ static notrace u32 msm_sched_clock_read(void) {
@@ -178,38 +195,35 @@ static notrace u32 msm_sched_clock_read(void)static void __init msm_timer_init (u32 dgt_hz,int sched_bits,int irq,bool percpu) { -struct clock_event_device *ce = &msm_clockevent;struct clocksource *cs = &msm_clocksource; -int res; +int res =0 ; + + msm_timer_irq = irq; + msm_timer_has_ppi = percpu; + + msm_evt = alloc_percpu(struct clock_event_device); +if (!msm_evt) { +pr_err ("memory allocation failed for clockevents\n" ); + goto err; + } - ce->cpumask =cpumask_of (0 ); - ce->irq = irq; +if (percpu) + res =request_percpu_irq (irq, msm_timer_interrupt, +"gp_timer" , msm_evt); -clockevents_config_and_register (ce,GPT_HZ ,4 ,0xffffffff ); -if (percpu) { - msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *); -if (!msm_evt.percpu_evt) { -pr_err ("memory allocation failed for %s\n" , ce->name); +if (res) { +pr_err ("request_percpu_irq failed\n" ); + }else { + res =register_cpu_notifier (&msm_timer_cpu_nb); +if (res) { +free_percpu_irq (irq, msm_evt); goto err; } - *__this_cpu_ptr (msm_evt.percpu_evt) = ce; - res =request_percpu_irq (ce->irq, msm_timer_interrupt, - ce->name, msm_evt.percpu_evt); -if (!res) { -enable_percpu_irq (ce->irq,IRQ_TYPE_EDGE_RISING ); -#ifdef CONFIG_LOCAL_TIMERS -local_timer_register (&msm_local_timer_ops); -#endif - } - }else { - msm_evt.evt = ce; - res =request_irq (ce->irq, msm_timer_interrupt, -IRQF_TIMER |IRQF_NOBALANCING | -IRQF_TRIGGER_RISING , ce->name, &msm_evt.evt); + +/* Immediately configure the timer on the boot CPU */ +msm_local_timer_setup (__this_cpu_ptr (msm_evt)); } -if (res) -pr_err ("request_irq failed for %s\n" , ce->name); err:writel_relaxed (TIMER_ENABLE_EN , source_base +TIMER_ENABLE ); res =clocksource_register_hz (cs, dgt_hz);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 9/11 clocksource: time-armada-370-xp: Fix sparse warning
In reply to Stephen Boyddrivers/clocksource/time-armada-370-xp.c:217:13: warning: symbol 'armada_370_xp_timer_init' was not declared. Should it be static?
Also remove the __init marking in the prototype as it's unnecessary and drop the init.h file.
--- drivers/clocksource/time-armada-370-xp.c | 3 ++- include/linux/time-armada-370-xp.h | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-)
drivers/clocksource/time-armada-370-xp.c +2 -1
@@ -27,10 +27,11 @@#include <linux/of_address.h> #include <linux/irq.h> #include <linux/module.h> +#include <linux/percpu.h> +#include <linux/time-armada-370-xp.h> #include <asm/sched_clock.h> #include <asm/localtimer.h> -#include <linux/percpu.h> /* * Timer block registers. */
include/linux/time-armada-370-xp.h +1 -3
@@ -11,8 +11,6 @@#ifndef __TIME_ARMADA_370_XPPRCMU_H#define __TIME_ARMADA_370_XPPRCMU_H -#include <linux/init.h> - -void __init armada_370_xp_timer_init (void ); +void armada_370_xp_timer_init (void );#endif
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 10/11 clocksource: time-armada-370-xp: Divorce from local timer API
In reply to Stephen BoydSeparate the armada 370xp local timers from the local timer API. This will allow us to remove ARM local timer support in the near future and makes this driver multi-architecture friendly.
--- drivers/clocksource/time-armada-370-xp.c | 89 +++++++++++++++----------------- 1 file changed, 41 insertions(+), 48 deletions(-)
drivers/clocksource/time-armada-370-xp.c +41 -48
@@ -19,6 +19,7 @@#include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/clk.h> +#include <linux/cpu.h> #include <linux/timer.h> #include <linux/clockchips.h> #include <linux/interrupt.h>
@@ -31,7 +32,6 @@#include <linux/time-armada-370-xp.h> #include <asm/sched_clock.h> -#include <asm/localtimer.h> /* * Timer block registers. */
@@ -70,7 +70,7 @@ static bool timer25Mhz = true;*/ static u32 ticks_per_jiffy; -static struct clock_event_device __percpu **percpu_armada_370_xp_evt; +static struct clock_event_device __percpu *armada_370_xp_evt; static u32 notrace armada_370_xp_read_sched_clock(void) {
@@ -143,21 +143,14 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, } } -static struct clock_event_device armada_370_xp_clkevt = { - .name ="armada_370_xp_per_cpu_tick" , - .features =CLOCK_EVT_FEAT_ONESHOT |CLOCK_EVT_FEAT_PERIODIC , - .shift =32 , - .rating =300 , - .set_next_event = armada_370_xp_clkevt_next_event, - .set_mode = armada_370_xp_clkevt_mode, -}; +static int armada_370_xp_clkevt_irq;static irqreturn_t armada_370_xp_timer_interrupt (int irq,void *dev_id) {/* * ACK timer interrupt and call event handler. */ -struct clock_event_device *evt = *(struct clock_event_device **)dev_id; +struct clock_event_device *evt = dev_id;writel (TIMER0_CLR_MASK , local_base +LCL_TIMER_EVENTS_STATUS ); evt->event_handler (evt);
@@ -173,42 +166,55 @@ static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt)u32 u;int cpu =smp_processor_id (); -/* Use existing clock_event for cpu 0 */ -if (!smp_processor_id ()) -return 0 ; - u =readl (local_base +TIMER_CTRL_OFF );if (timer25Mhz)writel (u |TIMER0_25MHZ , local_base +TIMER_CTRL_OFF );else writel (u & ~TIMER0_25MHZ , local_base +TIMER_CTRL_OFF ); - evt->name = armada_370_xp_clkevt.name; - evt->irq = armada_370_xp_clkevt.irq; - evt->features = armada_370_xp_clkevt.features; - evt->shift = armada_370_xp_clkevt.shift; - evt->rating = armada_370_xp_clkevt.rating, + evt->name ="armada_370_xp_per_cpu_tick" , + evt->features =CLOCK_EVT_FEAT_ONESHOT | +CLOCK_EVT_FEAT_PERIODIC ; + evt->shift =32 , + evt->rating =300 , evt->set_next_event = armada_370_xp_clkevt_next_event, evt->set_mode = armada_370_xp_clkevt_mode, + evt->irq = armada_370_xp_clkevt_irq; evt->cpumask =cpumask_of (cpu); - *__this_cpu_ptr (percpu_armada_370_xp_evt) = evt; -clockevents_config_and_register (evt, timer_clk,1 ,0xfffffffe );enable_percpu_irq (evt->irq,0 );return 0 ; } -static void armada_370_xp_timer_stop (struct clock_event_device *evt) +static void __cpuinit armada_370_xp_timer_stop (struct clock_event_device *evt) { evt->set_mode (CLOCK_EVT_MODE_UNUSED , evt);disable_percpu_irq (evt->irq); } -static struct local_timer_ops armada_370_xp_local_timer_ops__cpuinitdata = { - .setup = armada_370_xp_timer_setup, - .stop = armada_370_xp_timer_stop, +static int __cpuinit armada_370_xp_timer_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +/* +* Grab cpu pointer in each case to avoid spurious +* preemptible warnings +*/ +switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_STARTING : +armada_370_xp_timer_setup (this_cpu_ptr (armada_370_xp_evt)); +break ; +case CPU_DYING : +armada_370_xp_timer_stop (this_cpu_ptr (armada_370_xp_evt)); +break ; + } + +return NOTIFY_OK ; +} + +static struct notifier_block armada_370_xp_timer_cpu_nb__cpuinitdata = { + .notifier_call = armada_370_xp_timer_cpu_notify, };void __init armada_370_xp_timer_init (void )
@@ -224,9 +230,6 @@ void __init armada_370_xp_timer_init(void)if (of_find_property (np,"marvell,timer-25Mhz" ,NULL )) {/* The fixed 25MHz timer is available so let's use it */ - u =readl (local_base +TIMER_CTRL_OFF ); -writel (u |TIMER0_25MHZ , - local_base +TIMER_CTRL_OFF ); u =readl (timer_base +TIMER_CTRL_OFF );writel (u |TIMER0_25MHZ , timer_base +TIMER_CTRL_OFF );
@@ -236,9 +239,6 @@ void __init armada_370_xp_timer_init(void)struct clk *clk =of_clk_get (np,0 );WARN_ON (IS_ERR (clk)); rate =clk_get_rate (clk); - u =readl (local_base +TIMER_CTRL_OFF ); -writel (u & ~(TIMER0_25MHZ ), - local_base +TIMER_CTRL_OFF ); u =readl (timer_base +TIMER_CTRL_OFF ); writel(u & ~(TIMER0_25MHZ),
@@ -252,7 +252,7 @@ void __init armada_370_xp_timer_init(void)* We use timer 0 as clocksource, and private(local) timer 0 * for clockevents */ - armada_370_xp_clkevt.irq =irq_of_parse_and_map (np,4 ); + armada_370_xp_clkevt_irq =irq_of_parse_and_map (np,4 ); ticks_per_jiffy = (timer_clk +HZ /2 ) /HZ ;
@@ -277,26 +277,19 @@ void __init armada_370_xp_timer_init(void)"armada_370_xp_clocksource" , timer_clk, 300, 32, clocksource_mmio_readl_down); -/* Register the clockevent on the private timer of CPU 0 */ - armada_370_xp_clkevt.cpumask =cpumask_of (0 ); -clockevents_config_and_register (&armada_370_xp_clkevt, - timer_clk,1 ,0xfffffffe ); +register_cpu_notifier (&armada_370_xp_timer_cpu_nb); - percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *); + armada_370_xp_evt = alloc_percpu(struct clock_event_device);/* * Setup clockevent timer (interrupt-driven). */ - *__this_cpu_ptr (percpu_armada_370_xp_evt) = &armada_370_xp_clkevt; - res =request_percpu_irq (armada_370_xp_clkevt.irq, + res =request_percpu_irq (armada_370_xp_clkevt_irq, armada_370_xp_timer_interrupt, - armada_370_xp_clkevt.name, - percpu_armada_370_xp_evt); -if (!res) { -enable_percpu_irq (armada_370_xp_clkevt.irq,0 ); -#ifdef CONFIG_LOCAL_TIMERS -local_timer_register (&armada_370_xp_local_timer_ops); -#endif - } +"armada_370_xp_per_cpu_tick" , + armada_370_xp_evt); +/* Immediately configure the timer on the boot CPU */ +if (!res) +armada_370_xp_timer_setup (this_cpu_ptr (armada_370_xp_evt)); }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 11/11 ARM: smp: Remove local timer API
In reply to Stephen BoydThere are no more users of this API, remove it.
--- arch/arm/Kconfig | 10 ------ arch/arm/include/asm/localtimer.h | 34 ------------------- arch/arm/kernel/smp.c | 69 --------------------------------------- 3 files changed, 113 deletions(-) delete mode 100644 arch/arm/include/asm/localtimer.h
arch/arm/Kconfig +0 -10
@@ -1542,16 +1542,6 @@ config ARM_PSCI 0022A ("Power State Coordination Interface System Software on ARM processors"). -config LOCAL_TIMERS - bool "Use local timer interrupts" - depends on SMP - default y - help - Enable support for local timers on SMP platforms, rather then the - legacy IPI broadcast method. Local timers allows the system - accounting to be spread across the timer interval, preventing a - "thundering herd" at every timer tick. - # The GPIO number here must be sorted by descending number. In case of # a multiplatform kernel, we just want the highest value required by the # selected platforms.
arch/arm/include/asm/localtimer.h deleted +0 -34
@@ -1,34 +0,0 @@ -/* -* arch/arm/include/asm/localtimer.h -* -* Copyright (C) 2004-2005 ARM Ltd. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ -#ifndef __ASM_ARM_LOCALTIMER_H -#define __ASM_ARM_LOCALTIMER_H - -#include <linux/errno.h> - -struct clock_event_device ; - -struct local_timer_ops { -int (*setup)(struct clock_event_device *); -void (*stop)(struct clock_event_device *); -}; - -#ifdef CONFIG_LOCAL_TIMERS -/* -* Register a local timer driver -*/ -int local_timer_register (struct local_timer_ops *); -#else -static inline int local_timer_register (struct local_timer_ops *ops) -{ -return -ENXIO ; -} -#endif - -#endif
arch/arm/kernel/smp.c +0 -69
117 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation