linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv7 00/11] Remove ARM local timer API
@ 2013-06-03 20:33 Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
                   ` (10 more replies)
  0 siblings, 11 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, linux-arm-msm, Mark Rutland, Marc Zyngier,
	Barry Song, Daniel Walker, Bryan Huntsman, Tony Lindgren,
	John Stultz, Thomas Gleixner, Daniel Lezcano, Thomas Abraham,
	arm

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

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-06 15:12   ` Daniel Lezcano
  2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, linux-arm-msm, John Stultz, Thomas Gleixner,
	Daniel Lezcano

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.

Reported-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Sören Brinkmann <soren.brinkmann@xilinx.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 kernel/time/tick-common.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 5d3fb10..3da62de 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -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;
 	}
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 02/11] clocksource: add generic dummy timer driver
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-06 16:23   ` Daniel Lezcano
  2013-06-24 20:30   ` [tip:timers/core] clocksource: Add " tip-bot for Mark Rutland
  2013-06-03 20:33 ` [PATCHv7 03/11] ARM: smp: Remove duplicate dummy timer implementation Stephen Boyd
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner, Daniel Lezcano

From: Mark Rutland <mark.rutland@arm.com>

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 <mark.rutland@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
[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]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clocksource/Makefile      |  1 +
 drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 drivers/clocksource/dummy_timer.c

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8d979c7..1a17d76 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -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
diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c
new file mode 100644
index 0000000..1f55f96
--- /dev/null
+++ b/drivers/clocksource/dummy_timer.c
@@ -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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 03/11] ARM: smp: Remove duplicate dummy timer implementation
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 04/11] ARM: smp_twd: Divorce smp_twd from local timer API Stephen Boyd
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm, Russell King

Drop ARM's version of the dummy timer now that we have a generic
implementation in drivers/clocksource.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/kernel/smp.c | 22 ++--------------------
 1 file changed, 2 insertions(+), 20 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 47ab905..4dc883a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -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
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 04/11] ARM: smp_twd: Divorce smp_twd from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (2 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 03/11] ARM: smp: Remove duplicate dummy timer implementation Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 05/11] ARM: OMAP2+: Divorce " Stephen Boyd
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm, Russell King, Tony Lindgren

Separate 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.

Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 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(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d423d58..177cb39 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 90525d9..aac1495 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -24,7 +25,6 @@
 
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
-#include <asm/localtimer.h>
 
 /* set up by the platform code */
 static void __iomem *twd_base;
@@ -33,7 +33,7 @@ static struct clk *twd_clk;
 static unsigned long twd_timer_rate;
 static DEFINE_PER_CPU(bool, percpu_setup_called);
 
-static struct clock_event_device __percpu **twd_evt;
+static struct clock_event_device __percpu *twd_evt;
 static int twd_ppi;
 
 static void twd_set_mode(enum clock_event_mode mode,
@@ -90,8 +90,10 @@ static int twd_timer_ack(void)
 	return 0;
 }
 
-static void twd_timer_stop(struct clock_event_device *clk)
+static void twd_timer_stop(void)
 {
+	struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
+
 	twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
 	disable_percpu_irq(clk->irq);
 }
@@ -106,7 +108,7 @@ 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);
+	clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_rate_change(struct notifier_block *nb,
@@ -132,7 +134,7 @@ static struct notifier_block twd_clk_nb = {
 
 static int twd_clk_init(void)
 {
-	if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+	if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
 		return clk_notifier_register(twd_clk, &twd_clk_nb);
 
 	return 0;
@@ -151,7 +153,7 @@ static void twd_update_frequency(void *data)
 {
 	twd_timer_rate = clk_get_rate(twd_clk);
 
-	clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+	clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_cpufreq_transition(struct notifier_block *nb,
@@ -177,7 +179,7 @@ static struct notifier_block twd_cpufreq_nb = {
 
 static int twd_cpufreq_init(void)
 {
-	if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+	if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
 		return cpufreq_register_notifier(&twd_cpufreq_nb,
 			CPUFREQ_TRANSITION_NOTIFIER);
 
@@ -228,7 +230,7 @@ static void __cpuinit twd_calibrate_rate(void)
 
 static irqreturn_t twd_handler(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+	struct clock_event_device *evt = dev_id;
 
 	if (twd_timer_ack()) {
 		evt->event_handler(evt);
@@ -265,9 +267,9 @@ static void twd_get_clock(struct device_node *np)
 /*
  * Setup the local clock events for a CPU.
  */
-static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
+static void __cpuinit twd_timer_setup(void)
 {
-	struct clock_event_device **this_cpu_clk;
+	struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
 	int cpu = smp_processor_id();
 
 	/*
@@ -276,9 +278,9 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
 	 */
 	if (per_cpu(percpu_setup_called, cpu)) {
 		__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-		clockevents_register_device(*__this_cpu_ptr(twd_evt));
+		clockevents_register_device(clk);
 		enable_percpu_irq(clk->irq, 0);
-		return 0;
+		return;
 	}
 	per_cpu(percpu_setup_called, cpu) = true;
 
@@ -297,27 +299,37 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
 	clk->set_mode = twd_set_mode;
 	clk->set_next_event = twd_set_next_event;
 	clk->irq = twd_ppi;
-
-	this_cpu_clk = __this_cpu_ptr(twd_evt);
-	*this_cpu_clk = clk;
+	clk->cpumask = cpumask_of(cpu);
 
 	clockevents_config_and_register(clk, twd_timer_rate,
 					0xf, 0xffffffff);
 	enable_percpu_irq(clk->irq, 0);
+}
 
-	return 0;
+static int __cpuinit twd_timer_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		twd_timer_setup();
+		break;
+	case CPU_DYING:
+		twd_timer_stop();
+		break;
+	}
+
+	return NOTIFY_OK;
 }
 
-static struct local_timer_ops twd_lt_ops __cpuinitdata = {
-	.setup	= twd_timer_setup,
-	.stop	= twd_timer_stop,
+static struct notifier_block twd_timer_cpu_nb __cpuinitdata = {
+	.notifier_call = twd_timer_cpu_notify,
 };
 
 static int __init twd_local_timer_common_register(struct device_node *np)
 {
 	int err;
 
-	twd_evt = alloc_percpu(struct clock_event_device *);
+	twd_evt = alloc_percpu(struct clock_event_device);
 	if (!twd_evt) {
 		err = -ENOMEM;
 		goto out_free;
@@ -329,12 +341,22 @@ static int __init twd_local_timer_common_register(struct device_node *np)
 		goto out_free;
 	}
 
-	err = local_timer_register(&twd_lt_ops);
+	err = register_cpu_notifier(&twd_timer_cpu_nb);
 	if (err)
 		goto out_irq;
 
 	twd_get_clock(np);
 
+	/*
+	 * Immediately configure the timer on the boot CPU, unless we need
+	 * jiffies to be incrementing to calibrate the rate in which case
+	 * setup the timer in late_time_init.
+	 */
+	if (twd_timer_rate)
+		twd_timer_setup();
+	else
+		late_time_init = twd_timer_setup;
+
 	return 0;
 
 out_irq:
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index cd9fcb1..6acbdab 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ba44328..c8adc79 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index f49cd51..edb950a 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -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
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index d210c0f9..9db2029 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -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
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index 442917e..df0d59a 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -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
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 84d72fc..1f3ea1f 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -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
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 6a4387e..0614ee2 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -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
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 5907e10..5bfdd73 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -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
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index c1d61f2..04f8a4a 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -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
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 05/11] ARM: OMAP2+: Divorce from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (3 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 04/11] ARM: smp_twd: Divorce smp_twd from local timer API Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 06/11] ARM: EXYNOS4: Divorce mct " Stephen Boyd
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm

Now 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.

Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/mach-omap2/Kconfig | 1 -
 arch/arm/mach-omap2/timer.c | 7 -------
 2 files changed, 8 deletions(-)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index edb950a..4e0049a 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -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
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index f8b23b8..60e9cf8 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -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
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 06/11] ARM: EXYNOS4: Divorce mct from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (4 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 05/11] ARM: OMAP2+: Divorce " Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 07/11] ARM: PRIMA2: Divorce timer-marco " Stephen Boyd
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm, Thomas Abraham

Separate 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.

Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Thomas Abraham <thomas.abraham@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clocksource/exynos_mct.c | 60 ++++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 17 deletions(-)

diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 662fcc0..1c3f5a6 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -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 __iomem
 	if (!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)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 07/11] ARM: PRIMA2: Divorce timer-marco from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (5 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 06/11] ARM: EXYNOS4: Divorce mct " Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:33 ` [PATCHv7 08/11] ARM: msm: Divorce msm_timer " Stephen Boyd
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm, Barry Song

Separate 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.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Barry Song <baohua.song@csr.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clocksource/timer-marco.c | 100 ++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 46 deletions(-)

diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index 97738db..ba97bc1 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -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();
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 08/11] ARM: msm: Divorce msm_timer from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (6 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 07/11] ARM: PRIMA2: Divorce timer-marco " Stephen Boyd
@ 2013-06-03 20:33 ` Stephen Boyd
  2013-06-03 20:34 ` [PATCHv7 09/11] clocksource: time-armada-370-xp: Fix sparse warning Stephen Boyd
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, linux-arm-msm, Daniel Walker, Bryan Huntsman

Separate 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.

Acked-by: David Brown <davidb@codeaurora.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Daniel Walker <dwalker@fifo99.com>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/mach-msm/timer.c | 126 +++++++++++++++++++++++++---------------------
 1 file changed, 70 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 284313f..df947aa 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 09/11] clocksource: time-armada-370-xp: Fix sparse warning
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (7 preceding siblings ...)
  2013-06-03 20:33 ` [PATCHv7 08/11] ARM: msm: Divorce msm_timer " Stephen Boyd
@ 2013-06-03 20:34 ` Stephen Boyd
  2013-06-03 20:34 ` [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API Stephen Boyd
  2013-06-03 20:34 ` [PATCHv7 11/11] ARM: smp: Remove " Stephen Boyd
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:34 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm

drivers/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.

Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clocksource/time-armada-370-xp.c | 3 ++-
 include/linux/time-armada-370-xp.h       | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 47a6730..efe4aef 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -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.
  */
diff --git a/include/linux/time-armada-370-xp.h b/include/linux/time-armada-370-xp.h
index dfdfdc0..6fb0856 100644
--- a/include/linux/time-armada-370-xp.h
+++ b/include/linux/time-armada-370-xp.h
@@ -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
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (8 preceding siblings ...)
  2013-06-03 20:34 ` [PATCHv7 09/11] clocksource: time-armada-370-xp: Fix sparse warning Stephen Boyd
@ 2013-06-03 20:34 ` Stephen Boyd
  2013-06-03 20:34 ` [PATCHv7 11/11] ARM: smp: Remove " Stephen Boyd
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:34 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm

Separate 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.

Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clocksource/time-armada-370-xp.c | 89 +++++++++++++++-----------------
 1 file changed, 41 insertions(+), 48 deletions(-)

diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index efe4aef..4a31e86 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -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));
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCHv7 11/11] ARM: smp: Remove local timer API
  2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
                   ` (9 preceding siblings ...)
  2013-06-03 20:34 ` [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API Stephen Boyd
@ 2013-06-03 20:34 ` Stephen Boyd
  10 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-03 20:34 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, linux-arm-msm, Russell King

There are no more users of this API, remove it.

Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 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

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 177cb39..626a272 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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.
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
deleted file mode 100644
index f77ffc1..0000000
--- a/arch/arm/include/asm/localtimer.h
+++ /dev/null
@@ -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
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4dc883a..54aa994 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -41,7 +41,6 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
-#include <asm/localtimer.h>
 #include <asm/smp_plat.h>
 #include <asm/virt.h>
 #include <asm/mach/arch.h>
@@ -133,8 +132,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void percpu_timer_stop(void);
-
 static int platform_cpu_kill(unsigned int cpu)
 {
 	if (smp_ops.cpu_kill)
@@ -178,11 +175,6 @@ int __cpuinit __cpu_disable(void)
 	migrate_irqs();
 
 	/*
-	 * Stop the local timer for this CPU.
-	 */
-	percpu_timer_stop();
-
-	/*
 	 * Flush user cache and TLB mappings, and then remove this CPU
 	 * from the vm mask set of all processes.
 	 *
@@ -303,8 +295,6 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
 	store_cpu_topology(cpuid);
 }
 
-static void percpu_timer_setup(void);
-
 /*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
@@ -359,11 +349,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
-	/*
-	 * Setup the percpu timer for this CPU.
-	 */
-	percpu_timer_setup();
-
 	local_irq_enable();
 	local_fiq_enable();
 
@@ -410,12 +395,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 		max_cpus = ncores;
 	if (ncores > 1 && max_cpus) {
 		/*
-		 * Enable the local timer or broadcast device for the
-		 * boot CPU, but only if we have more than one CPU.
-		 */
-		percpu_timer_setup();
-
-		/*
 		 * Initialise the present map, which describes the set of CPUs
 		 * actually populated at the present time. A platform should
 		 * re-initialize the map in the platforms smp_prepare_cpus()
@@ -491,11 +470,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 	return sum;
 }
 
-/*
- * Timer (local or broadcast) support
- */
-static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 void tick_broadcast(const struct cpumask *mask)
 {
@@ -503,49 +477,6 @@ void tick_broadcast(const struct cpumask *mask)
 }
 #endif
 
-static struct local_timer_ops *lt_ops;
-
-#ifdef CONFIG_LOCAL_TIMERS
-int local_timer_register(struct local_timer_ops *ops)
-{
-	if (!is_smp() || !setup_max_cpus)
-		return -ENXIO;
-
-	if (lt_ops)
-		return -EBUSY;
-
-	lt_ops = ops;
-	return 0;
-}
-#endif
-
-static void __cpuinit percpu_timer_setup(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	evt->cpumask = cpumask_of(cpu);
-
-	if (lt_ops)
-		lt_ops->setup(evt);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * The generic clock events code purposely does not stop the local timer
- * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
- * manually here.
- */
-static void percpu_timer_stop(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	if (lt_ops)
-		lt_ops->stop(evt);
-}
-#endif
-
 static DEFINE_RAW_SPINLOCK(stop_lock);
 
 /*
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
@ 2013-06-06 15:12   ` Daniel Lezcano
  2013-06-06 18:04     ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Lezcano @ 2013-06-06 15:12 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner

On 06/03/2013 10:33 PM, Stephen Boyd wrote:
> 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.

It is not clear the connection between the changelog, the patch and the
comment. Could you clarify a bit ?

Thanks
  -- Daniel



> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Tested-by: Mark Rutland <mark.rutland@arm.com>
> Tested-by: Sören Brinkmann <soren.brinkmann@xilinx.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  kernel/time/tick-common.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
> index 5d3fb10..3da62de 100644
> --- a/kernel/time/tick-common.c
> +++ b/kernel/time/tick-common.c
> @@ -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;
>  	}
>  
> 


-- 
 <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


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 02/11] clocksource: add generic dummy timer driver
  2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
@ 2013-06-06 16:23   ` Daniel Lezcano
  2013-06-24 20:30   ` [tip:timers/core] clocksource: Add " tip-bot for Mark Rutland
  1 sibling, 0 replies; 28+ messages in thread
From: Daniel Lezcano @ 2013-06-06 16:23 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-kernel, Mark Rutland, linux-kernel, linux-arm-msm,
	John Stultz, Thomas Gleixner

On 06/03/2013 10:33 PM, Stephen Boyd wrote:
> From: Mark Rutland <mark.rutland@arm.com>
> 
> 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 <mark.rutland@arm.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> [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]
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---

Except the missing first letter capitalization, in the patch description
'add' => 'Add'.

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

>  drivers/clocksource/Makefile      |  1 +
>  drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+)
>  create mode 100644 drivers/clocksource/dummy_timer.c
> 
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 8d979c7..1a17d76 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -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
> diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c
> new file mode 100644
> index 0000000..1f55f96
> --- /dev/null
> +++ b/drivers/clocksource/dummy_timer.c
> @@ -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);
> 


-- 
 <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


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-06 15:12   ` Daniel Lezcano
@ 2013-06-06 18:04     ` Stephen Boyd
  2013-06-06 22:30       ` Daniel Lezcano
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-06 18:04 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner

On 06/06, Daniel Lezcano wrote:
> On 06/03/2013 10:33 PM, Stephen Boyd wrote:
> > 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.
> 
> 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.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-06 18:04     ` Stephen Boyd
@ 2013-06-06 22:30       ` Daniel Lezcano
  2013-06-06 22:38         ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Lezcano @ 2013-06-06 22:30 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner

On 06/06/2013 08:04 PM, Stephen Boyd wrote:
> On 06/06, Daniel Lezcano wrote:
>> On 06/03/2013 10:33 PM, Stephen Boyd wrote:
>>> 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.
>>
>> 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.

Thanks for the detailed explanation.

Did Thomas reacted to this patch ?


-- 
 <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


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-06 22:30       ` Daniel Lezcano
@ 2013-06-06 22:38         ` Stephen Boyd
  2013-06-12 21:44           ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-06 22:38 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner

On 06/07, Daniel Lezcano wrote:
> On 06/06/2013 08:04 PM, Stephen Boyd wrote:
> > On 06/06, Daniel Lezcano wrote:
> >> On 06/03/2013 10:33 PM, Stephen Boyd wrote:
> >>> 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.
> >>
> >> 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.
> 
> Thanks for the detailed explanation.
> 
> Did Thomas reacted to this patch ?
> 

So far there has been no response from Thomas.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-06 22:38         ` Stephen Boyd
@ 2013-06-12 21:44           ` Stephen Boyd
  2013-06-13  9:33             ` Daniel Lezcano
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-12 21:44 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz,
	Thomas Gleixner

On 06/06, Stephen Boyd wrote:
> On 06/07, Daniel Lezcano wrote:
> > On 06/06/2013 08:04 PM, Stephen Boyd wrote:
> > > On 06/06, Daniel Lezcano wrote:
> > >> On 06/03/2013 10:33 PM, Stephen Boyd wrote:
> > >>> 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.
> > >>
> > >> 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.
> > 
> > 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.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-12 21:44           ` Stephen Boyd
@ 2013-06-13  9:33             ` Daniel Lezcano
  2013-06-13 13:15               ` Thomas Gleixner
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Lezcano @ 2013-06-13  9:33 UTC (permalink / raw)
  To: Stephen Boyd, Thomas Gleixner
  Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz

On 06/12/2013 11:44 PM, Stephen Boyd wrote:
> On 06/06, Stephen Boyd wrote:
>> On 06/07, Daniel Lezcano wrote:
>>> On 06/06/2013 08:04 PM, Stephen Boyd wrote:
>>>> On 06/06, Daniel Lezcano wrote:
>>>>> On 06/03/2013 10:33 PM, Stephen Boyd wrote:
>>>>>> 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.
>>>>>
>>>>> 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.
>>>
>>> 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.

I prefer Thomas to have a look at it and ack it. I changed Cc to To for
Thomas.

Thanks
  -- Daniel


-- 
 <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


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-13  9:33             ` Daniel Lezcano
@ 2013-06-13 13:15               ` Thomas Gleixner
  2013-06-13 18:39                 ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Thomas Gleixner @ 2013-06-13 13:15 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Stephen Boyd, linux-arm-kernel, linux-kernel, linux-arm-msm, John Stultz

On Thu, 13 Jun 2013, Daniel Lezcano wrote:
> 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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-13 13:15               ` Thomas Gleixner
@ 2013-06-13 18:39                 ` Stephen Boyd
  2013-06-13 20:16                   ` Sören Brinkmann
                                     ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-13 18:39 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Daniel Lezcano, linux-arm-kernel, linux-kernel, linux-arm-msm,
	John Stultz, Mark Rutland, soren.brinkmann

On 06/13, Thomas Gleixner wrote:
> On Thu, 13 Jun 2013, Daniel Lezcano wrote:
> > 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.

Reported-by: Mark Rutland <mark.rutland@arm.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 kernel/time/tick-common.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 5edfb48..edd45f6 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -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);
 }
 
 /*

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-13 18:39                 ` Stephen Boyd
@ 2013-06-13 20:16                   ` Sören Brinkmann
  2013-06-18 10:22                   ` Mark Rutland
  2013-06-24 20:30                   ` [tip:timers/core] " tip-bot for Stephen Boyd
  2 siblings, 0 replies; 28+ messages in thread
From: Sören Brinkmann @ 2013-06-13 20:16 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Thomas Gleixner, Daniel Lezcano, linux-arm-kernel, linux-kernel,
	linux-arm-msm, John Stultz, Mark Rutland

On Thu, Jun 13, 2013 at 11:39:50AM -0700, Stephen Boyd wrote:
> On 06/13, Thomas Gleixner wrote:
> > On Thu, 13 Jun 2013, Daniel Lezcano wrote:
> > > 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.
> 
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested-by: Sören Brinkmann <soren.brinkmann@xilinx.com>

I retested my case on tip/timers/core with the same results.

	Sören



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-13 18:39                 ` Stephen Boyd
  2013-06-13 20:16                   ` Sören Brinkmann
@ 2013-06-18 10:22                   ` Mark Rutland
  2013-06-19 16:30                     ` Stephen Boyd
  2013-06-24 20:30                   ` [tip:timers/core] " tip-bot for Stephen Boyd
  2 siblings, 1 reply; 28+ messages in thread
From: Mark Rutland @ 2013-06-18 10:22 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Thomas Gleixner, Daniel Lezcano, linux-arm-kernel, linux-kernel,
	linux-arm-msm, John Stultz, soren.brinkmann

On Thu, Jun 13, 2013 at 07:39:50PM +0100, Stephen Boyd wrote:
> On 06/13, Thomas Gleixner wrote:
> > On Thu, 13 Jun 2013, Daniel Lezcano wrote:
> > > 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.
> 
> Reported-by: Mark Rutland <mark.rutland@arm.com>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

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 <mark.rutland@arm.com>

Thanks for working on this, Stephen.

Mark.

> ---
>  kernel/time/tick-common.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
> index 5edfb48..edd45f6 100644
> --- a/kernel/time/tick-common.c
> +++ b/kernel/time/tick-common.c
> @@ -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);
>  }
>  
>  /*
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by The Linux Foundation
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-18 10:22                   ` Mark Rutland
@ 2013-06-19 16:30                     ` Stephen Boyd
  2013-06-21 17:07                       ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-19 16:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Mark Rutland, Daniel Lezcano, linux-arm-kernel, linux-kernel,
	linux-arm-msm, John Stultz, arm, soren.brinkmann

Thomas,

On 06/18, Mark Rutland wrote:
> On Thu, Jun 13, 2013 at 07:39:50PM +0100, Stephen Boyd wrote:
> > On 06/13, Thomas Gleixner wrote:
> > > On Thu, 13 Jun 2013, Daniel Lezcano wrote:
> > > > 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.
> > 
> > Reported-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: John Stultz <john.stultz@linaro.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> 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 <mark.rutland@arm.com>
> 
> 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.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-19 16:30                     ` Stephen Boyd
@ 2013-06-21 17:07                       ` Stephen Boyd
  2013-06-24 20:07                         ` Stephen Boyd
  0 siblings, 1 reply; 28+ messages in thread
From: Stephen Boyd @ 2013-06-21 17:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Mark Rutland, Daniel Lezcano, linux-arm-kernel, linux-kernel,
	linux-arm-msm, John Stultz, arm, soren.brinkmann

On 06/19, Stephen Boyd wrote:
> 
> 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?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices
  2013-06-21 17:07                       ` Stephen Boyd
@ 2013-06-24 20:07                         ` Stephen Boyd
  0 siblings, 0 replies; 28+ messages in thread
From: Stephen Boyd @ 2013-06-24 20:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Mark Rutland, Daniel Lezcano, linux-arm-kernel, linux-kernel,
	linux-arm-msm, John Stultz, arm, soren.brinkmann

On 06/21/13 10:07, Stephen Boyd wrote:
> On 06/19, Stephen Boyd wrote:
>> 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.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/core] clockevents: Prefer CPU local devices over global devices
  2013-06-13 18:39                 ` Stephen Boyd
  2013-06-13 20:16                   ` Sören Brinkmann
  2013-06-18 10:22                   ` Mark Rutland
@ 2013-06-24 20:30                   ` tip-bot for Stephen Boyd
  2 siblings, 0 replies; 28+ messages in thread
From: tip-bot for Stephen Boyd @ 2013-06-24 20:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, mark.rutland, sboyd, john.stultz, tglx,
	daniel.lezcano

Commit-ID:  70e5975d3a04be5479a28eec4a2fb10f98ad2785
Gitweb:     http://git.kernel.org/tip/70e5975d3a04be5479a28eec4a2fb10f98ad2785
Author:     Stephen Boyd <sboyd@codeaurora.org>
AuthorDate: Thu, 13 Jun 2013 11:39:50 -0700
Committer:  Thomas Gleixner <tglx@linutronix.de>
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.

Reported-and-tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested-by: soren.brinkmann@xilinx.com
Cc: John Stultz <john.stultz@linaro.org>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: John Stultz <john.stultz@linaro.org>
Link: http://lkml.kernel.org/r/20130613183950.GA32061@codeaurora.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/tick-common.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 5edfb48..edd45f6 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -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);
 }
 
 /*

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [tip:timers/core] clocksource: Add generic dummy timer driver
  2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
  2013-06-06 16:23   ` Daniel Lezcano
@ 2013-06-24 20:30   ` tip-bot for Mark Rutland
  1 sibling, 0 replies; 28+ messages in thread
From: tip-bot for Mark Rutland @ 2013-06-24 20:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, mark.rutland, sboyd, john.stultz, tglx,
	daniel.lezcano

Commit-ID:  064706514ec3fea740c2656e03c4f01f6a551ac4
Gitweb:     http://git.kernel.org/tip/064706514ec3fea740c2656e03c4f01f6a551ac4
Author:     Mark Rutland <mark.rutland@arm.com>
AuthorDate: Mon, 3 Jun 2013 13:33:53 -0700
Committer:  Thomas Gleixner <tglx@linutronix.de>
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]

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Cc: John Stultz <john.stultz@linaro.org>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1370291642-13259-3-git-send-email-sboyd@codeaurora.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/clocksource/Makefile      |  1 +
 drivers/clocksource/dummy_timer.c | 69 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 4853ea0..9ba8b4d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -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
diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c
new file mode 100644
index 0000000..1f55f96
--- /dev/null
+++ b/drivers/clocksource/dummy_timer.c
@@ -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);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2013-06-24 20:31 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
2013-06-06 15:12   ` Daniel Lezcano
2013-06-06 18:04     ` Stephen Boyd
2013-06-06 22:30       ` Daniel Lezcano
2013-06-06 22:38         ` Stephen Boyd
2013-06-12 21:44           ` Stephen Boyd
2013-06-13  9:33             ` Daniel Lezcano
2013-06-13 13:15               ` Thomas Gleixner
2013-06-13 18:39                 ` Stephen Boyd
2013-06-13 20:16                   ` Sören Brinkmann
2013-06-18 10:22                   ` Mark Rutland
2013-06-19 16:30                     ` Stephen Boyd
2013-06-21 17:07                       ` Stephen Boyd
2013-06-24 20:07                         ` Stephen Boyd
2013-06-24 20:30                   ` [tip:timers/core] " tip-bot for Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
2013-06-06 16:23   ` Daniel Lezcano
2013-06-24 20:30   ` [tip:timers/core] clocksource: Add " tip-bot for Mark Rutland
2013-06-03 20:33 ` [PATCHv7 03/11] ARM: smp: Remove duplicate dummy timer implementation Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 04/11] ARM: smp_twd: Divorce smp_twd from local timer API Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 05/11] ARM: OMAP2+: Divorce " Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 06/11] ARM: EXYNOS4: Divorce mct " Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 07/11] ARM: PRIMA2: Divorce timer-marco " Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 08/11] ARM: msm: Divorce msm_timer " Stephen Boyd
2013-06-03 20:34 ` [PATCHv7 09/11] clocksource: time-armada-370-xp: Fix sparse warning Stephen Boyd
2013-06-03 20:34 ` [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API Stephen Boyd
2013-06-03 20:34 ` [PATCHv7 11/11] ARM: smp: Remove " Stephen Boyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).