linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/35] Some kernel/time cleanups
@ 2015-02-16 12:14 Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense Peter Zijlstra
                   ` (36 more replies)
  0 siblings, 37 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

Hi,

While working with Rafael on the suspend to idle machinery Thomas made these
cleanups; since one might as well clean code up while you've done the work of
thinking through it again.

As it stands there's very little overlap between Rafael's series and this one
aside from a few trivial fixups. So we'll merge them seperately.

---
 arch/arm/common/bL_switcher.c          |  16 +--
 arch/arm/kernel/smp.c                  |   2 +-
 arch/arm/mach-omap2/cpuidle44xx.c      |  10 +-
 arch/arm/mach-tegra/cpuidle-tegra114.c |   6 +-
 arch/arm/mach-tegra/cpuidle-tegra20.c  |  10 +-
 arch/arm/mach-tegra/cpuidle-tegra30.c  |  10 +-
 arch/arm64/Kconfig                     |   1 +
 arch/arm64/kernel/smp.c                |   1 +
 arch/arm64/kernel/time.c               |   2 +-
 arch/mips/kernel/smp.c                 |   1 +
 arch/powerpc/Kconfig                   |   1 +
 arch/powerpc/kernel/smp.c              |   1 +
 arch/powerpc/kernel/time.c             |   2 +-
 arch/x86/kernel/process.c              |  13 +--
 arch/x86/xen/suspend.c                 |  11 +-
 drivers/acpi/acpi_pad.c                |  29 +----
 drivers/acpi/processor_idle.c          |  20 ++--
 drivers/cpuidle/driver.c               |  23 ++--
 drivers/idle/intel_idle.c              |  17 ++-
 include/linux/clockchips.h             |  65 +----------
 include/linux/clocksource.h            |   2 -
 include/linux/tick.h                   | 200 ++++++++++++++-------------------
 kernel/cpu.c                           |   4 +
 kernel/sched/idle.c                    |   5 +-
 kernel/time/Kconfig                    |  10 +-
 kernel/time/Makefile                   |  12 +-
 kernel/time/clockevents.c              |  95 +++++-----------
 kernel/time/clocksource.c              |   2 +
 kernel/time/hrtimer.c                  |   9 +-
 kernel/time/jiffies.c                  |   2 +-
 kernel/time/ntp.c                      |   1 -
 kernel/time/tick-broadcast.c           | 194 ++++++++++++++++++--------------
 kernel/time/tick-common.c              |  89 ++++++++++-----
 kernel/time/tick-internal.h            | 189 +++++++++++++------------------
 kernel/time/tick-sched.c               |   7 +-
 kernel/time/timekeeping.c              |  12 +-
 kernel/time/timekeeping.h              |  10 ++
 kernel/time/timer_list.c               |   2 +-
 38 files changed, 477 insertions(+), 609 deletions(-)



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

* [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 18:54   ` Rafael J. Wysocki
  2015-02-16 12:14 ` [PATCH 02/35] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Peter Zijlstra
                   ` (35 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Len Brown, linux-acpi

[-- Attachment #1: acpi-pad-kill-lapic-nonsense.patch --]
[-- Type: text/plain, Size: 3882 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

While looking through the (ab)use of the clockevents_notify() function
I stumbled over the following gem in the acpi_pad code:

  if (lapic_detected_unstable && !lapic_marked_unstable) {
     /* LAPIC could halt in idle, so notify users */
     for_each_online_cpu(i)
       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
     lapic_marked_unstable = 1;
  }

This code calls on the cpu which detects the lapic unstable condition
first clockevents_notify() to tell the core code that the broadcast
should be enabled on all online cpus. Brilliant stuff that as it
notifies the core code a num_online_cpus() times that the broadcast
should be enabled on the current cpu.

This probably has never been noticed because that code got never
tested with NOHZ=n and HIGHRES_TIMER=n or it just worked by chance
because one of the other mechanisms told the core in the right way
that the local apic timer is wreckaged.

Sigh, this is:

 - The 4th incarnation of idle drivers which has their own mechanism
   to detect and deal with X86_FEATURE_ARAT.

 - The 2nd incarnation of fake idle mechanisms with a different set of
   brainmelting bugs.

 - Has been merged against an explicit NAK of the scheduler
   maintainer with the promise to improve it over time.

 - Another example of featuritis driven trainwreck engineering.

 - Another pointless waste of my time.

Fix this nonsense by removing that lapic detection and notification
logic and simply call into the clockevents code unconditonally. The
ARAT feature is marked in the lapic clockevent already so the core
code will just ignore the requests and return.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>
---
 drivers/acpi/acpi_pad.c |   26 +++++---------------------
 1 file changed, 5 insertions(+), 21 deletions(-)

Index: linux/drivers/acpi/acpi_pad.c
===================================================================
--- linux.orig/drivers/acpi/acpi_pad.c
+++ linux/drivers/acpi/acpi_pad.c
@@ -41,8 +41,6 @@ static unsigned long power_saving_mwait_
 
 static unsigned char tsc_detected_unstable;
 static unsigned char tsc_marked_unstable;
-static unsigned char lapic_detected_unstable;
-static unsigned char lapic_marked_unstable;
 
 static void power_saving_mwait_init(void)
 {
@@ -82,13 +80,10 @@ static void power_saving_mwait_init(void
 		 */
 		if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
 			tsc_detected_unstable = 1;
-		if (!boot_cpu_has(X86_FEATURE_ARAT))
-			lapic_detected_unstable = 1;
 		break;
 	default:
-		/* TSC & LAPIC could halt in idle */
+		/* TSC could halt in idle */
 		tsc_detected_unstable = 1;
-		lapic_detected_unstable = 1;
 	}
 #endif
 }
@@ -177,28 +172,17 @@ static int power_saving_thread(void *dat
 				mark_tsc_unstable("TSC halts in idle");
 				tsc_marked_unstable = 1;
 			}
-			if (lapic_detected_unstable && !lapic_marked_unstable) {
-				int i;
-				/* LAPIC could halt in idle, so notify users */
-				for_each_online_cpu(i)
-					clockevents_notify(
-						CLOCK_EVT_NOTIFY_BROADCAST_ON,
-						&i);
-				lapic_marked_unstable = 1;
-			}
+			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+
 			local_irq_disable();
 			cpu = smp_processor_id();
-			if (lapic_marked_unstable)
-				clockevents_notify(
-					CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 			stop_critical_timings();
 
 			mwait_idle_with_hints(power_saving_mwait_eax, 1);
 
 			start_critical_timings();
-			if (lapic_marked_unstable)
-				clockevents_notify(
-					CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 			local_irq_enable();
 
 			if (time_before(expire_time, jiffies)) {



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

* [PATCH 02/35] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 03/35] tick: Cleanup internal header files Peter Zijlstra
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-get-rid-of-build-option.patch --]
[-- Type: text/plain, Size: 4619 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

This option was for simpler migration to the clock events code. Most
architectures have been converted and the option has been
disfunctional as a standalone option for quite some time. Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/clockchips.h  |    9 +++------
 kernel/time/Kconfig         |    6 ------
 kernel/time/Makefile        |    6 ++----
 kernel/time/clockevents.c   |    3 ---
 kernel/time/tick-internal.h |    4 ++--
 5 files changed, 7 insertions(+), 21 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -22,7 +22,7 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #include <linux/clocksource.h>
 #include <linux/cpumask.h>
@@ -194,13 +194,9 @@ static inline int tick_check_broadcast_e
 static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern int clockevents_notify(unsigned long reason, void *arg);
-#else
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
-#endif
 
-#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
 
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
@@ -208,6 +204,7 @@ static inline void clockevents_resume(vo
 static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 
 #endif
 
Index: linux/kernel/time/Kconfig
===================================================================
--- linux.orig/kernel/time/Kconfig
+++ linux/kernel/time/Kconfig
@@ -33,12 +33,6 @@ config ARCH_USES_GETTIMEOFFSET
 config GENERIC_CLOCKEVENTS
 	bool
 
-# Migration helper. Builds, but does not invoke
-config GENERIC_CLOCKEVENTS_BUILD
-	bool
-	default y
-	depends on GENERIC_CLOCKEVENTS
-
 # Architecture can handle broadcast in a driver-agnostic way
 config ARCH_HAS_TICK_BROADCAST
 	bool
Index: linux/kernel/time/Makefile
===================================================================
--- linux.orig/kernel/time/Makefile
+++ linux/kernel/time/Makefile
@@ -2,15 +2,13 @@ obj-y += time.o timer.o hrtimer.o itimer
 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o posix-clock.o alarmtimer.o
 
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)		+= clockevents.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o tick-common.o
 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
  obj-y						+= tick-broadcast.o
  obj-$(CONFIG_TICK_ONESHOT)			+= tick-broadcast-hrtimer.o
 endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-sched.o
+obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
 obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
 obj-$(CONFIG_DEBUG_FS)				+= timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)			+= test_udelay.o
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -541,7 +541,6 @@ void clockevents_resume(void)
 			dev->resume(dev);
 }
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 /**
  * clockevents_notify - notification about relevant events
  * Returns 0 on success, any other value on error
@@ -727,5 +726,3 @@ static int __init clockevents_init_sysfs
 }
 device_initcall(clockevents_init_sysfs);
 #endif /* SYSFS */
-
-#endif /* GENERIC_CLOCK_EVENTS */
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -10,7 +10,7 @@ extern seqlock_t jiffies_lock;
 
 #define CS_NAME_LEN	32
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
 #define TICK_DO_TIMER_BOOT	-2
@@ -166,7 +166,7 @@ static inline int tick_device_is_functio
 
 int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 
-#endif
+#endif /* GENERIC_CLOCKEVENTS */
 
 extern void do_timer(unsigned long ticks);
 extern void update_wall_time(void);



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

* [PATCH 03/35] tick: Cleanup internal header files
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 02/35] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 04/35] tick: Cleanup internal header file Peter Zijlstra
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: tick-cleanup-header-file.patch --]
[-- Type: text/plain, Size: 2600 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Move clocksource related stuff to timekeeping.h and remove the
pointless include from ntp.c

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/clocksource.c   |    2 +-
 kernel/time/jiffies.c       |    2 +-
 kernel/time/ntp.c           |    1 -
 kernel/time/tick-internal.h |    6 ------
 kernel/time/timekeeping.h   |    7 +++++++
 5 files changed, 9 insertions(+), 9 deletions(-)

Index: linux/kernel/time/clocksource.c
===================================================================
--- linux.orig/kernel/time/clocksource.c
+++ linux/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 #include "timekeeping_internal.h"
 
 void timecounter_init(struct timecounter *tc,
Index: linux/kernel/time/jiffies.c
===================================================================
--- linux.orig/kernel/time/jiffies.c
+++ linux/kernel/time/jiffies.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 
 /* The Jiffies based clocksource is the lowest common
  * denominator clock source which should function on
Index: linux/kernel/time/ntp.c
===================================================================
--- linux.orig/kernel/time/ntp.c
+++ linux/kernel/time/ntp.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 
-#include "tick-internal.h"
 #include "ntp_internal.h"
 
 /*
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -6,10 +6,6 @@
 
 #include "timekeeping.h"
 
-extern seqlock_t jiffies_lock;
-
-#define CS_NAME_LEN	32
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
@@ -168,5 +164,3 @@ int __clockevents_update_freq(struct clo
 
 #endif /* GENERIC_CLOCKEVENTS */
 
-extern void do_timer(unsigned long ticks);
-extern void update_wall_time(void);
Index: linux/kernel/time/timekeeping.h
===================================================================
--- linux.orig/kernel/time/timekeeping.h
+++ linux/kernel/time/timekeeping.h
@@ -17,4 +17,11 @@ extern s32 timekeeping_get_tai_offset(vo
 extern void timekeeping_set_tai_offset(s32 tai_offset);
 extern void timekeeping_clocktai(struct timespec *ts);
 
+extern void do_timer(unsigned long ticks);
+extern void update_wall_time(void);
+
+extern seqlock_t jiffies_lock;
+
+#define CS_NAME_LEN	32
+
 #endif



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

* [PATCH 04/35] tick: Cleanup internal header file
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (2 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 03/35] tick: Cleanup internal header files Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 05/35] tick: Move core only declarations and functions to core Peter Zijlstra
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: tick-cleanup-header-file-2.patch --]
[-- Type: text/plain, Size: 8413 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

tick-internal.h is pretty confusing as a lot of the stub inlines are
there several times.

Distangle the maze and make clear functional sections.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/tick-internal.h |  145 ++++++++++++++------------------------------
 1 file changed, 49 insertions(+), 96 deletions(-)

Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -27,13 +27,18 @@ extern bool tick_check_replacement(struc
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 
-extern void clockevents_shutdown(struct clock_event_device *dev);
+/* Check, if the device is functional or a dummy for broadcast */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
 
+extern void clockevents_shutdown(struct clock_event_device *dev);
+extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#endif /* GENERIC_CLOCKEVENTS */
 
-/*
- * NO_HZ / high resolution timer shared code
- */
+/* Oneshot related functions */
 #ifdef CONFIG_TICK_ONESHOT
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
 			       void (*handler)(struct clock_event_device *),
@@ -42,69 +47,19 @@ extern int tick_program_event(ktime_t ex
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_control(unsigned long reason);
-extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_active(void);
-extern void tick_check_oneshot_broadcast_this_cpu(void);
-bool tick_broadcast_oneshot_available(void);
-# else /* BROADCAST */
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
-static inline bool tick_broadcast_oneshot_available(void) { return true; }
-# endif /* !BROADCAST */
-
+static inline bool tick_oneshot_possible(void) { return true; }
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
 			void (*handler)(struct clock_event_device *),
-			ktime_t nextevt)
-{
-	BUG();
-}
-static inline void tick_resume_oneshot(void)
-{
-	BUG();
-}
-static inline int tick_program_event(ktime_t expires, int force)
-{
-	return 0;
-}
+			ktime_t nextevt) { BUG(); }
+static inline void tick_resume_oneshot(void) { BUG(); }
+static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
-{
-	return 0;
-}
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline bool tick_broadcast_oneshot_available(void) { return false; }
+static inline bool tick_oneshot_possible(void) { return false; }
 #endif /* !TICK_ONESHOT */
 
-/* NO_HZ_FULL internal */
-#ifdef CONFIG_NO_HZ_FULL
-extern void tick_nohz_init(void);
-# else
-static inline void tick_nohz_init(void) { }
-#endif
-
-/*
- * Broadcasting support
- */
+/* Broadcasting support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
@@ -114,53 +69,51 @@ extern void tick_shutdown_broadcast(unsi
 extern void tick_suspend_broadcast(void);
 extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
-extern void
-tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
-int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
-
+extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
 #else /* !BROADCAST */
-
-static inline void tick_install_broadcast_device(struct clock_event_device *dev)
-{
-}
-
-static inline int tick_is_broadcast_device(struct clock_event_device *dev)
-{
-	return 0;
-}
-static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
-					     int cpu)
-{
-	return 0;
-}
+static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
+static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline int tick_resume_broadcast(void) { return 0; }
 static inline void tick_broadcast_init(void) { }
-static inline int tick_broadcast_update_freq(struct clock_event_device *dev,
-					     u32 freq) { return -ENODEV; }
+static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 
-/*
- * Set the periodic handler in non broadcast mode
- */
-static inline void tick_set_periodic_handler(struct clock_event_device *dev,
-					     int broadcast)
+/* Set the periodic handler in non broadcast mode */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
 {
 	dev->event_handler = tick_handle_periodic;
 }
 #endif /* !BROADCAST */
 
-/*
- * Check, if the device is functional or a dummy for broadcast
- */
-static inline int tick_device_is_functional(struct clock_event_device *dev)
-{
-	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
-}
-
-int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
-
-#endif /* GENERIC_CLOCKEVENTS */
+/* Functions related to oneshot broadcasting */
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_control(unsigned long reason);
+extern void tick_broadcast_switch_to_oneshot(void);
+extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_active(void);
+extern void tick_check_oneshot_broadcast_this_cpu(void);
+bool tick_broadcast_oneshot_available(void);
+#else /* BROADCAST && ONESHOT */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
+static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
+static inline void tick_broadcast_switch_to_oneshot(void) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
+static inline int tick_broadcast_oneshot_active(void) { return 0; }
+static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
+static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
+#endif /* !BROADCAST && ONESHOT */
 
+/* NO_HZ_FULL internal */
+#ifdef CONFIG_NO_HZ_FULL
+extern void tick_nohz_init(void);
+# else
+static inline void tick_nohz_init(void) { }
+#endif



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

* [PATCH 05/35] tick: Move core only declarations and functions to core
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (3 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 04/35] tick: Cleanup internal header file Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 06/35] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Peter Zijlstra
                   ` (31 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Nicolas Pitre

[-- Attachment #1: tick-move-core-only-declarations-to-core.patch --]
[-- Type: text/plain, Size: 15543 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

No point to expose everything to the world. People just believe such
functions can be abused for whatever purposes. Sigh.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nicolas Pitre <nico@linaro.org>
---
 include/linux/clockchips.h  |   15 ++---
 include/linux/tick.h        |  130 +++++---------------------------------------
 kernel/time/clocksource.c   |    2 
 kernel/time/hrtimer.c       |    2 
 kernel/time/tick-internal.h |   15 +++++
 kernel/time/tick-sched.c    |    7 ++
 kernel/time/tick-sched.h    |   64 +++++++++++++++++++++
 kernel/time/timer_list.c    |    2 
 8 files changed, 110 insertions(+), 127 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -158,15 +158,6 @@ extern void clockevents_config_and_regis
 
 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
 
-extern void clockevents_exchange_device(struct clock_event_device *old,
-					struct clock_event_device *new);
-extern void clockevents_set_mode(struct clock_event_device *dev,
-				 enum clock_event_mode mode);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
-
-extern void clockevents_handle_noop(struct clock_event_device *dev);
-
 static inline void
 clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 {
@@ -174,6 +165,12 @@ clockevents_calc_mult_shift(struct clock
 				      freq, minsec);
 }
 
+/* Should be core only, but is abused by arm bl_switcher */
+extern void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
+
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -1,7 +1,5 @@
-/*  linux/include/linux/tick.h
- *
- *  This file contains the structure definitions for tick related functions
- *
+/*
+ * Tick related global functions
  */
 #ifndef _LINUX_TICK_H
 #define _LINUX_TICK_H
@@ -9,13 +7,12 @@
 #include <linux/clockchips.h>
 #include <linux/irqflags.h>
 #include <linux/percpu.h>
-#include <linux/hrtimer.h>
 #include <linux/context_tracking_state.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
+/* ARM BL switcher abuse support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-
 enum tick_device_mode {
 	TICKDEV_MODE_PERIODIC,
 	TICKDEV_MODE_ONESHOT,
@@ -25,128 +22,34 @@ struct tick_device {
 	struct clock_event_device *evtdev;
 	enum tick_device_mode mode;
 };
-
-enum tick_nohz_mode {
-	NOHZ_MODE_INACTIVE,
-	NOHZ_MODE_LOWRES,
-	NOHZ_MODE_HIGHRES,
-};
-
-/**
- * struct tick_sched - sched tick emulation and no idle tick control/stats
- * @sched_timer:	hrtimer to schedule the periodic tick in high
- *			resolution mode
- * @last_tick:		Store the last tick expiry time when the tick
- *			timer is modified for nohz sleeps. This is necessary
- *			to resume the tick timer operation in the timeline
- *			when the CPU returns from nohz sleep.
- * @tick_stopped:	Indicator that the idle tick has been stopped
- * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
- * @idle_calls:		Total number of idle calls
- * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
- * @idle_entrytime:	Time when the idle call was entered
- * @idle_waketime:	Time when the idle was interrupted
- * @idle_exittime:	Time when the idle state was left
- * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
- * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
- * @sleep_length:	Duration of the current idle sleep
- * @do_timer_lst:	CPU was the last one doing do_timer before going idle
- */
-struct tick_sched {
-	struct hrtimer			sched_timer;
-	unsigned long			check_clocks;
-	enum tick_nohz_mode		nohz_mode;
-	ktime_t				last_tick;
-	int				inidle;
-	int				tick_stopped;
-	unsigned long			idle_jiffies;
-	unsigned long			idle_calls;
-	unsigned long			idle_sleeps;
-	int				idle_active;
-	ktime_t				idle_entrytime;
-	ktime_t				idle_waketime;
-	ktime_t				idle_exittime;
-	ktime_t				idle_sleeptime;
-	ktime_t				iowait_sleeptime;
-	ktime_t				sleep_length;
-	unsigned long			last_jiffies;
-	unsigned long			next_jiffies;
-	ktime_t				idle_expires;
-	int				do_timer_last;
-};
-
-extern void __init tick_init(void);
-extern int tick_is_oneshot_available(void);
 extern struct tick_device *tick_get_device(int cpu);
+#endif
 
-# ifdef CONFIG_HIGH_RES_TIMERS
-extern int tick_init_highres(void);
-extern int tick_program_event(ktime_t expires, int force);
-extern void tick_setup_sched_timer(void);
-# endif
-
-# if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
-extern void tick_cancel_sched_timer(int cpu);
-# else
-static inline void tick_cancel_sched_timer(int cpu) { }
-# endif
-
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern struct tick_device *tick_get_broadcast_device(void);
-extern struct cpumask *tick_get_broadcast_mask(void);
-
-#  ifdef CONFIG_TICK_ONESHOT
-extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
-#  endif
-
-# endif /* BROADCAST */
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+extern void __init tick_init(void);
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-# ifdef CONFIG_TICK_ONESHOT
-extern void tick_clock_notify(void);
-extern int tick_check_oneshot_change(int allow_nohz);
-extern struct tick_sched *tick_get_tick_sched(int cpu);
+#ifdef CONFIG_TICK_ONESHOT
 extern void tick_irq_enter(void);
-extern int tick_oneshot_mode_active(void);
 #  ifndef arch_needs_cpu
 #   define arch_needs_cpu() (0)
 #  endif
 # else
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-# endif
-
-#else /* CONFIG_GENERIC_CLOCKEVENTS */
-static inline void tick_init(void) { }
-static inline void tick_cancel_sched_timer(int cpu) { }
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
-
-# ifdef CONFIG_NO_HZ_COMMON
-DECLARE_PER_CPU(struct tick_sched, tick_cpu_sched);
-
-static inline int tick_nohz_tick_stopped(void)
-{
-	return __this_cpu_read(tick_cpu_sched.tick_stopped);
-}
+#endif
 
+#ifdef CONFIG_NO_HZ_COMMON
+extern int tick_nohz_tick_stopped(void);
 extern void tick_nohz_idle_enter(void);
 extern void tick_nohz_idle_exit(void);
 extern void tick_nohz_irq_exit(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
-
-# else /* !CONFIG_NO_HZ_COMMON */
-static inline int tick_nohz_tick_stopped(void)
-{
-	return 0;
-}
-
+#else /* !CONFIG_NO_HZ_COMMON */
+static inline int tick_nohz_tick_stopped(void) { return 0; }
 static inline void tick_nohz_idle_enter(void) { }
 static inline void tick_nohz_idle_exit(void) { }
 
@@ -158,7 +61,7 @@ static inline ktime_t tick_nohz_get_slee
 }
 static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
-# endif /* !CONFIG_NO_HZ_COMMON */
+#endif /* !CONFIG_NO_HZ_COMMON */
 
 #ifdef CONFIG_NO_HZ_FULL
 extern bool tick_nohz_full_running;
@@ -226,5 +129,4 @@ static inline void tick_nohz_task_switch
 		__tick_nohz_task_switch(tsk);
 }
 
-
 #endif
Index: linux/kernel/time/clocksource.c
===================================================================
--- linux.orig/kernel/time/clocksource.c
+++ linux/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 #include "timekeeping_internal.h"
 
 void timecounter_init(struct timecounter *tc,
Index: linux/kernel/time/hrtimer.c
===================================================================
--- linux.orig/kernel/time/hrtimer.c
+++ linux/kernel/time/hrtimer.c
@@ -54,7 +54,7 @@
 
 #include <trace/events/timer.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 
 /*
  * The timer bases:
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -5,6 +5,7 @@
 #include <linux/tick.h>
 
 #include "timekeeping.h"
+#include "tick-sched.h"
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
@@ -26,6 +27,7 @@ extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
+extern int tick_is_oneshot_available(void);
 
 /* Check, if the device is functional or a dummy for broadcast */
 static inline int tick_device_is_functional(struct clock_event_device *dev)
@@ -34,6 +36,9 @@ static inline int tick_device_is_functio
 }
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
+extern void clockevents_exchange_device(struct clock_event_device *old,
+					struct clock_event_device *new);
+extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #endif /* GENERIC_CLOCKEVENTS */
@@ -48,6 +53,10 @@ extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
 static inline bool tick_oneshot_possible(void) { return true; }
+extern int tick_oneshot_mode_active(void);
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern int tick_init_highres(void);
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
@@ -57,6 +66,9 @@ static inline void tick_resume_oneshot(v
 static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
 static inline bool tick_oneshot_possible(void) { return false; }
+static inline int tick_oneshot_mode_active(void) { return 0; }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 #endif /* !TICK_ONESHOT */
 
 /* Broadcasting support */
@@ -71,6 +83,8 @@ extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
+extern struct tick_device *tick_get_broadcast_device(void);
+extern struct cpumask *tick_get_broadcast_mask(void);
 #else /* !BROADCAST */
 static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
 static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
@@ -100,6 +114,7 @@ extern int tick_resume_broadcast_oneshot
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
+extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #else /* BROADCAST && ONESHOT */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
Index: linux/kernel/time/tick-sched.c
===================================================================
--- linux.orig/kernel/time/tick-sched.c
+++ linux/kernel/time/tick-sched.c
@@ -34,7 +34,7 @@
 /*
  * Per cpu nohz control structure
  */
-DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
 
 /*
  * The time, when the last jiffy update happened. Protected by jiffies_lock.
@@ -423,6 +423,11 @@ static int __init setup_tick_nohz(char *
 
 __setup("nohz=", setup_tick_nohz);
 
+int tick_nohz_tick_stopped(void)
+{
+	return __this_cpu_read(tick_cpu_sched.tick_stopped);
+}
+
 /**
  * tick_nohz_update_jiffies - update jiffies when idle was interrupted
  *
Index: linux/kernel/time/tick-sched.h
===================================================================
--- /dev/null
+++ linux/kernel/time/tick-sched.h
@@ -0,0 +1,64 @@
+#ifndef _TICK_SCHED_H
+#define _TICK_SCHED_H
+
+#include <linux/hrtimer.h>
+
+enum tick_nohz_mode {
+	NOHZ_MODE_INACTIVE,
+	NOHZ_MODE_LOWRES,
+	NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:	hrtimer to schedule the periodic tick in high
+ *			resolution mode
+ * @last_tick:		Store the last tick expiry time when the tick
+ *			timer is modified for nohz sleeps. This is necessary
+ *			to resume the tick timer operation in the timeline
+ *			when the CPU returns from nohz sleep.
+ * @tick_stopped:	Indicator that the idle tick has been stopped
+ * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
+ * @idle_calls:		Total number of idle calls
+ * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:	Time when the idle call was entered
+ * @idle_waketime:	Time when the idle was interrupted
+ * @idle_exittime:	Time when the idle state was left
+ * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
+ * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
+ * @sleep_length:	Duration of the current idle sleep
+ * @do_timer_lst:	CPU was the last one doing do_timer before going idle
+ */
+struct tick_sched {
+	struct hrtimer			sched_timer;
+	unsigned long			check_clocks;
+	enum tick_nohz_mode		nohz_mode;
+	ktime_t				last_tick;
+	int				inidle;
+	int				tick_stopped;
+	unsigned long			idle_jiffies;
+	unsigned long			idle_calls;
+	unsigned long			idle_sleeps;
+	int				idle_active;
+	ktime_t				idle_entrytime;
+	ktime_t				idle_waketime;
+	ktime_t				idle_exittime;
+	ktime_t				idle_sleeptime;
+	ktime_t				iowait_sleeptime;
+	ktime_t				sleep_length;
+	unsigned long			last_jiffies;
+	unsigned long			next_jiffies;
+	ktime_t				idle_expires;
+	int				do_timer_last;
+};
+
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+
+extern void tick_setup_sched_timer(void);
+#if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
+extern void tick_cancel_sched_timer(int cpu);
+#else
+static inline void tick_cancel_sched_timer(int cpu) { }
+#endif
+
+#endif
Index: linux/kernel/time/timer_list.c
===================================================================
--- linux.orig/kernel/time/timer_list.c
+++ linux/kernel/time/timer_list.c
@@ -16,10 +16,10 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
-#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 
+#include "tick-internal.h"
 
 struct timer_list_iter {
 	int cpu;



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

* [PATCH 06/35] clockevents: Remove extra local_irq_save in clockevents_exchange_device()
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (4 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 05/35] tick: Move core only declarations and functions to core Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 07/35] clockevents: Make suspend/resume calls explicit Peter Zijlstra
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-remove-extra-irq-disable.patch --]
[-- Type: text/plain, Size: 1217 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Called with clockevents_lock held and interrupts disabled already.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/clockevents.c |    7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -491,14 +491,12 @@ void clockevents_handle_noop(struct cloc
  * @old:	device to release (can be NULL)
  * @new:	device to request (can be NULL)
  *
- * Called from the notifier chain. clockevents_lock is held already
+ * Called from various tick functions with clockevents_lock held and
+ * interrupts disabled.
  */
 void clockevents_exchange_device(struct clock_event_device *old,
 				 struct clock_event_device *new)
 {
-	unsigned long flags;
-
-	local_irq_save(flags);
 	/*
 	 * Caller releases a clock event device. We queue it into the
 	 * released list and do a notify add later.
@@ -514,7 +512,6 @@ void clockevents_exchange_device(struct
 		BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
 		clockevents_shutdown(new);
 	}
-	local_irq_restore(flags);
 }
 
 /**



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

* [PATCH 07/35] clockevents: Make suspend/resume calls explicit
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (5 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 06/35] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 19:07   ` Rafael J. Wysocki
  2015-02-16 12:14 ` [PATCH 08/35] tick: Make tick_resume_broadcast_oneshot static Peter Zijlstra
                   ` (29 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-make-resume-call-explicit.patch --]
[-- Type: text/plain, Size: 6291 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call.

We are way better off to have explicit calls instead of this
monstrosity. Split out the suspend/resume() calls and invoke them
directly from the call sites.

No locking required at this point because these calls happen with
interrupts disabled and a single cpu online.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/xen/suspend.c      |   11 ++++-------
 include/linux/clockchips.h  |    2 --
 include/linux/tick.h        |    3 +++
 kernel/time/clockevents.c   |    9 ---------
 kernel/time/tick-common.c   |   23 +++++++++++++++++++++--
 kernel/time/tick-internal.h |    3 ++-
 kernel/time/timekeeping.c   |    6 ++----
 7 files changed, 32 insertions(+), 25 deletions(-)

Index: linux/arch/x86/xen/suspend.c
===================================================================
--- linux.orig/arch/x86/xen/suspend.c
+++ linux/arch/x86/xen/suspend.c
@@ -1,5 +1,5 @@
 #include <linux/types.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
@@ -81,17 +81,14 @@ void xen_arch_post_suspend(int cancelled
 
 static void xen_vcpu_notify_restore(void *data)
 {
-	unsigned long reason = (unsigned long)data;
-
 	/* Boot processor notified via generic timekeeping_resume() */
-	if ( smp_processor_id() == 0)
+	if (smp_processor_id() == 0)
 		return;
 
-	clockevents_notify(reason, NULL);
+	tick_resume();
 }
 
 void xen_arch_resume(void)
 {
-	on_each_cpu(xen_vcpu_notify_restore,
-		    (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+	on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
 }
Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -16,8 +16,6 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_SUSPEND,
-	CLOCK_EVT_NOTIFY_RESUME,
 	CLOCK_EVT_NOTIFY_CPU_DYING,
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -27,8 +27,11 @@ extern struct tick_device *tick_get_devi
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
+/* Should be core only, but XEN resume magic abuses this interface */
+extern void tick_resume(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
+static inline void tick_resume(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -566,15 +566,6 @@ int clockevents_notify(unsigned long rea
 		tick_handover_do_timer(arg);
 		break;
 
-	case CLOCK_EVT_NOTIFY_SUSPEND:
-		tick_suspend();
-		tick_suspend_broadcast();
-		break;
-
-	case CLOCK_EVT_NOTIFY_RESUME:
-		tick_resume();
-		break;
-
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
 		tick_shutdown_broadcast_oneshot(arg);
 		tick_shutdown_broadcast(arg);
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -372,18 +372,37 @@ void tick_shutdown(unsigned int *cpup)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_suspend(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
+	tick_suspend_broadcast();
 }
 
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_resume(void)
 {
-	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
-	int broadcast = tick_resume_broadcast();
+	struct tick_device *td;
+	int broadcast;
 
+	broadcast = tick_resume_broadcast();
+	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
 
 	if (!broadcast) {
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -23,7 +23,6 @@ extern void tick_check_new_device(struct
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
-extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -41,6 +40,8 @@ extern void clockevents_exchange_device(
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#else
+static inline void tick_suspend(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
Index: linux/kernel/time/timekeeping.c
===================================================================
--- linux.orig/kernel/time/timekeeping.c
+++ linux/kernel/time/timekeeping.c
@@ -1245,9 +1245,7 @@ static void timekeeping_resume(void)
 
 	touch_softlockup_watchdog();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-	/* Resume hrtimers */
+	tick_resume();
 	hrtimers_resume();
 }
 
@@ -1299,7 +1297,7 @@ static int timekeeping_suspend(void)
 	write_seqcount_end(&tk_core.seq);
 	raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+	tick_suspend();
 	clocksource_suspend();
 	clockevents_suspend();
 



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

* [PATCH 08/35] tick: Make tick_resume_broadcast_oneshot static
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (6 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 07/35] clockevents: Make suspend/resume calls explicit Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 09/35] tick/xen: Provide and use tick_resume_local() Peter Zijlstra
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: tick-broadcast-make-tick_resume_broadcast_oneshot-static.patch --]
[-- Type: text/plain, Size: 2725 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Solely used in tick-broadcast.c and the return value is hardcoded
0. Make it static and void.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/tick-broadcast.c |    7 ++++---
 kernel/time/tick-internal.h  |    2 --
 2 files changed, 4 insertions(+), 5 deletions(-)

Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -37,8 +37,10 @@ static int tick_broadcast_force;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 #else
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
+static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
 
 /*
@@ -475,7 +477,7 @@ int tick_resume_broadcast(void)
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
-				broadcast = tick_resume_broadcast_oneshot(bc);
+				tick_resume_broadcast_oneshot(bc);
 			break;
 		}
 	}
@@ -541,10 +543,9 @@ static int tick_broadcast_set_event(stru
 	return ret;
 }
 
-int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
 	clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-	return 0;
 }
 
 /*
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -111,7 +111,6 @@ extern void tick_broadcast_setup_oneshot
 extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
@@ -121,7 +120,6 @@ static inline void tick_broadcast_setup_
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }



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

* [PATCH 09/35] tick/xen: Provide and use tick_resume_local()
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (7 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 08/35] tick: Make tick_resume_broadcast_oneshot static Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 16:37   ` David Vrabel
  2015-02-16 12:14 ` [PATCH 10/35] clockevents: Make tick handover explicit Peter Zijlstra
                   ` (27 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw
  Cc: tglx, peterz, Konrad Rzeszutek Wilk, Boris Ostrovsky, David Vrabel

[-- Attachment #1: tick-xen-fix-absurd-hackery.patch --]
[-- Type: text/plain, Size: 7374 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Xen calls on every cpu into tick_resume() which is just
wrong. tick_resume() is for the syscore global suspend/resume
invocation. What XEN really wants is a per cpu local resume function,
but yes, its simpler to just use something which works by chance and
let those who want to change that code deal with the fallout.

Provide a tick_resume_local() function and use it in XEN.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
---
 arch/x86/xen/suspend.c       |    2 +-
 include/linux/tick.h         |    6 +++---
 kernel/time/tick-broadcast.c |   27 ++++++++++++++++++++-------
 kernel/time/tick-common.c    |   28 +++++++++++++++++++---------
 kernel/time/tick-internal.h  |    8 ++++++--
 5 files changed, 49 insertions(+), 22 deletions(-)

Index: linux/arch/x86/xen/suspend.c
===================================================================
--- linux.orig/arch/x86/xen/suspend.c
+++ linux/arch/x86/xen/suspend.c
@@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
 	if (smp_processor_id() == 0)
 		return;
 
-	tick_resume();
+	tick_resume_local();
 }
 
 void xen_arch_resume(void)
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -27,11 +27,11 @@ extern struct tick_device *tick_get_devi
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
-/* Should be core only, but XEN resume magic abuses this interface */
-extern void tick_resume(void);
+/* Should be core only, but XEN resume magic requires this */
+extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
-static inline void tick_resume(void) { }
+static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -455,11 +455,29 @@ void tick_suspend_broadcast(void)
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
-int tick_resume_broadcast(void)
+/*
+ * This is called from tick_resume_local() on a resuming cpu. That's *
+ * called from the core resume function and the magic XEN resume hackery.
+ *
+ * It's intended to be called from tick_unfreeze_local() if the
+ * freezer folks figure out to guarantee that this is called before
+ * they reenable interrupts.
+ *
+ * In none of these cases the broadcast device mode can change and the
+ * bit of the resuming cpu in the broadcast mask is safe as well.
+ */
+bool tick_resume_check_broadcast(void)
+{
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
+		return false;
+	else
+		return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
+}
+
+void tick_resume_broadcast(void)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
-	int broadcast = 0;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -472,8 +490,6 @@ int tick_resume_broadcast(void)
 		case TICKDEV_MODE_PERIODIC:
 			if (!cpumask_empty(tick_broadcast_mask))
 				tick_broadcast_start_periodic(bc);
-			broadcast = cpumask_test_cpu(smp_processor_id(),
-						     tick_broadcast_mask);
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
@@ -482,11 +498,8 @@ int tick_resume_broadcast(void)
 		}
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-
-	return broadcast;
 }
 
-
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_var_t tick_broadcast_oneshot_mask;
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -389,22 +389,18 @@ void tick_suspend(void)
 }
 
 /**
- * tick_resume - Resume the tick and the broadcast device
+ * tick_resume_local - Resume the local tick device
  *
- * Called from syscore_resume() via timekeeping_resume with only one
- * CPU online and interrupts disabled.
+ * Called from the local cpu for unfreeze or XEN resume magic
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_resume(void)
+void tick_resume_local(void)
 {
-	struct tick_device *td;
-	int broadcast;
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+	bool broadcast = tick_resume_check_broadcast();
 
-	broadcast = tick_resume_broadcast();
-	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
-
 	if (!broadcast) {
 		if (td->mode == TICKDEV_MODE_PERIODIC)
 			tick_setup_periodic(td->evtdev, 0);
@@ -414,6 +410,20 @@ void tick_resume(void)
 }
 
 /**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume(void)
+{
+	tick_resume_broadcast();
+	tick_resume_local();
+}
+
+/**
  * tick_init - initialize the tick control
  */
 void __init tick_init(void)
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -23,6 +23,7 @@ extern void tick_check_new_device(struct
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
+extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -42,6 +43,7 @@ extern int __clockevents_update_freq(str
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #else
 static inline void tick_suspend(void) { }
+static inline void tick_resume(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
@@ -80,7 +82,8 @@ extern int tick_is_broadcast_device(stru
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
-extern int tick_resume_broadcast(void);
+extern void tick_resume_broadcast(void);
+extern bool tick_resume_check_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
@@ -94,7 +97,8 @@ static inline void tick_do_periodic_broa
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
-static inline int tick_resume_broadcast(void) { return 0; }
+static inline void tick_resume_broadcast(void) { }
+static inline bool tick_resume_check_broadcast(void) { return false; }
 static inline void tick_broadcast_init(void) { }
 static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 



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

* [PATCH 10/35] clockevents: Make tick handover explicit
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (8 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 09/35] tick/xen: Provide and use tick_resume_local() Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 11/35] clockevents: Cleanup dead cpu explicitely Peter Zijlstra
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-make-tick-handover-explicit.patch --]
[-- Type: text/plain, Size: 4878 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call. We are way better off to have explicit calls instead of this
monstrosity.

Split out the tick_handover call and invoke it explicitely from the
hotplug code. Temporary solution will be cleaned up in later patches.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/clockchips.h  |    1 -
 include/linux/tick.h        |    2 ++
 kernel/cpu.c                |    3 +++
 kernel/time/clockevents.c   |    4 ----
 kernel/time/hrtimer.c       |    4 ----
 kernel/time/tick-common.c   |    9 ++++++---
 kernel/time/tick-internal.h |    1 -
 7 files changed, 11 insertions(+), 13 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -16,7 +16,6 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_CPU_DYING,
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -29,9 +29,11 @@ extern struct tick_device *tick_get_devi
 extern void __init tick_init(void);
 /* Should be core only, but XEN resume magic requires this */
 extern void tick_resume_local(void);
+extern void tick_handover_do_timer(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_resume_local(void) { }
+static inline void tick_handover_do_timer(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux/kernel/cpu.c
===================================================================
--- linux.orig/kernel/cpu.c
+++ linux/kernel/cpu.c
@@ -20,6 +20,7 @@
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 #include <linux/lockdep.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 
 #include "smpboot.h"
@@ -348,6 +349,8 @@ static int __ref take_cpu_down(void *_pa
 		return err;
 
 	cpu_notify(CPU_DYING | param->mod, param->hcpu);
+	/* Give up timekeeping duties */
+	tick_handover_do_timer();
 	/* Park the stopper thread */
 	kthread_park(current);
 	return 0;
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -562,10 +562,6 @@ int clockevents_notify(unsigned long rea
 		ret = tick_broadcast_oneshot_control(reason);
 		break;
 
-	case CLOCK_EVT_NOTIFY_CPU_DYING:
-		tick_handover_do_timer(arg);
-		break;
-
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
 		tick_shutdown_broadcast_oneshot(arg);
 		tick_shutdown_broadcast(arg);
Index: linux/kernel/time/hrtimer.c
===================================================================
--- linux.orig/kernel/time/hrtimer.c
+++ linux/kernel/time/hrtimer.c
@@ -1715,10 +1715,6 @@ static int hrtimer_cpu_notify(struct not
 		break;
 
 #ifdef CONFIG_HOTPLUG_CPU
-	case CPU_DYING:
-	case CPU_DYING_FROZEN:
-		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
-		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 	{
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -332,20 +332,23 @@ out_bc:
 	tick_install_broadcast_device(newdev);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * Transfer the do_timer job away from a dying cpu.
  *
- * Called with interrupts disabled.
+ * Called with interrupts disabled. Not locking required. If
+ * tick_do_timer_cpu is owned by this cpu, nothing can change it.
  */
-void tick_handover_do_timer(int *cpup)
+void tick_handover_do_timer(void)
 {
-	if (*cpup == tick_do_timer_cpu) {
+	if (tick_do_timer_cpu == smp_processor_id()) {
 		int cpu = cpumask_first(cpu_online_mask);
 
 		tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
 			TICK_DO_TIMER_NONE;
 	}
 }
+#endif
 
 /*
  * Shutdown an event device on a given cpu:
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -20,7 +20,6 @@ extern int tick_do_timer_cpu __read_most
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_check_new_device(struct clock_event_device *dev);
-extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
 extern void tick_resume(void);



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

* [PATCH 11/35] clockevents: Cleanup dead cpu explicitely
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (9 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 10/35] clockevents: Make tick handover explicit Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 12/35] clockevents: Provide explicit broadcast control function Peter Zijlstra
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-cleanup-dead-cpu-explicitely.patch --]
[-- Type: text/plain, Size: 11608 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call. We are way better off to have explicit calls instead of this
monstrosity.

Split out the cleanup function for a dead cpu and invoke it directly
from the cpu down code. Make it conditional on CPU_HOTPLUG as well.

Temporary change, will be refined in later patches.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/clockchips.h   |    1 
 include/linux/tick.h         |    2 +
 kernel/cpu.c                 |    1 
 kernel/time/clockevents.c    |   61 +++++++++++++++++++++++++------------------
 kernel/time/hrtimer.c        |    3 --
 kernel/time/tick-broadcast.c |   29 ++++++++++----------
 kernel/time/tick-common.c    |    6 ++--
 kernel/time/tick-internal.h  |   10 +++----
 8 files changed, 62 insertions(+), 51 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -16,7 +16,6 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -30,10 +30,12 @@ extern void __init tick_init(void);
 /* Should be core only, but XEN resume magic requires this */
 extern void tick_resume_local(void);
 extern void tick_handover_do_timer(void);
+extern void tick_cleanup_dead_cpu(int cpu);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_resume_local(void) { }
 static inline void tick_handover_do_timer(void) { }
+static inline void tick_cleanup_dead_cpu(int cpu) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux/kernel/cpu.c
===================================================================
--- linux.orig/kernel/cpu.c
+++ linux/kernel/cpu.c
@@ -428,6 +428,7 @@ static int __ref _cpu_down(unsigned int
 	__cpu_die(cpu);
 
 	/* CPU is completely dead: tell everyone.  Too late to complain. */
+	tick_cleanup_dead_cpu(cpu);
 	cpu_notify_nofail(CPU_DEAD | mod, hcpu);
 
 	check_for_tasks(cpu);
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -538,15 +538,49 @@ void clockevents_resume(void)
 			dev->resume(dev);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/**
+ * tick_cleanup_dead_cpu - Cleanup the tick and clockevents of a dead cpu
+ */
+void tick_cleanup_dead_cpu(int cpu)
+{
+	struct clock_event_device *dev, *tmp;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&clockevents_lock, flags);
+
+	tick_shutdown_broadcast_oneshot(cpu);
+	tick_shutdown_broadcast(cpu);
+	tick_shutdown(cpu);
+	/*
+	 * Unregister the clock event devices which were
+	 * released from the users in the notify chain.
+	 */
+	list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+		list_del(&dev->list);
+	/*
+	 * Now check whether the CPU has left unused per cpu devices
+	 */
+	list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+		if (cpumask_test_cpu(cpu, dev->cpumask) &&
+		    cpumask_weight(dev->cpumask) == 1 &&
+		    !tick_is_broadcast_device(dev)) {
+			BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+			list_del(&dev->list);
+		}
+	}
+	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
+}
+#endif
+
 /**
  * clockevents_notify - notification about relevant events
  * Returns 0 on success, any other value on error
  */
 int clockevents_notify(unsigned long reason, void *arg)
 {
-	struct clock_event_device *dev, *tmp;
 	unsigned long flags;
-	int cpu, ret = 0;
+	int ret = 0;
 
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
 
@@ -562,29 +596,6 @@ int clockevents_notify(unsigned long rea
 		ret = tick_broadcast_oneshot_control(reason);
 		break;
 
-	case CLOCK_EVT_NOTIFY_CPU_DEAD:
-		tick_shutdown_broadcast_oneshot(arg);
-		tick_shutdown_broadcast(arg);
-		tick_shutdown(arg);
-		/*
-		 * Unregister the clock event devices which were
-		 * released from the users in the notify chain.
-		 */
-		list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
-			list_del(&dev->list);
-		/*
-		 * Now check whether the CPU has left unused per cpu devices
-		 */
-		cpu = *((int *)arg);
-		list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
-			if (cpumask_test_cpu(cpu, dev->cpumask) &&
-			    cpumask_weight(dev->cpumask) == 1 &&
-			    !tick_is_broadcast_device(dev)) {
-				BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
-				list_del(&dev->list);
-			}
-		}
-		break;
 	default:
 		break;
 	}
Index: linux/kernel/time/hrtimer.c
===================================================================
--- linux.orig/kernel/time/hrtimer.c
+++ linux/kernel/time/hrtimer.c
@@ -1717,11 +1717,8 @@ static int hrtimer_cpu_notify(struct not
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
-	{
-		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
 		migrate_hrtimers(scpu);
 		break;
-	}
 #endif
 
 	default:
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -418,14 +418,14 @@ void tick_set_periodic_handler(struct cl
 		dev->event_handler = tick_handle_periodic_broadcast;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * Remove a CPU from broadcasting
  */
-void tick_shutdown_broadcast(unsigned int *cpup)
+void tick_shutdown_broadcast(unsigned int cpu)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
-	unsigned int cpu = *cpup;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -440,6 +440,7 @@ void tick_shutdown_broadcast(unsigned in
 
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 void tick_suspend_broadcast(void)
 {
@@ -683,16 +684,6 @@ static void broadcast_shutdown_local(str
 	clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
 }
 
-static void broadcast_move_bc(int deadcpu)
-{
-	struct clock_event_device *bc = tick_broadcast_device.evtdev;
-
-	if (!bc || !broadcast_needs_cpu(bc, deadcpu))
-		return;
-	/* This moves the broadcast assignment to this cpu */
-	clockevents_program_event(bc, bc->next_event, 1);
-}
-
 /*
  * Powerstate information: The system enters/leaves a state, where
  * affected devices might stop
@@ -908,14 +899,23 @@ void tick_broadcast_switch_to_oneshot(vo
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void broadcast_move_bc(int deadcpu)
+{
+	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+
+	if (!bc || !broadcast_needs_cpu(bc, deadcpu))
+		return;
+	/* This moves the broadcast assignment to this cpu */
+	clockevents_program_event(bc, bc->next_event, 1);
+}
 
 /*
  * Remove a dead CPU from broadcasting
  */
-void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
+void tick_shutdown_broadcast_oneshot(unsigned int cpu)
 {
 	unsigned long flags;
-	unsigned int cpu = *cpup;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -931,6 +931,7 @@ void tick_shutdown_broadcast_oneshot(uns
 
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 /*
  * Check, whether the broadcast device is in one shot mode
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -348,7 +348,6 @@ void tick_handover_do_timer(void)
 			TICK_DO_TIMER_NONE;
 	}
 }
-#endif
 
 /*
  * Shutdown an event device on a given cpu:
@@ -357,9 +356,9 @@ void tick_handover_do_timer(void)
  * access the hardware device itself.
  * We just set the mode and remove it from the lists.
  */
-void tick_shutdown(unsigned int *cpup)
+void tick_shutdown(unsigned int cpu)
 {
-	struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
+	struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
 	struct clock_event_device *dev = td->evtdev;
 
 	td->mode = TICKDEV_MODE_PERIODIC;
@@ -374,6 +373,7 @@ void tick_shutdown(unsigned int *cpup)
 		td->evtdev = NULL;
 	}
 }
+#endif
 
 /**
  * tick_suspend - Suspend the tick and the broadcast device
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -20,7 +20,7 @@ extern int tick_do_timer_cpu __read_most
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_check_new_device(struct clock_event_device *dev);
-extern void tick_shutdown(unsigned int *cpup);
+extern void tick_shutdown(unsigned int cpu);
 extern void tick_suspend(void);
 extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
@@ -79,7 +79,7 @@ extern int tick_device_uses_broadcast(st
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
 extern int tick_is_broadcast_device(struct clock_event_device *dev);
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
-extern void tick_shutdown_broadcast(unsigned int *cpup);
+extern void tick_shutdown_broadcast(unsigned int cpu);
 extern void tick_suspend_broadcast(void);
 extern void tick_resume_broadcast(void);
 extern bool tick_resume_check_broadcast(void);
@@ -94,7 +94,7 @@ static inline int tick_is_broadcast_devi
 static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
-static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
+static inline void tick_shutdown_broadcast(unsigned int cpu) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline void tick_resume_broadcast(void) { }
 static inline bool tick_resume_check_broadcast(void) { return false; }
@@ -113,7 +113,7 @@ static inline void tick_set_periodic_han
 extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+extern void tick_shutdown_broadcast_oneshot(unsigned int cpu);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
@@ -122,7 +122,7 @@ extern struct cpumask *tick_get_broadcas
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }



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

* [PATCH 12/35] clockevents: Provide explicit broadcast control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (10 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 11/35] clockevents: Cleanup dead cpu explicitely Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-23 18:08   ` Daniel Lezcano
  2015-02-24  0:38   ` Tony Lindgren
  2015-02-16 12:14 ` [PATCH 13/35] x86, amd_idle: Use explicit broadcast control functions Peter Zijlstra
                   ` (24 subsequent siblings)
  36 siblings, 2 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw
  Cc: tglx, peterz, Tony Lindgren, Fenghua Yu, Len Brown, Daniel Lezcano

[-- Attachment #1: clockevents-provide-explicit-broadcast-control-functions.patch --]
[-- Type: text/plain, Size: 7461 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call. We are way better off to have explicit calls instead of this
monstrosity.

Split out the broadcast control into a separate function and provide
inline helpers. Switch clockevents_notify() over. This will go away
once all callers are converted.

This also gets rid of the nested locking of clockevents_lock and
broadcast_lock. The broadcast control functions do not require
clockevents_lock. Only the managing functions
(setup/shutdown/suspend/resume of the broadcast device require 
clockevents_lock.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 include/linux/tick.h         |   25 +++++++++++++++++
 kernel/time/clockevents.c    |    6 +++-
 kernel/time/tick-broadcast.c |   62 ++++++++++++++++++-------------------------
 kernel/time/tick-internal.h  |    2 -
 4 files changed, 57 insertions(+), 38 deletions(-)

Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -47,6 +47,31 @@ extern void tick_irq_enter(void);
 static inline void tick_irq_enter(void) { }
 #endif
 
+enum tick_broadcast_mode {
+	TICK_BROADCAST_OFF,
+	TICK_BROADCAST_ON,
+	TICK_BROADCAST_FORCE,
+};
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern void tick_broadcast_control(enum tick_broadcast_mode mode);
+#else
+static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { }
+#endif /* BROADCAST */
+
+static inline void tick_broadcast_enable(void)
+{
+	tick_broadcast_control(TICK_BROADCAST_ON);
+}
+static inline void tick_broadcast_disable(void)
+{
+	tick_broadcast_control(TICK_BROADCAST_OFF);
+}
+static inline void tick_broadcast_force(void)
+{
+	tick_broadcast_control(TICK_BROADCAST_FORCE);
+}
+
 #ifdef CONFIG_NO_HZ_COMMON
 extern int tick_nohz_tick_stopped(void);
 extern void tick_nohz_idle_enter(void);
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -586,9 +586,13 @@ int clockevents_notify(unsigned long rea
 
 	switch (reason) {
 	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+		tick_broadcast_enable();
+		break;
 	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
+		tick_broadcast_disable();
+		break;
 	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
-		tick_broadcast_on_off(reason, arg);
+		tick_broadcast_force();
 		break;
 
 	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -33,7 +33,7 @@ static cpumask_var_t tick_broadcast_mask
 static cpumask_var_t tick_broadcast_on;
 static cpumask_var_t tmpmask;
 static DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
-static int tick_broadcast_force;
+static int tick_broadcast_forced;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
@@ -326,49 +326,54 @@ unlock:
 	raw_spin_unlock(&tick_broadcast_lock);
 }
 
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop
+/**
+ * tick_broadcast_control - Enable/disable or force broadcast mode
+ * @mode:	The selected broadcast mode
+ *
+ * Called when the system enters a state where affected tick devices
+ * might stop. Note: TICK_BROADCAST_FORCE cannot be undone.
+ *
+ * Called with interrupts disabled, so clockevents_lock is not
+ * required here because the local clock event device cannot go away
+ * under us.
  */
-static void tick_do_broadcast_on_off(unsigned long *reason)
+void tick_broadcast_control(enum tick_broadcast_mode mode)
 {
 	struct clock_event_device *bc, *dev;
 	struct tick_device *td;
-	unsigned long flags;
 	int cpu, bc_stopped;
 
-	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-
-	cpu = smp_processor_id();
-	td = &per_cpu(tick_cpu_device, cpu);
+	td = this_cpu_ptr(&tick_cpu_device);
 	dev = td->evtdev;
-	bc = tick_broadcast_device.evtdev;
 
 	/*
 	 * Is the device not affected by the powerstate ?
 	 */
 	if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
-		goto out;
+		return;
 
 	if (!tick_device_is_functional(dev))
-		goto out;
+		return;
 
+	raw_spin_lock(&tick_broadcast_lock);
+	cpu = smp_processor_id();
+	bc = tick_broadcast_device.evtdev;
 	bc_stopped = cpumask_empty(tick_broadcast_mask);
 
-	switch (*reason) {
-	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
-	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
+	switch (mode) {
+	case TICK_BROADCAST_FORCE:
+		tick_broadcast_forced = 1;
+	case TICK_BROADCAST_ON:
 		cpumask_set_cpu(cpu, tick_broadcast_on);
 		if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) {
 			if (tick_broadcast_device.mode ==
 			    TICKDEV_MODE_PERIODIC)
 				clockevents_shutdown(dev);
 		}
-		if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
-			tick_broadcast_force = 1;
 		break;
-	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
-		if (tick_broadcast_force)
+
+	case TICK_BROADCAST_OFF:
+		if (tick_broadcast_forced)
 			break;
 		cpumask_clear_cpu(cpu, tick_broadcast_on);
 		if (!tick_device_is_functional(dev))
@@ -390,22 +395,9 @@ static void tick_do_broadcast_on_off(uns
 		else
 			tick_broadcast_setup_oneshot(bc);
 	}
-out:
-	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-}
-
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop.
- */
-void tick_broadcast_on_off(unsigned long reason, int *oncpu)
-{
-	if (!cpumask_test_cpu(*oncpu, cpu_online_mask))
-		printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
-		       "offline CPU #%d\n", *oncpu);
-	else
-		tick_do_broadcast_on_off(&reason);
+	raw_spin_unlock(&tick_broadcast_lock);
 }
+EXPORT_SYMBOL_GPL(tick_broadcast_control);
 
 /*
  * Set the periodic handler depending on broadcast on/off
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -78,7 +78,6 @@ static inline int tick_check_oneshot_cha
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
 extern int tick_is_broadcast_device(struct clock_event_device *dev);
-extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int cpu);
 extern void tick_suspend_broadcast(void);
 extern void tick_resume_broadcast(void);
@@ -93,7 +92,6 @@ static inline void tick_install_broadcas
 static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
 static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
-static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int cpu) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline void tick_resume_broadcast(void) { }



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

* [PATCH 13/35] x86, amd_idle: Use explicit broadcast control functions
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (11 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 12/35] clockevents: Provide explicit broadcast control function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 14/35] ACPI / PAD: Use explicit broadcast control function Peter Zijlstra
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: x86-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 1187 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/process.c |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

Index: linux/arch/x86/kernel/process.c
===================================================================
--- linux.orig/arch/x86/kernel/process.c
+++ linux/arch/x86/kernel/process.c
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/random.h>
 #include <linux/user-return-notifier.h>
 #include <linux/dmi.h>
@@ -376,11 +376,8 @@ static void amd_e400_idle(void)
 
 		if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
 			cpumask_set_cpu(cpu, amd_e400_c1e_mask);
-			/*
-			 * Force broadcast so ACPI can not interfere.
-			 */
-			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
-					   &cpu);
+			/* Force broadcast so ACPI can not interfere. */
+			tick_broadcast_force();
 			pr_info("Switch to broadcast mode on CPU%d\n", cpu);
 		}
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);



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

* [PATCH 14/35] ACPI / PAD: Use explicit broadcast control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (12 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 13/35] x86, amd_idle: Use explicit broadcast control functions Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 15/35] ACPI/ processor_idle: Use explicit broadcast controll function Peter Zijlstra
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Fenghua Yu, Len Brown

[-- Attachment #1: apci-acpi-pad-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 1163 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/acpi/acpi_pad.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux/drivers/acpi/acpi_pad.c
===================================================================
--- linux.orig/drivers/acpi/acpi_pad.c
+++ linux/drivers/acpi/acpi_pad.c
@@ -26,7 +26,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/cpu.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <asm/mwait.h>
@@ -172,9 +172,8 @@ static int power_saving_thread(void *dat
 				mark_tsc_unstable("TSC halts in idle");
 				tsc_marked_unstable = 1;
 			}
-			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
-
 			local_irq_disable();
+			tick_broadcast_enable();
 			cpu = smp_processor_id();
 			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 			stop_critical_timings();



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

* [PATCH 15/35] ACPI/ processor_idle: Use explicit broadcast controll function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (13 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 14/35] ACPI / PAD: Use explicit broadcast control function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 16/35] cpuidle: Use explicit broadcast control function Peter Zijlstra
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Fenghua Yu, Len Brown

[-- Attachment #1: acpi-processor-idle-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 1417 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/acpi/processor_idle.c |   11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

Index: linux/drivers/acpi/processor_idle.c
===================================================================
--- linux.orig/drivers/acpi/processor_idle.c
+++ linux/drivers/acpi/processor_idle.c
@@ -32,7 +32,7 @@
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/sched.h>       /* need_resched() */
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/syscore_ops.h>
 #include <acpi/processor.h>
@@ -157,12 +157,11 @@ static void lapic_timer_check_state(int
 static void __lapic_timer_propagate_broadcast(void *arg)
 {
 	struct acpi_processor *pr = (struct acpi_processor *) arg;
-	unsigned long reason;
 
-	reason = pr->power.timer_broadcast_on_state < INT_MAX ?
-		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
-
-	clockevents_notify(reason, &pr->id);
+	if (pr->power.timer_broadcast_on_state < INT_MAX)
+		tick_broadcast_enable();
+	else
+		tick_broadcast_disable();
 }
 
 static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)



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

* [PATCH 16/35] cpuidle: Use explicit broadcast control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (14 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 15/35] ACPI/ processor_idle: Use explicit broadcast controll function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-23 18:11   ` Daniel Lezcano
  2015-02-16 12:14 ` [PATCH 17/35] intel_idle: " Peter Zijlstra
                   ` (20 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Daniel Lezcano

[-- Attachment #1: cpuilde-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 2255 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/cpuidle/driver.c |   25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

Index: linux/drivers/cpuidle/driver.c
===================================================================
--- linux.orig/drivers/cpuidle/driver.c
+++ linux/drivers/cpuidle/driver.c
@@ -13,7 +13,7 @@
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
 #include <linux/cpumask.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include "cpuidle.h"
 
@@ -130,21 +130,20 @@ static inline void __cpuidle_unset_drive
 #endif
 
 /**
- * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer
+ * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer on a cpu
  * @arg: a void pointer used to match the SMP cross call API
  *
- * @arg is used as a value of type 'long' with one of the two values:
- * - CLOCK_EVT_NOTIFY_BROADCAST_ON
- * - CLOCK_EVT_NOTIFY_BROADCAST_OFF
- *
- * Set the broadcast timer notification for the current CPU.  This function
- * is executed per CPU by an SMP cross call.  It not supposed to be called
- * directly.
+ * If @arg is NULL broadcast is disabled otherwise enabled
+ *
+ * This function is executed per CPU by an SMP cross call.  It's not
+ * supposed to be called directly.
  */
 static void cpuidle_setup_broadcast_timer(void *arg)
 {
-	int cpu = smp_processor_id();
-	clockevents_notify((long)(arg), &cpu);
+	if (arg)
+		tick_broadcast_enable();
+	else
+		tick_broadcast_disable();
 }
 
 /**
@@ -239,7 +238,7 @@ static int __cpuidle_register_driver(str
 
 	if (drv->bctimer)
 		on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
-				 (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
+				 (void *)1, 1);
 
 	poll_idle_init(drv);
 
@@ -263,7 +262,7 @@ static void __cpuidle_unregister_driver(
 	if (drv->bctimer) {
 		drv->bctimer = 0;
 		on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
-				 (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1);
+				 NULL, 1);
 	}
 
 	__cpuidle_unset_driver(drv);



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

* [PATCH 17/35] intel_idle: Use explicit broadcast control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (15 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 16/35] cpuidle: Use explicit broadcast control function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 18/35] ARM: OMAP: " Peter Zijlstra
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Fenghua Yu, Len Brown

[-- Attachment #1: intelidle-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 1285 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/idle/intel_idle.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

Index: linux/drivers/idle/intel_idle.c
===================================================================
--- linux.orig/drivers/idle/intel_idle.c
+++ linux/drivers/idle/intel_idle.c
@@ -55,7 +55,7 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
@@ -594,13 +594,12 @@ static int intel_idle(struct cpuidle_dev
 
 static void __setup_broadcast_timer(void *arg)
 {
-	unsigned long reason = (unsigned long)arg;
-	int cpu = smp_processor_id();
-
-	reason = reason ?
-		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+	unsigned long on = (unsigned long)arg;
 
-	clockevents_notify(reason, &cpu);
+	if (on)
+		tick_broadcast_enable();
+	else
+		tick_broadcast_disable();
 }
 
 static int cpu_hotplug_notify(struct notifier_block *n,



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

* [PATCH 18/35] ARM: OMAP: Use explicit broadcast control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (16 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 17/35] intel_idle: " Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-24  0:40   ` Tony Lindgren
  2015-02-16 12:14 ` [PATCH 19/35] clockevents: Remove the broadcast control leftovers Peter Zijlstra
                   ` (18 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Tony Lindgren

[-- Attachment #1: arm-omap-use-explicit-broadcast-control-function.patch --]
[-- Type: text/plain, Size: 987 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/cpuidle44xx.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux/arch/arm/mach-omap2/cpuidle44xx.c
===================================================================
--- linux.orig/arch/arm/mach-omap2/cpuidle44xx.c
+++ linux/arch/arm/mach-omap2/cpuidle44xx.c
@@ -14,7 +14,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/export.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
@@ -184,8 +184,7 @@ fail:
  */
 static void omap_setup_broadcast_timer(void *arg)
 {
-	int cpu = smp_processor_id();
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+	tick_broadcast_enable();
 }
 
 static struct cpuidle_driver omap4_idle_driver = {



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

* [PATCH 19/35] clockevents: Remove the broadcast control leftovers
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (17 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 18/35] ARM: OMAP: " Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function Peter Zijlstra
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-remove-the-broadcast-control-leftovers.patch --]
[-- Type: text/plain, Size: 1432 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

All users converted. Remove the notify leftovers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/clockchips.h |    3 ---
 kernel/time/clockevents.c  |   10 ----------
 2 files changed, 13 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -11,9 +11,6 @@
 /* Clock event notification values */
 enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_ADD,
-	CLOCK_EVT_NOTIFY_BROADCAST_ON,
-	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
-	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
 };
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -585,16 +585,6 @@ int clockevents_notify(unsigned long rea
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
 
 	switch (reason) {
-	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
-		tick_broadcast_enable();
-		break;
-	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
-		tick_broadcast_disable();
-		break;
-	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
-		tick_broadcast_force();
-		break;
-
 	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
 	case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
 		ret = tick_broadcast_oneshot_control(reason);



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

* [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (18 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 19/35] clockevents: Remove the broadcast control leftovers Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-24  0:41   ` Tony Lindgren
  2015-02-16 12:14 ` [PATCH 21/35] x86, amd_idle: Use explicit broadcast oneshot control functions Peter Zijlstra
                   ` (16 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw
  Cc: tglx, peterz, Tony Lindgren, Stephen Warren, Thierry Reding,
	Alexandre Courbot, Daniel Lezcano, Rafael J. Wysocki, Fenghua Yu,
	Len Brown

[-- Attachment #1: clockevents-provide-explicit-broadcast-oneshot-control-functions.patch --]
[-- Type: text/plain, Size: 6684 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call. We are way better off to have explicit calls instead of this
monstrosity.

Split out the broadcast oneshot control into a separate function and
provide inline helpers. Switch clockevents_notify() over. This will go
away once all callers are converted.

This also gets rid of the nested locking of clockevents_lock and
broadcast_lock. The broadcast oneshot control functions do not require
clockevents_lock. Only the managing functions
(setup/shutdown/suspend/resume of the broadcast device require
clockevents_lock.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Len Brown <lenb@kernel.org>
---
 include/linux/tick.h         |   19 +++++++++++++++++++
 kernel/time/clockevents.c    |    4 +++-
 kernel/time/tick-broadcast.c |   28 +++++++++++++++++-----------
 kernel/time/tick-internal.h  |    2 --
 4 files changed, 39 insertions(+), 14 deletions(-)

Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -53,12 +53,23 @@ enum tick_broadcast_mode {
 	TICK_BROADCAST_FORCE,
 };
 
+enum tick_broadcast_state {
+	TICK_BROADCAST_EXIT,
+	TICK_BROADCAST_ENTER,
+};
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern void tick_broadcast_control(enum tick_broadcast_mode mode);
 #else
 static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { }
 #endif /* BROADCAST */
 
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
+#else
+static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; }
+#endif
+
 static inline void tick_broadcast_enable(void)
 {
 	tick_broadcast_control(TICK_BROADCAST_ON);
@@ -71,6 +82,14 @@ static inline void tick_broadcast_force(
 {
 	tick_broadcast_control(TICK_BROADCAST_FORCE);
 }
+static inline int tick_broadcast_enter(void)
+{
+	return tick_broadcast_oneshot_control(TICK_BROADCAST_ENTER);
+}
+static inline void tick_broadcast_exit(void)
+{
+	tick_broadcast_oneshot_control(TICK_BROADCAST_EXIT);
+}
 
 #ifdef CONFIG_NO_HZ_COMMON
 extern int tick_nohz_tick_stopped(void);
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -586,8 +586,10 @@ int clockevents_notify(unsigned long rea
 
 	switch (reason) {
 	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
+		tick_broadcast_enter();
+		break;
 	case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
-		ret = tick_broadcast_oneshot_control(reason);
+		tick_broadcast_exit();
 		break;
 
 	default:
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -676,18 +676,23 @@ static void broadcast_shutdown_local(str
 	clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
 }
 
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop
+/**
+ * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode
+ * @state:	The target state (enter/exit)
+ *
+ * The system enters/leaves a state, where affected devices might stop
  * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
+ *
+ * Called with interrupts disabled, so clockevents_lock is not
+ * required here because the local clock event device cannot go away
+ * under us.
  */
-int tick_broadcast_oneshot_control(unsigned long reason)
+int tick_broadcast_oneshot_control(enum tick_broadcast_state state)
 {
 	struct clock_event_device *bc, *dev;
 	struct tick_device *td;
-	unsigned long flags;
-	ktime_t now;
 	int cpu, ret = 0;
+	ktime_t now;
 
 	/*
 	 * Periodic mode does not care about the enter/exit of power
@@ -700,17 +705,17 @@ int tick_broadcast_oneshot_control(unsig
 	 * We are called with preemtion disabled from the depth of the
 	 * idle code, so we can't be moved away.
 	 */
-	cpu = smp_processor_id();
-	td = &per_cpu(tick_cpu_device, cpu);
+	td = this_cpu_ptr(&tick_cpu_device);
 	dev = td->evtdev;
 
 	if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
 		return 0;
 
+	raw_spin_lock(&tick_broadcast_lock);
 	bc = tick_broadcast_device.evtdev;
+	cpu = smp_processor_id();
 
-	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-	if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
+	if (state == TICK_BROADCAST_ENTER) {
 		if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
 			WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
 			broadcast_shutdown_local(bc, dev);
@@ -802,9 +807,10 @@ int tick_broadcast_oneshot_control(unsig
 		}
 	}
 out:
-	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+	raw_spin_unlock(&tick_broadcast_lock);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(tick_broadcast_oneshot_control);
 
 /*
  * Reset the one shot broadcast for a cpu
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -109,7 +109,6 @@ static inline void tick_set_periodic_han
 /* Functions related to oneshot broadcasting */
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int cpu);
 extern int tick_broadcast_oneshot_active(void);
@@ -118,7 +117,6 @@ bool tick_broadcast_oneshot_available(vo
 extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #else /* BROADCAST && ONESHOT */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }



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

* [PATCH 21/35] x86, amd_idle: Use explicit broadcast oneshot control functions
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (19 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 22/35] ACPI / PAD: Use explicit broadcast oneshot control function Peter Zijlstra
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: x86-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 962 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/process.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux/arch/x86/kernel/process.c
===================================================================
--- linux.orig/arch/x86/kernel/process.c
+++ linux/arch/x86/kernel/process.c
@@ -380,7 +380,7 @@ static void amd_e400_idle(void)
 			tick_broadcast_force();
 			pr_info("Switch to broadcast mode on CPU%d\n", cpu);
 		}
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+		tick_broadcast_enter();
 
 		default_idle();
 
@@ -389,7 +389,7 @@ static void amd_e400_idle(void)
 		 * called with interrupts disabled.
 		 */
 		local_irq_disable();
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+		tick_broadcast_exit();
 		local_irq_enable();
 	} else
 		default_idle();



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

* [PATCH 22/35] ACPI / PAD: Use explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (20 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 21/35] x86, amd_idle: Use explicit broadcast oneshot control functions Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 23/35] ACPI/ processor_idle: Use explicit broadcast oneshot controll function Peter Zijlstra
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Fenghua Yu, Len Brown

[-- Attachment #1: apci-acpi-pad-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 1288 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/acpi/acpi_pad.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

Index: linux/drivers/acpi/acpi_pad.c
===================================================================
--- linux.orig/drivers/acpi/acpi_pad.c
+++ linux/drivers/acpi/acpi_pad.c
@@ -150,7 +150,6 @@ static int power_saving_thread(void *dat
 	sched_setscheduler(current, SCHED_RR, &param);
 
 	while (!kthread_should_stop()) {
-		int cpu;
 		unsigned long expire_time;
 
 		try_to_freeze();
@@ -174,14 +173,13 @@ static int power_saving_thread(void *dat
 			}
 			local_irq_disable();
 			tick_broadcast_enable();
-			cpu = smp_processor_id();
-			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+			tick_broadcast_enter();
 			stop_critical_timings();
 
 			mwait_idle_with_hints(power_saving_mwait_eax, 1);
 
 			start_critical_timings();
-			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+			tick_broadcast_exit();
 			local_irq_enable();
 
 			if (time_before(expire_time, jiffies)) {



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

* [PATCH 23/35] ACPI/ processor_idle: Use explicit broadcast oneshot controll function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (21 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 22/35] ACPI / PAD: Use explicit broadcast oneshot control function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:14 ` [PATCH 24/35] intel_idle: Use explicit broadcast oneshot control function Peter Zijlstra
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: acpi-processor-idle-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 876 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/acpi/processor_idle.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

Index: linux/drivers/acpi/processor_idle.c
===================================================================
--- linux.orig/drivers/acpi/processor_idle.c
+++ linux/drivers/acpi/processor_idle.c
@@ -178,11 +178,10 @@ static void lapic_timer_state_broadcast(
 	int state = cx - pr->power.states;
 
 	if (state >= pr->power.timer_broadcast_on_state) {
-		unsigned long reason;
-
-		reason = broadcast ?  CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
-			CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
-		clockevents_notify(reason, &pr->id);
+		if (broadcast)
+			tick_broadcast_enter();
+		else
+			tick_broadcast_exit();
 	}
 }
 



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

* [PATCH 24/35] intel_idle: Use explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (22 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 23/35] ACPI/ processor_idle: Use explicit broadcast oneshot controll function Peter Zijlstra
@ 2015-02-16 12:14 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 25/35] ARM: OMAP: " Peter Zijlstra
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:14 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Fenghua Yu, Len Brown

[-- Attachment #1: intelidle-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 993 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/idle/intel_idle.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux/drivers/idle/intel_idle.c
===================================================================
--- linux.orig/drivers/idle/intel_idle.c
+++ linux/drivers/idle/intel_idle.c
@@ -582,12 +582,12 @@ static int intel_idle(struct cpuidle_dev
 		leave_mm(cpu);
 
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+		tick_broadcast_enter();
 
 	mwait_idle_with_hints(eax, ecx);
 
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+		tick_broadcast_exit();
 
 	return index;
 }



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

* [PATCH 25/35] ARM: OMAP: Use explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (23 preceding siblings ...)
  2015-02-16 12:14 ` [PATCH 24/35] intel_idle: Use explicit broadcast oneshot control function Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-24  0:41   ` Tony Lindgren
  2015-02-16 12:15 ` [PATCH 26/35] ARM: tegra: " Peter Zijlstra
                   ` (11 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Tony Lindgren

[-- Attachment #1: arm-omap-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 1378 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/cpuidle44xx.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux/arch/arm/mach-omap2/cpuidle44xx.c
===================================================================
--- linux.orig/arch/arm/mach-omap2/cpuidle44xx.c
+++ linux/arch/arm/mach-omap2/cpuidle44xx.c
@@ -84,7 +84,6 @@ static int omap_enter_idle_coupled(struc
 {
 	struct idle_statedata *cx = state_ptr + index;
 	u32 mpuss_can_lose_context = 0;
-	int cpu_id = smp_processor_id();
 
 	/*
 	 * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -112,7 +111,7 @@ static int omap_enter_idle_coupled(struc
 	mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
 				 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
+	tick_broadcast_enter();
 
 	/*
 	 * Call idle CPU PM enter notifier chain so that
@@ -169,7 +168,7 @@ static int omap_enter_idle_coupled(struc
 	if (dev->cpu == 0 && mpuss_can_lose_context)
 		cpu_cluster_pm_exit();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
+	tick_broadcast_exit();
 
 fail:
 	cpuidle_coupled_parallel_barrier(dev, &abort_barrier);



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

* [PATCH 26/35] ARM: tegra: Use explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (24 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 25/35] ARM: OMAP: " Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 27/35] sched/idle: " Peter Zijlstra
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw
  Cc: tglx, peterz, Stephen Warren, Thierry Reding, Alexandre Courbot

[-- Attachment #1: arm-tegra-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 3841 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Alexandre Courbot <gnurou@gmail.com>
---
 arch/arm/mach-tegra/cpuidle-tegra114.c |    6 +++---
 arch/arm/mach-tegra/cpuidle-tegra20.c  |   10 +++++-----
 arch/arm/mach-tegra/cpuidle-tegra30.c  |   10 +++++-----
 3 files changed, 13 insertions(+), 13 deletions(-)

Index: linux/arch/arm/mach-tegra/cpuidle-tegra114.c
===================================================================
--- linux.orig/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ linux/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -15,7 +15,7 @@
  */
 
 #include <asm/firmware.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -44,7 +44,7 @@ static int tegra114_idle_power_down(stru
 	tegra_set_cpu_in_lp2();
 	cpu_pm_enter();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	tick_broadcast_enter();
 
 	call_firmware_op(prepare_idle);
 
@@ -52,7 +52,7 @@ static int tegra114_idle_power_down(stru
 	if (call_firmware_op(do_idle, 0) == -ENOSYS)
 		cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+	tick_broadcast_exit();
 
 	cpu_pm_exit();
 	tegra_clear_cpu_in_lp2();
Index: linux/arch/arm/mach-tegra/cpuidle-tegra20.c
===================================================================
--- linux.orig/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ linux/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -20,7 +20,7 @@
  */
 
 #include <linux/clk/tegra.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -136,11 +136,11 @@ static bool tegra20_cpu_cluster_power_do
 	if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
 		return false;
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	tick_broadcast_enter();
 
 	tegra_idle_lp2_last();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+	tick_broadcast_exit();
 
 	if (cpu_online(1))
 		tegra20_wake_cpu1_from_reset();
@@ -153,13 +153,13 @@ static bool tegra20_idle_enter_lp2_cpu_1
 					 struct cpuidle_driver *drv,
 					 int index)
 {
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	tick_broadcast_enter();
 
 	cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
 
 	tegra20_cpu_clear_resettable();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+	tick_broadcast_exit();
 
 	return true;
 }
Index: linux/arch/arm/mach-tegra/cpuidle-tegra30.c
===================================================================
--- linux.orig/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ linux/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -20,7 +20,7 @@
  */
 
 #include <linux/clk/tegra.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -76,11 +76,11 @@ static bool tegra30_cpu_cluster_power_do
 		return false;
 	}
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	tick_broadcast_enter();
 
 	tegra_idle_lp2_last();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+	tick_broadcast_exit();
 
 	return true;
 }
@@ -90,13 +90,13 @@ static bool tegra30_cpu_core_power_down(
 					struct cpuidle_driver *drv,
 					int index)
 {
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+	tick_broadcast_enter();
 
 	smp_wmb();
 
 	cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+	tick_broadcast_exit();
 
 	return true;
 }



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

* [PATCH 27/35] sched/idle: Use explicit broadcast oneshot control function
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (25 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 26/35] ARM: tegra: " Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-21  0:56   ` Nicolas Pitre
  2015-02-16 12:15 ` [PATCH 28/35] clockevents: Remove the broadcast oneshot control leftovers Peter Zijlstra
                   ` (9 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: sched-idle-use-explicit-broadcast-oneshot-control-function.patch --]
[-- Type: text/plain, Size: 1013 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Replace the clockevents_notify() call with an explicit function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/sched/idle.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux/kernel/sched/idle.c
===================================================================
--- linux.orig/kernel/sched/idle.c
+++ linux/kernel/sched/idle.c
@@ -143,8 +143,7 @@ use_default:
 	 * is used from another cpu as a broadcast timer, this call may
 	 * fail if it is not available
 	 */
-	if (broadcast &&
-	    clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
+	if (broadcast && tick_broadcast_enter())
 		goto use_default;
 
 	/* Take note of the planned idle state. */
@@ -161,7 +160,7 @@ use_default:
 	idle_set_state(this_rq(), NULL);
 
 	if (broadcast)
-		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+		tick_broadcast_exit();
 
 	/*
 	 * Give the governor an opportunity to reflect on the outcome



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

* [PATCH 28/35] clockevents: Remove the broadcast oneshot control leftovers
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (26 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 27/35] sched/idle: " Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 29/35] tick/timekeeping: Make PM_SLEEP related code conditional Peter Zijlstra
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-remove-the-broadcast-oneshot-control-leftovers.patch --]
[-- Type: text/plain, Size: 2512 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

All users converted. Remove the notify leftovers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/clockchips.h |   12 ------------
 kernel/time/clockevents.c  |   27 ---------------------------
 2 files changed, 39 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -8,19 +8,11 @@
 #ifndef _LINUX_CLOCKCHIPS_H
 #define _LINUX_CLOCKCHIPS_H
 
-/* Clock event notification values */
-enum clock_event_nofitiers {
-	CLOCK_EVT_NOTIFY_ADD,
-	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
-	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-};
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #include <linux/clocksource.h>
 #include <linux/cpumask.h>
 #include <linux/ktime.h>
-#include <linux/notifier.h>
 
 struct clock_event_device;
 struct module;
@@ -184,17 +176,13 @@ static inline int tick_check_broadcast_e
 static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
-extern int clockevents_notify(unsigned long reason, void *arg);
-
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
 
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 
 #endif
 
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -573,33 +573,6 @@ void tick_cleanup_dead_cpu(int cpu)
 }
 #endif
 
-/**
- * clockevents_notify - notification about relevant events
- * Returns 0 on success, any other value on error
- */
-int clockevents_notify(unsigned long reason, void *arg)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	raw_spin_lock_irqsave(&clockevents_lock, flags);
-
-	switch (reason) {
-	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
-		tick_broadcast_enter();
-		break;
-	case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
-		tick_broadcast_exit();
-		break;
-
-	default:
-		break;
-	}
-	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(clockevents_notify);
-
 #ifdef CONFIG_SYSFS
 struct bus_type clockevents_subsys = {
 	.name		= "clockevents",



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

* [PATCH 29/35] tick/timekeeping: Make PM_SLEEP related code conditional
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (27 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 28/35] clockevents: Remove the broadcast oneshot control leftovers Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 30/35] timekeeping: Get rid of stale comment Peter Zijlstra
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, John Stultz

[-- Attachment #1: tick-timekeeping-make-pm-stuff-conditional.patch --]
[-- Type: text/plain, Size: 6934 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

No point in compiling this in if PM_SLEEP=n

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
---
 include/linux/clockchips.h   |    6 ------
 include/linux/clocksource.h  |    2 --
 kernel/time/clockevents.c    |    2 ++
 kernel/time/clocksource.c    |    2 ++
 kernel/time/tick-broadcast.c |   12 ++++++------
 kernel/time/tick-common.c    |    2 ++
 kernel/time/tick-internal.h  |    4 ++++
 kernel/time/timekeeping.c    |    2 ++
 kernel/time/timekeeping.h    |    3 +++
 9 files changed, 21 insertions(+), 14 deletions(-)

Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -156,9 +156,6 @@ extern void clockevents_set_mode(struct
 extern int clockevents_program_event(struct clock_event_device *dev,
 				     ktime_t expires, bool force);
 
-extern void clockevents_suspend(void);
-extern void clockevents_resume(void);
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 #ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
 extern void tick_broadcast(const struct cpumask *mask);
@@ -178,9 +175,6 @@ static inline void tick_setup_hrtimer_br
 
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 
-static inline void clockevents_suspend(void) {}
-static inline void clockevents_resume(void) {}
-
 static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
 
Index: linux/include/linux/clocksource.h
===================================================================
--- linux.orig/include/linux/clocksource.h
+++ linux/include/linux/clocksource.h
@@ -285,8 +285,6 @@ extern int clocksource_unregister(struct
 extern void clocksource_touch_watchdog(void);
 extern struct clocksource* clocksource_get_next(void);
 extern void clocksource_change_rating(struct clocksource *cs, int rating);
-extern void clocksource_suspend(void);
-extern void clocksource_resume(void);
 extern struct clocksource * __init clocksource_default_clock(void);
 extern void clocksource_mark_unstable(struct clocksource *cs);
 
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -514,6 +514,7 @@ void clockevents_exchange_device(struct
 	}
 }
 
+#ifdef CONFIG_PM_SLEEP
 /**
  * clockevents_suspend - suspend clock devices
  */
@@ -537,6 +538,7 @@ void clockevents_resume(void)
 		if (dev->resume)
 			dev->resume(dev);
 }
+#endif
 
 #ifdef CONFIG_HOTPLUG_CPU
 /**
Index: linux/kernel/time/clocksource.c
===================================================================
--- linux.orig/kernel/time/clocksource.c
+++ linux/kernel/time/clocksource.c
@@ -485,6 +485,7 @@ void clocksource_mark_unstable(struct cl
 
 #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
 
+#ifdef CONFIG_PM_SLEEP
 /**
  * clocksource_suspend - suspend the clocksource(s)
  */
@@ -510,6 +511,7 @@ void clocksource_resume(void)
 
 	clocksource_resume_watchdog();
 }
+#endif
 
 /**
  * clocksource_touch_watchdog - Update watchdog
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -37,7 +37,10 @@ static int tick_broadcast_forced;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
-static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
+static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+{
+	clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+}
 #else
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
 static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
@@ -434,6 +437,7 @@ void tick_shutdown_broadcast(unsigned in
 }
 #endif
 
+#ifdef CONFIG_PM_SLEEP
 void tick_suspend_broadcast(void)
 {
 	struct clock_event_device *bc;
@@ -492,6 +496,7 @@ void tick_resume_broadcast(void)
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 #ifdef CONFIG_TICK_ONESHOT
 
@@ -549,11 +554,6 @@ static int tick_broadcast_set_event(stru
 	return ret;
 }
 
-static void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
-{
-	clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-}
-
 /*
  * Called from irq_enter() when idle was interrupted to reenable the
  * per cpu device.
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -375,6 +375,7 @@ void tick_shutdown(unsigned int cpu)
 }
 #endif
 
+#ifdef CONFIG_PM_SLEEP
 /**
  * tick_suspend - Suspend the tick and the broadcast device
  *
@@ -425,6 +426,7 @@ void tick_resume(void)
 	tick_resume_broadcast();
 	tick_resume_local();
 }
+#endif
 
 /**
  * tick_init - initialize the tick control
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -39,10 +39,14 @@ extern void clockevents_exchange_device(
 					struct clock_event_device *new);
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
+extern void clockevents_suspend(void);
+extern void clockevents_resume(void);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #else
 static inline void tick_suspend(void) { }
 static inline void tick_resume(void) { }
+static inline void clockevents_suspend(void) {}
+static inline void clockevents_resume(void) {}
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
Index: linux/kernel/time/timekeeping.c
===================================================================
--- linux.orig/kernel/time/timekeeping.c
+++ linux/kernel/time/timekeeping.c
@@ -1100,6 +1100,7 @@ void __init timekeeping_init(void)
 	raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 }
 
+#ifdef CONFIG_PM_SLEEP
 /* time in seconds when suspend began */
 static struct timespec64 timekeeping_suspend_time;
 
@@ -1316,6 +1317,7 @@ static int __init timekeeping_init_ops(v
 	return 0;
 }
 device_initcall(timekeeping_init_ops);
+#endif
 
 /*
  * Apply a multiplier adjustment to the timekeeper
Index: linux/kernel/time/timekeeping.h
===================================================================
--- linux.orig/kernel/time/timekeeping.h
+++ linux/kernel/time/timekeeping.h
@@ -20,6 +20,9 @@ extern void timekeeping_clocktai(struct
 extern void do_timer(unsigned long ticks);
 extern void update_wall_time(void);
 
+extern void clocksource_suspend(void);
+extern void clocksource_resume(void);
+
 extern seqlock_t jiffies_lock;
 
 #define CS_NAME_LEN	32



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

* [PATCH 30/35] timekeeping: Get rid of stale comment
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (28 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 29/35] tick/timekeeping: Make PM_SLEEP related code conditional Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 31/35] clockevents: Consolidate tick_shutdown() Peter Zijlstra
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, John Stultz

[-- Attachment #1: timekeeping-getrid-of-stale-comments.patch --]
[-- Type: text/plain, Size: 852 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Arch specific management of xtime/jiffies/wall_to_monotonic is gone
for quite a while. Zap the stale comment.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
---
 kernel/time/timekeeping.c |    4 ----
 1 file changed, 4 deletions(-)

Index: linux/kernel/time/timekeeping.c
===================================================================
--- linux.orig/kernel/time/timekeeping.c
+++ linux/kernel/time/timekeeping.c
@@ -1166,10 +1166,6 @@ void timekeeping_inject_sleeptime64(stru
 
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
- *
- * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/etc are
- * still managed by arch specific suspend/resume code.
  */
 static void timekeeping_resume(void)
 {



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

* [PATCH 31/35] clockevents: Consolidate tick_shutdown()
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (29 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 30/35] timekeeping: Get rid of stale comment Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 12:15 ` [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting Peter Zijlstra
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz

[-- Attachment #1: clockevents-consolidate-shutdown.patch --]
[-- Type: text/plain, Size: 4467 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

No point in having 3 global functions in the clockevents code if we
can chain them internally.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/clockevents.c    |    2 --
 kernel/time/tick-broadcast.c |   21 ++++++++++++---------
 kernel/time/tick-common.c    |    3 +++
 kernel/time/tick-internal.h  |    2 --
 4 files changed, 15 insertions(+), 13 deletions(-)

Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -551,8 +551,6 @@ void tick_cleanup_dead_cpu(int cpu)
 
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
 
-	tick_shutdown_broadcast_oneshot(cpu);
-	tick_shutdown_broadcast(cpu);
 	tick_shutdown(cpu);
 	/*
 	 * Unregister the clock event devices which were
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -46,6 +46,12 @@ static inline void tick_broadcast_clear_
 static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
 
+#if defined(CONFIG_TICK_ONESHOT) && defined (CONFIG_HOTPLUG_CPU)
+static void tick_shutdown_broadcast_oneshot(unsigned int cpu);
+#else
+static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
+#endif
+
 /*
  * Debugging: see timer_list.c
  */
@@ -424,15 +430,17 @@ void tick_shutdown_broadcast(unsigned in
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
-	bc = tick_broadcast_device.evtdev;
 	cpumask_clear_cpu(cpu, tick_broadcast_mask);
 	cpumask_clear_cpu(cpu, tick_broadcast_on);
 
+	bc = tick_broadcast_device.evtdev;
 	if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
 		if (bc && cpumask_empty(tick_broadcast_mask))
 			clockevents_shutdown(bc);
 	}
 
+	tick_shutdown_broadcast_oneshot(cpu);
+
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 #endif
@@ -909,14 +917,11 @@ static void broadcast_move_bc(int deadcp
 }
 
 /*
- * Remove a dead CPU from broadcasting
+ * Remove a dead CPU from broadcasting, called with broadcast lock
+ * held.
  */
-void tick_shutdown_broadcast_oneshot(unsigned int cpu)
+static void tick_shutdown_broadcast_oneshot(unsigned int cpu)
 {
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-
 	/*
 	 * Clear the broadcast masks for the dead cpu, but do not stop
 	 * the broadcast device!
@@ -926,8 +931,6 @@ void tick_shutdown_broadcast_oneshot(uns
 	cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
 
 	broadcast_move_bc(cpu);
-
-	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 #endif
 
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -361,6 +361,9 @@ void tick_shutdown(unsigned int cpu)
 	struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
 	struct clock_event_device *dev = td->evtdev;
 
+	/* Remove the CPU from the broadcast machinery */
+	tick_shutdown_broadcast(cpu);
+
 	td->mode = TICKDEV_MODE_PERIODIC;
 	if (dev) {
 		/*
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -114,7 +114,6 @@ static inline void tick_set_periodic_han
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
 extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int cpu);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
@@ -122,7 +121,6 @@ extern struct cpumask *tick_get_broadcas
 #else /* BROADCAST && ONESHOT */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }



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

* [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (30 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 31/35] clockevents: Consolidate tick_shutdown() Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-17  4:03   ` Preeti U Murthy
  2015-02-19 17:51   ` Nicolas Pitre
  2015-02-16 12:15 ` [PATCH 33/35] tick: Make hrtimer broadcasting opt-in Peter Zijlstra
                   ` (4 subsequent siblings)
  36 siblings, 2 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Preeti U Murthy

[-- Attachment #1: clockevents-fix-cpu-down-race.patch --]
[-- Type: text/plain, Size: 11837 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Preeti reported a cpu down race with hrtimer based broadcasting:

Assume CPU1 is the CPU which holds the hrtimer broadcasting duty
before it is taken down.

CPU0				CPU1
cpu_down()
				takedown_cpu()
			   	  disable_interrupts()
cpu_die()
  while (CPU1 != DEAD) {
    msleep(100);
      switch_to_idle()
        stop_cpu_timer()
          schedule_broadcast()
  }

tick_cleanup_dead_cpu()
     take_over_broadcast()	

So after CPU1 disabled interrupts it cannot handle the broadcast
hrtimer anymore, so CPU0 will be stuck forever.

Doing a "while (CPU1 != DEAD) msleep(100);" periodic poll is silly at
best, but we need to fix that nevertheless.

Split the tick cleanup into two pieces:

1) Shutdown and remove all per cpu clockevent devices from
   takedown_cpu()

   This is done carefully with respect to existing arch code which
   works around the shortcoming of the clockevents core code in
   interesting ways. We really want a separate callback for this to
   cleanup the workarounds, but that's not scope of this patch

2) Takeover the broadcast duty explicitely before calling cpu_die()

   This is a temporary workaround as well. What we really want is a
   callback in the clockevent device which allows us to do that from
   the dying CPU by pushing the hrtimer onto a different cpu. That
   might involve an IPI and is definitely more complex than this
   immediate fix.

Reported-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/tick.h         |    9 +++++----
 kernel/cpu.c                 |    6 +++---
 kernel/time/clockevents.c    |   30 ++++++++++++++++++------------
 kernel/time/tick-broadcast.c |   32 ++++++++++++++++++++++----------
 kernel/time/tick-common.c    |   34 ++++++++++++----------------------
 kernel/time/tick-internal.h  |    6 +++---
 6 files changed, 63 insertions(+), 54 deletions(-)

Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -29,13 +29,12 @@ extern struct tick_device *tick_get_devi
 extern void __init tick_init(void);
 /* Should be core only, but XEN resume magic requires this */
 extern void tick_resume_local(void);
-extern void tick_handover_do_timer(void);
-extern void tick_cleanup_dead_cpu(int cpu);
+/* CPU hotplug */
+extern void tick_shutdown_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_resume_local(void) { }
-static inline void tick_handover_do_timer(void) { }
-static inline void tick_cleanup_dead_cpu(int cpu) { }
+static inline void tick_shutdown_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
@@ -66,8 +65,10 @@ static inline void tick_broadcast_contro
 
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
+extern void tick_takeover(int deadcpu);
 #else
 static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; }
+static inline void tick_takeover(int deadcpu) { }
 #endif
 
 static inline void tick_broadcast_enable(void)
Index: linux/kernel/cpu.c
===================================================================
--- linux.orig/kernel/cpu.c
+++ linux/kernel/cpu.c
@@ -349,8 +349,8 @@ static int __ref take_cpu_down(void *_pa
 		return err;
 
 	cpu_notify(CPU_DYING | param->mod, param->hcpu);
-	/* Give up timekeeping duties */
-	tick_handover_do_timer();
+	/* Shutdown the per cpu tick */
+	tick_shutdown_local();
 	/* Park the stopper thread */
 	kthread_park(current);
 	return 0;
@@ -428,7 +428,7 @@ static int __ref _cpu_down(unsigned int
 	__cpu_die(cpu);
 
 	/* CPU is completely dead: tell everyone.  Too late to complain. */
-	tick_cleanup_dead_cpu(cpu);
+	tick_takeover(cpu);
 	cpu_notify_nofail(CPU_DEAD | mod, hcpu);
 
 	check_for_tasks(cpu);
Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -541,26 +541,32 @@ void clockevents_resume(void)
 #endif
 
 #ifdef CONFIG_HOTPLUG_CPU
-/**
- * tick_cleanup_dead_cpu - Cleanup the tick and clockevents of a dead cpu
+/*
+ * Cleanup the clock events devices on the dying cpu. curdev is the
+ * current installed tick device on that cpu
  */
-void tick_cleanup_dead_cpu(int cpu)
+void clockevents_cleanup_dying_cpu(struct clock_event_device *curdev)
 {
 	struct clock_event_device *dev, *tmp;
 	unsigned long flags;
+	int cpu;
 
 	raw_spin_lock_irqsave(&clockevents_lock, flags);
-
-	tick_shutdown(cpu);
-	/*
-	 * Unregister the clock event devices which were
-	 * released from the users in the notify chain.
-	 */
-	list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
-		list_del(&dev->list);
+	if (!curdev)
+		goto cleanup;
 	/*
-	 * Now check whether the CPU has left unused per cpu devices
+	 * We cannot call the set mode function here at the moment
+	 * because existing architecture cpu down code shuts down
+	 * stuff already and we cannot interfere with that. So we just
+	 * set the mode to unused for now.
 	 */
+	curdev->mode = CLOCK_EVT_MODE_UNUSED;
+	list_del(&curdev->list);
+	module_put(curdev->owner);
+
+cleanup:
+	/* Remove the unused percpu devices from the list */
+	cpu = smp_processor_id();
 	list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
 		if (cpumask_test_cpu(cpu, dev->cpumask) &&
 		    cpumask_weight(dev->cpumask) == 1 &&
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -421,15 +421,17 @@ void tick_set_periodic_handler(struct cl
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
- * Remove a CPU from broadcasting
+ * Remove a CPU from broadcasting. Called from the dying cpu.
  */
-void tick_shutdown_broadcast(unsigned int cpu)
+void tick_shutdown_broadcast(void)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
+	int cpu;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
+	cpu = smp_processor_id();
 	cpumask_clear_cpu(cpu, tick_broadcast_mask);
 	cpumask_clear_cpu(cpu, tick_broadcast_on);
 
@@ -906,14 +908,26 @@ void tick_broadcast_switch_to_oneshot(vo
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void broadcast_move_bc(int deadcpu)
+/*
+ * Called from the cpu hotplug code after a cpu is dead. This ensures
+ * that a hrtimer based broad cast device is taken over.
+ *
+ * FIXME: This should go away. We should replace this by a mechanism
+ * which pushes the hrtimer over to a different cpu from
+ * tick_shutdown_broadcast_oneshot()
+ */
+void tick_broadcast_takeover_bc(int deadcpu)
 {
-	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+	struct clock_event_device *bc;
+	unsigned long flags;
 
-	if (!bc || !broadcast_needs_cpu(bc, deadcpu))
-		return;
-	/* This moves the broadcast assignment to this cpu */
-	clockevents_program_event(bc, bc->next_event, 1);
+	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
+	bc = tick_broadcast_device.evtdev;
+	if (bc && broadcast_needs_cpu(bc, deadcpu)) {
+		/* This moves the broadcast assignment to this cpu */
+		clockevents_program_event(bc, bc->next_event, 1);
+	}
+	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
 /*
@@ -929,8 +943,6 @@ static void tick_shutdown_broadcast_ones
 	cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
 	cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
 	cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
-
-	broadcast_move_bc(cpu);
 }
 #endif
 
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -336,10 +336,10 @@ out_bc:
 /*
  * Transfer the do_timer job away from a dying cpu.
  *
- * Called with interrupts disabled. Not locking required. If
- * tick_do_timer_cpu is owned by this cpu, nothing can change it.
+ * No locking required. If tick_do_timer_cpu is owned by this cpu,
+ * nothing can change it.
  */
-void tick_handover_do_timer(void)
+static void tick_handover_do_timer(void)
 {
 	if (tick_do_timer_cpu == smp_processor_id()) {
 		int cpu = cpumask_first(cpu_online_mask);
@@ -349,32 +349,22 @@ void tick_handover_do_timer(void)
 	}
 }
 
-/*
- * Shutdown an event device on a given cpu:
+/**
+ * tick_shutdown_local - Shutdown the tick related functions on a cpu
  *
- * This is called on a life CPU, when a CPU is dead. So we cannot
- * access the hardware device itself.
- * We just set the mode and remove it from the lists.
+ * This is called from the dying cpu.
  */
-void tick_shutdown(unsigned int cpu)
+void tick_shutdown_local(void)
 {
-	struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
-	struct clock_event_device *dev = td->evtdev;
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	/* Remove the CPU from the broadcast machinery */
-	tick_shutdown_broadcast(cpu);
+	tick_shutdown_broadcast();
 
+	clockevents_cleanup_dying_cpu(td->evtdev);
 	td->mode = TICKDEV_MODE_PERIODIC;
-	if (dev) {
-		/*
-		 * Prevent that the clock events layer tries to call
-		 * the set mode function!
-		 */
-		dev->mode = CLOCK_EVT_MODE_UNUSED;
-		clockevents_exchange_device(dev, NULL);
-		dev->event_handler = clockevents_handle_noop;
-		td->evtdev = NULL;
-	}
+
+	tick_handover_do_timer();
 }
 #endif
 
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -20,7 +20,6 @@ extern int tick_do_timer_cpu __read_most
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_check_new_device(struct clock_event_device *dev);
-extern void tick_shutdown(unsigned int cpu);
 extern void tick_suspend(void);
 extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
@@ -38,6 +37,7 @@ extern void clockevents_shutdown(struct
 extern void clockevents_exchange_device(struct clock_event_device *old,
 					struct clock_event_device *new);
 extern void clockevents_handle_noop(struct clock_event_device *dev);
+extern void clockevents_cleanup_dying_cpu(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
@@ -82,7 +82,7 @@ static inline int tick_check_oneshot_cha
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
 extern int tick_is_broadcast_device(struct clock_event_device *dev);
-extern void tick_shutdown_broadcast(unsigned int cpu);
+extern void tick_shutdown_broadcast(void);
 extern void tick_suspend_broadcast(void);
 extern void tick_resume_broadcast(void);
 extern bool tick_resume_check_broadcast(void);
@@ -96,7 +96,7 @@ static inline void tick_install_broadcas
 static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
 static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
-static inline void tick_shutdown_broadcast(unsigned int cpu) { }
+static inline void tick_shutdown_broadcast(void) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline void tick_resume_broadcast(void) { }
 static inline bool tick_resume_check_broadcast(void) { return false; }



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

* [PATCH 33/35] tick: Make hrtimer broadcasting opt-in
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (31 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-17  3:06   ` Preeti U Murthy
  2015-02-17 10:04   ` Lorenzo Pieralisi
  2015-02-16 12:15 ` [PATCH 34/35] tick: Provide tick_suspend_local() Peter Zijlstra
                   ` (3 subsequent siblings)
  36 siblings, 2 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw
  Cc: tglx, peterz, Preeti U Murthy, Michael Ellerman,
	Benjamin Herrenschmidt, Lorenzo Pieralisi

[-- Attachment #1: tick-make-hrtimer-broadcastin-opt-in.patch --]
[-- Type: text/plain, Size: 9491 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

We keep adding unconditional stuff to the core code which just bloats
the text and data size for no value. hrtimer based broadcasting is
currently only used on arm64 and powerpc. Make it conditional.

While at it move these tick related interfaces out of the clockchips
header file.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
 arch/arm/kernel/smp.c        |    2 +-
 arch/arm64/Kconfig           |    1 +
 arch/arm64/kernel/smp.c      |    1 +
 arch/arm64/kernel/time.c     |    2 +-
 arch/mips/kernel/smp.c       |    1 +
 arch/powerpc/Kconfig         |    1 +
 arch/powerpc/kernel/smp.c    |    1 +
 arch/powerpc/kernel/time.c   |    2 +-
 include/linux/clockchips.h   |   26 +-------------------------
 include/linux/tick.h         |   25 +++++++++++++++++++++++--
 kernel/time/Kconfig          |    4 ++++
 kernel/time/Makefile         |    6 ++----
 kernel/time/tick-broadcast.c |    4 +++-
 13 files changed, 41 insertions(+), 35 deletions(-)

Index: linux/arch/arm/kernel/smp.c
===================================================================
--- linux.orig/arch/arm/kernel/smp.c
+++ linux/arch/arm/kernel/smp.c
@@ -22,7 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <linux/percpu.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/completion.h>
 #include <linux/cpufreq.h>
 #include <linux/irq_work.h>
Index: linux/arch/arm64/Kconfig
===================================================================
--- linux.orig/arch/arm64/Kconfig
+++ linux/arch/arm64/Kconfig
@@ -25,6 +25,7 @@ config ARM64
 	select GENERIC_ALLOCATOR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST if SMP
 	select GENERIC_CPU_AUTOPROBE
 	select GENERIC_EARLY_IOREMAP
 	select GENERIC_IRQ_PROBE
Index: linux/arch/arm64/kernel/smp.c
===================================================================
--- linux.orig/arch/arm64/kernel/smp.c
+++ linux/arch/arm64/kernel/smp.c
@@ -36,6 +36,7 @@
 #include <linux/completion.h>
 #include <linux/of.h>
 #include <linux/irq_work.h>
+#include <linux/tick.h>
 
 #include <asm/alternative.h>
 #include <asm/atomic.h>
Index: linux/arch/arm64/kernel/time.c
===================================================================
--- linux.orig/arch/arm64/kernel/time.c
+++ linux/arch/arm64/kernel/time.c
@@ -18,11 +18,11 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clockchips.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
+#include <linux/tick.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
Index: linux/arch/mips/kernel/smp.c
===================================================================
--- linux.orig/arch/mips/kernel/smp.c
+++ linux/arch/mips/kernel/smp.c
@@ -33,6 +33,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/ftrace.h>
+#include <linux/tick.h>
 
 #include <linux/atomic.h>
 #include <asm/cpu.h>
Index: linux/arch/powerpc/Kconfig
===================================================================
--- linux.orig/arch/powerpc/Kconfig
+++ linux/arch/powerpc/Kconfig
@@ -135,6 +135,7 @@ config PPC
 	select GENERIC_TIME_VSYSCALL_OLD
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST if SMP
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
Index: linux/arch/powerpc/kernel/smp.c
===================================================================
--- linux.orig/arch/powerpc/kernel/smp.c
+++ linux/arch/powerpc/kernel/smp.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/topology.h>
+#include <linux/tick.h>
 
 #include <asm/ptrace.h>
 #include <linux/atomic.h>
Index: linux/arch/powerpc/kernel/time.c
===================================================================
--- linux.orig/arch/powerpc/kernel/time.c
+++ linux/arch/powerpc/kernel/time.c
@@ -42,7 +42,7 @@
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
 #include <linux/time.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/init.h>
 #include <linux/profile.h>
 #include <linux/cpu.h>
Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -155,29 +155,5 @@ extern void clockevents_set_mode(struct
 				 enum clock_event_mode mode);
 extern int clockevents_program_event(struct clock_event_device *dev,
 				     ktime_t expires, bool force);
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
-extern void tick_broadcast(const struct cpumask *mask);
-#else
-#define tick_broadcast	NULL
-#endif
-extern int tick_receive_broadcast(void);
-#endif
-
-#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
-extern void tick_setup_hrtimer_broadcast(void);
-extern int tick_check_broadcast_expired(void);
-#else
-static inline int tick_check_broadcast_expired(void) { return 0; }
-static inline void tick_setup_hrtimer_broadcast(void) {};
-#endif
-
-#else /* CONFIG_GENERIC_CLOCKEVENTS */
-
-static inline int tick_check_broadcast_expired(void) { return 0; }
-static inline void tick_setup_hrtimer_broadcast(void) {};
-
-#endif
-
+#endif /* CONFIG_GENERIC_CLOCKEVENTS */
 #endif
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -65,10 +65,8 @@ static inline void tick_broadcast_contro
 
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
-extern void tick_takeover(int deadcpu);
 #else
 static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; }
-static inline void tick_takeover(int deadcpu) { }
 #endif
 
 static inline void tick_broadcast_enable(void)
@@ -181,4 +179,27 @@ static inline void tick_nohz_task_switch
 		__tick_nohz_task_switch(tsk);
 }
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
+extern void tick_broadcast(const struct cpumask *mask);
+#else
+#define tick_broadcast	NULL
+#endif
+extern int tick_receive_broadcast(void);
+#endif
+
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern int tick_check_broadcast_expired(void);
+#else
+static inline int tick_check_broadcast_expired(void) { return 0; }
+#endif
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
+extern void tick_setup_hrtimer_broadcast(void);
+extern void tick_takeover(int deadcpu);
+#else
+static inline void tick_setup_hrtimer_broadcast(void) { };
+static inline void tick_takeover(int deadcpu) { }
+#endif
+
 #endif
Index: linux/kernel/time/Kconfig
===================================================================
--- linux.orig/kernel/time/Kconfig
+++ linux/kernel/time/Kconfig
@@ -42,6 +42,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST
 	bool
 	depends on GENERIC_CLOCKEVENTS
 
+config GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
+	bool
+	depends on GENERIC_CLOCKEVENTS && TICK_ONESHOT
+
 # Automatically adjust the min. reprogramming time for
 # clock event device
 config GENERIC_CLOCKEVENTS_MIN_ADJUST
Index: linux/kernel/time/Makefile
===================================================================
--- linux.orig/kernel/time/Makefile
+++ linux/kernel/time/Makefile
@@ -3,10 +3,8 @@ obj-y += timekeeping.o ntp.o clocksource
 obj-y += timeconv.o posix-clock.o alarmtimer.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o tick-common.o
-ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
- obj-y						+= tick-broadcast.o
- obj-$(CONFIG_TICK_ONESHOT)			+= tick-broadcast-hrtimer.o
-endif
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= tick-broadcast.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST)	+= tick-broadcast-hrtimer.o
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
 obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
 obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
Index: linux/kernel/time/tick-broadcast.c
===================================================================
--- linux.orig/kernel/time/tick-broadcast.c
+++ linux/kernel/time/tick-broadcast.c
@@ -908,6 +908,7 @@ void tick_broadcast_switch_to_oneshot(vo
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
 /*
  * Called from the cpu hotplug code after a cpu is dead. This ensures
  * that a hrtimer based broad cast device is taken over.
@@ -916,7 +917,7 @@ void tick_broadcast_switch_to_oneshot(vo
  * which pushes the hrtimer over to a different cpu from
  * tick_shutdown_broadcast_oneshot()
  */
-void tick_broadcast_takeover_bc(int deadcpu)
+void tick_takeover(int deadcpu)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
@@ -929,6 +930,7 @@ void tick_broadcast_takeover_bc(int dead
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 /*
  * Remove a dead CPU from broadcasting, called with broadcast lock



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

* [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (32 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 33/35] tick: Make hrtimer broadcasting opt-in Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-17 14:31   ` Lorenzo Pieralisi
  2015-02-16 12:15 ` [PATCH 35/35] arm: bl_switcher: Kill tick suspend hackery Peter Zijlstra
                   ` (2 subsequent siblings)
  36 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Nicolas Pitre, Russell King

[-- Attachment #1: tick-provide-tick-suspend-local.patch --]
[-- Type: text/plain, Size: 2322 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

This function is intended to use by the freezer once the freezer folks
solved their race issues. Also required to get rid of the ARM BL
switcher tick hackery.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>

---
 include/linux/tick.h      |    3 +++
 kernel/time/tick-common.c |   18 +++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -27,12 +27,15 @@ extern struct tick_device *tick_get_devi
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
+/* Should be core only, but arm BL switcher has its homebrewn implementation */
+extern void tick_suspend_local(void);
 /* Should be core only, but XEN resume magic requires this */
 extern void tick_resume_local(void);
 /* CPU hotplug */
 extern void tick_shutdown_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
+static inline void tick_suspend_local(void) { }
 static inline void tick_resume_local(void) { }
 static inline void tick_shutdown_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
Index: linux/kernel/time/tick-common.c
===================================================================
--- linux.orig/kernel/time/tick-common.c
+++ linux/kernel/time/tick-common.c
@@ -370,6 +370,20 @@ void tick_shutdown_local(void)
 
 #ifdef CONFIG_PM_SLEEP
 /**
+ * tick_suspend_local - Suspend the local tick device
+ *
+ * Called from the local cpu for freeze with interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend_local(void)
+{
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+
+	clockevents_shutdown(td->evtdev);
+}
+
+/**
  * tick_suspend - Suspend the tick and the broadcast device
  *
  * Called from syscore_suspend() via timekeeping_suspend with only one
@@ -379,9 +393,7 @@ void tick_shutdown_local(void)
  */
 void tick_suspend(void)
 {
-	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
-
-	clockevents_shutdown(td->evtdev);
+	tick_suspend_local();
 	tick_suspend_broadcast();
 }
 



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

* [PATCH 35/35] arm: bl_switcher: Kill tick suspend hackery
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (33 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 34/35] tick: Provide tick_suspend_local() Peter Zijlstra
@ 2015-02-16 12:15 ` Peter Zijlstra
  2015-02-16 19:14 ` [PATCH 00/35] Some kernel/time cleanups Rafael J. Wysocki
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
  36 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-16 12:15 UTC (permalink / raw)
  To: linux-kernel, mingo, rjw; +Cc: tglx, peterz, Nicolas Pitre, Russell King

[-- Attachment #1: arm-bl-switcher-kill-tick-suspend-hackery.patch --]
[-- Type: text/plain, Size: 5983 bytes --]

From: Thomas Gleixner <tglx@linutronix.de>

Sure it's simple to abuse random functions and data structures and let
the people who made the mistake to put the declarations into a global
header file deal with the fallout.

Adding a tick_suspend/resume_local() pair to the core code would have
been a trivial thing to do.

Use the new tick_suspend/resume_local() and get rid of the homebrewn
hackery. The check for the cpumask is completely pointless. There is
no harm to suspend a per cpu tick device unconditionally. If that's a
real issue then we fix it proper at the core level and not with some
completely undocumented hacks in some random arch code.

Move the tick internals to the core code, now that this nuisance is
gone.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/common/bL_switcher.c |   16 ++--------------
 include/linux/clockchips.h    |    6 ------
 include/linux/tick.h          |   18 ++----------------
 kernel/time/tick-internal.h   |    5 +++++
 kernel/time/tick-sched.h      |   10 ++++++++++
 5 files changed, 19 insertions(+), 36 deletions(-)

Index: linux/arch/arm/common/bL_switcher.c
===================================================================
--- linux.orig/arch/arm/common/bL_switcher.c
+++ linux/arch/arm/common/bL_switcher.c
@@ -151,8 +151,6 @@ static int bL_switch_to(unsigned int new
 	unsigned int mpidr, this_cpu, that_cpu;
 	unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
 	struct completion inbound_alive;
-	struct tick_device *tdev;
-	enum clock_event_mode tdev_mode;
 	long volatile *handshake_ptr;
 	int ipi_nr, ret;
 
@@ -219,13 +217,7 @@ static int bL_switch_to(unsigned int new
 	/* redirect GIC's SGIs to our counterpart */
 	gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
 
-	tdev = tick_get_device(this_cpu);
-	if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
-		tdev = NULL;
-	if (tdev) {
-		tdev_mode = tdev->evtdev->mode;
-		clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
-	}
+	tick_suspend_local();
 
 	ret = cpu_pm_enter();
 
@@ -251,11 +243,7 @@ static int bL_switch_to(unsigned int new
 
 	ret = cpu_pm_exit();
 
-	if (tdev) {
-		clockevents_set_mode(tdev->evtdev, tdev_mode);
-		clockevents_program_event(tdev->evtdev,
-					  tdev->evtdev->next_event, 1);
-	}
+	tick_resume_local();
 
 	trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
 	local_fiq_enable();
Index: linux/include/linux/clockchips.h
===================================================================
--- linux.orig/include/linux/clockchips.h
+++ linux/include/linux/clockchips.h
@@ -149,11 +149,5 @@ clockevents_calc_mult_shift(struct clock
 	return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC,
 				      freq, minsec);
 }
-
-/* Should be core only, but is abused by arm bl_switcher */
-extern void clockevents_set_mode(struct clock_event_device *dev,
-				 enum clock_event_mode mode);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
 #endif /* CONFIG_GENERIC_CLOCKEVENTS */
 #endif
Index: linux/include/linux/tick.h
===================================================================
--- linux.orig/include/linux/tick.h
+++ linux/include/linux/tick.h
@@ -11,25 +11,11 @@
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
-/* ARM BL switcher abuse support */
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-enum tick_device_mode {
-	TICKDEV_MODE_PERIODIC,
-	TICKDEV_MODE_ONESHOT,
-};
-
-struct tick_device {
-	struct clock_event_device *evtdev;
-	enum tick_device_mode mode;
-};
-extern struct tick_device *tick_get_device(int cpu);
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
-/* Should be core only, but arm BL switcher has its homebrewn implementation */
+/* Should be core only, but arm BL switcher requires it */
 extern void tick_suspend_local(void);
-/* Should be core only, but XEN resume magic requires this */
+/* Should be core only, but XEN resume magic and arm BL switcher require it */
 extern void tick_resume_local(void);
 /* CPU hotplug */
 extern void tick_shutdown_local(void);
Index: linux/kernel/time/tick-internal.h
===================================================================
--- linux.orig/kernel/time/tick-internal.h
+++ linux/kernel/time/tick-internal.h
@@ -26,6 +26,7 @@ extern bool tick_check_replacement(struc
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
 
 /* Check, if the device is functional or a dummy for broadcast */
 static inline int tick_device_is_functional(struct clock_event_device *dev)
@@ -36,6 +37,10 @@ static inline int tick_device_is_functio
 extern void clockevents_shutdown(struct clock_event_device *dev);
 extern void clockevents_exchange_device(struct clock_event_device *old,
 					struct clock_event_device *new);
+extern void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern void clockevents_cleanup_dying_cpu(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
Index: linux/kernel/time/tick-sched.h
===================================================================
--- linux.orig/kernel/time/tick-sched.h
+++ linux/kernel/time/tick-sched.h
@@ -3,6 +3,16 @@
 
 #include <linux/hrtimer.h>
 
+enum tick_device_mode {
+	TICKDEV_MODE_PERIODIC,
+	TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+	struct clock_event_device *evtdev;
+	enum tick_device_mode mode;
+};
+
 enum tick_nohz_mode {
 	NOHZ_MODE_INACTIVE,
 	NOHZ_MODE_LOWRES,



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

* Re: [PATCH 09/35] tick/xen: Provide and use tick_resume_local()
  2015-02-16 12:14 ` [PATCH 09/35] tick/xen: Provide and use tick_resume_local() Peter Zijlstra
@ 2015-02-16 16:37   ` David Vrabel
  0 siblings, 0 replies; 106+ messages in thread
From: David Vrabel @ 2015-02-16 16:37 UTC (permalink / raw)
  To: Peter Zijlstra, linux-kernel, mingo, rjw
  Cc: tglx, Konrad Rzeszutek Wilk, Boris Ostrovsky

On 16/02/15 12:14, Peter Zijlstra wrote:
> 
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Xen calls on every cpu into tick_resume() which is just
> wrong. tick_resume() is for the syscore global suspend/resume
> invocation. What XEN really wants is a per cpu local resume function,
> but yes, its simpler to just use something which works by chance and
> let those who want to change that code deal with the fallout.
> 
> Provide a tick_resume_local() function and use it in XEN.

Acked-by: David Vrabel <david.vrabel@citrix.com>

David

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

* Re: [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense
  2015-02-16 12:14 ` [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense Peter Zijlstra
@ 2015-02-16 18:54   ` Rafael J. Wysocki
  2015-02-18  6:16     ` Rafael J. Wysocki
  0 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-02-16 18:54 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Len Brown, linux-acpi

On Monday, February 16, 2015 01:14:36 PM Peter Zijlstra wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> While looking through the (ab)use of the clockevents_notify() function
> I stumbled over the following gem in the acpi_pad code:
> 
>   if (lapic_detected_unstable && !lapic_marked_unstable) {
>      /* LAPIC could halt in idle, so notify users */
>      for_each_online_cpu(i)
>        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
>      lapic_marked_unstable = 1;
>   }
> 
> This code calls on the cpu which detects the lapic unstable condition
> first clockevents_notify() to tell the core code that the broadcast
> should be enabled on all online cpus. Brilliant stuff that as it
> notifies the core code a num_online_cpus() times that the broadcast
> should be enabled on the current cpu.
> 
> This probably has never been noticed because that code got never
> tested with NOHZ=n and HIGHRES_TIMER=n or it just worked by chance
> because one of the other mechanisms told the core in the right way
> that the local apic timer is wreckaged.
> 
> Sigh, this is:
> 
>  - The 4th incarnation of idle drivers which has their own mechanism
>    to detect and deal with X86_FEATURE_ARAT.
> 
>  - The 2nd incarnation of fake idle mechanisms with a different set of
>    brainmelting bugs.
> 
>  - Has been merged against an explicit NAK of the scheduler
>    maintainer with the promise to improve it over time.
> 
>  - Another example of featuritis driven trainwreck engineering.
> 
>  - Another pointless waste of my time.
> 
> Fix this nonsense by removing that lapic detection and notification
> logic and simply call into the clockevents code unconditonally. The
> ARAT feature is marked in the lapic clockevent already so the core
> code will just ignore the requests and return.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> Cc: Len Brown <lenb@kernel.org>
> Cc: linux-acpi@vger.kernel.org
> Cc: Peter Zijlstra <peterz@infradead.org>
> ---
>  drivers/acpi/acpi_pad.c |   26 +++++---------------------
>  1 file changed, 5 insertions(+), 21 deletions(-)
> 
> Index: linux/drivers/acpi/acpi_pad.c
> ===================================================================
> --- linux.orig/drivers/acpi/acpi_pad.c
> +++ linux/drivers/acpi/acpi_pad.c
> @@ -41,8 +41,6 @@ static unsigned long power_saving_mwait_
>  
>  static unsigned char tsc_detected_unstable;
>  static unsigned char tsc_marked_unstable;
> -static unsigned char lapic_detected_unstable;
> -static unsigned char lapic_marked_unstable;
>  
>  static void power_saving_mwait_init(void)
>  {
> @@ -82,13 +80,10 @@ static void power_saving_mwait_init(void
>  		 */
>  		if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
>  			tsc_detected_unstable = 1;
> -		if (!boot_cpu_has(X86_FEATURE_ARAT))
> -			lapic_detected_unstable = 1;
>  		break;
>  	default:
> -		/* TSC & LAPIC could halt in idle */
> +		/* TSC could halt in idle */
>  		tsc_detected_unstable = 1;
> -		lapic_detected_unstable = 1;
>  	}
>  #endif
>  }
> @@ -177,28 +172,17 @@ static int power_saving_thread(void *dat
>  				mark_tsc_unstable("TSC halts in idle");
>  				tsc_marked_unstable = 1;
>  			}
> -			if (lapic_detected_unstable && !lapic_marked_unstable) {
> -				int i;
> -				/* LAPIC could halt in idle, so notify users */
> -				for_each_online_cpu(i)
> -					clockevents_notify(
> -						CLOCK_EVT_NOTIFY_BROADCAST_ON,
> -						&i);
> -				lapic_marked_unstable = 1;
> -			}
> +			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
> +
>  			local_irq_disable();
>  			cpu = smp_processor_id();
> -			if (lapic_marked_unstable)
> -				clockevents_notify(
> -					CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
> +			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
>  			stop_critical_timings();
>  
>  			mwait_idle_with_hints(power_saving_mwait_eax, 1);
>  
>  			start_critical_timings();
> -			if (lapic_marked_unstable)
> -				clockevents_notify(
> -					CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
> +			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
>  			local_irq_enable();
>  
>  			if (time_before(expire_time, jiffies)) {
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 07/35] clockevents: Make suspend/resume calls explicit
  2015-02-16 12:14 ` [PATCH 07/35] clockevents: Make suspend/resume calls explicit Peter Zijlstra
@ 2015-02-16 19:07   ` Rafael J. Wysocki
  0 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-02-16 19:07 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx

On Monday, February 16, 2015 01:14:42 PM Peter Zijlstra wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> clockevents_notify() is a leftover from the early design of the
> clockevents facility. It's really not a notification mechanism, it's a
> multiplex call.
> 
> We are way better off to have explicit calls instead of this
> monstrosity. Split out the suspend/resume() calls and invoke them
> directly from the call sites.
> 
> No locking required at this point because these calls happen with
> interrupts disabled and a single cpu online.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/x86/xen/suspend.c      |   11 ++++-------
>  include/linux/clockchips.h  |    2 --
>  include/linux/tick.h        |    3 +++
>  kernel/time/clockevents.c   |    9 ---------
>  kernel/time/tick-common.c   |   23 +++++++++++++++++++++--
>  kernel/time/tick-internal.h |    3 ++-
>  kernel/time/timekeeping.c   |    6 ++----
>  7 files changed, 32 insertions(+), 25 deletions(-)

[cut]
 
> Index: linux/include/linux/tick.h
> ===================================================================
> --- linux.orig/include/linux/tick.h
> +++ linux/include/linux/tick.h
> @@ -27,8 +27,11 @@ extern struct tick_device *tick_get_devi
>  
>  #ifdef CONFIG_GENERIC_CLOCKEVENTS
>  extern void __init tick_init(void);
> +/* Should be core only, but XEN resume magic abuses this interface */
> +extern void tick_resume(void);
>  #else /* CONFIG_GENERIC_CLOCKEVENTS */
>  static inline void tick_init(void) { }
> +static inline void tick_resume(void) { }
>  #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
>  
>  #ifdef CONFIG_TICK_ONESHOT

[cut]

> Index: linux/kernel/time/tick-common.c
> ===================================================================
> --- linux.orig/kernel/time/tick-common.c
> +++ linux/kernel/time/tick-common.c
> @@ -372,18 +372,37 @@ void tick_shutdown(unsigned int *cpup)
>  	}
>  }
>  
> +/**
> + * tick_suspend - Suspend the tick and the broadcast device
> + *
> + * Called from syscore_suspend() via timekeeping_suspend with only one
> + * CPU online and interrupts disabled.
> + *
> + * No locks required. Nothing can change the per cpu device.
> + */
>  void tick_suspend(void)
>  {
>  	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
>  
>  	clockevents_shutdown(td->evtdev);
> +	tick_suspend_broadcast();
>  }
>  

The above will slightly conflict with that commit of mine:

http://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-next&id=124cf9117c5f93cc5b324530b7e105b09c729d5d

but that's not a big deal I guess.

Rafael


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

* Re: [PATCH 00/35] Some kernel/time cleanups
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (34 preceding siblings ...)
  2015-02-16 12:15 ` [PATCH 35/35] arm: bl_switcher: Kill tick suspend hackery Peter Zijlstra
@ 2015-02-16 19:14 ` Rafael J. Wysocki
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
  36 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-02-16 19:14 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx

On Monday, February 16, 2015 01:14:35 PM Peter Zijlstra wrote:
> Hi,
> 
> While working with Rafael on the suspend to idle machinery Thomas made these
> cleanups; since one might as well clean code up while you've done the work of
> thinking through it again.
> 
> As it stands there's very little overlap between Rafael's series and this one
> aside from a few trivial fixups. So we'll merge them seperately.

Yes, except for the one patch where I can see the overlap (reply sent), there
should be no collisions.  We may want to compile more stuff conditional on
PM_SLEEP (or even SUSPEND for that matter), but that can be fixed up later
quite easily.

So for all the series:

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>


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

* Re: [PATCH 33/35] tick: Make hrtimer broadcasting opt-in
  2015-02-16 12:15 ` [PATCH 33/35] tick: Make hrtimer broadcasting opt-in Peter Zijlstra
@ 2015-02-17  3:06   ` Preeti U Murthy
  2015-02-17 10:04   ` Lorenzo Pieralisi
  1 sibling, 0 replies; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-17  3:06 UTC (permalink / raw)
  To: Peter Zijlstra, linux-kernel, mingo, rjw
  Cc: tglx, Michael Ellerman, Benjamin Herrenschmidt, Lorenzo Pieralisi

On 02/16/2015 05:45 PM, Peter Zijlstra wrote:

Reviewed-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-16 12:15 ` [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting Peter Zijlstra
@ 2015-02-17  4:03   ` Preeti U Murthy
  2015-02-17 10:39     ` Peter Zijlstra
  2015-02-19 17:51   ` Nicolas Pitre
  1 sibling, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-17  4:03 UTC (permalink / raw)
  To: Peter Zijlstra, linux-kernel, mingo, rjw, tglx

On 02/16/2015 05:45 PM, Peter Zijlstra wrote:

>> From: Thomas Gleixner <tglx@linutronix.de>

>> @@ -428,7 +428,7 @@ static int __ref _cpu_down(unsigned int
>> 	__cpu_die(cpu);
>>
>> 	/* CPU is completely dead: tell everyone.  Too late to complain. */
>>-	tick_cleanup_dead_cpu(cpu);
>>+	tick_takeover(cpu);

Why is tick_handover() called after __cpu_die()? And the function tick_takeover()
is not introduced until the next patch. tick_broadcast_takeover_bc() is the
function used instead in this patch. 

Regards
Preeti U Murthy


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

* Re: [PATCH 33/35] tick: Make hrtimer broadcasting opt-in
  2015-02-16 12:15 ` [PATCH 33/35] tick: Make hrtimer broadcasting opt-in Peter Zijlstra
  2015-02-17  3:06   ` Preeti U Murthy
@ 2015-02-17 10:04   ` Lorenzo Pieralisi
  1 sibling, 0 replies; 106+ messages in thread
From: Lorenzo Pieralisi @ 2015-02-17 10:04 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy,
	Michael Ellerman, Benjamin Herrenschmidt

On Mon, Feb 16, 2015 at 12:15:08PM +0000, Peter Zijlstra wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> We keep adding unconditional stuff to the core code which just bloats
> the text and data size for no value. hrtimer based broadcasting is
> currently only used on arm64 and powerpc. Make it conditional.
> 
> While at it move these tick related interfaces out of the clockchips
> header file.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Preeti U Murthy <preeti@linux.vnet.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> ---
>  arch/arm/kernel/smp.c        |    2 +-
>  arch/arm64/Kconfig           |    1 +
>  arch/arm64/kernel/smp.c      |    1 +
>  arch/arm64/kernel/time.c     |    2 +-
>  arch/mips/kernel/smp.c       |    1 +
>  arch/powerpc/Kconfig         |    1 +
>  arch/powerpc/kernel/smp.c    |    1 +
>  arch/powerpc/kernel/time.c   |    2 +-
>  include/linux/clockchips.h   |   26 +-------------------------
>  include/linux/tick.h         |   25 +++++++++++++++++++++++--
>  kernel/time/Kconfig          |    4 ++++
>  kernel/time/Makefile         |    6 ++----
>  kernel/time/tick-broadcast.c |    4 +++-
>  13 files changed, 41 insertions(+), 35 deletions(-)
> 
> Index: linux/arch/arm/kernel/smp.c
> ===================================================================
> --- linux.orig/arch/arm/kernel/smp.c
> +++ linux/arch/arm/kernel/smp.c
> @@ -22,7 +22,7 @@
>  #include <linux/seq_file.h>
>  #include <linux/irq.h>
>  #include <linux/percpu.h>
> -#include <linux/clockchips.h>
> +#include <linux/tick.h>
>  #include <linux/completion.h>
>  #include <linux/cpufreq.h>
>  #include <linux/irq_work.h>
> Index: linux/arch/arm64/Kconfig
> ===================================================================
> --- linux.orig/arch/arm64/Kconfig
> +++ linux/arch/arm64/Kconfig
> @@ -25,6 +25,7 @@ config ARM64
>  	select GENERIC_ALLOCATOR
>  	select GENERIC_CLOCKEVENTS
>  	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
> +	select GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST if SMP
>  	select GENERIC_CPU_AUTOPROBE
>  	select GENERIC_EARLY_IOREMAP
>  	select GENERIC_IRQ_PROBE
> Index: linux/arch/arm64/kernel/smp.c
> ===================================================================
> --- linux.orig/arch/arm64/kernel/smp.c
> +++ linux/arch/arm64/kernel/smp.c
> @@ -36,6 +36,7 @@
>  #include <linux/completion.h>
>  #include <linux/of.h>
>  #include <linux/irq_work.h>
> +#include <linux/tick.h>
>  
>  #include <asm/alternative.h>
>  #include <asm/atomic.h>
> Index: linux/arch/arm64/kernel/time.c
> ===================================================================
> --- linux.orig/arch/arm64/kernel/time.c
> +++ linux/arch/arm64/kernel/time.c
> @@ -18,11 +18,11 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> -#include <linux/clockchips.h>
>  #include <linux/export.h>
>  #include <linux/kernel.h>
>  #include <linux/interrupt.h>
>  #include <linux/time.h>
> +#include <linux/tick.h>
>  #include <linux/init.h>
>  #include <linux/sched.h>
>  #include <linux/smp.h>
> Index: linux/arch/mips/kernel/smp.c
> ===================================================================
> --- linux.orig/arch/mips/kernel/smp.c
> +++ linux/arch/mips/kernel/smp.c
> @@ -33,6 +33,7 @@
>  #include <linux/cpu.h>
>  #include <linux/err.h>
>  #include <linux/ftrace.h>
> +#include <linux/tick.h>
>  
>  #include <linux/atomic.h>
>  #include <asm/cpu.h>
> Index: linux/arch/powerpc/Kconfig
> ===================================================================
> --- linux.orig/arch/powerpc/Kconfig
> +++ linux/arch/powerpc/Kconfig
> @@ -135,6 +135,7 @@ config PPC
>  	select GENERIC_TIME_VSYSCALL_OLD
>  	select GENERIC_CLOCKEVENTS
>  	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
> +	select GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST if SMP
>  	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
>  	select GENERIC_STRNCPY_FROM_USER
>  	select GENERIC_STRNLEN_USER
> Index: linux/arch/powerpc/kernel/smp.c
> ===================================================================
> --- linux.orig/arch/powerpc/kernel/smp.c
> +++ linux/arch/powerpc/kernel/smp.c
> @@ -31,6 +31,7 @@
>  #include <linux/cpu.h>
>  #include <linux/notifier.h>
>  #include <linux/topology.h>
> +#include <linux/tick.h>
>  
>  #include <asm/ptrace.h>
>  #include <linux/atomic.h>
> Index: linux/arch/powerpc/kernel/time.c
> ===================================================================
> --- linux.orig/arch/powerpc/kernel/time.c
> +++ linux/arch/powerpc/kernel/time.c
> @@ -42,7 +42,7 @@
>  #include <linux/timex.h>
>  #include <linux/kernel_stat.h>
>  #include <linux/time.h>
> -#include <linux/clockchips.h>
> +#include <linux/tick.h>
>  #include <linux/init.h>
>  #include <linux/profile.h>
>  #include <linux/cpu.h>
> Index: linux/include/linux/clockchips.h
> ===================================================================
> --- linux.orig/include/linux/clockchips.h
> +++ linux/include/linux/clockchips.h
> @@ -155,29 +155,5 @@ extern void clockevents_set_mode(struct
>  				 enum clock_event_mode mode);
>  extern int clockevents_program_event(struct clock_event_device *dev,
>  				     ktime_t expires, bool force);
> -
> -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
> -#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
> -extern void tick_broadcast(const struct cpumask *mask);
> -#else
> -#define tick_broadcast	NULL
> -#endif
> -extern int tick_receive_broadcast(void);
> -#endif
> -
> -#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
> -extern void tick_setup_hrtimer_broadcast(void);
> -extern int tick_check_broadcast_expired(void);
> -#else
> -static inline int tick_check_broadcast_expired(void) { return 0; }
> -static inline void tick_setup_hrtimer_broadcast(void) {};
> -#endif
> -
> -#else /* CONFIG_GENERIC_CLOCKEVENTS */
> -
> -static inline int tick_check_broadcast_expired(void) { return 0; }
> -static inline void tick_setup_hrtimer_broadcast(void) {};
> -
> -#endif
> -
> +#endif /* CONFIG_GENERIC_CLOCKEVENTS */
>  #endif
> Index: linux/include/linux/tick.h
> ===================================================================
> --- linux.orig/include/linux/tick.h
> +++ linux/include/linux/tick.h
> @@ -65,10 +65,8 @@ static inline void tick_broadcast_contro
>  
>  #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
>  extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
> -extern void tick_takeover(int deadcpu);
>  #else
>  static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; }
> -static inline void tick_takeover(int deadcpu) { }
>  #endif
>  
>  static inline void tick_broadcast_enable(void)
> @@ -181,4 +179,27 @@ static inline void tick_nohz_task_switch
>  		__tick_nohz_task_switch(tsk);
>  }
>  
> +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
> +#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
> +extern void tick_broadcast(const struct cpumask *mask);
> +#else
> +#define tick_broadcast	NULL
> +#endif
> +extern int tick_receive_broadcast(void);
> +#endif
> +
> +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
> +extern int tick_check_broadcast_expired(void);
> +#else
> +static inline int tick_check_broadcast_expired(void) { return 0; }
> +#endif
> +
> +#ifdef CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
> +extern void tick_setup_hrtimer_broadcast(void);
> +extern void tick_takeover(int deadcpu);
> +#else
> +static inline void tick_setup_hrtimer_broadcast(void) { };
> +static inline void tick_takeover(int deadcpu) { }
> +#endif
> +
>  #endif
> Index: linux/kernel/time/Kconfig
> ===================================================================
> --- linux.orig/kernel/time/Kconfig
> +++ linux/kernel/time/Kconfig
> @@ -42,6 +42,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST
>  	bool
>  	depends on GENERIC_CLOCKEVENTS
>  
> +config GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
> +	bool
> +	depends on GENERIC_CLOCKEVENTS && TICK_ONESHOT
> +
>  # Automatically adjust the min. reprogramming time for
>  # clock event device
>  config GENERIC_CLOCKEVENTS_MIN_ADJUST
> Index: linux/kernel/time/Makefile
> ===================================================================
> --- linux.orig/kernel/time/Makefile
> +++ linux/kernel/time/Makefile
> @@ -3,10 +3,8 @@ obj-y += timekeeping.o ntp.o clocksource
>  obj-y += timeconv.o posix-clock.o alarmtimer.o
>  
>  obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o tick-common.o
> -ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
> - obj-y						+= tick-broadcast.o
> - obj-$(CONFIG_TICK_ONESHOT)			+= tick-broadcast-hrtimer.o
> -endif
> +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= tick-broadcast.o
> +obj-$(CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST)	+= tick-broadcast-hrtimer.o
>  obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
>  obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
>  obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
> Index: linux/kernel/time/tick-broadcast.c
> ===================================================================
> --- linux.orig/kernel/time/tick-broadcast.c
> +++ linux/kernel/time/tick-broadcast.c
> @@ -908,6 +908,7 @@ void tick_broadcast_switch_to_oneshot(vo
>  }
>  
>  #ifdef CONFIG_HOTPLUG_CPU
> +#ifdef CONFIG_GENERIC_CLOCKEVENTS_HRTIMER_BROADCAST
>  /*
>   * Called from the cpu hotplug code after a cpu is dead. This ensures
>   * that a hrtimer based broad cast device is taken over.
> @@ -916,7 +917,7 @@ void tick_broadcast_switch_to_oneshot(vo
>   * which pushes the hrtimer over to a different cpu from
>   * tick_shutdown_broadcast_oneshot()
>   */
> -void tick_broadcast_takeover_bc(int deadcpu)
> +void tick_takeover(int deadcpu)
>  {
>  	struct clock_event_device *bc;
>  	unsigned long flags;
> @@ -929,6 +930,7 @@ void tick_broadcast_takeover_bc(int dead
>  	}
>  	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
>  }
> +#endif
>  
>  /*
>   * Remove a dead CPU from broadcasting, called with broadcast lock
> 
> 
> 

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-17  4:03   ` Preeti U Murthy
@ 2015-02-17 10:39     ` Peter Zijlstra
  2015-02-18  3:10       ` Preeti U Murthy
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-17 10:39 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: linux-kernel, mingo, rjw, tglx

On Tue, Feb 17, 2015 at 09:33:45AM +0530, Preeti U Murthy wrote:
> On 02/16/2015 05:45 PM, Peter Zijlstra wrote:
> 
> >> From: Thomas Gleixner <tglx@linutronix.de>
> 
> >> @@ -428,7 +428,7 @@ static int __ref _cpu_down(unsigned int
> >> 	__cpu_die(cpu);
> >>
> >> 	/* CPU is completely dead: tell everyone.  Too late to complain. */
> >>-	tick_cleanup_dead_cpu(cpu);
> >>+	tick_takeover(cpu);
> 
> Why is tick_handover() called after __cpu_die()?

See: [PATCH 11/35] clockevents: Cleanup dead cpu explicitely
it used to be a CPU_DEAD notifier.

But, I think, the actual reason would be that you cannot be sure its not
still ticking until its actually proper dead and buried, so trying to
take over a tick from a cpu that's still ticking is... well, suspect.

> And the function tick_takeover()
> is not introduced until the next patch. tick_broadcast_takeover_bc() is the
> function used instead in this patch.

Indeed so; let me correct that for bisection's sake.

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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-16 12:15 ` [PATCH 34/35] tick: Provide tick_suspend_local() Peter Zijlstra
@ 2015-02-17 14:31   ` Lorenzo Pieralisi
  2015-02-17 17:55     ` Nicolas Pitre
  2015-02-18 13:35     ` Peter Zijlstra
  0 siblings, 2 replies; 106+ messages in thread
From: Lorenzo Pieralisi @ 2015-02-17 14:31 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, rjw, tglx, Nicolas Pitre, Russell King

On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> This function is intended to use by the freezer once the freezer folks
> solved their race issues. Also required to get rid of the ARM BL
> switcher tick hackery.

Totally agree with the patch(es), but I noticed that the ARM bL switcher
does not depend on PM_SLEEP, so I do not think you can compile
tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
is enforced by the ARM bL switcher config but I do not think that
the config dependency really exists, Nico please correct me if I am
wrong.

Lorenzo

> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Nicolas Pitre <nico@linaro.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> 
> ---
>  include/linux/tick.h      |    3 +++
>  kernel/time/tick-common.c |   18 +++++++++++++++---
>  2 files changed, 18 insertions(+), 3 deletions(-)
> 
> Index: linux/include/linux/tick.h
> ===================================================================
> --- linux.orig/include/linux/tick.h
> +++ linux/include/linux/tick.h
> @@ -27,12 +27,15 @@ extern struct tick_device *tick_get_devi
>  
>  #ifdef CONFIG_GENERIC_CLOCKEVENTS
>  extern void __init tick_init(void);
> +/* Should be core only, but arm BL switcher has its homebrewn implementation */
> +extern void tick_suspend_local(void);
>  /* Should be core only, but XEN resume magic requires this */
>  extern void tick_resume_local(void);
>  /* CPU hotplug */
>  extern void tick_shutdown_local(void);
>  #else /* CONFIG_GENERIC_CLOCKEVENTS */
>  static inline void tick_init(void) { }
> +static inline void tick_suspend_local(void) { }
>  static inline void tick_resume_local(void) { }
>  static inline void tick_shutdown_local(void) { }
>  #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
> Index: linux/kernel/time/tick-common.c
> ===================================================================
> --- linux.orig/kernel/time/tick-common.c
> +++ linux/kernel/time/tick-common.c
> @@ -370,6 +370,20 @@ void tick_shutdown_local(void)
>  
>  #ifdef CONFIG_PM_SLEEP
>  /**
> + * tick_suspend_local - Suspend the local tick device
> + *
> + * Called from the local cpu for freeze with interrupts disabled.
> + *
> + * No locks required. Nothing can change the per cpu device.
> + */
> +void tick_suspend_local(void)
> +{
> +	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
> +
> +	clockevents_shutdown(td->evtdev);
> +}
> +
> +/**
>   * tick_suspend - Suspend the tick and the broadcast device
>   *
>   * Called from syscore_suspend() via timekeeping_suspend with only one
> @@ -379,9 +393,7 @@ void tick_shutdown_local(void)
>   */
>  void tick_suspend(void)
>  {
> -	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
> -
> -	clockevents_shutdown(td->evtdev);
> +	tick_suspend_local();
>  	tick_suspend_broadcast();
>  }
>  
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-17 14:31   ` Lorenzo Pieralisi
@ 2015-02-17 17:55     ` Nicolas Pitre
  2015-02-17 21:29       ` Nicolas Pitre
  2015-02-18 13:35     ` Peter Zijlstra
  1 sibling, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-17 17:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Peter Zijlstra, linux-kernel, mingo, rjw, tglx, Russell King

On Tue, 17 Feb 2015, Lorenzo Pieralisi wrote:

> On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> > From: Thomas Gleixner <tglx@linutronix.de>
> > 
> > This function is intended to use by the freezer once the freezer folks
> > solved their race issues. Also required to get rid of the ARM BL
> > switcher tick hackery.
> 
> Totally agree with the patch(es), but I noticed that the ARM bL switcher
> does not depend on PM_SLEEP, so I do not think you can compile
> tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
> is enforced by the ARM bL switcher config but I do not think that
> the config dependency really exists, Nico please correct me if I am
> wrong.

The ARM bL switcher does not depend on PM_SUSPEND nor does it enforce it 
because it currently doesn't need it.  So yeah, either PM_SUSPEND is 
selected bringing quite a lot of code with it, or another symbol is used 
for those functions (CONFIG_HOTPLUG_CPU maybe?).


Nicolas

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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-17 17:55     ` Nicolas Pitre
@ 2015-02-17 21:29       ` Nicolas Pitre
  0 siblings, 0 replies; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-17 21:29 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Peter Zijlstra, linux-kernel, mingo, rjw, tglx, Russell King

On Tue, 17 Feb 2015, Nicolas Pitre wrote:

> On Tue, 17 Feb 2015, Lorenzo Pieralisi wrote:
> 
> > On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> > > From: Thomas Gleixner <tglx@linutronix.de>
> > > 
> > > This function is intended to use by the freezer once the freezer folks
> > > solved their race issues. Also required to get rid of the ARM BL
> > > switcher tick hackery.
> > 
> > Totally agree with the patch(es), but I noticed that the ARM bL switcher
> > does not depend on PM_SLEEP, so I do not think you can compile
> > tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
> > is enforced by the ARM bL switcher config but I do not think that
> > the config dependency really exists, Nico please correct me if I am
> > wrong.
> 
> The ARM bL switcher does not depend on PM_SUSPEND nor does it enforce it 
> because it currently doesn't need it.  So yeah, either PM_SUSPEND is 
> selected bringing quite a lot of code with it, or another symbol is used 
> for those functions (CONFIG_HOTPLUG_CPU maybe?).

Note the same problem exists with arch/x86/xen/suspend.c that calls 
tick_resume_local() yet this file is not subject to a dependency on 
CONFIG_PM_SUSPEND.


Nicolas

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-17 10:39     ` Peter Zijlstra
@ 2015-02-18  3:10       ` Preeti U Murthy
  2015-02-18 13:06         ` Peter Zijlstra
  0 siblings, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-18  3:10 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx



On 02/17/2015 04:09 PM, Peter Zijlstra wrote:
>> [PATCH 11/35] clockevents: Cleanup dead cpu explicitely
n Tue, Feb 17, 2015 at 09:33:45AM +0530, Preeti U Murthy wrote:
>> On 02/16/2015 05:45 PM, Peter Zijlstra wrote:
>>
>>>> From: Thomas Gleixner <tglx@linutronix.de>
>>
>>>> @@ -428,7 +428,7 @@ static int __ref _cpu_down(unsigned int
>>>> 	__cpu_die(cpu);
>>>>
>>>> 	/* CPU is completely dead: tell everyone.  Too late to complain. */
>>>> -	tick_cleanup_dead_cpu(cpu);
>>>> +	tick_takeover(cpu);
>>
>> Why is tick_handover() called after __cpu_die()?

> See: [PATCH 11/35] clockevents: Cleanup dead cpu explicitely
> it used to be a CPU_DEAD notifier.

> But, I think, the actual reason would be that you cannot be sure its not
> still ticking until its actually proper dead and buried, so trying to
> take over a tick from a cpu that's still ticking is... well, suspect.

Look at the changelog, it explains why tick_takeover must be called
*before* __cpu_die(). The above hunk is not solving the issue, it is
equivalent to the scenario where we took over broadcast duty in the
CPU_DEAD phase as a consequence of which the cpu doing the hotplug
operation is stuck sleeping forever. Cleanup functions can be handled
after __cpu_die() for the reason that you mention above.

Regards
Preeti U Murthy


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

* Re: [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense
  2015-02-16 18:54   ` Rafael J. Wysocki
@ 2015-02-18  6:16     ` Rafael J. Wysocki
  0 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-02-18  6:16 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Len Brown, linux-acpi

On Monday, February 16, 2015 07:54:12 PM Rafael J. Wysocki wrote:
> On Monday, February 16, 2015 01:14:36 PM Peter Zijlstra wrote:
> > From: Thomas Gleixner <tglx@linutronix.de>
> > 
> > While looking through the (ab)use of the clockevents_notify() function
> > I stumbled over the following gem in the acpi_pad code:
> > 
> >   if (lapic_detected_unstable && !lapic_marked_unstable) {
> >      /* LAPIC could halt in idle, so notify users */
> >      for_each_online_cpu(i)
> >        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
> >      lapic_marked_unstable = 1;
> >   }
> > 
> > This code calls on the cpu which detects the lapic unstable condition
> > first clockevents_notify() to tell the core code that the broadcast
> > should be enabled on all online cpus. Brilliant stuff that as it
> > notifies the core code a num_online_cpus() times that the broadcast
> > should be enabled on the current cpu.
> > 
> > This probably has never been noticed because that code got never
> > tested with NOHZ=n and HIGHRES_TIMER=n or it just worked by chance
> > because one of the other mechanisms told the core in the right way
> > that the local apic timer is wreckaged.
> > 
> > Sigh, this is:
> > 
> >  - The 4th incarnation of idle drivers which has their own mechanism
> >    to detect and deal with X86_FEATURE_ARAT.
> > 
> >  - The 2nd incarnation of fake idle mechanisms with a different set of
> >    brainmelting bugs.
> > 
> >  - Has been merged against an explicit NAK of the scheduler
> >    maintainer with the promise to improve it over time.
> > 
> >  - Another example of featuritis driven trainwreck engineering.
> > 
> >  - Another pointless waste of my time.
> > 
> > Fix this nonsense by removing that lapic detection and notification
> > logic and simply call into the clockevents code unconditonally. The
> > ARAT feature is marked in the lapic clockevent already so the core
> > code will just ignore the requests and return.
> > 
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> 
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Or I can apply it right away if you want me to.

Rafael


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-18  3:10       ` Preeti U Murthy
@ 2015-02-18 13:06         ` Peter Zijlstra
  2015-02-19  7:01           ` Preeti U Murthy
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-18 13:06 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: linux-kernel, mingo, rjw, tglx

On Wed, Feb 18, 2015 at 08:40:52AM +0530, Preeti U Murthy wrote:
> 
> Look at the changelog, 

Heh, yah, clearly I tl;dr'd that. Indeed.

> it explains why tick_takeover must be called
> *before* __cpu_die(). 

Since you reported this, can you test if things work if you move that
function call to before __cpu_die() ?

I _think_ it should be fine, but what do I know ;-)

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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-17 14:31   ` Lorenzo Pieralisi
  2015-02-17 17:55     ` Nicolas Pitre
@ 2015-02-18 13:35     ` Peter Zijlstra
  2015-02-18 16:22       ` Rafael J. Wysocki
  2015-02-18 16:38       ` Lorenzo Pieralisi
  1 sibling, 2 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-18 13:35 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-kernel, mingo, rjw, tglx, Nicolas Pitre, Russell King

On Tue, Feb 17, 2015 at 02:31:42PM +0000, Lorenzo Pieralisi wrote:
> On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> > From: Thomas Gleixner <tglx@linutronix.de>
> > 
> > This function is intended to use by the freezer once the freezer folks
> > solved their race issues. Also required to get rid of the ARM BL
> > switcher tick hackery.
> 
> Totally agree with the patch(es), but I noticed that the ARM bL switcher
> does not depend on PM_SLEEP, so I do not think you can compile
> tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
> is enforced by the ARM bL switcher config but I do not think that
> the config dependency really exists, Nico please correct me if I am
> wrong.

Ah I see, the headers seem to do the right thing and declare the
function in core (GENERIC_CLOCKEVENTS) with a comment.

But then the patch continues defining the functions under PM_SLEEP.

I wonder why the build robot has not reported fail on this..

Would the below make sense?

---
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -368,7 +368,6 @@ void tick_shutdown_local(void)
 }
 #endif
 
-#ifdef CONFIG_PM_SLEEP
 /**
  * tick_suspend_local - Suspend the local tick device
  *
@@ -384,20 +383,6 @@ void tick_suspend_local(void)
 }
 
 /**
- * tick_suspend - Suspend the tick and the broadcast device
- *
- * Called from syscore_suspend() via timekeeping_suspend with only one
- * CPU online and interrupts disabled.
- *
- * No locks required. Nothing can change the per cpu device.
- */
-void tick_suspend(void)
-{
-	tick_suspend_local();
-	tick_suspend_broadcast();
-}
-
-/**
  * tick_resume_local - Resume the local tick device
  *
  * Called from the local cpu for unfreeze or XEN resume magic
@@ -418,6 +403,21 @@ void tick_resume_local(void)
 	}
 }
 
+#ifdef CONFIG_PM_SLEEP
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend(void)
+{
+	tick_suspend_local();
+	tick_suspend_broadcast();
+}
+
 /**
  * tick_resume - Resume the tick and the broadcast device
  *

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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-18 13:35     ` Peter Zijlstra
@ 2015-02-18 16:22       ` Rafael J. Wysocki
  2015-02-18 16:38       ` Lorenzo Pieralisi
  1 sibling, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-02-18 16:22 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Lorenzo Pieralisi, linux-kernel, mingo, tglx, Nicolas Pitre,
	Russell King

On Wednesday, February 18, 2015 02:35:24 PM Peter Zijlstra wrote:
> On Tue, Feb 17, 2015 at 02:31:42PM +0000, Lorenzo Pieralisi wrote:
> > On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> > > From: Thomas Gleixner <tglx@linutronix.de>
> > > 
> > > This function is intended to use by the freezer once the freezer folks
> > > solved their race issues. Also required to get rid of the ARM BL
> > > switcher tick hackery.
> > 
> > Totally agree with the patch(es), but I noticed that the ARM bL switcher
> > does not depend on PM_SLEEP, so I do not think you can compile
> > tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
> > is enforced by the ARM bL switcher config but I do not think that
> > the config dependency really exists, Nico please correct me if I am
> > wrong.
> 
> Ah I see, the headers seem to do the right thing and declare the
> function in core (GENERIC_CLOCKEVENTS) with a comment.
> 
> But then the patch continues defining the functions under PM_SLEEP.
> 
> I wonder why the build robot has not reported fail on this..
> 
> Would the below make sense?

That needs to be done on top of the suspend-to-idle material that has just
been merged.

Why don't you drop the PM_SLEEP-related changes from the series for the time
being and let's clean things up top of it?  That should be more straightforward
I think.

Rafael


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

* Re: [PATCH 34/35] tick: Provide tick_suspend_local()
  2015-02-18 13:35     ` Peter Zijlstra
  2015-02-18 16:22       ` Rafael J. Wysocki
@ 2015-02-18 16:38       ` Lorenzo Pieralisi
  1 sibling, 0 replies; 106+ messages in thread
From: Lorenzo Pieralisi @ 2015-02-18 16:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, rjw, tglx, Nicolas Pitre, Russell King

On Wed, Feb 18, 2015 at 01:35:24PM +0000, Peter Zijlstra wrote:
> On Tue, Feb 17, 2015 at 02:31:42PM +0000, Lorenzo Pieralisi wrote:
> > On Mon, Feb 16, 2015 at 12:15:09PM +0000, Peter Zijlstra wrote:
> > > From: Thomas Gleixner <tglx@linutronix.de>
> > > 
> > > This function is intended to use by the freezer once the freezer folks
> > > solved their race issues. Also required to get rid of the ARM BL
> > > switcher tick hackery.
> > 
> > Totally agree with the patch(es), but I noticed that the ARM bL switcher
> > does not depend on PM_SLEEP, so I do not think you can compile
> > tick_{suspend/resume}_local() out if !PM_SLEEP, unless dependency
> > is enforced by the ARM bL switcher config but I do not think that
> > the config dependency really exists, Nico please correct me if I am
> > wrong.
> 
> Ah I see, the headers seem to do the right thing and declare the
> function in core (GENERIC_CLOCKEVENTS) with a comment.
> 
> But then the patch continues defining the functions under PM_SLEEP.
> 
> I wonder why the build robot has not reported fail on this..
> 
> Would the below make sense?

Yes, but please see Rafael's remark, whatever makes it easier for you.

Thanks,
Lorenzo

> 
> ---
> --- a/kernel/time/tick-common.c
> +++ b/kernel/time/tick-common.c
> @@ -368,7 +368,6 @@ void tick_shutdown_local(void)
>  }
>  #endif
>  
> -#ifdef CONFIG_PM_SLEEP
>  /**
>   * tick_suspend_local - Suspend the local tick device
>   *
> @@ -384,20 +383,6 @@ void tick_suspend_local(void)
>  }
>  
>  /**
> - * tick_suspend - Suspend the tick and the broadcast device
> - *
> - * Called from syscore_suspend() via timekeeping_suspend with only one
> - * CPU online and interrupts disabled.
> - *
> - * No locks required. Nothing can change the per cpu device.
> - */
> -void tick_suspend(void)
> -{
> -	tick_suspend_local();
> -	tick_suspend_broadcast();
> -}
> -
> -/**
>   * tick_resume_local - Resume the local tick device
>   *
>   * Called from the local cpu for unfreeze or XEN resume magic
> @@ -418,6 +403,21 @@ void tick_resume_local(void)
>  	}
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
> +/**
> + * tick_suspend - Suspend the tick and the broadcast device
> + *
> + * Called from syscore_suspend() via timekeeping_suspend with only one
> + * CPU online and interrupts disabled.
> + *
> + * No locks required. Nothing can change the per cpu device.
> + */
> +void tick_suspend(void)
> +{
> +	tick_suspend_local();
> +	tick_suspend_broadcast();
> +}
> +
>  /**
>   * tick_resume - Resume the tick and the broadcast device
>   *
> 

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-18 13:06         ` Peter Zijlstra
@ 2015-02-19  7:01           ` Preeti U Murthy
  2015-02-19  9:53             ` Peter Zijlstra
  0 siblings, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-19  7:01 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx

On 02/18/2015 06:36 PM, Peter Zijlstra wrote:
> On Wed, Feb 18, 2015 at 08:40:52AM +0530, Preeti U Murthy wrote:
>>
>> Look at the changelog, 
> 
> Heh, yah, clearly I tl;dr'd that. Indeed.
> 
>> it explains why tick_takeover must be called
>> *before* __cpu_die(). 
> 
> Since you reported this, can you test if things work if you move that
> function call to before __cpu_die() ?

Yes it does. I had tested and posted out a patch to fix the issue
here:https://lkml.org/lkml/2015/1/30/821. I see now that tglx proposes
to get rid of "taking over" tick duties going forward, rather "handing
over" tick duties would be better. So the patch in the above link would
not be acceptable. But minus the taking over of the do_timer, the cpu
doing the hotplug takes over broadcast duty before __cpu_die() in this
patch. This design works.

Regards
Preeti U Murthy
> 
> I _think_ it should be fine, but what do I know ;-)
> 


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-19  7:01           ` Preeti U Murthy
@ 2015-02-19  9:53             ` Peter Zijlstra
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-19  9:53 UTC (permalink / raw)
  To: Preeti U Murthy; +Cc: linux-kernel, mingo, rjw, tglx

On Thu, Feb 19, 2015 at 12:31:53PM +0530, Preeti U Murthy wrote:
> On 02/18/2015 06:36 PM, Peter Zijlstra wrote:
> > On Wed, Feb 18, 2015 at 08:40:52AM +0530, Preeti U Murthy wrote:
> >>
> >> Look at the changelog, 
> > 
> > Heh, yah, clearly I tl;dr'd that. Indeed.
> > 
> >> it explains why tick_takeover must be called
> >> *before* __cpu_die(). 
> > 
> > Since you reported this, can you test if things work if you move that
> > function call to before __cpu_die() ?
> 
> Yes it does. I had tested and posted out a patch to fix the issue
> here:https://lkml.org/lkml/2015/1/30/821. I see now that tglx proposes
> to get rid of "taking over" tick duties going forward, rather "handing
> over" tick duties would be better. So the patch in the above link would
> not be acceptable. But minus the taking over of the do_timer, the cpu
> doing the hotplug takes over broadcast duty before __cpu_die() in this
> patch. This design works.

Great, /me amends patch.

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-16 12:15 ` [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting Peter Zijlstra
  2015-02-17  4:03   ` Preeti U Murthy
@ 2015-02-19 17:51   ` Nicolas Pitre
  2015-02-21 12:46     ` Peter Zijlstra
  1 sibling, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-19 17:51 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Mon, 16 Feb 2015, Peter Zijlstra wrote:

> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Preeti reported a cpu down race with hrtimer based broadcasting:
> 
> Assume CPU1 is the CPU which holds the hrtimer broadcasting duty
> before it is taken down.
> 
> CPU0				CPU1
> cpu_down()
> 				takedown_cpu()
> 			   	  disable_interrupts()
> cpu_die()
>   while (CPU1 != DEAD) {
>     msleep(100);
>       switch_to_idle()
>         stop_cpu_timer()
>           schedule_broadcast()
>   }
> 
> tick_cleanup_dead_cpu()
>      take_over_broadcast()	
> 
> So after CPU1 disabled interrupts it cannot handle the broadcast
> hrtimer anymore, so CPU0 will be stuck forever.
> 
> Doing a "while (CPU1 != DEAD) msleep(100);" periodic poll is silly at
> best, but we need to fix that nevertheless.
> 
> Split the tick cleanup into two pieces:
> 
> 1) Shutdown and remove all per cpu clockevent devices from
>    takedown_cpu()
> 
>    This is done carefully with respect to existing arch code which
>    works around the shortcoming of the clockevents core code in
>    interesting ways. We really want a separate callback for this to
>    cleanup the workarounds, but that's not scope of this patch
> 
> 2) Takeover the broadcast duty explicitely before calling cpu_die()
> 
>    This is a temporary workaround as well. What we really want is a
>    callback in the clockevent device which allows us to do that from
>    the dying CPU by pushing the hrtimer onto a different cpu. That
>    might involve an IPI and is definitely more complex than this
>    immediate fix.
> 
> Reported-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

This breaks the b.L switcher disabling code which essentially does:

static void bL_switcher_restore_cpus(void)
{
        int i;

        for_each_cpu(i, &bL_switcher_removed_logical_cpus) {
                struct device *cpu_dev = get_cpu_device(i);
                int ret = device_online(cpu_dev);
                if (ret)
                        dev_err(cpu_dev, "switcher: unable to restore CPU\n");
        }
}

However, as soon as one new CPU becomes online, the following crash 
occurs on that CPU:

[  547.858031] ------------[ cut here ]------------
[  547.871868] kernel BUG at kernel/time/hrtimer.c:1249!
[  547.886991] Internal error: Oops - BUG: 0 [#1] SMP THUMB2
[  547.903155] Modules linked in:
[  547.912303] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 3.19.0-rc5-00058-gdd7a65fbc5 #527
[...]
[  548.599060] [<c005a1c2>] (hrtimer_interrupt) from [<c00639db>] (tick_do_broadcast.constprop.8+0x8f/0x90)
[  548.627482] [<c00639db>] (tick_do_broadcast.constprop.8) from [<c0063acd>] (tick_handle_oneshot_broadcast+0xf1/0x168)
[  548.659290] [<c0063acd>] (tick_handle_oneshot_broadcast) from [<c001a07f>] (sp804_timer_interrupt+0x2b/0x30)
[  548.688755] [<c001a07f>] (sp804_timer_interrupt) from [<c004ee9b>] (handle_irq_event_percpu+0x37/0x130)
[  548.716916] [<c004ee9b>] (handle_irq_event_percpu) from [<c004efc7>] (handle_irq_event+0x33/0x48)
[  548.743511] [<c004efc7>] (handle_irq_event) from [<c0050c1d>] (handle_fasteoi_irq+0x69/0xe4)
[  548.768804] [<c0050c1d>] (handle_fasteoi_irq) from [<c004e835>] (generic_handle_irq+0x1d/0x28)
[  548.794619] [<c004e835>] (generic_handle_irq) from [<c004ea17>] (__handle_domain_irq+0x3f/0x80)
[  548.820694] [<c004ea17>] (__handle_domain_irq) from [<c00084f5>] (gic_handle_irq+0x21/0x4c)
[  548.845729] [<c00084f5>] (gic_handle_irq) from [<c04521db>] (__irq_svc+0x3b/0x5c)

The corresponding code is:

void hrtimer_interrupt(struct clock_event_device *dev)
{
        struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
        ktime_t expires_next, now, entry_time, delta;
        int i, retries = 0;

        BUG_ON(!cpu_base->hres_active);
[...]

Reverting this patch "fixes" the problem.


Nicolas

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

* Re: [PATCH 27/35] sched/idle: Use explicit broadcast oneshot control function
  2015-02-16 12:15 ` [PATCH 27/35] sched/idle: " Peter Zijlstra
@ 2015-02-21  0:56   ` Nicolas Pitre
  2015-02-21 11:19     ` Peter Zijlstra
  0 siblings, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-21  0:56 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx

On Mon, 16 Feb 2015, Peter Zijlstra wrote:

> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Replace the clockevents_notify() call with an explicit function call.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

This patch makes my test system hang solid after letting it sit idle for 
5 to 15 minutes.  Reverting it and this issue goes away.

The explicit function call is not an equivalent replacement. In 
clockevents_notify() the clockevents_lock is held across the call to 
tick_broadcast_enter() or tick_broadcast_exit(). This patch drops the 
locking.

> ---
>  kernel/sched/idle.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> Index: linux/kernel/sched/idle.c
> ===================================================================
> --- linux.orig/kernel/sched/idle.c
> +++ linux/kernel/sched/idle.c
> @@ -143,8 +143,7 @@ use_default:
>  	 * is used from another cpu as a broadcast timer, this call may
>  	 * fail if it is not available
>  	 */
> -	if (broadcast &&
> -	    clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
> +	if (broadcast && tick_broadcast_enter())
>  		goto use_default;
>  
>  	/* Take note of the planned idle state. */
> @@ -161,7 +160,7 @@ use_default:
>  	idle_set_state(this_rq(), NULL);
>  
>  	if (broadcast)
> -		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
> +		tick_broadcast_exit();
>  
>  	/*
>  	 * Give the governor an opportunity to reflect on the outcome
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 
> 

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

* Re: [PATCH 27/35] sched/idle: Use explicit broadcast oneshot control function
  2015-02-21  0:56   ` Nicolas Pitre
@ 2015-02-21 11:19     ` Peter Zijlstra
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-21 11:19 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: linux-kernel, mingo, rjw, tglx

On Fri, Feb 20, 2015 at 07:56:17PM -0500, Nicolas Pitre wrote:
> On Mon, 16 Feb 2015, Peter Zijlstra wrote:
> 
> > From: Thomas Gleixner <tglx@linutronix.de>
> > 
> > Replace the clockevents_notify() call with an explicit function call.
> > 
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> 
> This patch makes my test system hang solid after letting it sit idle for 
> 5 to 15 minutes.  Reverting it and this issue goes away.
> 
> The explicit function call is not an equivalent replacement. In 
> clockevents_notify() the clockevents_lock is held across the call to 
> tick_broadcast_enter() or tick_broadcast_exit(). This patch drops the 
> locking.

Yeah, the Changelog introducing the explicit call states as much. I'll
have to go figure out why that matters here.

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-19 17:51   ` Nicolas Pitre
@ 2015-02-21 12:46     ` Peter Zijlstra
  2015-02-21 17:45       ` Nicolas Pitre
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-21 12:46 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Thu, Feb 19, 2015 at 12:51:52PM -0500, Nicolas Pitre wrote:
> 
> This breaks the b.L switcher disabling code which essentially does:
> 
> static void bL_switcher_restore_cpus(void)
> {
>         int i;
> 
>         for_each_cpu(i, &bL_switcher_removed_logical_cpus) {
>                 struct device *cpu_dev = get_cpu_device(i);
>                 int ret = device_online(cpu_dev);
>                 if (ret)
>                         dev_err(cpu_dev, "switcher: unable to restore CPU\n");
>         }
> }

Just so I understand, this device_{on,ofF}line() stuff is basically just
cpu_{up,down}() but obfuscated through the device model nonsense, right?

Also it seems bL_switcher_enable() relies on lock_device_hotplug() to
stabilize the online cpu mask; it does not, only the hotplug lock does.

I'm having a very hard time trying to follow wth this thing all is
doing; its using hotplug but its also doing magic with cpu_suspend().

/me confused..

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-21 12:46     ` Peter Zijlstra
@ 2015-02-21 17:45       ` Nicolas Pitre
  2015-02-23 16:14         ` Peter Zijlstra
  0 siblings, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-21 17:45 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Sat, 21 Feb 2015, Peter Zijlstra wrote:

> On Thu, Feb 19, 2015 at 12:51:52PM -0500, Nicolas Pitre wrote:
> > 
> > This breaks the b.L switcher disabling code which essentially does:
> > 
> > static void bL_switcher_restore_cpus(void)
> > {
> >         int i;
> > 
> >         for_each_cpu(i, &bL_switcher_removed_logical_cpus) {
> >                 struct device *cpu_dev = get_cpu_device(i);
> >                 int ret = device_online(cpu_dev);
> >                 if (ret)
> >                         dev_err(cpu_dev, "switcher: unable to restore CPU\n");
> >         }
> > }
> 
> Just so I understand, this device_{on,ofF}line() stuff is basically just
> cpu_{up,down}() but obfuscated through the device model nonsense, right?

Right.  Before commit 3f8517e793 cpu_{up,down}() were used directly.

> Also it seems bL_switcher_enable() relies on lock_device_hotplug() to
> stabilize the online cpu mask; it does not, only the hotplug lock does.

This is there to prevent any concurrent hotplug operations via sysfs.  
Once the switcher is active, we deny hotplugging operations on any 
physical CPU the switcher has removed.

> I'm having a very hard time trying to follow wth this thing all is
> doing; its using hotplug but its also doing magic with cpu_suspend().

You're fully aware of the on-going work on the scheduler to better 
support the big.LITTLE architecture amongst other things.  The switcher 
is an interim solution where one big CPU is paired with one little CPU, 
and that pair is conceptually used as one logical CPU where only one of 
the big or little physical CPU runs at a time. Those logical CPUs have 
identical capacities therefore the current scheduler may works well with 
them.

The switch between the two physical CPUs is abstracted behind an 
extended cpufreq scale i.e. when cpufreq asks for a frequency exceeding 
the little CPU then a transparent switch is made to the big CPU.  The 
transparent switch is performed by suspending the current CPU and 
immediately resuming the same context on the other CPU, hence the 
cpu_suspend() usage.

The switcher is runtime activated.  To do so, one physical CPU per 
logical pairing is hotplugged out so the system considers only the 
"logical" CPUs.  When the switcher is disabled, those CPUs are brought 
back online.

> /me confused..

If you want more background info, you may have a look at this article:

http://lwn.net/Articles/481055/

Or just ask away.


Nicolas

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-21 17:45       ` Nicolas Pitre
@ 2015-02-23 16:14         ` Peter Zijlstra
  2015-02-23 16:32           ` Nicolas Pitre
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Zijlstra @ 2015-02-23 16:14 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Sat, Feb 21, 2015 at 12:45:51PM -0500, Nicolas Pitre wrote:
> > I'm having a very hard time trying to follow wth this thing all is
> > doing; its using hotplug but its also doing magic with cpu_suspend().
> 
> You're fully aware of the on-going work on the scheduler to better 
> support the big.LITTLE architecture amongst other things.  The switcher 
> is an interim solution where one big CPU is paired with one little CPU, 
> and that pair is conceptually used as one logical CPU where only one of 
> the big or little physical CPU runs at a time. Those logical CPUs have 
> identical capacities therefore the current scheduler may works well with 
> them.

Yeah, I'm aware of roughly what and why its doing things.

But I was trying to piece together how exactly stuff gets done so I
could figure out why that patch broke stuff.

So while it appears to use the regular hotplug code for some of the
work, it also has some extra magic on top to affect the actual
switcheroo of the cpu.


In any case, having had a second look I think I might have some ideas:

 - bL_switcher_enable() -- enables the whole switcher thing and
   disables half the cpus with hot-un-plug, creates a mapping etc..

 - bL_switcher_disable() -- disabled the whole switcher thing and
   gives us back all our cpus with hot-plug.

When the switcher is enabled; we switch by this magic cpu_suspend() call
that saves the entire cpu state and allows you to restore it on another
cpu.

You muck about with the tick; you disable it before cpu_suspend() and
re-enable it after on the target cpu. You further reprogram the
interrupt routing from the old to the new cpu.

But that appears to be it, no more. I suppose the tick is special
because its the only per-cpu device?


The reported function that fails: bL_switcher_restore_cpus() is called
in the error paths of the former and the main path in the latter to make
the 'stolen' cpus re-appear.

The patch in question somehow makes that go boom.


Now what all do you need to do to make it go boom? Just enable/disable
the switcher once and it'll explode? Or does it need to do actual
switches while it is enabled?

The place where it explodes is a bit surprising, it thinks hrtimers are
not enabled even though its calling into hrtimer code on that cpu...




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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-23 16:14         ` Peter Zijlstra
@ 2015-02-23 16:32           ` Nicolas Pitre
  2015-02-23 17:33             ` Nicolas Pitre
  0 siblings, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-23 16:32 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Mon, 23 Feb 2015, Peter Zijlstra wrote:

> In any case, having had a second look I think I might have some ideas:
> 
>  - bL_switcher_enable() -- enables the whole switcher thing and
>    disables half the cpus with hot-un-plug, creates a mapping etc..
> 
>  - bL_switcher_disable() -- disabled the whole switcher thing and
>    gives us back all our cpus with hot-plug.
> 
> When the switcher is enabled; we switch by this magic cpu_suspend() call
> that saves the entire cpu state and allows you to restore it on another
> cpu.
> 
> You muck about with the tick; you disable it before cpu_suspend() and
> re-enable it after on the target cpu. You further reprogram the
> interrupt routing from the old to the new cpu.
> 
> But that appears to be it, no more. 

Exact.

> I suppose the tick is special because its the only per-cpu device?

Right.

> The reported function that fails: bL_switcher_restore_cpus() is called
> in the error paths of the former and the main path in the latter to make
> the 'stolen' cpus re-appear.
> 
> The patch in question somehow makes that go boom.
> 
> 
> Now what all do you need to do to make it go boom? Just enable/disable
> the switcher once and it'll explode? Or does it need to do actual
> switches while it is enabled?

It gets automatically enabled during boot.  Then several switches are 
performed while user space is brought up.  If I manually disable it 
via /sys then it goes boom.

> The place where it explodes is a bit surprising, it thinks hrtimers are
> not enabled even though its calling into hrtimer code on that cpu...
> 
> 
> 
> 

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-23 16:32           ` Nicolas Pitre
@ 2015-02-23 17:33             ` Nicolas Pitre
  2015-02-26  5:31               ` Preeti U Murthy
  0 siblings, 1 reply; 106+ messages in thread
From: Nicolas Pitre @ 2015-02-23 17:33 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx, Preeti U Murthy

On Mon, 23 Feb 2015, Nicolas Pitre wrote:

> On Mon, 23 Feb 2015, Peter Zijlstra wrote:
> 
> > The reported function that fails: bL_switcher_restore_cpus() is called
> > in the error paths of the former and the main path in the latter to make
> > the 'stolen' cpus re-appear.
> > 
> > The patch in question somehow makes that go boom.
> > 
> > 
> > Now what all do you need to do to make it go boom? Just enable/disable
> > the switcher once and it'll explode? Or does it need to do actual
> > switches while it is enabled?
> 
> It gets automatically enabled during boot.  Then several switches are 
> performed while user space is brought up.  If I manually disable it 
> via /sys then it goes boom.

OK. Forget the bL switcher.  I configured it out of my kernel and then 
managed to get the same crash by simply hotplugging out one CPU and 
plugging it back in.

$ echo 0 > /sys/devices/system/cpu/cpu2/online
[CPU2 gone]
$ echo 1 > /sys/devices/system/cpu/cpu2/online
[Boom!]


Nicolas

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

* Re: [PATCH 12/35] clockevents: Provide explicit broadcast control function
  2015-02-16 12:14 ` [PATCH 12/35] clockevents: Provide explicit broadcast control function Peter Zijlstra
@ 2015-02-23 18:08   ` Daniel Lezcano
  2015-02-24  0:38   ` Tony Lindgren
  1 sibling, 0 replies; 106+ messages in thread
From: Daniel Lezcano @ 2015-02-23 18:08 UTC (permalink / raw)
  To: Peter Zijlstra, linux-kernel, mingo, rjw
  Cc: tglx, Tony Lindgren, Fenghua Yu, Len Brown

On 02/16/2015 01:14 PM, Peter Zijlstra wrote:

[ patch is not inlined in my email ].

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

-- 
  <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] 106+ messages in thread

* Re: [PATCH 16/35] cpuidle: Use explicit broadcast control function
  2015-02-16 12:14 ` [PATCH 16/35] cpuidle: Use explicit broadcast control function Peter Zijlstra
@ 2015-02-23 18:11   ` Daniel Lezcano
  0 siblings, 0 replies; 106+ messages in thread
From: Daniel Lezcano @ 2015-02-23 18:11 UTC (permalink / raw)
  To: Peter Zijlstra, linux-kernel, mingo, rjw; +Cc: tglx

On 02/16/2015 01:14 PM, Peter Zijlstra wrote:

[ patch not inline ]

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

-- 
  <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] 106+ messages in thread

* Re: [PATCH 12/35] clockevents: Provide explicit broadcast control function
  2015-02-16 12:14 ` [PATCH 12/35] clockevents: Provide explicit broadcast control function Peter Zijlstra
  2015-02-23 18:08   ` Daniel Lezcano
@ 2015-02-24  0:38   ` Tony Lindgren
  1 sibling, 0 replies; 106+ messages in thread
From: Tony Lindgren @ 2015-02-24  0:38 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, rjw, tglx, Fenghua Yu, Len Brown, Daniel Lezcano

* Peter Zijlstra <peterz@infradead.org> [150216 05:13]:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> clockevents_notify() is a leftover from the early design of the
> clockevents facility. It's really not a notification mechanism, it's a
> multiplex call. We are way better off to have explicit calls instead of this
> monstrosity.
> 
> Split out the broadcast control into a separate function and provide
> inline helpers. Switch clockevents_notify() over. This will go away
> once all callers are converted.
> 
> This also gets rid of the nested locking of clockevents_lock and
> broadcast_lock. The broadcast control functions do not require
> clockevents_lock. Only the managing functions
> (setup/shutdown/suspend/resume of the broadcast device require 
> clockevents_lock.

Seems to still behave for my off-idle PM tests after a quick
try on Peter's timers/core branch. Might be too late, but just
in case it's not:

Tested-by: Tony Lindgren <tony@atomide.com>

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

* Re: [PATCH 18/35] ARM: OMAP: Use explicit broadcast control function
  2015-02-16 12:14 ` [PATCH 18/35] ARM: OMAP: " Peter Zijlstra
@ 2015-02-24  0:40   ` Tony Lindgren
  0 siblings, 0 replies; 106+ messages in thread
From: Tony Lindgren @ 2015-02-24  0:40 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx

* Peter Zijlstra <peterz@infradead.org> [150216 05:13]:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Replace the clockevents_notify() call with an explicit function call.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Tony Lindgren <tony@atomide.com>

This too seems to work just fine:

Tested-by: Tony Lindgren <tony@atomide.com>

> ---
>  arch/arm/mach-omap2/cpuidle44xx.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> Index: linux/arch/arm/mach-omap2/cpuidle44xx.c
> ===================================================================
> --- linux.orig/arch/arm/mach-omap2/cpuidle44xx.c
> +++ linux/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -14,7 +14,7 @@
>  #include <linux/cpuidle.h>
>  #include <linux/cpu_pm.h>
>  #include <linux/export.h>
> -#include <linux/clockchips.h>
> +#include <linux/tick.h>
>  
>  #include <asm/cpuidle.h>
>  #include <asm/proc-fns.h>
> @@ -184,8 +184,7 @@ fail:
>   */
>  static void omap_setup_broadcast_timer(void *arg)
>  {
> -	int cpu = smp_processor_id();
> -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
> +	tick_broadcast_enable();
>  }
>  
>  static struct cpuidle_driver omap4_idle_driver = {
> 
> 

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

* Re: [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function
  2015-02-16 12:14 ` [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function Peter Zijlstra
@ 2015-02-24  0:41   ` Tony Lindgren
  0 siblings, 0 replies; 106+ messages in thread
From: Tony Lindgren @ 2015-02-24  0:41 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, rjw, tglx, Stephen Warren, Thierry Reding,
	Alexandre Courbot, Daniel Lezcano, Rafael J. Wysocki, Fenghua Yu,
	Len Brown

* Peter Zijlstra <peterz@infradead.org> [150216 05:13]:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> clockevents_notify() is a leftover from the early design of the
> clockevents facility. It's really not a notification mechanism, it's a
> multiplex call. We are way better off to have explicit calls instead of this
> monstrosity.
> 
> Split out the broadcast oneshot control into a separate function and
> provide inline helpers. Switch clockevents_notify() over. This will go
> away once all callers are converted.
> 
> This also gets rid of the nested locking of clockevents_lock and
> broadcast_lock. The broadcast oneshot control functions do not require
> clockevents_lock. Only the managing functions
> (setup/shutdown/suspend/resume of the broadcast device require
> clockevents_lock.

Still works for me:

Tested-by: Tony Lindgren <tony@atomide.com>

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

* Re: [PATCH 25/35] ARM: OMAP: Use explicit broadcast oneshot control function
  2015-02-16 12:15 ` [PATCH 25/35] ARM: OMAP: " Peter Zijlstra
@ 2015-02-24  0:41   ` Tony Lindgren
  0 siblings, 0 replies; 106+ messages in thread
From: Tony Lindgren @ 2015-02-24  0:41 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx

* Peter Zijlstra <peterz@infradead.org> [150216 05:13]:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Replace the clockevents_notify() call with an explicit function call.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Tony Lindgren <tony@atomide.com>

Works for me:

Tested-by: Tony Lindgren <tony@atomide.com>

> ---
>  arch/arm/mach-omap2/cpuidle44xx.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> Index: linux/arch/arm/mach-omap2/cpuidle44xx.c
> ===================================================================
> --- linux.orig/arch/arm/mach-omap2/cpuidle44xx.c
> +++ linux/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -84,7 +84,6 @@ static int omap_enter_idle_coupled(struc
>  {
>  	struct idle_statedata *cx = state_ptr + index;
>  	u32 mpuss_can_lose_context = 0;
> -	int cpu_id = smp_processor_id();
>  
>  	/*
>  	 * CPU0 has to wait and stay ON until CPU1 is OFF state.
> @@ -112,7 +111,7 @@ static int omap_enter_idle_coupled(struc
>  	mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
>  				 (cx->mpu_logic_state == PWRDM_POWER_OFF);
>  
> -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
> +	tick_broadcast_enter();
>  
>  	/*
>  	 * Call idle CPU PM enter notifier chain so that
> @@ -169,7 +168,7 @@ static int omap_enter_idle_coupled(struc
>  	if (dev->cpu == 0 && mpuss_can_lose_context)
>  		cpu_cluster_pm_exit();
>  
> -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
> +	tick_broadcast_exit();
>  
>  fail:
>  	cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
> 
> 

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-23 17:33             ` Nicolas Pitre
@ 2015-02-26  5:31               ` Preeti U Murthy
  2015-02-27  8:49                 ` Preeti U Murthy
  0 siblings, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-26  5:31 UTC (permalink / raw)
  To: Nicolas Pitre, Peter Zijlstra; +Cc: linux-kernel, mingo, rjw, tglx

On 02/23/2015 11:03 PM, Nicolas Pitre wrote:
> On Mon, 23 Feb 2015, Nicolas Pitre wrote:
> 
>> On Mon, 23 Feb 2015, Peter Zijlstra wrote:
>>
>>> The reported function that fails: bL_switcher_restore_cpus() is called
>>> in the error paths of the former and the main path in the latter to make
>>> the 'stolen' cpus re-appear.
>>>
>>> The patch in question somehow makes that go boom.
>>>
>>>
>>> Now what all do you need to do to make it go boom? Just enable/disable
>>> the switcher once and it'll explode? Or does it need to do actual
>>> switches while it is enabled?
>>
>> It gets automatically enabled during boot.  Then several switches are 
>> performed while user space is brought up.  If I manually disable it 
>> via /sys then it goes boom.
> 
> OK. Forget the bL switcher.  I configured it out of my kernel and then 
> managed to get the same crash by simply hotplugging out one CPU and 
> plugging it back in.
> 
> $ echo 0 > /sys/devices/system/cpu/cpu2/online
> [CPU2 gone]
> $ echo 1 > /sys/devices/system/cpu/cpu2/online
> [Boom!]
> 
> 
I saw an issue with this patch as well. I tried to do an smt mode switch
on a power machine, i.e varying the number of hyperthreads on an SMT 8
system, and the system hangs. Worse, there are no softlockup
messages/warnings/bug_ons reported. I am digging into this issue.

A couple of points though. Looking at the patch, I see that we are
shutting down tick device of the hotplugged out cpu *much before*
migrating the timers and hrtimers from it. Migration of timers is done
in the CPU_DEAD phase, while we shutdown tick devices in the CPU_DYING
phase. There is quite a bit of a gap here. Earlier we would do both in a
single notification.

Another point is that the tick devices are shutdown before the
hotplugged out cpu actually dies in __cpu_die(). At first look none of
these two points should create any issues. But since we are noticing
problems with this patch, I thought it would be best to put them forth.

But why are tick devices being shutdown that early ? Is there any
specific advantage to this? Taking/handing over tick duties should be
done before __cpu_die(), but shutdown of tick devices should be done
after this phase. This seems more natural, doesn't it?


Regards
Preeti U Murthy

> Nicolas
> 


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-26  5:31               ` Preeti U Murthy
@ 2015-02-27  8:49                 ` Preeti U Murthy
  2015-03-02 14:56                   ` Peter Zijlstra
  0 siblings, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-02-27  8:49 UTC (permalink / raw)
  To: Nicolas Pitre, Peter Zijlstra, tglx
  Cc: linux-kernel, mingo, rjw, Michael Ellerman

On 02/26/2015 11:01 AM, Preeti U Murthy wrote:
> On 02/23/2015 11:03 PM, Nicolas Pitre wrote:
>> On Mon, 23 Feb 2015, Nicolas Pitre wrote:
>>
>>> On Mon, 23 Feb 2015, Peter Zijlstra wrote:
>>>
>>>> The reported function that fails: bL_switcher_restore_cpus() is called
>>>> in the error paths of the former and the main path in the latter to make
>>>> the 'stolen' cpus re-appear.
>>>>
>>>> The patch in question somehow makes that go boom.
>>>>
>>>>
>>>> Now what all do you need to do to make it go boom? Just enable/disable
>>>> the switcher once and it'll explode? Or does it need to do actual
>>>> switches while it is enabled?
>>>
>>> It gets automatically enabled during boot.  Then several switches are 
>>> performed while user space is brought up.  If I manually disable it 
>>> via /sys then it goes boom.
>>
>> OK. Forget the bL switcher.  I configured it out of my kernel and then 
>> managed to get the same crash by simply hotplugging out one CPU and 
>> plugging it back in.
>>
>> $ echo 0 > /sys/devices/system/cpu/cpu2/online
>> [CPU2 gone]
>> $ echo 1 > /sys/devices/system/cpu/cpu2/online
>> [Boom!]
>>
>>
> I saw an issue with this patch as well. I tried to do an smt mode switch
> on a power machine, i.e varying the number of hyperthreads on an SMT 8
> system, and the system hangs. Worse, there are no softlockup
> messages/warnings/bug_ons reported. I am digging into this issue.
> 
> A couple of points though. Looking at the patch, I see that we are
> shutting down tick device of the hotplugged out cpu *much before*
> migrating the timers and hrtimers from it. Migration of timers is done
> in the CPU_DEAD phase, while we shutdown tick devices in the CPU_DYING
> phase. There is quite a bit of a gap here. Earlier we would do both in a
> single notification.
> 
> Another point is that the tick devices are shutdown before the
> hotplugged out cpu actually dies in __cpu_die(). At first look none of
> these two points should create any issues. But since we are noticing
> problems with this patch, I thought it would be best to put them forth.
> 
> But why are tick devices being shutdown that early ? Is there any
> specific advantage to this? Taking/handing over tick duties should be
> done before __cpu_die(), but shutdown of tick devices should be done
> after this phase. This seems more natural, doesn't it?

The problem reported in the changelog of this patch is causing severe
regressions very frequently on our machines for certain usecases. It would
help to put in a fix in place first and then follow that up with these
cleanups.  A fix on the below lines :

---------------------------------------------------------------------

clockevents: Fix cpu down race for hrtimer based broadcasting

---
 include/linux/tick.h         |   10 +++++++---
 kernel/cpu.c                 |    2 ++
 kernel/time/tick-broadcast.c |   19 +++++++++++--------
 3 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/include/linux/tick.h b/include/linux/tick.h
index eda850c..8735776 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -91,14 +91,18 @@ extern void tick_cancel_sched_timer(int cpu);
 static inline void tick_cancel_sched_timer(int cpu) { }
 # endif
 
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+# if defined CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern struct tick_device *tick_get_broadcast_device(void);
 extern struct cpumask *tick_get_broadcast_mask(void);
 
-#  ifdef CONFIG_TICK_ONESHOT
+#  if defined CONFIG_TICK_ONESHOT
 extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
+extern void tick_takeover(int deadcpu);
+# else
+static void tick_takeover(int deadcpu) {}
 #  endif
-
+# else
+static void tick_takeover(int deadcpu) {}
 # endif /* BROADCAST */
 
 # ifdef CONFIG_TICK_ONESHOT
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 1972b16..f9ca351 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -20,6 +20,7 @@
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 #include <linux/lockdep.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 
 #include "smpboot.h"
@@ -411,6 +412,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 	while (!idle_cpu(cpu))
 		cpu_relax();
 
+	tick_takeover(cpu);
 	/* This actually kills the CPU. */
 	__cpu_die(cpu);
 
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 066f0ec..0fd6634 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -669,14 +669,19 @@ static void broadcast_shutdown_local(struct clock_event_device *bc,
 	clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
 }
 
-static void broadcast_move_bc(int deadcpu)
+void tick_takeover(int deadcpu)
 {
-	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+	struct clock_event_device *bc;
+	unsigned long flags;
 
-	if (!bc || !broadcast_needs_cpu(bc, deadcpu))
-		return;
-	/* This moves the broadcast assignment to this cpu */
-	clockevents_program_event(bc, bc->next_event, 1);
+	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
+	bc = tick_broadcast_device.evtdev;
+
+	if (bc && broadcast_needs_cpu(bc, deadcpu)) {
+		/* This moves the broadcast assignment to this cpu */
+		clockevents_program_event(bc, bc->next_event, 1);
+	}
+	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
 /*
@@ -913,8 +918,6 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
 	cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
 	cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
 
-	broadcast_move_bc(cpu);
-
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }

Regards
Preeti U Murthy
 
> 
> 
> Regards
> Preeti U Murthy
> 
>> Nicolas
>>


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-02-27  8:49                 ` Preeti U Murthy
@ 2015-03-02 14:56                   ` Peter Zijlstra
  2015-03-05  4:20                     ` Preeti U Murthy
  2015-03-16  4:52                     ` Preeti U Murthy
  0 siblings, 2 replies; 106+ messages in thread
From: Peter Zijlstra @ 2015-03-02 14:56 UTC (permalink / raw)
  To: Preeti U Murthy
  Cc: Nicolas Pitre, tglx, linux-kernel, mingo, rjw, Michael Ellerman

On Fri, Feb 27, 2015 at 02:19:05PM +0530, Preeti U Murthy wrote:
> The problem reported in the changelog of this patch is causing severe
> regressions very frequently on our machines for certain usecases. It would
> help to put in a fix in place first and then follow that up with these
> cleanups.  A fix on the below lines :

Regression how? Neither Thomas' Changelog, nor yours mention its a
regression.

If its a (recent) Regression you need to have a Fixes tag at the very
least. So when was this broken and by which patch?

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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-03-02 14:56                   ` Peter Zijlstra
@ 2015-03-05  4:20                     ` Preeti U Murthy
  2015-03-29  6:45                       ` Ingo Molnar
  2015-03-16  4:52                     ` Preeti U Murthy
  1 sibling, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-03-05  4:20 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Nicolas Pitre, tglx, linux-kernel, mingo, rjw, Michael Ellerman

On 03/02/2015 08:26 PM, Peter Zijlstra wrote:
> On Fri, Feb 27, 2015 at 02:19:05PM +0530, Preeti U Murthy wrote:
>> The problem reported in the changelog of this patch is causing severe
>> regressions very frequently on our machines for certain usecases. It would
>> help to put in a fix in place first and then follow that up with these
>> cleanups.  A fix on the below lines :
> 
> Regression how? Neither Thomas' Changelog, nor yours mention its a
> regression.
> 
> If its a (recent) Regression you need to have a Fixes tag at the very
> least. So when was this broken and by which patch?
> 

It was found recently when doing a hotplug stress test on POWER, that
the machine hits lockups spewing

NMI watchdog: BUG: soft lockup - CPU#20 stuck for 23s! [swapper/20:0]

or

INFO: rcu_sched detected stalls on CPUs/tasks: { 2 7 8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23 2
4 25 26 27 28 29 30 31} (detected by 6, t=2102 jiffies, g=1617, c=1616,
q=1441)

and many other messages about lockups.

This issue was reported here:
http://linuxppc.10917.n7.nabble.com/offlining-cpus-breakage-td88619.html
and was traced to
commit 7cba160ad789a powernv/cpuidle: Redesign idle states management,
which exposed the loophole in commit 5d1638acb9f6(tick: Introduce
hrtimer based broadcast) and is reported in the changelog of the patch.

Regards
Preeti U Murthy


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-03-02 14:56                   ` Peter Zijlstra
  2015-03-05  4:20                     ` Preeti U Murthy
@ 2015-03-16  4:52                     ` Preeti U Murthy
  2015-03-25  5:32                       ` Preeti U Murthy
  1 sibling, 1 reply; 106+ messages in thread
From: Preeti U Murthy @ 2015-03-16  4:52 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: tglx, linux-kernel, mingo, rjw, Michael Ellerman

Hi Peter, Ingo, Thomas,

Can you please take a look at the conversation on this thread ?
This fix is urgent.

Regards
Preeti U Murthy

On 03/02/2015 08:26 PM, Peter Zijlstra wrote:
> On Fri, Feb 27, 2015 at 02:19:05PM +0530, Preeti U Murthy wrote:
>> The problem reported in the changelog of this patch is causing severe
>> regressions very frequently on our machines for certain usecases. It would
>> help to put in a fix in place first and then follow that up with these
>> cleanups.  A fix on the below lines :
> 
> Regression how? Neither Thomas' Changelog, nor yours mention its a
> regression.
> 
> If its a (recent) Regression you need to have a Fixes tag at the very
> least. So when was this broken and by which patch?
> 


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-03-16  4:52                     ` Preeti U Murthy
@ 2015-03-25  5:32                       ` Preeti U Murthy
  0 siblings, 0 replies; 106+ messages in thread
From: Preeti U Murthy @ 2015-03-25  5:32 UTC (permalink / raw)
  To: Peter Zijlstra, tglx, mingo; +Cc: linux-kernel, rjw, Michael Ellerman

Ping.

On 03/16/2015 10:22 AM, Preeti U Murthy wrote:
> Hi Peter, Ingo, Thomas,
> 
> Can you please take a look at the conversation on this thread ?
> This fix is urgent.
> 
> Regards
> Preeti U Murthy
> 
> On 03/02/2015 08:26 PM, Peter Zijlstra wrote:
>> On Fri, Feb 27, 2015 at 02:19:05PM +0530, Preeti U Murthy wrote:
>>> The problem reported in the changelog of this patch is causing severe
>>> regressions very frequently on our machines for certain usecases. It would
>>> help to put in a fix in place first and then follow that up with these
>>> cleanups.  A fix on the below lines :
>>
>> Regression how? Neither Thomas' Changelog, nor yours mention its a
>> regression.
>>
>> If its a (recent) Regression you need to have a Fixes tag at the very
>> least. So when was this broken and by which patch?
>>


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

* [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume)
  2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
                   ` (35 preceding siblings ...)
  2015-02-16 19:14 ` [PATCH 00/35] Some kernel/time cleanups Rafael J. Wysocki
@ 2015-03-25 12:04 ` Rafael J. Wysocki
  2015-03-25 12:05   ` [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Rafael J. Wysocki
                     ` (10 more replies)
  36 siblings, 11 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:04 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

Hi,

On Monday, February 16, 2015 01:14:35 PM Peter Zijlstra wrote:
> Hi,
> 
> While working with Rafael on the suspend to idle machinery Thomas made these
> cleanups; since one might as well clean code up while you've done the work of
> thinking through it again.
> 
> As it stands there's very little overlap between Rafael's series and this one
> aside from a few trivial fixups. So we'll merge them seperately.

Since some of the original Thomas' patches needed to be rebased on top of the
suspend-to-idle material that went in during the 4.0 merge window, I did
that with the patches related to the suspending/resuming of ticks which
follow.

Thanks,
Rafael


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

* [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
@ 2015-03-25 12:05   ` Rafael J. Wysocki
  2015-04-02 12:28     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:06   ` [PATCH 02/09] tick: Move clocksource related stuff to timekeeping.h Rafael J. Wysocki
                     ` (9 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:05 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

This option was for simpler migration to the clock events code. Most
architectures have been converted and the option has been
disfunctional as a standalone option for quite some time. Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 include/linux/clockchips.h  |    9 +++------
 kernel/time/Kconfig         |    6 ------
 kernel/time/Makefile        |    6 ++----
 kernel/time/clockevents.c   |    3 ---
 kernel/time/tick-internal.h |    4 ++--
 5 files changed, 7 insertions(+), 21 deletions(-)

Index: linux-pm/include/linux/clockchips.h
===================================================================
--- linux-pm.orig/include/linux/clockchips.h
+++ linux-pm/include/linux/clockchips.h
@@ -22,7 +22,7 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #include <linux/clocksource.h>
 #include <linux/cpumask.h>
@@ -194,13 +194,9 @@ static inline int tick_check_broadcast_e
 static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern int clockevents_notify(unsigned long reason, void *arg);
-#else
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
-#endif
 
-#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
 
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
@@ -208,6 +204,7 @@ static inline void clockevents_resume(vo
 static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 
 #endif
 
Index: linux-pm/kernel/time/Kconfig
===================================================================
--- linux-pm.orig/kernel/time/Kconfig
+++ linux-pm/kernel/time/Kconfig
@@ -33,12 +33,6 @@ config ARCH_USES_GETTIMEOFFSET
 config GENERIC_CLOCKEVENTS
 	bool
 
-# Migration helper. Builds, but does not invoke
-config GENERIC_CLOCKEVENTS_BUILD
-	bool
-	default y
-	depends on GENERIC_CLOCKEVENTS
-
 # Architecture can handle broadcast in a driver-agnostic way
 config ARCH_HAS_TICK_BROADCAST
 	bool
Index: linux-pm/kernel/time/Makefile
===================================================================
--- linux-pm.orig/kernel/time/Makefile
+++ linux-pm/kernel/time/Makefile
@@ -2,15 +2,13 @@ obj-y += time.o timer.o hrtimer.o itimer
 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
 
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)		+= clockevents.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o tick-common.o
 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
  obj-y						+= tick-broadcast.o
  obj-$(CONFIG_TICK_ONESHOT)			+= tick-broadcast-hrtimer.o
 endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-sched.o
+obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
 obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
 obj-$(CONFIG_DEBUG_FS)				+= timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)			+= test_udelay.o
Index: linux-pm/kernel/time/clockevents.c
===================================================================
--- linux-pm.orig/kernel/time/clockevents.c
+++ linux-pm/kernel/time/clockevents.c
@@ -541,7 +541,6 @@ void clockevents_resume(void)
 			dev->resume(dev);
 }
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 /**
  * clockevents_notify - notification about relevant events
  * Returns 0 on success, any other value on error
@@ -727,5 +726,3 @@ static int __init clockevents_init_sysfs
 }
 device_initcall(clockevents_init_sysfs);
 #endif /* SYSFS */
-
-#endif /* GENERIC_CLOCK_EVENTS */
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -10,7 +10,7 @@ extern seqlock_t jiffies_lock;
 
 #define CS_NAME_LEN	32
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
 #define TICK_DO_TIMER_BOOT	-2
@@ -166,7 +166,7 @@ static inline int tick_device_is_functio
 
 int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 
-#endif
+#endif /* GENERIC_CLOCKEVENTS */
 
 extern void do_timer(unsigned long ticks);
 extern void update_wall_time(void);


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

* [PATCH 02/09] tick: Move clocksource related stuff to timekeeping.h
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
  2015-03-25 12:05   ` [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Rafael J. Wysocki
@ 2015-03-25 12:06   ` Rafael J. Wysocki
  2015-04-02 12:28     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:06   ` [PATCH 03/09] tick: Simplify tick-internal.h Rafael J. Wysocki
                     ` (8 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:06 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

Move clocksource related stuff to timekeeping.h and remove the
pointless include from ntp.c

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/clocksource.c   |    2 +-
 kernel/time/jiffies.c       |    2 +-
 kernel/time/ntp.c           |    1 -
 kernel/time/tick-internal.h |    6 ------
 kernel/time/timekeeping.h   |    7 +++++++
 5 files changed, 9 insertions(+), 9 deletions(-)

Index: linux-pm/kernel/time/clocksource.c
===================================================================
--- linux-pm.orig/kernel/time/clocksource.c
+++ linux-pm/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 #include "timekeeping_internal.h"
 
 /**
Index: linux-pm/kernel/time/jiffies.c
===================================================================
--- linux-pm.orig/kernel/time/jiffies.c
+++ linux-pm/kernel/time/jiffies.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 
 /* The Jiffies based clocksource is the lowest common
  * denominator clock source which should function on
Index: linux-pm/kernel/time/ntp.c
===================================================================
--- linux-pm.orig/kernel/time/ntp.c
+++ linux-pm/kernel/time/ntp.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 
-#include "tick-internal.h"
 #include "ntp_internal.h"
 
 /*
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -6,10 +6,6 @@
 
 #include "timekeeping.h"
 
-extern seqlock_t jiffies_lock;
-
-#define CS_NAME_LEN	32
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
@@ -168,5 +164,3 @@ int __clockevents_update_freq(struct clo
 
 #endif /* GENERIC_CLOCKEVENTS */
 
-extern void do_timer(unsigned long ticks);
-extern void update_wall_time(void);
Index: linux-pm/kernel/time/timekeeping.h
===================================================================
--- linux-pm.orig/kernel/time/timekeeping.h
+++ linux-pm/kernel/time/timekeeping.h
@@ -19,4 +19,11 @@ extern void timekeeping_clocktai(struct
 extern int timekeeping_suspend(void);
 extern void timekeeping_resume(void);
 
+extern void do_timer(unsigned long ticks);
+extern void update_wall_time(void);
+
+extern seqlock_t jiffies_lock;
+
+#define CS_NAME_LEN	32
+
 #endif


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

* [PATCH 03/09] tick: Simplify tick-internal.h
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
  2015-03-25 12:05   ` [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Rafael J. Wysocki
  2015-03-25 12:06   ` [PATCH 02/09] tick: Move clocksource related stuff to timekeeping.h Rafael J. Wysocki
@ 2015-03-25 12:06   ` Rafael J. Wysocki
  2015-04-02 12:29     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:07   ` [PATCH 04/09] tick: Move core only declarations and functions to core Rafael J. Wysocki
                     ` (7 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:06 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

tick-internal.h is pretty confusing as a lot of the stub inlines are
there several times.

Distangle the maze and make clear functional sections.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/tick-internal.h |  145 ++++++++++++++------------------------------
 1 file changed, 49 insertions(+), 96 deletions(-)

Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -27,13 +27,18 @@ extern bool tick_check_replacement(struc
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 
-extern void clockevents_shutdown(struct clock_event_device *dev);
+/* Check, if the device is functional or a dummy for broadcast */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
 
+extern void clockevents_shutdown(struct clock_event_device *dev);
+extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#endif /* GENERIC_CLOCKEVENTS */
 
-/*
- * NO_HZ / high resolution timer shared code
- */
+/* Oneshot related functions */
 #ifdef CONFIG_TICK_ONESHOT
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
 			       void (*handler)(struct clock_event_device *),
@@ -42,69 +47,19 @@ extern int tick_program_event(ktime_t ex
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_control(unsigned long reason);
-extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_active(void);
-extern void tick_check_oneshot_broadcast_this_cpu(void);
-bool tick_broadcast_oneshot_available(void);
-# else /* BROADCAST */
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
-static inline bool tick_broadcast_oneshot_available(void) { return true; }
-# endif /* !BROADCAST */
-
+static inline bool tick_oneshot_possible(void) { return true; }
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
 			void (*handler)(struct clock_event_device *),
-			ktime_t nextevt)
-{
-	BUG();
-}
-static inline void tick_resume_oneshot(void)
-{
-	BUG();
-}
-static inline int tick_program_event(ktime_t expires, int force)
-{
-	return 0;
-}
+			ktime_t nextevt) { BUG(); }
+static inline void tick_resume_oneshot(void) { BUG(); }
+static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
-{
-	return 0;
-}
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline bool tick_broadcast_oneshot_available(void) { return false; }
+static inline bool tick_oneshot_possible(void) { return false; }
 #endif /* !TICK_ONESHOT */
 
-/* NO_HZ_FULL internal */
-#ifdef CONFIG_NO_HZ_FULL
-extern void tick_nohz_init(void);
-# else
-static inline void tick_nohz_init(void) { }
-#endif
-
-/*
- * Broadcasting support
- */
+/* Broadcasting support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
@@ -114,53 +69,51 @@ extern void tick_shutdown_broadcast(unsi
 extern void tick_suspend_broadcast(void);
 extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
-extern void
-tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
-int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
-
+extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
 #else /* !BROADCAST */
-
-static inline void tick_install_broadcast_device(struct clock_event_device *dev)
-{
-}
-
-static inline int tick_is_broadcast_device(struct clock_event_device *dev)
-{
-	return 0;
-}
-static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
-					     int cpu)
-{
-	return 0;
-}
+static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
+static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline int tick_resume_broadcast(void) { return 0; }
 static inline void tick_broadcast_init(void) { }
-static inline int tick_broadcast_update_freq(struct clock_event_device *dev,
-					     u32 freq) { return -ENODEV; }
+static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 
-/*
- * Set the periodic handler in non broadcast mode
- */
-static inline void tick_set_periodic_handler(struct clock_event_device *dev,
-					     int broadcast)
+/* Set the periodic handler in non broadcast mode */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
 {
 	dev->event_handler = tick_handle_periodic;
 }
 #endif /* !BROADCAST */
 
-/*
- * Check, if the device is functional or a dummy for broadcast
- */
-static inline int tick_device_is_functional(struct clock_event_device *dev)
-{
-	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
-}
-
-int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
-
-#endif /* GENERIC_CLOCKEVENTS */
+/* Functions related to oneshot broadcasting */
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_control(unsigned long reason);
+extern void tick_broadcast_switch_to_oneshot(void);
+extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_active(void);
+extern void tick_check_oneshot_broadcast_this_cpu(void);
+bool tick_broadcast_oneshot_available(void);
+#else /* BROADCAST && ONESHOT */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
+static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
+static inline void tick_broadcast_switch_to_oneshot(void) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
+static inline int tick_broadcast_oneshot_active(void) { return 0; }
+static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
+static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
+#endif /* !BROADCAST && ONESHOT */
 
+/* NO_HZ_FULL internal */
+#ifdef CONFIG_NO_HZ_FULL
+extern void tick_nohz_init(void);
+# else
+static inline void tick_nohz_init(void) { }
+#endif


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

* [PATCH 04/09] tick: Move core only declarations and functions to core
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2015-03-25 12:06   ` [PATCH 03/09] tick: Simplify tick-internal.h Rafael J. Wysocki
@ 2015-03-25 12:07   ` Rafael J. Wysocki
  2015-04-02 12:29     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:08   ` [PATCH 05/09] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Rafael J. Wysocki
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:07 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list, Nicolas Pitre

From: Thomas Gleixner <tglx@linutronix.de>

No point to expose everything to the world. People just believe such
functions can be abused for whatever purposes. Sigh.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nicolas Pitre <nico@linaro.org>
[ rjw: Rebased on top of 4.0-rc5 ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 include/linux/clockchips.h  |   15 +---
 include/linux/tick.h        |  134 +++++---------------------------------------
 kernel/time/clocksource.c   |    2 
 kernel/time/hrtimer.c       |    2 
 kernel/time/tick-internal.h |   15 ++++
 kernel/time/tick-sched.c    |    7 +-
 kernel/time/tick-sched.h    |   64 +++++++++++++++++++++
 kernel/time/timer_list.c    |    2 
 8 files changed, 112 insertions(+), 129 deletions(-)

Index: linux-pm/include/linux/clockchips.h
===================================================================
--- linux-pm.orig/include/linux/clockchips.h
+++ linux-pm/include/linux/clockchips.h
@@ -158,15 +158,6 @@ extern void clockevents_config_and_regis
 
 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
 
-extern void clockevents_exchange_device(struct clock_event_device *old,
-					struct clock_event_device *new);
-extern void clockevents_set_mode(struct clock_event_device *dev,
-				 enum clock_event_mode mode);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
-
-extern void clockevents_handle_noop(struct clock_event_device *dev);
-
 static inline void
 clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 {
@@ -174,6 +165,12 @@ clockevents_calc_mult_shift(struct clock
 				      freq, minsec);
 }
 
+/* Should be core only, but is abused by arm bl_switcher */
+extern void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
+
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
Index: linux-pm/include/linux/tick.h
===================================================================
--- linux-pm.orig/include/linux/tick.h
+++ linux-pm/include/linux/tick.h
@@ -1,7 +1,5 @@
-/*  linux/include/linux/tick.h
- *
- *  This file contains the structure definitions for tick related functions
- *
+/*
+ * Tick related global functions
  */
 #ifndef _LINUX_TICK_H
 #define _LINUX_TICK_H
@@ -9,13 +7,12 @@
 #include <linux/clockchips.h>
 #include <linux/irqflags.h>
 #include <linux/percpu.h>
-#include <linux/hrtimer.h>
 #include <linux/context_tracking_state.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
+/* ARM BL switcher abuse support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-
 enum tick_device_mode {
 	TICKDEV_MODE_PERIODIC,
 	TICKDEV_MODE_ONESHOT,
@@ -25,133 +22,38 @@ struct tick_device {
 	struct clock_event_device *evtdev;
 	enum tick_device_mode mode;
 };
-
-enum tick_nohz_mode {
-	NOHZ_MODE_INACTIVE,
-	NOHZ_MODE_LOWRES,
-	NOHZ_MODE_HIGHRES,
-};
-
-/**
- * struct tick_sched - sched tick emulation and no idle tick control/stats
- * @sched_timer:	hrtimer to schedule the periodic tick in high
- *			resolution mode
- * @last_tick:		Store the last tick expiry time when the tick
- *			timer is modified for nohz sleeps. This is necessary
- *			to resume the tick timer operation in the timeline
- *			when the CPU returns from nohz sleep.
- * @tick_stopped:	Indicator that the idle tick has been stopped
- * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
- * @idle_calls:		Total number of idle calls
- * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
- * @idle_entrytime:	Time when the idle call was entered
- * @idle_waketime:	Time when the idle was interrupted
- * @idle_exittime:	Time when the idle state was left
- * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
- * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
- * @sleep_length:	Duration of the current idle sleep
- * @do_timer_lst:	CPU was the last one doing do_timer before going idle
- */
-struct tick_sched {
-	struct hrtimer			sched_timer;
-	unsigned long			check_clocks;
-	enum tick_nohz_mode		nohz_mode;
-	ktime_t				last_tick;
-	int				inidle;
-	int				tick_stopped;
-	unsigned long			idle_jiffies;
-	unsigned long			idle_calls;
-	unsigned long			idle_sleeps;
-	int				idle_active;
-	ktime_t				idle_entrytime;
-	ktime_t				idle_waketime;
-	ktime_t				idle_exittime;
-	ktime_t				idle_sleeptime;
-	ktime_t				iowait_sleeptime;
-	ktime_t				sleep_length;
-	unsigned long			last_jiffies;
-	unsigned long			next_jiffies;
-	ktime_t				idle_expires;
-	int				do_timer_last;
-};
-
-extern void __init tick_init(void);
-extern int tick_is_oneshot_available(void);
 extern struct tick_device *tick_get_device(int cpu);
+#endif
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+static inline void tick_freeze(void) { }
+static inline void tick_unfreeze(void) { }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-# ifdef CONFIG_HIGH_RES_TIMERS
-extern int tick_init_highres(void);
-extern int tick_program_event(ktime_t expires, int force);
-extern void tick_setup_sched_timer(void);
-# endif
-
-# if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
-extern void tick_cancel_sched_timer(int cpu);
-# else
-static inline void tick_cancel_sched_timer(int cpu) { }
-# endif
-
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern struct tick_device *tick_get_broadcast_device(void);
-extern struct cpumask *tick_get_broadcast_mask(void);
-
-#  ifdef CONFIG_TICK_ONESHOT
-extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
-#  endif
-
-# endif /* BROADCAST */
-
-# ifdef CONFIG_TICK_ONESHOT
-extern void tick_clock_notify(void);
-extern int tick_check_oneshot_change(int allow_nohz);
-extern struct tick_sched *tick_get_tick_sched(int cpu);
+#ifdef CONFIG_TICK_ONESHOT
 extern void tick_irq_enter(void);
-extern int tick_oneshot_mode_active(void);
 #  ifndef arch_needs_cpu
 #   define arch_needs_cpu() (0)
 #  endif
 # else
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-# endif
-
-#else /* CONFIG_GENERIC_CLOCKEVENTS */
-static inline void tick_init(void) { }
-static inline void tick_freeze(void) { }
-static inline void tick_unfreeze(void) { }
-static inline void tick_cancel_sched_timer(int cpu) { }
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
-
-# ifdef CONFIG_NO_HZ_COMMON
-DECLARE_PER_CPU(struct tick_sched, tick_cpu_sched);
-
-static inline int tick_nohz_tick_stopped(void)
-{
-	return __this_cpu_read(tick_cpu_sched.tick_stopped);
-}
+#endif
 
+#ifdef CONFIG_NO_HZ_COMMON
+extern int tick_nohz_tick_stopped(void);
 extern void tick_nohz_idle_enter(void);
 extern void tick_nohz_idle_exit(void);
 extern void tick_nohz_irq_exit(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
-
-# else /* !CONFIG_NO_HZ_COMMON */
-static inline int tick_nohz_tick_stopped(void)
-{
-	return 0;
-}
-
+#else /* !CONFIG_NO_HZ_COMMON */
+static inline int tick_nohz_tick_stopped(void) { return 0; }
 static inline void tick_nohz_idle_enter(void) { }
 static inline void tick_nohz_idle_exit(void) { }
 
@@ -163,7 +65,7 @@ static inline ktime_t tick_nohz_get_slee
 }
 static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
-# endif /* !CONFIG_NO_HZ_COMMON */
+#endif /* !CONFIG_NO_HZ_COMMON */
 
 #ifdef CONFIG_NO_HZ_FULL
 extern bool tick_nohz_full_running;
Index: linux-pm/kernel/time/clocksource.c
===================================================================
--- linux-pm.orig/kernel/time/clocksource.c
+++ linux-pm/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 #include "timekeeping_internal.h"
 
 /**
Index: linux-pm/kernel/time/hrtimer.c
===================================================================
--- linux-pm.orig/kernel/time/hrtimer.c
+++ linux-pm/kernel/time/hrtimer.c
@@ -54,7 +54,7 @@
 
 #include <trace/events/timer.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 
 /*
  * The timer bases:
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -5,6 +5,7 @@
 #include <linux/tick.h>
 
 #include "timekeeping.h"
+#include "tick-sched.h"
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
@@ -26,6 +27,7 @@ extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
+extern int tick_is_oneshot_available(void);
 
 /* Check, if the device is functional or a dummy for broadcast */
 static inline int tick_device_is_functional(struct clock_event_device *dev)
@@ -34,6 +36,9 @@ static inline int tick_device_is_functio
 }
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
+extern void clockevents_exchange_device(struct clock_event_device *old,
+					struct clock_event_device *new);
+extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #endif /* GENERIC_CLOCKEVENTS */
@@ -48,6 +53,10 @@ extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
 static inline bool tick_oneshot_possible(void) { return true; }
+extern int tick_oneshot_mode_active(void);
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern int tick_init_highres(void);
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
@@ -57,6 +66,9 @@ static inline void tick_resume_oneshot(v
 static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
 static inline bool tick_oneshot_possible(void) { return false; }
+static inline int tick_oneshot_mode_active(void) { return 0; }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 #endif /* !TICK_ONESHOT */
 
 /* Broadcasting support */
@@ -71,6 +83,8 @@ extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
+extern struct tick_device *tick_get_broadcast_device(void);
+extern struct cpumask *tick_get_broadcast_mask(void);
 #else /* !BROADCAST */
 static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
 static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
@@ -100,6 +114,7 @@ extern int tick_resume_broadcast_oneshot
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
+extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #else /* BROADCAST && ONESHOT */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
Index: linux-pm/kernel/time/tick-sched.c
===================================================================
--- linux-pm.orig/kernel/time/tick-sched.c
+++ linux-pm/kernel/time/tick-sched.c
@@ -34,7 +34,7 @@
 /*
  * Per cpu nohz control structure
  */
-DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
 
 /*
  * The time, when the last jiffy update happened. Protected by jiffies_lock.
@@ -416,6 +416,11 @@ static int __init setup_tick_nohz(char *
 
 __setup("nohz=", setup_tick_nohz);
 
+int tick_nohz_tick_stopped(void)
+{
+	return __this_cpu_read(tick_cpu_sched.tick_stopped);
+}
+
 /**
  * tick_nohz_update_jiffies - update jiffies when idle was interrupted
  *
Index: linux-pm/kernel/time/tick-sched.h
===================================================================
--- /dev/null
+++ linux-pm/kernel/time/tick-sched.h
@@ -0,0 +1,64 @@
+#ifndef _TICK_SCHED_H
+#define _TICK_SCHED_H
+
+#include <linux/hrtimer.h>
+
+enum tick_nohz_mode {
+	NOHZ_MODE_INACTIVE,
+	NOHZ_MODE_LOWRES,
+	NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:	hrtimer to schedule the periodic tick in high
+ *			resolution mode
+ * @last_tick:		Store the last tick expiry time when the tick
+ *			timer is modified for nohz sleeps. This is necessary
+ *			to resume the tick timer operation in the timeline
+ *			when the CPU returns from nohz sleep.
+ * @tick_stopped:	Indicator that the idle tick has been stopped
+ * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
+ * @idle_calls:		Total number of idle calls
+ * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:	Time when the idle call was entered
+ * @idle_waketime:	Time when the idle was interrupted
+ * @idle_exittime:	Time when the idle state was left
+ * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
+ * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
+ * @sleep_length:	Duration of the current idle sleep
+ * @do_timer_lst:	CPU was the last one doing do_timer before going idle
+ */
+struct tick_sched {
+	struct hrtimer			sched_timer;
+	unsigned long			check_clocks;
+	enum tick_nohz_mode		nohz_mode;
+	ktime_t				last_tick;
+	int				inidle;
+	int				tick_stopped;
+	unsigned long			idle_jiffies;
+	unsigned long			idle_calls;
+	unsigned long			idle_sleeps;
+	int				idle_active;
+	ktime_t				idle_entrytime;
+	ktime_t				idle_waketime;
+	ktime_t				idle_exittime;
+	ktime_t				idle_sleeptime;
+	ktime_t				iowait_sleeptime;
+	ktime_t				sleep_length;
+	unsigned long			last_jiffies;
+	unsigned long			next_jiffies;
+	ktime_t				idle_expires;
+	int				do_timer_last;
+};
+
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+
+extern void tick_setup_sched_timer(void);
+#if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
+extern void tick_cancel_sched_timer(int cpu);
+#else
+static inline void tick_cancel_sched_timer(int cpu) { }
+#endif
+
+#endif
Index: linux-pm/kernel/time/timer_list.c
===================================================================
--- linux-pm.orig/kernel/time/timer_list.c
+++ linux-pm/kernel/time/timer_list.c
@@ -16,10 +16,10 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
-#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 
+#include "tick-internal.h"
 
 struct timer_list_iter {
 	int cpu;


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

* [PATCH 05/09] clockevents: Remove extra local_irq_save in clockevents_exchange_device()
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  2015-03-25 12:07   ` [PATCH 04/09] tick: Move core only declarations and functions to core Rafael J. Wysocki
@ 2015-03-25 12:08   ` Rafael J. Wysocki
  2015-04-02 12:29     ` [tip:timers/core] clockevents: Remove extra local_irq_save() " tip-bot for Thomas Gleixner
  2015-03-25 12:09   ` [PATCH 06/09] clockevents: Make suspend/resume calls explicit Rafael J. Wysocki
                     ` (5 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:08 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

Called with clockevents_lock held and interrupts disabled already.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/clockevents.c |    7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

Index: linux/kernel/time/clockevents.c
===================================================================
--- linux.orig/kernel/time/clockevents.c
+++ linux/kernel/time/clockevents.c
@@ -491,14 +491,12 @@ void clockevents_handle_noop(struct cloc
  * @old:	device to release (can be NULL)
  * @new:	device to request (can be NULL)
  *
- * Called from the notifier chain. clockevents_lock is held already
+ * Called from various tick functions with clockevents_lock held and
+ * interrupts disabled.
  */
 void clockevents_exchange_device(struct clock_event_device *old,
 				 struct clock_event_device *new)
 {
-	unsigned long flags;
-
-	local_irq_save(flags);
 	/*
 	 * Caller releases a clock event device. We queue it into the
 	 * released list and do a notify add later.
@@ -514,7 +512,6 @@ void clockevents_exchange_device(struct
 		BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
 		clockevents_shutdown(new);
 	}
-	local_irq_restore(flags);
 }
 
 /**


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

* [PATCH 06/09] clockevents: Make suspend/resume calls explicit
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  2015-03-25 12:08   ` [PATCH 05/09] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Rafael J. Wysocki
@ 2015-03-25 12:09   ` Rafael J. Wysocki
  2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:09   ` [PATCH 07/09] tick: Make tick_resume_broadcast_oneshot static Rafael J. Wysocki
                     ` (4 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:09 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism, it's a
multiplex call.

We are way better off to have explicit calls instead of this
monstrosity. Split out the suspend/resume() calls and invoke them
directly from the call sites.

No locking required at this point because these calls happen with
interrupts disabled and a single cpu online.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Rebased on top of 4.0-rc5 ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 arch/x86/xen/suspend.c      |   11 ++++-------
 include/linux/clockchips.h  |    2 --
 include/linux/tick.h        |    3 +++
 kernel/time/clockevents.c   |    9 ---------
 kernel/time/tick-common.c   |   26 +++++++++++++++++++++++---
 kernel/time/tick-internal.h |    3 ++-
 kernel/time/timekeeping.c   |    6 ++----
 7 files changed, 34 insertions(+), 26 deletions(-)

Index: linux-pm/arch/x86/xen/suspend.c
===================================================================
--- linux-pm.orig/arch/x86/xen/suspend.c
+++ linux-pm/arch/x86/xen/suspend.c
@@ -1,5 +1,5 @@
 #include <linux/types.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
@@ -81,17 +81,14 @@ void xen_arch_post_suspend(int cancelled
 
 static void xen_vcpu_notify_restore(void *data)
 {
-	unsigned long reason = (unsigned long)data;
-
 	/* Boot processor notified via generic timekeeping_resume() */
-	if ( smp_processor_id() == 0)
+	if (smp_processor_id() == 0)
 		return;
 
-	clockevents_notify(reason, NULL);
+	tick_resume();
 }
 
 void xen_arch_resume(void)
 {
-	on_each_cpu(xen_vcpu_notify_restore,
-		    (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+	on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
 }
Index: linux-pm/include/linux/clockchips.h
===================================================================
--- linux-pm.orig/include/linux/clockchips.h
+++ linux-pm/include/linux/clockchips.h
@@ -16,8 +16,6 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_SUSPEND,
-	CLOCK_EVT_NOTIFY_RESUME,
 	CLOCK_EVT_NOTIFY_CPU_DYING,
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
Index: linux-pm/include/linux/tick.h
===================================================================
--- linux-pm.orig/include/linux/tick.h
+++ linux-pm/include/linux/tick.h
@@ -29,10 +29,13 @@ extern struct tick_device *tick_get_devi
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
+/* Should be core only, but XEN resume magic abuses this interface */
+extern void tick_resume(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
+static inline void tick_resume(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux-pm/kernel/time/clockevents.c
===================================================================
--- linux-pm.orig/kernel/time/clockevents.c
+++ linux-pm/kernel/time/clockevents.c
@@ -566,15 +566,6 @@ int clockevents_notify(unsigned long rea
 		tick_handover_do_timer(arg);
 		break;
 
-	case CLOCK_EVT_NOTIFY_SUSPEND:
-		tick_suspend();
-		tick_suspend_broadcast();
-		break;
-
-	case CLOCK_EVT_NOTIFY_RESUME:
-		tick_resume();
-		break;
-
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
 		tick_shutdown_broadcast_oneshot(arg);
 		tick_shutdown_broadcast(arg);
Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -372,18 +372,39 @@ void tick_shutdown(unsigned int *cpup)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_suspend(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
+	tick_suspend_broadcast();
 }
 
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_resume(void)
 {
-	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
-	int broadcast = tick_resume_broadcast();
+	struct tick_device *td;
+	int broadcast;
 
+	broadcast = tick_resume_broadcast();
+	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
 
 	if (!broadcast) {
@@ -420,7 +441,6 @@ void tick_freeze(void)
 		timekeeping_suspend_count++;
 	} else {
 		tick_suspend();
-		tick_suspend_broadcast();
 	}
 
 	raw_spin_unlock(&tick_freeze_lock);
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -23,7 +23,6 @@ extern void tick_check_new_device(struct
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
-extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -41,6 +40,8 @@ extern void clockevents_exchange_device(
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#else
+static inline void tick_suspend(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
Index: linux-pm/kernel/time/timekeeping.c
===================================================================
--- linux-pm.orig/kernel/time/timekeeping.c
+++ linux-pm/kernel/time/timekeeping.c
@@ -1272,9 +1272,7 @@ void timekeeping_resume(void)
 
 	touch_softlockup_watchdog();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-	/* Resume hrtimers */
+	tick_resume();
 	hrtimers_resume();
 }
 
@@ -1327,7 +1325,7 @@ int timekeeping_suspend(void)
 	write_seqcount_end(&tk_core.seq);
 	raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+	tick_suspend();
 	clocksource_suspend();
 	clockevents_suspend();
 


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

* [PATCH 07/09] tick: Make tick_resume_broadcast_oneshot static
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (5 preceding siblings ...)
  2015-03-25 12:09   ` [PATCH 06/09] clockevents: Make suspend/resume calls explicit Rafael J. Wysocki
@ 2015-03-25 12:09   ` Rafael J. Wysocki
  2015-04-02 12:30     ` [tip:timers/core] tick: Make tick_resume_broadcast_oneshot() static tip-bot for Thomas Gleixner
  2015-03-25 12:11   ` [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local() Rafael J. Wysocki
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:09 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

From: Thomas Gleixner <tglx@linutronix.de>

Solely used in tick-broadcast.c and the return value is hardcoded 0.
Make it static and void.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/tick-broadcast.c |    7 ++++---
 kernel/time/tick-internal.h  |    2 --
 2 files changed, 4 insertions(+), 5 deletions(-)

Index: linux-pm/kernel/time/tick-broadcast.c
===================================================================
--- linux-pm.orig/kernel/time/tick-broadcast.c
+++ linux-pm/kernel/time/tick-broadcast.c
@@ -37,8 +37,10 @@ static int tick_broadcast_force;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 #else
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
+static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
 
 /*
@@ -475,7 +477,7 @@ int tick_resume_broadcast(void)
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
-				broadcast = tick_resume_broadcast_oneshot(bc);
+				tick_resume_broadcast_oneshot(bc);
 			break;
 		}
 	}
@@ -541,10 +543,9 @@ static int tick_broadcast_set_event(stru
 	return ret;
 }
 
-int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
 	clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-	return 0;
 }
 
 /*
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -111,7 +111,6 @@ extern void tick_broadcast_setup_oneshot
 extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
@@ -121,7 +120,6 @@ static inline void tick_broadcast_setup_
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }


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

* [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (6 preceding siblings ...)
  2015-03-25 12:09   ` [PATCH 07/09] tick: Make tick_resume_broadcast_oneshot static Rafael J. Wysocki
@ 2015-03-25 12:11   ` Rafael J. Wysocki
  2015-03-25 20:13     ` Konrad Rzeszutek Wilk
  2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  2015-03-25 12:11   ` [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery Rafael J. Wysocki
                     ` (2 subsequent siblings)
  10 siblings, 2 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:11 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, tglx, Linux PM list, Konrad Rzeszutek Wilk,
	Boris Ostrovsky, David Vrabel

From: Thomas Gleixner <tglx@linutronix.de>

Xen calls on every cpu into tick_resume() which is just wrong.
tick_resume() is for the syscore global suspend/resume invocation.
What XEN really wants is a per cpu local resume function.

Provide a tick_resume_local() function and use it in XEN.

Also provide a complementary tick_suspend_local() and modify
tick_unfreeze() and tick_freeze(), respectively, to use the
new local tick resume/suspend functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
[ rjw: Combined two patches, rebased, modified subject/changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 arch/x86/xen/suspend.c       |    2 -
 include/linux/tick.h         |    6 ++--
 kernel/time/tick-broadcast.c |   24 ++++++++++++------
 kernel/time/tick-common.c    |   57 +++++++++++++++++++++++++++++--------------
 kernel/time/tick-internal.h  |    8 ++++--
 5 files changed, 66 insertions(+), 31 deletions(-)

Index: linux-pm/arch/x86/xen/suspend.c
===================================================================
--- linux-pm.orig/arch/x86/xen/suspend.c
+++ linux-pm/arch/x86/xen/suspend.c
@@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
 	if (smp_processor_id() == 0)
 		return;
 
-	tick_resume();
+	tick_resume_local();
 }
 
 void xen_arch_resume(void)
Index: linux-pm/include/linux/tick.h
===================================================================
--- linux-pm.orig/include/linux/tick.h
+++ linux-pm/include/linux/tick.h
@@ -29,13 +29,13 @@ extern struct tick_device *tick_get_devi
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
-/* Should be core only, but XEN resume magic abuses this interface */
-extern void tick_resume(void);
+/* Should be core only, but XEN resume magic requires this */
+extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
-static inline void tick_resume(void) { }
+static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux-pm/kernel/time/tick-broadcast.c
===================================================================
--- linux-pm.orig/kernel/time/tick-broadcast.c
+++ linux-pm/kernel/time/tick-broadcast.c
@@ -455,11 +455,26 @@ void tick_suspend_broadcast(void)
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
-int tick_resume_broadcast(void)
+/*
+ * This is called from tick_resume_local() on a resuming CPU. That's
+ * called from the core resume function, tick_unfreeze() and the magic XEN
+ * resume hackery.
+ *
+ * In none of these cases the broadcast device mode can change and the
+ * bit of the resuming CPU in the broadcast mask is safe as well.
+ */
+bool tick_resume_check_broadcast(void)
+{
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
+		return false;
+	else
+		return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
+}
+
+void tick_resume_broadcast(void)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
-	int broadcast = 0;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -472,8 +487,6 @@ int tick_resume_broadcast(void)
 		case TICKDEV_MODE_PERIODIC:
 			if (!cpumask_empty(tick_broadcast_mask))
 				tick_broadcast_start_periodic(bc);
-			broadcast = cpumask_test_cpu(smp_processor_id(),
-						     tick_broadcast_mask);
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
@@ -482,11 +495,8 @@ int tick_resume_broadcast(void)
 		}
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-
-	return broadcast;
 }
 
-
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_var_t tick_broadcast_oneshot_mask;
Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -373,40 +373,32 @@ void tick_shutdown(unsigned int *cpup)
 }
 
 /**
- * tick_suspend - Suspend the tick and the broadcast device
+ * tick_suspend_local - Suspend the local tick device
  *
- * Called from syscore_suspend() via timekeeping_suspend with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local cpu for freeze with interrupts disabled.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_suspend(void)
+static void tick_suspend_local(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
-	tick_suspend_broadcast();
 }
 
 /**
- * tick_resume - Resume the tick and the broadcast device
+ * tick_resume_local - Resume the local tick device
  *
- * Called from syscore_resume() via timekeeping_resume with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local CPU for unfreeze or XEN resume magic.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_resume(void)
+void tick_resume_local(void)
 {
-	struct tick_device *td;
-	int broadcast;
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+	bool broadcast = tick_resume_check_broadcast();
 
-	broadcast = tick_resume_broadcast();
-	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
-
 	if (!broadcast) {
 		if (td->mode == TICKDEV_MODE_PERIODIC)
 			tick_setup_periodic(td->evtdev, 0);
@@ -415,6 +407,35 @@ void tick_resume(void)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend(void)
+{
+	tick_suspend_local();
+	tick_suspend_broadcast();
+}
+
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume(void)
+{
+	tick_resume_broadcast();
+	tick_resume_local();
+}
+
 static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
 static unsigned int tick_freeze_depth;
 
@@ -440,7 +461,7 @@ void tick_freeze(void)
 		timekeeping_suspend();
 		timekeeping_suspend_count++;
 	} else {
-		tick_suspend();
+		tick_suspend_local();
 	}
 
 	raw_spin_unlock(&tick_freeze_lock);
@@ -465,7 +486,7 @@ void tick_unfreeze(void)
 			smp_processor_id(), tick_freeze_depth,
 			timekeeping_suspend_count);
 	} else {
-		tick_resume();
+		tick_resume_local();
 	}
 	tick_freeze_depth--;
 
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -23,6 +23,7 @@ extern void tick_check_new_device(struct
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
+extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -42,6 +43,7 @@ extern int __clockevents_update_freq(str
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #else
 static inline void tick_suspend(void) { }
+static inline void tick_resume(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
@@ -80,7 +82,8 @@ extern int tick_is_broadcast_device(stru
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
-extern int tick_resume_broadcast(void);
+extern void tick_resume_broadcast(void);
+extern bool tick_resume_check_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
@@ -94,7 +97,8 @@ static inline void tick_do_periodic_broa
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
-static inline int tick_resume_broadcast(void) { return 0; }
+static inline void tick_resume_broadcast(void) { }
+static inline bool tick_resume_check_broadcast(void) { return false; }
 static inline void tick_broadcast_init(void) { }
 static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 


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

* [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (7 preceding siblings ...)
  2015-03-25 12:11   ` [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local() Rafael J. Wysocki
@ 2015-03-25 12:11   ` Rafael J. Wysocki
  2015-03-25 12:34     ` Nicolas Pitre
  2015-04-02 12:30     ` [tip:timers/core] arm/bL_switcher: " tip-bot for Thomas Gleixner
  2015-03-25 12:13   ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
  2015-03-31 22:45   ` [GIT PULL] kernel/time cleanups (related to tick_suspend/resume) Rafael J. Wysocki
  10 siblings, 2 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:11 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, mingo, tglx, Linux PM list, Nicolas Pitre, Russell King

From: Thomas Gleixner <tglx@linutronix.de>

Use the new tick_suspend/resume_local() and get rid of the homebrewn
implementation of these in the ARM bL switcher.  The check for the
cpumask is completely pointless.  There is no harm to suspend a per
cpu tick device unconditionally.  If that's a real issue then we fix
it proper at the core level and not with some completely undocumented
hacks in some random core code.

Move the tick internals to the core code, now that this nuisance is
gone.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
[ rjw: Rebase, changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 arch/arm/common/bL_switcher.c |   16 ++--------------
 include/linux/clockchips.h    |    6 ------
 include/linux/tick.h          |   19 ++++---------------
 kernel/time/tick-common.c     |    2 +-
 kernel/time/tick-internal.h   |    5 +++++
 kernel/time/tick-sched.h      |   10 ++++++++++
 6 files changed, 22 insertions(+), 36 deletions(-)

Index: linux-pm/include/linux/tick.h
===================================================================
--- linux-pm.orig/include/linux/tick.h
+++ linux-pm/include/linux/tick.h
@@ -11,30 +11,19 @@
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
-/* ARM BL switcher abuse support */
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-enum tick_device_mode {
-	TICKDEV_MODE_PERIODIC,
-	TICKDEV_MODE_ONESHOT,
-};
-
-struct tick_device {
-	struct clock_event_device *evtdev;
-	enum tick_device_mode mode;
-};
-extern struct tick_device *tick_get_device(int cpu);
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
-/* Should be core only, but XEN resume magic requires this */
+/* Should be core only, but ARM BL switcher requires it */
+extern void tick_suspend_local(void);
+/* Should be core only, but XEN resume magic and ARM BL switcher require it */
 extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
+static inline void tick_suspend_local(void) { }
 static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
Index: linux-pm/arch/arm/common/bL_switcher.c
===================================================================
--- linux-pm.orig/arch/arm/common/bL_switcher.c
+++ linux-pm/arch/arm/common/bL_switcher.c
@@ -151,8 +151,6 @@ static int bL_switch_to(unsigned int new
 	unsigned int mpidr, this_cpu, that_cpu;
 	unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
 	struct completion inbound_alive;
-	struct tick_device *tdev;
-	enum clock_event_mode tdev_mode;
 	long volatile *handshake_ptr;
 	int ipi_nr, ret;
 
@@ -219,13 +217,7 @@ static int bL_switch_to(unsigned int new
 	/* redirect GIC's SGIs to our counterpart */
 	gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
 
-	tdev = tick_get_device(this_cpu);
-	if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
-		tdev = NULL;
-	if (tdev) {
-		tdev_mode = tdev->evtdev->mode;
-		clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
-	}
+	tick_suspend_local();
 
 	ret = cpu_pm_enter();
 
@@ -251,11 +243,7 @@ static int bL_switch_to(unsigned int new
 
 	ret = cpu_pm_exit();
 
-	if (tdev) {
-		clockevents_set_mode(tdev->evtdev, tdev_mode);
-		clockevents_program_event(tdev->evtdev,
-					  tdev->evtdev->next_event, 1);
-	}
+	tick_resume_local();
 
 	trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
 	local_fiq_enable();
Index: linux-pm/include/linux/clockchips.h
===================================================================
--- linux-pm.orig/include/linux/clockchips.h
+++ linux-pm/include/linux/clockchips.h
@@ -163,12 +163,6 @@ clockevents_calc_mult_shift(struct clock
 				      freq, minsec);
 }
 
-/* Should be core only, but is abused by arm bl_switcher */
-extern void clockevents_set_mode(struct clock_event_device *dev,
-				 enum clock_event_mode mode);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
-
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -28,6 +28,7 @@ extern bool tick_check_replacement(struc
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
 
 /* Check, if the device is functional or a dummy for broadcast */
 static inline int tick_device_is_functional(struct clock_event_device *dev)
@@ -38,6 +39,10 @@ static inline int tick_device_is_functio
 extern void clockevents_shutdown(struct clock_event_device *dev);
 extern void clockevents_exchange_device(struct clock_event_device *old,
 					struct clock_event_device *new);
+extern void clockevents_set_mode(struct clock_event_device *dev,
+				 enum clock_event_mode mode);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
Index: linux-pm/kernel/time/tick-sched.h
===================================================================
--- linux-pm.orig/kernel/time/tick-sched.h
+++ linux-pm/kernel/time/tick-sched.h
@@ -3,6 +3,16 @@
 
 #include <linux/hrtimer.h>
 
+enum tick_device_mode {
+	TICKDEV_MODE_PERIODIC,
+	TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+	struct clock_event_device *evtdev;
+	enum tick_device_mode mode;
+};
+
 enum tick_nohz_mode {
 	NOHZ_MODE_INACTIVE,
 	NOHZ_MODE_LOWRES,
Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -379,7 +379,7 @@ void tick_shutdown(unsigned int *cpup)
  *
  * No locks required. Nothing can change the per cpu device.
  */
-static void tick_suspend_local(void)
+void tick_suspend_local(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 


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

* Re: [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume)
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (8 preceding siblings ...)
  2015-03-25 12:11   ` [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery Rafael J. Wysocki
@ 2015-03-25 12:13   ` Rafael J. Wysocki
  2015-03-31 22:45   ` [GIT PULL] kernel/time cleanups (related to tick_suspend/resume) Rafael J. Wysocki
  10 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 12:13 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, mingo, tglx, Linux PM list

On Wednesday, March 25, 2015 01:04:23 PM Rafael J. Wysocki wrote:
> Hi,
> 
> On Monday, February 16, 2015 01:14:35 PM Peter Zijlstra wrote:
> > Hi,
> > 
> > While working with Rafael on the suspend to idle machinery Thomas made these
> > cleanups; since one might as well clean code up while you've done the work of
> > thinking through it again.
> > 
> > As it stands there's very little overlap between Rafael's series and this one
> > aside from a few trivial fixups. So we'll merge them seperately.
> 
> Since some of the original Thomas' patches needed to be rebased on top of the
> suspend-to-idle material that went in during the 4.0 merge window, I did
> that with the patches related to the suspending/resuming of ticks which
> follow.

I forgot to mention that I'd tested these vs suspend-to-idle and suspend-to-RAM
on a couple of different systems and they don't seem to break anything for me.

Also I have a plan to make the compilation of some PM-related stuff conditional
on CONFIG_PM_SLEEP etc. on top of these.

Rafael


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

* Re: [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery
  2015-03-25 12:11   ` [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery Rafael J. Wysocki
@ 2015-03-25 12:34     ` Nicolas Pitre
  2015-04-02 12:30     ` [tip:timers/core] arm/bL_switcher: " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 106+ messages in thread
From: Nicolas Pitre @ 2015-03-25 12:34 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Peter Zijlstra, linux-kernel, mingo, tglx, Linux PM list, Russell King

On Wed, 25 Mar 2015, Rafael J. Wysocki wrote:

> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Use the new tick_suspend/resume_local() and get rid of the homebrewn
> implementation of these in the ARM bL switcher.  The check for the
> cpumask is completely pointless.  There is no harm to suspend a per
> cpu tick device unconditionally.  If that's a real issue then we fix
> it proper at the core level and not with some completely undocumented
> hacks in some random core code.
> 
> Move the tick internals to the core code, now that this nuisance is
> gone.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> [ rjw: Rebase, changelog ]
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>

> ---
>  arch/arm/common/bL_switcher.c |   16 ++--------------
>  include/linux/clockchips.h    |    6 ------
>  include/linux/tick.h          |   19 ++++---------------
>  kernel/time/tick-common.c     |    2 +-
>  kernel/time/tick-internal.h   |    5 +++++
>  kernel/time/tick-sched.h      |   10 ++++++++++
>  6 files changed, 22 insertions(+), 36 deletions(-)
> 
> Index: linux-pm/include/linux/tick.h
> ===================================================================
> --- linux-pm.orig/include/linux/tick.h
> +++ linux-pm/include/linux/tick.h
> @@ -11,30 +11,19 @@
>  #include <linux/cpumask.h>
>  #include <linux/sched.h>
>  
> -/* ARM BL switcher abuse support */
> -#ifdef CONFIG_GENERIC_CLOCKEVENTS
> -enum tick_device_mode {
> -	TICKDEV_MODE_PERIODIC,
> -	TICKDEV_MODE_ONESHOT,
> -};
> -
> -struct tick_device {
> -	struct clock_event_device *evtdev;
> -	enum tick_device_mode mode;
> -};
> -extern struct tick_device *tick_get_device(int cpu);
> -#endif
> -
>  #ifdef CONFIG_GENERIC_CLOCKEVENTS
>  extern void __init tick_init(void);
>  extern void tick_freeze(void);
>  extern void tick_unfreeze(void);
> -/* Should be core only, but XEN resume magic requires this */
> +/* Should be core only, but ARM BL switcher requires it */
> +extern void tick_suspend_local(void);
> +/* Should be core only, but XEN resume magic and ARM BL switcher require it */
>  extern void tick_resume_local(void);
>  #else /* CONFIG_GENERIC_CLOCKEVENTS */
>  static inline void tick_init(void) { }
>  static inline void tick_freeze(void) { }
>  static inline void tick_unfreeze(void) { }
> +static inline void tick_suspend_local(void) { }
>  static inline void tick_resume_local(void) { }
>  #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
>  
> Index: linux-pm/arch/arm/common/bL_switcher.c
> ===================================================================
> --- linux-pm.orig/arch/arm/common/bL_switcher.c
> +++ linux-pm/arch/arm/common/bL_switcher.c
> @@ -151,8 +151,6 @@ static int bL_switch_to(unsigned int new
>  	unsigned int mpidr, this_cpu, that_cpu;
>  	unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
>  	struct completion inbound_alive;
> -	struct tick_device *tdev;
> -	enum clock_event_mode tdev_mode;
>  	long volatile *handshake_ptr;
>  	int ipi_nr, ret;
>  
> @@ -219,13 +217,7 @@ static int bL_switch_to(unsigned int new
>  	/* redirect GIC's SGIs to our counterpart */
>  	gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
>  
> -	tdev = tick_get_device(this_cpu);
> -	if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
> -		tdev = NULL;
> -	if (tdev) {
> -		tdev_mode = tdev->evtdev->mode;
> -		clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
> -	}
> +	tick_suspend_local();
>  
>  	ret = cpu_pm_enter();
>  
> @@ -251,11 +243,7 @@ static int bL_switch_to(unsigned int new
>  
>  	ret = cpu_pm_exit();
>  
> -	if (tdev) {
> -		clockevents_set_mode(tdev->evtdev, tdev_mode);
> -		clockevents_program_event(tdev->evtdev,
> -					  tdev->evtdev->next_event, 1);
> -	}
> +	tick_resume_local();
>  
>  	trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
>  	local_fiq_enable();
> Index: linux-pm/include/linux/clockchips.h
> ===================================================================
> --- linux-pm.orig/include/linux/clockchips.h
> +++ linux-pm/include/linux/clockchips.h
> @@ -163,12 +163,6 @@ clockevents_calc_mult_shift(struct clock
>  				      freq, minsec);
>  }
>  
> -/* Should be core only, but is abused by arm bl_switcher */
> -extern void clockevents_set_mode(struct clock_event_device *dev,
> -				 enum clock_event_mode mode);
> -extern int clockevents_program_event(struct clock_event_device *dev,
> -				     ktime_t expires, bool force);
> -
>  extern void clockevents_suspend(void);
>  extern void clockevents_resume(void);
>  
> Index: linux-pm/kernel/time/tick-internal.h
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-internal.h
> +++ linux-pm/kernel/time/tick-internal.h
> @@ -28,6 +28,7 @@ extern bool tick_check_replacement(struc
>  				   struct clock_event_device *newdev);
>  extern void tick_install_replacement(struct clock_event_device *dev);
>  extern int tick_is_oneshot_available(void);
> +extern struct tick_device *tick_get_device(int cpu);
>  
>  /* Check, if the device is functional or a dummy for broadcast */
>  static inline int tick_device_is_functional(struct clock_event_device *dev)
> @@ -38,6 +39,10 @@ static inline int tick_device_is_functio
>  extern void clockevents_shutdown(struct clock_event_device *dev);
>  extern void clockevents_exchange_device(struct clock_event_device *old,
>  					struct clock_event_device *new);
> +extern void clockevents_set_mode(struct clock_event_device *dev,
> +				 enum clock_event_mode mode);
> +extern int clockevents_program_event(struct clock_event_device *dev,
> +				     ktime_t expires, bool force);
>  extern void clockevents_handle_noop(struct clock_event_device *dev);
>  extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
>  extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
> Index: linux-pm/kernel/time/tick-sched.h
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-sched.h
> +++ linux-pm/kernel/time/tick-sched.h
> @@ -3,6 +3,16 @@
>  
>  #include <linux/hrtimer.h>
>  
> +enum tick_device_mode {
> +	TICKDEV_MODE_PERIODIC,
> +	TICKDEV_MODE_ONESHOT,
> +};
> +
> +struct tick_device {
> +	struct clock_event_device *evtdev;
> +	enum tick_device_mode mode;
> +};
> +
>  enum tick_nohz_mode {
>  	NOHZ_MODE_INACTIVE,
>  	NOHZ_MODE_LOWRES,
> Index: linux-pm/kernel/time/tick-common.c
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-common.c
> +++ linux-pm/kernel/time/tick-common.c
> @@ -379,7 +379,7 @@ void tick_shutdown(unsigned int *cpup)
>   *
>   * No locks required. Nothing can change the per cpu device.
>   */
> -static void tick_suspend_local(void)
> +void tick_suspend_local(void)
>  {
>  	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
>  
> 
> 

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

* Re: [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 12:11   ` [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local() Rafael J. Wysocki
@ 2015-03-25 20:13     ` Konrad Rzeszutek Wilk
  2015-03-25 20:57       ` Rafael J. Wysocki
  2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
  1 sibling, 1 reply; 106+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-03-25 20:13 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Peter Zijlstra, linux-kernel, mingo, tglx, Linux PM list,
	Boris Ostrovsky, David Vrabel

On Wed, Mar 25, 2015 at 01:11:04PM +0100, Rafael J. Wysocki wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Xen calls on every cpu into tick_resume() which is just wrong.
> tick_resume() is for the syscore global suspend/resume invocation.
> What XEN really wants is a per cpu local resume function.
> 
> Provide a tick_resume_local() function and use it in XEN.
> 
> Also provide a complementary tick_suspend_local() and modify
> tick_unfreeze() and tick_freeze(), respectively, to use the
> new local tick resume/suspend functions.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> Cc: David Vrabel <david.vrabel@citrix.com>
> [ rjw: Combined two patches, rebased, modified subject/changelog ]
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  arch/x86/xen/suspend.c       |    2 -
>  include/linux/tick.h         |    6 ++--
>  kernel/time/tick-broadcast.c |   24 ++++++++++++------
>  kernel/time/tick-common.c    |   57 +++++++++++++++++++++++++++++--------------
>  kernel/time/tick-internal.h  |    8 ++++--
>  5 files changed, 66 insertions(+), 31 deletions(-)
> 
> Index: linux-pm/arch/x86/xen/suspend.c
> ===================================================================
> --- linux-pm.orig/arch/x86/xen/suspend.c
> +++ linux-pm/arch/x86/xen/suspend.c
> @@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
>  	if (smp_processor_id() == 0)
>  		return;
>  
> -	tick_resume();
> +	tick_resume_local();

I am looking at Linus's tree and I see:

82 static void xen_vcpu_notify_restore(void *data)                                 
 83 {                                                                               
 84         unsigned long reason = (unsigned long)data;                             
 85                                                                                 
 86         /* Boot processor notified via generic timekeeping_resume() */          
 87         if ( smp_processor_id() == 0)                                           
 88                 return;                                                         
 89                                                                                 
 90         clockevents_notify(reason, NULL);                                       
 91 }                             

So there must be another patch that altered the clockevents_notify?

Is there an git tree with all of these patches?

>  }
>  
>  void xen_arch_resume(void)
> Index: linux-pm/include/linux/tick.h
> ===================================================================
> --- linux-pm.orig/include/linux/tick.h
> +++ linux-pm/include/linux/tick.h
> @@ -29,13 +29,13 @@ extern struct tick_device *tick_get_devi
>  extern void __init tick_init(void);
>  extern void tick_freeze(void);
>  extern void tick_unfreeze(void);
> -/* Should be core only, but XEN resume magic abuses this interface */
> -extern void tick_resume(void);
> +/* Should be core only, but XEN resume magic requires this */
> +extern void tick_resume_local(void);
>  #else /* CONFIG_GENERIC_CLOCKEVENTS */
>  static inline void tick_init(void) { }
>  static inline void tick_freeze(void) { }
>  static inline void tick_unfreeze(void) { }
> -static inline void tick_resume(void) { }
> +static inline void tick_resume_local(void) { }
>  #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
>  
>  #ifdef CONFIG_TICK_ONESHOT
> Index: linux-pm/kernel/time/tick-broadcast.c
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-broadcast.c
> +++ linux-pm/kernel/time/tick-broadcast.c
> @@ -455,11 +455,26 @@ void tick_suspend_broadcast(void)
>  	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
>  }
>  
> -int tick_resume_broadcast(void)
> +/*
> + * This is called from tick_resume_local() on a resuming CPU. That's
> + * called from the core resume function, tick_unfreeze() and the magic XEN
> + * resume hackery.
> + *
> + * In none of these cases the broadcast device mode can change and the
> + * bit of the resuming CPU in the broadcast mask is safe as well.
> + */
> +bool tick_resume_check_broadcast(void)
> +{
> +	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
> +		return false;
> +	else
> +		return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
> +}
> +
> +void tick_resume_broadcast(void)
>  {
>  	struct clock_event_device *bc;
>  	unsigned long flags;
> -	int broadcast = 0;
>  
>  	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
>  
> @@ -472,8 +487,6 @@ int tick_resume_broadcast(void)
>  		case TICKDEV_MODE_PERIODIC:
>  			if (!cpumask_empty(tick_broadcast_mask))
>  				tick_broadcast_start_periodic(bc);
> -			broadcast = cpumask_test_cpu(smp_processor_id(),
> -						     tick_broadcast_mask);
>  			break;
>  		case TICKDEV_MODE_ONESHOT:
>  			if (!cpumask_empty(tick_broadcast_mask))
> @@ -482,11 +495,8 @@ int tick_resume_broadcast(void)
>  		}
>  	}
>  	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
> -
> -	return broadcast;
>  }
>  
> -
>  #ifdef CONFIG_TICK_ONESHOT
>  
>  static cpumask_var_t tick_broadcast_oneshot_mask;
> Index: linux-pm/kernel/time/tick-common.c
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-common.c
> +++ linux-pm/kernel/time/tick-common.c
> @@ -373,40 +373,32 @@ void tick_shutdown(unsigned int *cpup)
>  }
>  
>  /**
> - * tick_suspend - Suspend the tick and the broadcast device
> + * tick_suspend_local - Suspend the local tick device
>   *
> - * Called from syscore_suspend() via timekeeping_suspend with only one
> - * CPU online and interrupts disabled or from tick_unfreeze() under
> - * tick_freeze_lock.
> + * Called from the local cpu for freeze with interrupts disabled.
>   *
>   * No locks required. Nothing can change the per cpu device.
>   */
> -void tick_suspend(void)
> +static void tick_suspend_local(void)
>  {
>  	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
>  
>  	clockevents_shutdown(td->evtdev);
> -	tick_suspend_broadcast();
>  }
>  
>  /**
> - * tick_resume - Resume the tick and the broadcast device
> + * tick_resume_local - Resume the local tick device
>   *
> - * Called from syscore_resume() via timekeeping_resume with only one
> - * CPU online and interrupts disabled or from tick_unfreeze() under
> - * tick_freeze_lock.
> + * Called from the local CPU for unfreeze or XEN resume magic.
>   *
>   * No locks required. Nothing can change the per cpu device.
>   */
> -void tick_resume(void)
> +void tick_resume_local(void)
>  {
> -	struct tick_device *td;
> -	int broadcast;
> +	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
> +	bool broadcast = tick_resume_check_broadcast();
>  
> -	broadcast = tick_resume_broadcast();
> -	td = this_cpu_ptr(&tick_cpu_device);
>  	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
> -
>  	if (!broadcast) {
>  		if (td->mode == TICKDEV_MODE_PERIODIC)
>  			tick_setup_periodic(td->evtdev, 0);
> @@ -415,6 +407,35 @@ void tick_resume(void)
>  	}
>  }
>  
> +/**
> + * tick_suspend - Suspend the tick and the broadcast device
> + *
> + * Called from syscore_suspend() via timekeeping_suspend with only one
> + * CPU online and interrupts disabled or from tick_unfreeze() under
> + * tick_freeze_lock.
> + *
> + * No locks required. Nothing can change the per cpu device.
> + */
> +void tick_suspend(void)
> +{
> +	tick_suspend_local();
> +	tick_suspend_broadcast();
> +}
> +
> +/**
> + * tick_resume - Resume the tick and the broadcast device
> + *
> + * Called from syscore_resume() via timekeeping_resume with only one
> + * CPU online and interrupts disabled.
> + *
> + * No locks required. Nothing can change the per cpu device.
> + */
> +void tick_resume(void)
> +{
> +	tick_resume_broadcast();
> +	tick_resume_local();
> +}
> +
>  static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
>  static unsigned int tick_freeze_depth;
>  
> @@ -440,7 +461,7 @@ void tick_freeze(void)
>  		timekeeping_suspend();
>  		timekeeping_suspend_count++;
>  	} else {
> -		tick_suspend();
> +		tick_suspend_local();
>  	}
>  
>  	raw_spin_unlock(&tick_freeze_lock);
> @@ -465,7 +486,7 @@ void tick_unfreeze(void)
>  			smp_processor_id(), tick_freeze_depth,
>  			timekeeping_suspend_count);
>  	} else {
> -		tick_resume();
> +		tick_resume_local();
>  	}
>  	tick_freeze_depth--;
>  
> Index: linux-pm/kernel/time/tick-internal.h
> ===================================================================
> --- linux-pm.orig/kernel/time/tick-internal.h
> +++ linux-pm/kernel/time/tick-internal.h
> @@ -23,6 +23,7 @@ extern void tick_check_new_device(struct
>  extern void tick_handover_do_timer(int *cpup);
>  extern void tick_shutdown(unsigned int *cpup);
>  extern void tick_suspend(void);
> +extern void tick_resume(void);
>  extern bool tick_check_replacement(struct clock_event_device *curdev,
>  				   struct clock_event_device *newdev);
>  extern void tick_install_replacement(struct clock_event_device *dev);
> @@ -42,6 +43,7 @@ extern int __clockevents_update_freq(str
>  extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
>  #else
>  static inline void tick_suspend(void) { }
> +static inline void tick_resume(void) { }
>  #endif /* GENERIC_CLOCKEVENTS */
>  
>  /* Oneshot related functions */
> @@ -80,7 +82,8 @@ extern int tick_is_broadcast_device(stru
>  extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
>  extern void tick_shutdown_broadcast(unsigned int *cpup);
>  extern void tick_suspend_broadcast(void);
> -extern int tick_resume_broadcast(void);
> +extern void tick_resume_broadcast(void);
> +extern bool tick_resume_check_broadcast(void);
>  extern void tick_broadcast_init(void);
>  extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
>  extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
> @@ -94,7 +97,8 @@ static inline void tick_do_periodic_broa
>  static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
>  static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
>  static inline void tick_suspend_broadcast(void) { }
> -static inline int tick_resume_broadcast(void) { return 0; }
> +static inline void tick_resume_broadcast(void) { }
> +static inline bool tick_resume_check_broadcast(void) { return false; }
>  static inline void tick_broadcast_init(void) { }
>  static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
>  
> 

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

* Re: [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 20:57       ` Rafael J. Wysocki
@ 2015-03-25 20:44         ` Konrad Rzeszutek Wilk
  2015-03-25 21:36           ` Rafael J. Wysocki
  0 siblings, 1 reply; 106+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-03-25 20:44 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Peter Zijlstra, linux-kernel, mingo, tglx, Linux PM list,
	Boris Ostrovsky, David Vrabel

On Wed, Mar 25, 2015 at 09:57:18PM +0100, Rafael J. Wysocki wrote:
> On Wednesday, March 25, 2015 04:13:09 PM Konrad Rzeszutek Wilk wrote:
> > On Wed, Mar 25, 2015 at 01:11:04PM +0100, Rafael J. Wysocki wrote:
> > > From: Thomas Gleixner <tglx@linutronix.de>
> > > 
> > > Xen calls on every cpu into tick_resume() which is just wrong.
> > > tick_resume() is for the syscore global suspend/resume invocation.
> > > What XEN really wants is a per cpu local resume function.
> > > 
> > > Provide a tick_resume_local() function and use it in XEN.
> > > 
> > > Also provide a complementary tick_suspend_local() and modify
> > > tick_unfreeze() and tick_freeze(), respectively, to use the
> > > new local tick resume/suspend functions.
> > > 
> > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > > Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > > Cc: David Vrabel <david.vrabel@citrix.com>
> > > [ rjw: Combined two patches, rebased, modified subject/changelog ]
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >  arch/x86/xen/suspend.c       |    2 -
> > >  include/linux/tick.h         |    6 ++--
> > >  kernel/time/tick-broadcast.c |   24 ++++++++++++------
> > >  kernel/time/tick-common.c    |   57 +++++++++++++++++++++++++++++--------------
> > >  kernel/time/tick-internal.h  |    8 ++++--
> > >  5 files changed, 66 insertions(+), 31 deletions(-)
> > > 
> > > Index: linux-pm/arch/x86/xen/suspend.c
> > > ===================================================================
> > > --- linux-pm.orig/arch/x86/xen/suspend.c
> > > +++ linux-pm/arch/x86/xen/suspend.c
> > > @@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
> > >  	if (smp_processor_id() == 0)
> > >  		return;
> > >  
> > > -	tick_resume();
> > > +	tick_resume_local();
> > 
> > I am looking at Linus's tree and I see:
> > 
> > 82 static void xen_vcpu_notify_restore(void *data)                                 
> >  83 {                                                                               
> >  84         unsigned long reason = (unsigned long)data;                             
> >  85                                                                                 
> >  86         /* Boot processor notified via generic timekeeping_resume() */          
> >  87         if ( smp_processor_id() == 0)                                           
> >  88                 return;                                                         
> >  89                                                                                 
> >  90         clockevents_notify(reason, NULL);                                       
> >  91 }                             
> > 
> > So there must be another patch that altered the clockevents_notify?
> 
> Yes, there is.  It is the [06/09] in this series
> (https://patchwork.kernel.org/patch/6090631/).
> 
> I should have CCed it to you too, sorry about that.

That is alright.
> 
> > Is there an git tree with all of these patches?
> 
> Not yet, but they all are in the linux-pm patchwork at
> 
> https://patchwork.kernel.org/project/linux-pm/list/
> 
> I can create a branch in the linux-pm.git tree for them if that helps,
> please let me know.

If it is not too much trouble.. 

Thank you.
> 
> 
> -- 
> I speak only for myself.
> Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 20:13     ` Konrad Rzeszutek Wilk
@ 2015-03-25 20:57       ` Rafael J. Wysocki
  2015-03-25 20:44         ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 20:57 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Peter Zijlstra, linux-kernel, mingo, tglx, Linux PM list,
	Boris Ostrovsky, David Vrabel

On Wednesday, March 25, 2015 04:13:09 PM Konrad Rzeszutek Wilk wrote:
> On Wed, Mar 25, 2015 at 01:11:04PM +0100, Rafael J. Wysocki wrote:
> > From: Thomas Gleixner <tglx@linutronix.de>
> > 
> > Xen calls on every cpu into tick_resume() which is just wrong.
> > tick_resume() is for the syscore global suspend/resume invocation.
> > What XEN really wants is a per cpu local resume function.
> > 
> > Provide a tick_resume_local() function and use it in XEN.
> > 
> > Also provide a complementary tick_suspend_local() and modify
> > tick_unfreeze() and tick_freeze(), respectively, to use the
> > new local tick resume/suspend functions.
> > 
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > Cc: David Vrabel <david.vrabel@citrix.com>
> > [ rjw: Combined two patches, rebased, modified subject/changelog ]
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  arch/x86/xen/suspend.c       |    2 -
> >  include/linux/tick.h         |    6 ++--
> >  kernel/time/tick-broadcast.c |   24 ++++++++++++------
> >  kernel/time/tick-common.c    |   57 +++++++++++++++++++++++++++++--------------
> >  kernel/time/tick-internal.h  |    8 ++++--
> >  5 files changed, 66 insertions(+), 31 deletions(-)
> > 
> > Index: linux-pm/arch/x86/xen/suspend.c
> > ===================================================================
> > --- linux-pm.orig/arch/x86/xen/suspend.c
> > +++ linux-pm/arch/x86/xen/suspend.c
> > @@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
> >  	if (smp_processor_id() == 0)
> >  		return;
> >  
> > -	tick_resume();
> > +	tick_resume_local();
> 
> I am looking at Linus's tree and I see:
> 
> 82 static void xen_vcpu_notify_restore(void *data)                                 
>  83 {                                                                               
>  84         unsigned long reason = (unsigned long)data;                             
>  85                                                                                 
>  86         /* Boot processor notified via generic timekeeping_resume() */          
>  87         if ( smp_processor_id() == 0)                                           
>  88                 return;                                                         
>  89                                                                                 
>  90         clockevents_notify(reason, NULL);                                       
>  91 }                             
> 
> So there must be another patch that altered the clockevents_notify?

Yes, there is.  It is the [06/09] in this series
(https://patchwork.kernel.org/patch/6090631/).

I should have CCed it to you too, sorry about that.

> Is there an git tree with all of these patches?

Not yet, but they all are in the linux-pm patchwork at

https://patchwork.kernel.org/project/linux-pm/list/

I can create a branch in the linux-pm.git tree for them if that helps,
please let me know.


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 20:44         ` Konrad Rzeszutek Wilk
@ 2015-03-25 21:36           ` Rafael J. Wysocki
  0 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-25 21:36 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Peter Zijlstra, linux-kernel, mingo, tglx, Linux PM list,
	Boris Ostrovsky, David Vrabel

On Wednesday, March 25, 2015 04:44:45 PM Konrad Rzeszutek Wilk wrote:
> On Wed, Mar 25, 2015 at 09:57:18PM +0100, Rafael J. Wysocki wrote:
> > On Wednesday, March 25, 2015 04:13:09 PM Konrad Rzeszutek Wilk wrote:
> > > On Wed, Mar 25, 2015 at 01:11:04PM +0100, Rafael J. Wysocki wrote:
> > > > From: Thomas Gleixner <tglx@linutronix.de>
> > > > 
> > > > Xen calls on every cpu into tick_resume() which is just wrong.
> > > > tick_resume() is for the syscore global suspend/resume invocation.
> > > > What XEN really wants is a per cpu local resume function.
> > > > 
> > > > Provide a tick_resume_local() function and use it in XEN.
> > > > 
> > > > Also provide a complementary tick_suspend_local() and modify
> > > > tick_unfreeze() and tick_freeze(), respectively, to use the
> > > > new local tick resume/suspend functions.
> > > > 
> > > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > > > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > > > Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > > > Cc: David Vrabel <david.vrabel@citrix.com>
> > > > [ rjw: Combined two patches, rebased, modified subject/changelog ]
> > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > ---
> > > >  arch/x86/xen/suspend.c       |    2 -
> > > >  include/linux/tick.h         |    6 ++--
> > > >  kernel/time/tick-broadcast.c |   24 ++++++++++++------
> > > >  kernel/time/tick-common.c    |   57 +++++++++++++++++++++++++++++--------------
> > > >  kernel/time/tick-internal.h  |    8 ++++--
> > > >  5 files changed, 66 insertions(+), 31 deletions(-)
> > > > 
> > > > Index: linux-pm/arch/x86/xen/suspend.c
> > > > ===================================================================
> > > > --- linux-pm.orig/arch/x86/xen/suspend.c
> > > > +++ linux-pm/arch/x86/xen/suspend.c
> > > > @@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
> > > >  	if (smp_processor_id() == 0)
> > > >  		return;
> > > >  
> > > > -	tick_resume();
> > > > +	tick_resume_local();
> > > 
> > > I am looking at Linus's tree and I see:
> > > 
> > > 82 static void xen_vcpu_notify_restore(void *data)                                 
> > >  83 {                                                                               
> > >  84         unsigned long reason = (unsigned long)data;                             
> > >  85                                                                                 
> > >  86         /* Boot processor notified via generic timekeeping_resume() */          
> > >  87         if ( smp_processor_id() == 0)                                           
> > >  88                 return;                                                         
> > >  89                                                                                 
> > >  90         clockevents_notify(reason, NULL);                                       
> > >  91 }                             
> > > 
> > > So there must be another patch that altered the clockevents_notify?
> > 
> > Yes, there is.  It is the [06/09] in this series
> > (https://patchwork.kernel.org/patch/6090631/).
> > 
> > I should have CCed it to you too, sorry about that.
> 
> That is alright.
> > 
> > > Is there an git tree with all of these patches?
> > 
> > Not yet, but they all are in the linux-pm patchwork at
> > 
> > https://patchwork.kernel.org/project/linux-pm/list/
> > 
> > I can create a branch in the linux-pm.git tree for them if that helps,
> > please let me know.
> 
> If it is not too much trouble.. 

Done:

git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git tick-pm

Also turns out that the $subject patch was actually on top of some debug stuff
I have in tick_freeze()/tick_unfreeze(), so here goes a cleaned-up updated.

---
From: Thomas Gleixner <tglx@linutronix.de>
Subject: tick/xen: Provide and use tick_suspend_local() and tick_resume_local()

Xen calls on every cpu into tick_resume() which is just wrong.
tick_resume() is for the syscore global suspend/resume invocation.
What XEN really wants is a per cpu local resume function.

Provide a tick_resume_local() function and use it in XEN.

Also provide a complementary tick_suspend_local() and modify
tick_unfreeze() and tick_freeze(), respectively, to use the
new local tick resume/suspend functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
[ rjw: Combined two patches, rebased, modified subject/changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 arch/x86/xen/suspend.c       |    2 -
 include/linux/tick.h         |    6 ++--
 kernel/time/tick-broadcast.c |   24 +++++++++++-----
 kernel/time/tick-common.c    |   62 ++++++++++++++++++++++++++++---------------
 kernel/time/tick-internal.h  |    8 ++++-
 5 files changed, 68 insertions(+), 34 deletions(-)

Index: linux-pm/arch/x86/xen/suspend.c
===================================================================
--- linux-pm.orig/arch/x86/xen/suspend.c
+++ linux-pm/arch/x86/xen/suspend.c
@@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void
 	if (smp_processor_id() == 0)
 		return;
 
-	tick_resume();
+	tick_resume_local();
 }
 
 void xen_arch_resume(void)
Index: linux-pm/include/linux/tick.h
===================================================================
--- linux-pm.orig/include/linux/tick.h
+++ linux-pm/include/linux/tick.h
@@ -29,13 +29,13 @@ extern struct tick_device *tick_get_devi
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
-/* Should be core only, but XEN resume magic abuses this interface */
-extern void tick_resume(void);
+/* Should be core only, but XEN resume magic requires this */
+extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
-static inline void tick_resume(void) { }
+static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
Index: linux-pm/kernel/time/tick-broadcast.c
===================================================================
--- linux-pm.orig/kernel/time/tick-broadcast.c
+++ linux-pm/kernel/time/tick-broadcast.c
@@ -455,11 +455,26 @@ void tick_suspend_broadcast(void)
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
-int tick_resume_broadcast(void)
+/*
+ * This is called from tick_resume_local() on a resuming CPU. That's
+ * called from the core resume function, tick_unfreeze() and the magic XEN
+ * resume hackery.
+ *
+ * In none of these cases the broadcast device mode can change and the
+ * bit of the resuming CPU in the broadcast mask is safe as well.
+ */
+bool tick_resume_check_broadcast(void)
+{
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
+		return false;
+	else
+		return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
+}
+
+void tick_resume_broadcast(void)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
-	int broadcast = 0;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -472,8 +487,6 @@ int tick_resume_broadcast(void)
 		case TICKDEV_MODE_PERIODIC:
 			if (!cpumask_empty(tick_broadcast_mask))
 				tick_broadcast_start_periodic(bc);
-			broadcast = cpumask_test_cpu(smp_processor_id(),
-						     tick_broadcast_mask);
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
@@ -482,11 +495,8 @@ int tick_resume_broadcast(void)
 		}
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-
-	return broadcast;
 }
 
-
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_var_t tick_broadcast_oneshot_mask;
Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -373,40 +373,32 @@ void tick_shutdown(unsigned int *cpup)
 }
 
 /**
- * tick_suspend - Suspend the tick and the broadcast device
+ * tick_suspend_local - Suspend the local tick device
  *
- * Called from syscore_suspend() via timekeeping_suspend with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local cpu for freeze with interrupts disabled.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_suspend(void)
+static void tick_suspend_local(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
-	tick_suspend_broadcast();
 }
 
 /**
- * tick_resume - Resume the tick and the broadcast device
+ * tick_resume_local - Resume the local tick device
  *
- * Called from syscore_resume() via timekeeping_resume with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local CPU for unfreeze or XEN resume magic.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_resume(void)
+void tick_resume_local(void)
 {
-	struct tick_device *td;
-	int broadcast;
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+	bool broadcast = tick_resume_check_broadcast();
 
-	broadcast = tick_resume_broadcast();
-	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
-
 	if (!broadcast) {
 		if (td->mode == TICKDEV_MODE_PERIODIC)
 			tick_setup_periodic(td->evtdev, 0);
@@ -415,6 +407,35 @@ void tick_resume(void)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend(void)
+{
+	tick_suspend_local();
+	tick_suspend_broadcast();
+}
+
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume(void)
+{
+	tick_resume_broadcast();
+	tick_resume_local();
+}
+
 static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
 static unsigned int tick_freeze_depth;
 
@@ -432,11 +453,10 @@ void tick_freeze(void)
 	raw_spin_lock(&tick_freeze_lock);
 
 	tick_freeze_depth++;
-	if (tick_freeze_depth == num_online_cpus()) {
+	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_suspend();
-	} else {
-		tick_suspend();
-	}
+	else
+		tick_suspend_local();
 
 	raw_spin_unlock(&tick_freeze_lock);
 }
@@ -457,7 +477,7 @@ void tick_unfreeze(void)
 	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_resume();
 	else
-		tick_resume();
+		tick_resume_local();
 
 	tick_freeze_depth--;
 
Index: linux-pm/kernel/time/tick-internal.h
===================================================================
--- linux-pm.orig/kernel/time/tick-internal.h
+++ linux-pm/kernel/time/tick-internal.h
@@ -23,6 +23,7 @@ extern void tick_check_new_device(struct
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
+extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -42,6 +43,7 @@ extern int __clockevents_update_freq(str
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #else
 static inline void tick_suspend(void) { }
+static inline void tick_resume(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
@@ -80,7 +82,8 @@ extern int tick_is_broadcast_device(stru
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
-extern int tick_resume_broadcast(void);
+extern void tick_resume_broadcast(void);
+extern bool tick_resume_check_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
@@ -94,7 +97,8 @@ static inline void tick_do_periodic_broa
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
-static inline int tick_resume_broadcast(void) { return 0; }
+static inline void tick_resume_broadcast(void) { }
+static inline bool tick_resume_check_broadcast(void) { return false; }
 static inline void tick_broadcast_init(void) { }
 static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 


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

* Re: [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting
  2015-03-05  4:20                     ` Preeti U Murthy
@ 2015-03-29  6:45                       ` Ingo Molnar
  0 siblings, 0 replies; 106+ messages in thread
From: Ingo Molnar @ 2015-03-29  6:45 UTC (permalink / raw)
  To: Preeti U Murthy
  Cc: Peter Zijlstra, Nicolas Pitre, tglx, linux-kernel, rjw, Michael Ellerman


* Preeti U Murthy <preeti@linux.vnet.ibm.com> wrote:

> On 03/02/2015 08:26 PM, Peter Zijlstra wrote:
> > On Fri, Feb 27, 2015 at 02:19:05PM +0530, Preeti U Murthy wrote:
> >> The problem reported in the changelog of this patch is causing severe
> >> regressions very frequently on our machines for certain usecases. It would
> >> help to put in a fix in place first and then follow that up with these
> >> cleanups.  A fix on the below lines :
> > 
> > Regression how? Neither Thomas' Changelog, nor yours mention its a
> > regression.
> > 
> > If its a (recent) Regression you need to have a Fixes tag at the very
> > least. So when was this broken and by which patch?
> > 
> 
> It was found recently when doing a hotplug stress test on POWER, that
> the machine hits lockups spewing
> 
> NMI watchdog: BUG: soft lockup - CPU#20 stuck for 23s! [swapper/20:0]
> 
> or
> 
> INFO: rcu_sched detected stalls on CPUs/tasks: { 2 7 8 9 10 11 12 13 14 15
> 16 17 18 19 20 21 22 23 2
> 4 25 26 27 28 29 30 31} (detected by 6, t=2102 jiffies, g=1617, c=1616,
> q=1441)
> 
> and many other messages about lockups.
> 
> This issue was reported here:
> http://linuxppc.10917.n7.nabble.com/offlining-cpus-breakage-td88619.html
> and was traced to
> commit 7cba160ad789a powernv/cpuidle: Redesign idle states management,
> which exposed the loophole in commit 5d1638acb9f6(tick: Introduce
> hrtimer based broadcast) and is reported in the changelog of the patch.

Please send the patch with an updated changelog.

Thanks,

	Ingo

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

* [GIT PULL] kernel/time cleanups (related to tick_suspend/resume)
  2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
                     ` (9 preceding siblings ...)
  2015-03-25 12:13   ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
@ 2015-03-31 22:45   ` Rafael J. Wysocki
  10 siblings, 0 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-03-31 22:45 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, linux-kernel, tglx, Linux PM list, Stephen Rothwell

Hi Ingo,

Please pull from

git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git tick-pm

to receive kernel/time cleanups related to tick_suspend/resume from Thomas Gleixner
that I've rebased on top of the Linus' tree and reworked slightly.

There will be a conflict between this branch and tip that can be resolved with
the help of the patch from Stephen Rothwell available at:

http://marc.info/?l=linux-kernel&m=142778874014355&w=4

Kind regards,
Rafael


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

* [tip:timers/core] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD
  2015-03-25 12:05   ` [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Rafael J. Wysocki
@ 2015-04-02 12:28     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, linux-kernel, peterz, hpa, mingo, rafael.j.wysocki

Commit-ID:  9f083b74df3a7eaa100b456f2dc195512daf728e
Gitweb:     http://git.kernel.org/tip/9f083b74df3a7eaa100b456f2dc195512daf728e
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:05:19 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:57 +0200

clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD

This option was for simpler migration to the clock events code.
Most architectures have been converted and the option has been
disfunctional as a standalone option for quite some time. Remove
it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/5021859.jl9OC1medj@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 include/linux/clockchips.h  | 9 +++------
 kernel/time/Kconfig         | 6 ------
 kernel/time/Makefile        | 6 ++----
 kernel/time/clockevents.c   | 3 ---
 kernel/time/tick-internal.h | 4 ++--
 5 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index e20232c..5797513 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -22,7 +22,7 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #include <linux/clocksource.h>
 #include <linux/cpumask.h>
@@ -229,13 +229,9 @@ static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern int clockevents_notify(unsigned long reason, void *arg);
-#else
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
-#endif
 
-#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
 
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
@@ -243,6 +239,7 @@ static inline void clockevents_resume(void) {}
 static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
 static inline void tick_setup_hrtimer_broadcast(void) {};
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 
 #endif
 
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index d626dc9..579ce1b 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -33,12 +33,6 @@ config ARCH_USES_GETTIMEOFFSET
 config GENERIC_CLOCKEVENTS
 	bool
 
-# Migration helper. Builds, but does not invoke
-config GENERIC_CLOCKEVENTS_BUILD
-	bool
-	default y
-	depends on GENERIC_CLOCKEVENTS
-
 # Architecture can handle broadcast in a driver-agnostic way
 config ARCH_HAS_TICK_BROADCAST
 	bool
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index c09c078..01f0312 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -2,15 +2,13 @@ obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
 
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)		+= clockevents.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o tick-common.o
 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
  obj-y						+= tick-broadcast.o
  obj-$(CONFIG_TICK_ONESHOT)			+= tick-broadcast-hrtimer.o
 endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o
-obj-$(CONFIG_TICK_ONESHOT)			+= tick-sched.o
+obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
 obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
 obj-$(CONFIG_DEBUG_FS)				+= timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)			+= test_udelay.o
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 73689df..3531bee 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -645,7 +645,6 @@ void clockevents_resume(void)
 			dev->resume(dev);
 }
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 /**
  * clockevents_notify - notification about relevant events
  * Returns 0 on success, any other value on error
@@ -831,5 +830,3 @@ static int __init clockevents_init_sysfs(void)
 }
 device_initcall(clockevents_init_sysfs);
 #endif /* SYSFS */
-
-#endif /* GENERIC_CLOCK_EVENTS */
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 98700e4..c7b75be 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -10,7 +10,7 @@ extern seqlock_t jiffies_lock;
 
 #define CS_NAME_LEN	32
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
 #define TICK_DO_TIMER_BOOT	-2
@@ -167,7 +167,7 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
 
 int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 
-#endif
+#endif /* GENERIC_CLOCKEVENTS */
 
 extern void do_timer(unsigned long ticks);
 extern void update_wall_time(void);

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

* [tip:timers/core] tick: Move clocksource related stuff to timekeeping.h
  2015-03-25 12:06   ` [PATCH 02/09] tick: Move clocksource related stuff to timekeeping.h Rafael J. Wysocki
@ 2015-04-02 12:28     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, hpa, rafael.j.wysocki, peterz, linux-kernel, tglx

Commit-ID:  bfb83b27519aa7ed9510f601a8f825a2c1484bc2
Gitweb:     http://git.kernel.org/tip/bfb83b27519aa7ed9510f601a8f825a2c1484bc2
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:06:04 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:58 +0200

tick: Move clocksource related stuff to timekeeping.h

Move clocksource related stuff to timekeeping.h and remove the
pointless include from ntp.c

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/2714218.nM5AEfAHj0@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/clocksource.c   | 2 +-
 kernel/time/jiffies.c       | 2 +-
 kernel/time/ntp.c           | 1 -
 kernel/time/tick-internal.h | 6 ------
 kernel/time/timekeeping.h   | 7 +++++++
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index c3be3c7..8b4010f 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 #include "timekeeping_internal.h"
 
 /**
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index c4bb518..347fecf 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 
 /* The Jiffies based clocksource is the lowest common
  * denominator clock source which should function on
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 0f60b08..9ad60d0 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 
-#include "tick-internal.h"
 #include "ntp_internal.h"
 
 /*
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index c7b75be..cba5214 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -6,10 +6,6 @@
 
 #include "timekeeping.h"
 
-extern seqlock_t jiffies_lock;
-
-#define CS_NAME_LEN	32
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 #define TICK_DO_TIMER_NONE	-1
@@ -169,5 +165,3 @@ int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 
 #endif /* GENERIC_CLOCKEVENTS */
 
-extern void do_timer(unsigned long ticks);
-extern void update_wall_time(void);
diff --git a/kernel/time/timekeeping.h b/kernel/time/timekeeping.h
index 1d91416..ead8794 100644
--- a/kernel/time/timekeeping.h
+++ b/kernel/time/timekeeping.h
@@ -19,4 +19,11 @@ extern void timekeeping_clocktai(struct timespec *ts);
 extern int timekeeping_suspend(void);
 extern void timekeeping_resume(void);
 
+extern void do_timer(unsigned long ticks);
+extern void update_wall_time(void);
+
+extern seqlock_t jiffies_lock;
+
+#define CS_NAME_LEN	32
+
 #endif

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

* [tip:timers/core] tick: Simplify tick-internal.h
  2015-03-25 12:06   ` [PATCH 03/09] tick: Simplify tick-internal.h Rafael J. Wysocki
@ 2015-04-02 12:29     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rafael.j.wysocki, linux-kernel, peterz, tglx, hpa, mingo

Commit-ID:  b7475eb599ddb2e8cab2dc86ff38a9507463ad6b
Gitweb:     http://git.kernel.org/tip/b7475eb599ddb2e8cab2dc86ff38a9507463ad6b
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:06:47 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:58 +0200

tick: Simplify tick-internal.h

tick-internal.h is pretty confusing as a lot of the stub inlines
are there several times.

Distangle the maze and make clear functional sections.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/16068264.vcNp79HLaT@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/tick-internal.h | 145 +++++++++++++++-----------------------------
 1 file changed, 49 insertions(+), 96 deletions(-)

diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index cba5214..d86eb8d 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -27,14 +27,19 @@ extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 
-extern void clockevents_shutdown(struct clock_event_device *dev);
 extern int clockevents_tick_resume(struct clock_event_device *dev);
+/* Check, if the device is functional or a dummy for broadcast */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
 
+extern void clockevents_shutdown(struct clock_event_device *dev);
+extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#endif /* GENERIC_CLOCKEVENTS */
 
-/*
- * NO_HZ / high resolution timer shared code
- */
+/* Oneshot related functions */
 #ifdef CONFIG_TICK_ONESHOT
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
 			       void (*handler)(struct clock_event_device *),
@@ -43,69 +48,19 @@ extern int tick_program_event(ktime_t expires, int force);
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_control(unsigned long reason);
-extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_active(void);
-extern void tick_check_oneshot_broadcast_this_cpu(void);
-bool tick_broadcast_oneshot_available(void);
-# else /* BROADCAST */
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
-static inline bool tick_broadcast_oneshot_available(void) { return true; }
-# endif /* !BROADCAST */
-
+static inline bool tick_oneshot_possible(void) { return true; }
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
 			void (*handler)(struct clock_event_device *),
-			ktime_t nextevt)
-{
-	BUG();
-}
-static inline void tick_resume_oneshot(void)
-{
-	BUG();
-}
-static inline int tick_program_event(ktime_t expires, int force)
-{
-	return 0;
-}
+			ktime_t nextevt) { BUG(); }
+static inline void tick_resume_oneshot(void) { BUG(); }
+static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-	BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
-{
-	return 0;
-}
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline bool tick_broadcast_oneshot_available(void) { return false; }
+static inline bool tick_oneshot_possible(void) { return false; }
 #endif /* !TICK_ONESHOT */
 
-/* NO_HZ_FULL internal */
-#ifdef CONFIG_NO_HZ_FULL
-extern void tick_nohz_init(void);
-# else
-static inline void tick_nohz_init(void) { }
-#endif
-
-/*
- * Broadcasting support
- */
+/* Broadcasting support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
 extern void tick_install_broadcast_device(struct clock_event_device *dev);
@@ -115,53 +70,51 @@ extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
 extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
-extern void
-tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
-int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
-
+extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
 #else /* !BROADCAST */
-
-static inline void tick_install_broadcast_device(struct clock_event_device *dev)
-{
-}
-
-static inline int tick_is_broadcast_device(struct clock_event_device *dev)
-{
-	return 0;
-}
-static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
-					     int cpu)
-{
-	return 0;
-}
+static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
+static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
 static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline int tick_resume_broadcast(void) { return 0; }
 static inline void tick_broadcast_init(void) { }
-static inline int tick_broadcast_update_freq(struct clock_event_device *dev,
-					     u32 freq) { return -ENODEV; }
+static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 
-/*
- * Set the periodic handler in non broadcast mode
- */
-static inline void tick_set_periodic_handler(struct clock_event_device *dev,
-					     int broadcast)
+/* Set the periodic handler in non broadcast mode */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
 {
 	dev->event_handler = tick_handle_periodic;
 }
 #endif /* !BROADCAST */
 
-/*
- * Check, if the device is functional or a dummy for broadcast
- */
-static inline int tick_device_is_functional(struct clock_event_device *dev)
-{
-	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
-}
-
-int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
-
-#endif /* GENERIC_CLOCKEVENTS */
+/* Functions related to oneshot broadcasting */
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_control(unsigned long reason);
+extern void tick_broadcast_switch_to_oneshot(void);
+extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
+extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
+extern int tick_broadcast_oneshot_active(void);
+extern void tick_check_oneshot_broadcast_this_cpu(void);
+bool tick_broadcast_oneshot_available(void);
+#else /* BROADCAST && ONESHOT */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
+static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
+static inline void tick_broadcast_switch_to_oneshot(void) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
+static inline int tick_broadcast_oneshot_active(void) { return 0; }
+static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
+static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
+#endif /* !BROADCAST && ONESHOT */
 
+/* NO_HZ_FULL internal */
+#ifdef CONFIG_NO_HZ_FULL
+extern void tick_nohz_init(void);
+# else
+static inline void tick_nohz_init(void) { }
+#endif

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

* [tip:timers/core] tick: Move core only declarations and functions to core
  2015-03-25 12:07   ` [PATCH 04/09] tick: Move core only declarations and functions to core Rafael J. Wysocki
@ 2015-04-02 12:29     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, peterz, nico, linux-kernel, tglx, hpa, rafael.j.wysocki

Commit-ID:  c1797baf6880174f899ce3960d0598f5bbeeb7ff
Gitweb:     http://git.kernel.org/tip/c1797baf6880174f899ce3960d0598f5bbeeb7ff
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:07:37 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:58 +0200

tick: Move core only declarations and functions to core

No point to expose everything to the world. People just believe
such functions can be abused for whatever purposes. Sigh.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ Rebased on top of 4.0-rc5 ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/28017337.VbCUc39Gme@vostro.rjw.lan
[ Merged to latest timers/core ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 include/linux/clockchips.h  |  15 ++---
 include/linux/tick.h        | 134 ++++++--------------------------------------
 kernel/time/clocksource.c   |   2 +-
 kernel/time/hrtimer.c       |   2 +-
 kernel/time/tick-internal.h |  15 +++++
 kernel/time/tick-sched.c    |   7 ++-
 kernel/time/tick-sched.h    |  64 +++++++++++++++++++++
 kernel/time/timer_list.c    |   2 +-
 8 files changed, 112 insertions(+), 129 deletions(-)

diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 5797513..bc3af82 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -193,15 +193,6 @@ extern void clockevents_config_and_register(struct clock_event_device *dev,
 
 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
 
-extern void clockevents_exchange_device(struct clock_event_device *old,
-					struct clock_event_device *new);
-extern void clockevents_set_state(struct clock_event_device *dev,
-				  enum clock_event_state state);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
-
-extern void clockevents_handle_noop(struct clock_event_device *dev);
-
 static inline void
 clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 {
@@ -209,6 +200,12 @@ clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 				      freq, minsec);
 }
 
+/* Should be core only, but is abused by arm bl_switcher */
+extern void clockevents_set_state(struct clock_event_device *dev,
+				 enum clock_event_state state);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
+
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 9c085dc..f9a2d26 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -1,7 +1,5 @@
-/*  linux/include/linux/tick.h
- *
- *  This file contains the structure definitions for tick related functions
- *
+/*
+ * Tick related global functions
  */
 #ifndef _LINUX_TICK_H
 #define _LINUX_TICK_H
@@ -9,13 +7,12 @@
 #include <linux/clockchips.h>
 #include <linux/irqflags.h>
 #include <linux/percpu.h>
-#include <linux/hrtimer.h>
 #include <linux/context_tracking_state.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
+/* ARM BL switcher abuse support */
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-
 enum tick_device_mode {
 	TICKDEV_MODE_PERIODIC,
 	TICKDEV_MODE_ONESHOT,
@@ -25,133 +22,38 @@ struct tick_device {
 	struct clock_event_device *evtdev;
 	enum tick_device_mode mode;
 };
-
-enum tick_nohz_mode {
-	NOHZ_MODE_INACTIVE,
-	NOHZ_MODE_LOWRES,
-	NOHZ_MODE_HIGHRES,
-};
-
-/**
- * struct tick_sched - sched tick emulation and no idle tick control/stats
- * @sched_timer:	hrtimer to schedule the periodic tick in high
- *			resolution mode
- * @last_tick:		Store the last tick expiry time when the tick
- *			timer is modified for nohz sleeps. This is necessary
- *			to resume the tick timer operation in the timeline
- *			when the CPU returns from nohz sleep.
- * @tick_stopped:	Indicator that the idle tick has been stopped
- * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
- * @idle_calls:		Total number of idle calls
- * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
- * @idle_entrytime:	Time when the idle call was entered
- * @idle_waketime:	Time when the idle was interrupted
- * @idle_exittime:	Time when the idle state was left
- * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
- * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
- * @sleep_length:	Duration of the current idle sleep
- * @do_timer_lst:	CPU was the last one doing do_timer before going idle
- */
-struct tick_sched {
-	struct hrtimer			sched_timer;
-	unsigned long			check_clocks;
-	enum tick_nohz_mode		nohz_mode;
-	ktime_t				last_tick;
-	int				inidle;
-	int				tick_stopped;
-	unsigned long			idle_jiffies;
-	unsigned long			idle_calls;
-	unsigned long			idle_sleeps;
-	int				idle_active;
-	ktime_t				idle_entrytime;
-	ktime_t				idle_waketime;
-	ktime_t				idle_exittime;
-	ktime_t				idle_sleeptime;
-	ktime_t				iowait_sleeptime;
-	ktime_t				sleep_length;
-	unsigned long			last_jiffies;
-	unsigned long			next_jiffies;
-	ktime_t				idle_expires;
-	int				do_timer_last;
-};
-
-extern void __init tick_init(void);
-extern int tick_is_oneshot_available(void);
 extern struct tick_device *tick_get_device(int cpu);
+#endif
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+static inline void tick_freeze(void) { }
+static inline void tick_unfreeze(void) { }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-# ifdef CONFIG_HIGH_RES_TIMERS
-extern int tick_init_highres(void);
-extern int tick_program_event(ktime_t expires, int force);
-extern void tick_setup_sched_timer(void);
-# endif
-
-# if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
-extern void tick_cancel_sched_timer(int cpu);
-# else
-static inline void tick_cancel_sched_timer(int cpu) { }
-# endif
-
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern struct tick_device *tick_get_broadcast_device(void);
-extern struct cpumask *tick_get_broadcast_mask(void);
-
-#  ifdef CONFIG_TICK_ONESHOT
-extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
-#  endif
-
-# endif /* BROADCAST */
-
-# ifdef CONFIG_TICK_ONESHOT
-extern void tick_clock_notify(void);
-extern int tick_check_oneshot_change(int allow_nohz);
-extern struct tick_sched *tick_get_tick_sched(int cpu);
+#ifdef CONFIG_TICK_ONESHOT
 extern void tick_irq_enter(void);
-extern int tick_oneshot_mode_active(void);
 #  ifndef arch_needs_cpu
 #   define arch_needs_cpu() (0)
 #  endif
 # else
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-# endif
-
-#else /* CONFIG_GENERIC_CLOCKEVENTS */
-static inline void tick_init(void) { }
-static inline void tick_freeze(void) { }
-static inline void tick_unfreeze(void) { }
-static inline void tick_cancel_sched_timer(int cpu) { }
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
-
-# ifdef CONFIG_NO_HZ_COMMON
-DECLARE_PER_CPU(struct tick_sched, tick_cpu_sched);
-
-static inline int tick_nohz_tick_stopped(void)
-{
-	return __this_cpu_read(tick_cpu_sched.tick_stopped);
-}
+#endif
 
+#ifdef CONFIG_NO_HZ_COMMON
+extern int tick_nohz_tick_stopped(void);
 extern void tick_nohz_idle_enter(void);
 extern void tick_nohz_idle_exit(void);
 extern void tick_nohz_irq_exit(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
-
-# else /* !CONFIG_NO_HZ_COMMON */
-static inline int tick_nohz_tick_stopped(void)
-{
-	return 0;
-}
-
+#else /* !CONFIG_NO_HZ_COMMON */
+static inline int tick_nohz_tick_stopped(void) { return 0; }
 static inline void tick_nohz_idle_enter(void) { }
 static inline void tick_nohz_idle_exit(void) { }
 
@@ -163,7 +65,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void)
 }
 static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
-# endif /* !CONFIG_NO_HZ_COMMON */
+#endif /* !CONFIG_NO_HZ_COMMON */
 
 #ifdef CONFIG_NO_HZ_FULL
 extern bool tick_nohz_full_running;
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 8b4010f..c3be3c7 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -31,7 +31,7 @@
 #include <linux/tick.h>
 #include <linux/kthread.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 #include "timekeeping_internal.h"
 
 /**
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index bee0c1f..721d29b 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -54,7 +54,7 @@
 
 #include <trace/events/timer.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 
 /*
  * The timer bases:
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index d86eb8d..dd2c45d 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -5,6 +5,7 @@
 #include <linux/tick.h>
 
 #include "timekeeping.h"
+#include "tick-sched.h"
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
@@ -26,6 +27,7 @@ extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
+extern int tick_is_oneshot_available(void);
 
 extern int clockevents_tick_resume(struct clock_event_device *dev);
 /* Check, if the device is functional or a dummy for broadcast */
@@ -35,6 +37,9 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
 }
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
+extern void clockevents_exchange_device(struct clock_event_device *old,
+					struct clock_event_device *new);
+extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #endif /* GENERIC_CLOCKEVENTS */
@@ -49,6 +54,10 @@ extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
 static inline bool tick_oneshot_possible(void) { return true; }
+extern int tick_oneshot_mode_active(void);
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern int tick_init_highres(void);
 #else /* !ONESHOT */
 static inline
 void tick_setup_oneshot(struct clock_event_device *newdev,
@@ -58,6 +67,9 @@ static inline void tick_resume_oneshot(void) { BUG(); }
 static inline int tick_program_event(ktime_t expires, int force) { return 0; }
 static inline void tick_oneshot_notify(void) { }
 static inline bool tick_oneshot_possible(void) { return false; }
+static inline int tick_oneshot_mode_active(void) { return 0; }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 #endif /* !TICK_ONESHOT */
 
 /* Broadcasting support */
@@ -72,6 +84,8 @@ extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
+extern struct tick_device *tick_get_broadcast_device(void);
+extern struct cpumask *tick_get_broadcast_mask(void);
 #else /* !BROADCAST */
 static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
 static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
@@ -101,6 +115,7 @@ extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
+extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #else /* BROADCAST && ONESHOT */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index a4c4eda..9142591 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -34,7 +34,7 @@
 /*
  * Per cpu nohz control structure
  */
-DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
 
 /*
  * The time, when the last jiffy update happened. Protected by jiffies_lock.
@@ -416,6 +416,11 @@ static int __init setup_tick_nohz(char *str)
 
 __setup("nohz=", setup_tick_nohz);
 
+int tick_nohz_tick_stopped(void)
+{
+	return __this_cpu_read(tick_cpu_sched.tick_stopped);
+}
+
 /**
  * tick_nohz_update_jiffies - update jiffies when idle was interrupted
  *
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h
new file mode 100644
index 0000000..9307432
--- /dev/null
+++ b/kernel/time/tick-sched.h
@@ -0,0 +1,64 @@
+#ifndef _TICK_SCHED_H
+#define _TICK_SCHED_H
+
+#include <linux/hrtimer.h>
+
+enum tick_nohz_mode {
+	NOHZ_MODE_INACTIVE,
+	NOHZ_MODE_LOWRES,
+	NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:	hrtimer to schedule the periodic tick in high
+ *			resolution mode
+ * @last_tick:		Store the last tick expiry time when the tick
+ *			timer is modified for nohz sleeps. This is necessary
+ *			to resume the tick timer operation in the timeline
+ *			when the CPU returns from nohz sleep.
+ * @tick_stopped:	Indicator that the idle tick has been stopped
+ * @idle_jiffies:	jiffies at the entry to idle for idle time accounting
+ * @idle_calls:		Total number of idle calls
+ * @idle_sleeps:	Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:	Time when the idle call was entered
+ * @idle_waketime:	Time when the idle was interrupted
+ * @idle_exittime:	Time when the idle state was left
+ * @idle_sleeptime:	Sum of the time slept in idle with sched tick stopped
+ * @iowait_sleeptime:	Sum of the time slept in idle with sched tick stopped, with IO outstanding
+ * @sleep_length:	Duration of the current idle sleep
+ * @do_timer_lst:	CPU was the last one doing do_timer before going idle
+ */
+struct tick_sched {
+	struct hrtimer			sched_timer;
+	unsigned long			check_clocks;
+	enum tick_nohz_mode		nohz_mode;
+	ktime_t				last_tick;
+	int				inidle;
+	int				tick_stopped;
+	unsigned long			idle_jiffies;
+	unsigned long			idle_calls;
+	unsigned long			idle_sleeps;
+	int				idle_active;
+	ktime_t				idle_entrytime;
+	ktime_t				idle_waketime;
+	ktime_t				idle_exittime;
+	ktime_t				idle_sleeptime;
+	ktime_t				iowait_sleeptime;
+	ktime_t				sleep_length;
+	unsigned long			last_jiffies;
+	unsigned long			next_jiffies;
+	ktime_t				idle_expires;
+	int				do_timer_last;
+};
+
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+
+extern void tick_setup_sched_timer(void);
+#if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
+extern void tick_cancel_sched_timer(int cpu);
+#else
+static inline void tick_cancel_sched_timer(int cpu) { }
+#endif
+
+#endif
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 05aa559..e878c2e 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -16,10 +16,10 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
-#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 
+#include "tick-internal.h"
 
 struct timer_list_iter {
 	int cpu;

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

* [tip:timers/core] clockevents: Remove extra local_irq_save() in clockevents_exchange_device()
  2015-03-25 12:08   ` [PATCH 05/09] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Rafael J. Wysocki
@ 2015-04-02 12:29     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, linux-kernel, mingo, peterz, rafael.j.wysocki

Commit-ID:  db6f672ef11d7a3c5aa128a3c3e57c92580a25f7
Gitweb:     http://git.kernel.org/tip/db6f672ef11d7a3c5aa128a3c3e57c92580a25f7
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:08:27 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:59 +0200

clockevents: Remove extra local_irq_save() in clockevents_exchange_device()

Called with 'clockevents_lock' held and interrupts disabled
already.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/51005827.yXt5tjZMBs@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/clockevents.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 3531bee..b730027 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -595,14 +595,12 @@ void clockevents_handle_noop(struct clock_event_device *dev)
  * @old:	device to release (can be NULL)
  * @new:	device to request (can be NULL)
  *
- * Called from the notifier chain. clockevents_lock is held already
+ * Called from various tick functions with clockevents_lock held and
+ * interrupts disabled.
  */
 void clockevents_exchange_device(struct clock_event_device *old,
 				 struct clock_event_device *new)
 {
-	unsigned long flags;
-
-	local_irq_save(flags);
 	/*
 	 * Caller releases a clock event device. We queue it into the
 	 * released list and do a notify add later.
@@ -618,7 +616,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
 		BUG_ON(new->state != CLOCK_EVT_STATE_DETACHED);
 		clockevents_shutdown(new);
 	}
-	local_irq_restore(flags);
 }
 
 /**

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

* [tip:timers/core] clockevents: Make suspend/resume calls explicit
  2015-03-25 12:09   ` [PATCH 06/09] clockevents: Make suspend/resume calls explicit Rafael J. Wysocki
@ 2015-04-02 12:30     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rafael.j.wysocki, hpa, tglx, linux-kernel, peterz, mingo

Commit-ID:  4ffee521f36390c7720d493591b764ca35c8030b
Gitweb:     http://git.kernel.org/tip/4ffee521f36390c7720d493591b764ca35c8030b
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:09:16 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:59 +0200

clockevents: Make suspend/resume calls explicit

clockevents_notify() is a leftover from the early design of the
clockevents facility. It's really not a notification mechanism,
it's a multiplex call.

We are way better off to have explicit calls instead of this
monstrosity. Split out the suspend/resume() calls and invoke
them directly from the call sites.

No locking required at this point because these calls happen
with interrupts disabled and a single cpu online.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ Rebased on top of 4.0-rc5. ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/713674030.jVm1qaHuPf@vostro.rjw.lan
[ Rebased on top of latest timers/core. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/xen/suspend.c      | 11 ++++-------
 include/linux/clockchips.h  |  2 --
 include/linux/tick.h        |  3 +++
 kernel/time/clockevents.c   |  9 ---------
 kernel/time/tick-common.c   | 26 +++++++++++++++++++++++---
 kernel/time/tick-internal.h |  3 ++-
 kernel/time/timekeeping.c   |  6 ++----
 7 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index c4df9db..033e428 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -1,5 +1,5 @@
 #include <linux/types.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
@@ -81,17 +81,14 @@ void xen_arch_post_suspend(int cancelled)
 
 static void xen_vcpu_notify_restore(void *data)
 {
-	unsigned long reason = (unsigned long)data;
-
 	/* Boot processor notified via generic timekeeping_resume() */
-	if ( smp_processor_id() == 0)
+	if (smp_processor_id() == 0)
 		return;
 
-	clockevents_notify(reason, NULL);
+	tick_resume();
 }
 
 void xen_arch_resume(void)
 {
-	on_each_cpu(xen_vcpu_notify_restore,
-		    (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+	on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
 }
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index bc3af82..50ce975 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -16,8 +16,6 @@ enum clock_event_nofitiers {
 	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-	CLOCK_EVT_NOTIFY_SUSPEND,
-	CLOCK_EVT_NOTIFY_RESUME,
 	CLOCK_EVT_NOTIFY_CPU_DYING,
 	CLOCK_EVT_NOTIFY_CPU_DEAD,
 };
diff --git a/include/linux/tick.h b/include/linux/tick.h
index f9a2d26..7e07e0e 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -29,10 +29,13 @@ extern struct tick_device *tick_get_device(int cpu);
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
+/* Should be core only, but XEN resume magic abuses this interface */
+extern void tick_resume(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
+static inline void tick_resume(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index b730027..7af6148 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -670,15 +670,6 @@ int clockevents_notify(unsigned long reason, void *arg)
 		tick_handover_do_timer(arg);
 		break;
 
-	case CLOCK_EVT_NOTIFY_SUSPEND:
-		tick_suspend();
-		tick_suspend_broadcast();
-		break;
-
-	case CLOCK_EVT_NOTIFY_RESUME:
-		tick_resume();
-		break;
-
 	case CLOCK_EVT_NOTIFY_CPU_DEAD:
 		tick_shutdown_broadcast_oneshot(arg);
 		tick_shutdown_broadcast(arg);
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index a5b8771..1a60c2a 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -373,18 +373,39 @@ void tick_shutdown(unsigned int *cpup)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_suspend(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
+	tick_suspend_broadcast();
 }
 
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
 void tick_resume(void)
 {
-	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
-	int broadcast = tick_resume_broadcast();
+	struct tick_device *td;
+	int broadcast;
 
+	broadcast = tick_resume_broadcast();
+	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_tick_resume(td->evtdev);
 
 	if (!broadcast) {
@@ -416,7 +437,6 @@ void tick_freeze(void)
 		timekeeping_suspend();
 	} else {
 		tick_suspend();
-		tick_suspend_broadcast();
 	}
 
 	raw_spin_unlock(&tick_freeze_lock);
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index dd2c45d..85a9571 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -23,7 +23,6 @@ extern void tick_check_new_device(struct clock_event_device *dev);
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
-extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -42,6 +41,8 @@ extern void clockevents_exchange_device(struct clock_event_device *old,
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+#else
+static inline void tick_suspend(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index c3fcff0..5b12292 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1389,9 +1389,7 @@ void timekeeping_resume(void)
 
 	touch_softlockup_watchdog();
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-	/* Resume hrtimers */
+	tick_resume();
 	hrtimers_resume();
 }
 
@@ -1444,7 +1442,7 @@ int timekeeping_suspend(void)
 	write_seqcount_end(&tk_core.seq);
 	raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
-	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+	tick_suspend();
 	clocksource_suspend();
 	clockevents_suspend();
 

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

* [tip:timers/core] tick: Make tick_resume_broadcast_oneshot() static
  2015-03-25 12:09   ` [PATCH 07/09] tick: Make tick_resume_broadcast_oneshot static Rafael J. Wysocki
@ 2015-04-02 12:30     ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, tglx, hpa, linux-kernel, mingo, rafael.j.wysocki

Commit-ID:  080873ce2d1abd8c0a2b8c87bfa0762546a6b713
Gitweb:     http://git.kernel.org/tip/080873ce2d1abd8c0a2b8c87bfa0762546a6b713
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:09:55 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:22:59 +0200

tick: Make tick_resume_broadcast_oneshot() static

Solely used in tick-broadcast.c and the return value is
hardcoded 0. Make it static and void.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1689058.QkHYDJSRKu@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/tick-broadcast.c | 7 ++++---
 kernel/time/tick-internal.h  | 2 --
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f0f8ee9..60e6c23 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -37,8 +37,10 @@ static int tick_broadcast_force;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 #else
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
+static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
 
 /*
@@ -475,7 +477,7 @@ int tick_resume_broadcast(void)
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
-				broadcast = tick_resume_broadcast_oneshot(bc);
+				tick_resume_broadcast_oneshot(bc);
 			break;
 		}
 	}
@@ -541,10 +543,9 @@ static int tick_broadcast_set_event(struct clock_event_device *bc, int cpu,
 	return ret;
 }
 
-int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
 	clockevents_set_state(bc, CLOCK_EVT_STATE_ONESHOT);
-	return 0;
 }
 
 /*
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 85a9571..5c9f0ee 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -112,7 +112,6 @@ extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
@@ -122,7 +121,6 @@ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) {
 static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }

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

* [tip:timers/core] tick/xen: Provide and use tick_suspend_local() and tick_resume_local()
  2015-03-25 12:11   ` [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local() Rafael J. Wysocki
  2015-03-25 20:13     ` Konrad Rzeszutek Wilk
@ 2015-04-02 12:30     ` tip-bot for Thomas Gleixner
  2015-04-03 13:21       ` [PATCH][fix for tip/timers/core] timers / PM: Fix up tick_unfreeze() Rafael J. Wysocki
  1 sibling, 1 reply; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, linux-kernel, david.vrabel, peterz, boris.ostrovsky,
	konrad.wilk, rafael.j.wysocki, hpa, mingo

Commit-ID:  f46481d0a7cb942b84145acb80ad43bdb1ff8eb4
Gitweb:     http://git.kernel.org/tip/f46481d0a7cb942b84145acb80ad43bdb1ff8eb4
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:11:04 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:23:00 +0200

tick/xen: Provide and use tick_suspend_local() and tick_resume_local()

Xen calls on every cpu into tick_resume() which is just wrong.
tick_resume() is for the syscore global suspend/resume
invocation. What XEN really wants is a per cpu local resume
function.

Provide a tick_resume_local() function and use it in XEN.

Also provide a complementary tick_suspend_local() and modify
tick_unfreeze() and tick_freeze(), respectively, to use the
new local tick resume/suspend functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ Combined two patches, rebased, modified subject/changelog. ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1698741.eezk9tnXtG@vostro.rjw.lan
[ Merged to latest timers/core. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/xen/suspend.c       |  2 +-
 include/linux/tick.h         |  6 ++---
 kernel/time/tick-broadcast.c | 24 +++++++++++++------
 kernel/time/tick-common.c    | 55 ++++++++++++++++++++++++++++++--------------
 kernel/time/tick-internal.h  |  8 +++++--
 5 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 033e428..d949769 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -85,7 +85,7 @@ static void xen_vcpu_notify_restore(void *data)
 	if (smp_processor_id() == 0)
 		return;
 
-	tick_resume();
+	tick_resume_local();
 }
 
 void xen_arch_resume(void)
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 7e07e0e..a3d4d28 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -29,13 +29,13 @@ extern struct tick_device *tick_get_device(int cpu);
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
-/* Should be core only, but XEN resume magic abuses this interface */
-extern void tick_resume(void);
+/* Should be core only, but XEN resume magic requires this */
+extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
-static inline void tick_resume(void) { }
+static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_TICK_ONESHOT
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 60e6c23..19cfb38 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -455,11 +455,26 @@ void tick_suspend_broadcast(void)
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
-int tick_resume_broadcast(void)
+/*
+ * This is called from tick_resume_local() on a resuming CPU. That's
+ * called from the core resume function, tick_unfreeze() and the magic XEN
+ * resume hackery.
+ *
+ * In none of these cases the broadcast device mode can change and the
+ * bit of the resuming CPU in the broadcast mask is safe as well.
+ */
+bool tick_resume_check_broadcast(void)
+{
+	if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
+		return false;
+	else
+		return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
+}
+
+void tick_resume_broadcast(void)
 {
 	struct clock_event_device *bc;
 	unsigned long flags;
-	int broadcast = 0;
 
 	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -472,8 +487,6 @@ int tick_resume_broadcast(void)
 		case TICKDEV_MODE_PERIODIC:
 			if (!cpumask_empty(tick_broadcast_mask))
 				tick_broadcast_start_periodic(bc);
-			broadcast = cpumask_test_cpu(smp_processor_id(),
-						     tick_broadcast_mask);
 			break;
 		case TICKDEV_MODE_ONESHOT:
 			if (!cpumask_empty(tick_broadcast_mask))
@@ -482,11 +495,8 @@ int tick_resume_broadcast(void)
 		}
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-
-	return broadcast;
 }
 
-
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_var_t tick_broadcast_oneshot_mask;
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 1a60c2a..da796d6 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -374,40 +374,32 @@ void tick_shutdown(unsigned int *cpup)
 }
 
 /**
- * tick_suspend - Suspend the tick and the broadcast device
+ * tick_suspend_local - Suspend the local tick device
  *
- * Called from syscore_suspend() via timekeeping_suspend with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local cpu for freeze with interrupts disabled.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_suspend(void)
+static void tick_suspend_local(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
 	clockevents_shutdown(td->evtdev);
-	tick_suspend_broadcast();
 }
 
 /**
- * tick_resume - Resume the tick and the broadcast device
+ * tick_resume_local - Resume the local tick device
  *
- * Called from syscore_resume() via timekeeping_resume with only one
- * CPU online and interrupts disabled or from tick_unfreeze() under
- * tick_freeze_lock.
+ * Called from the local CPU for unfreeze or XEN resume magic.
  *
  * No locks required. Nothing can change the per cpu device.
  */
-void tick_resume(void)
+void tick_resume_local(void)
 {
-	struct tick_device *td;
-	int broadcast;
+	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+	bool broadcast = tick_resume_check_broadcast();
 
-	broadcast = tick_resume_broadcast();
-	td = this_cpu_ptr(&tick_cpu_device);
 	clockevents_tick_resume(td->evtdev);
-
 	if (!broadcast) {
 		if (td->mode == TICKDEV_MODE_PERIODIC)
 			tick_setup_periodic(td->evtdev, 0);
@@ -416,6 +408,35 @@ void tick_resume(void)
 	}
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend(void)
+{
+	tick_suspend_local();
+	tick_suspend_broadcast();
+}
+
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume(void)
+{
+	tick_resume_broadcast();
+	tick_resume_local();
+}
+
 static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
 static unsigned int tick_freeze_depth;
 
@@ -436,7 +457,7 @@ void tick_freeze(void)
 	if (tick_freeze_depth == num_online_cpus()) {
 		timekeeping_suspend();
 	} else {
-		tick_suspend();
+		tick_suspend_local();
 	}
 
 	raw_spin_unlock(&tick_freeze_lock);
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 5c9f0ee..6ba7bce 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -23,6 +23,7 @@ extern void tick_check_new_device(struct clock_event_device *dev);
 extern void tick_handover_do_timer(int *cpup);
 extern void tick_shutdown(unsigned int *cpup);
 extern void tick_suspend(void);
+extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
@@ -43,6 +44,7 @@ extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 #else
 static inline void tick_suspend(void) { }
+static inline void tick_resume(void) { }
 #endif /* GENERIC_CLOCKEVENTS */
 
 /* Oneshot related functions */
@@ -81,7 +83,8 @@ extern int tick_is_broadcast_device(struct clock_event_device *dev);
 extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
 extern void tick_shutdown_broadcast(unsigned int *cpup);
 extern void tick_suspend_broadcast(void);
-extern int tick_resume_broadcast(void);
+extern void tick_resume_broadcast(void);
+extern bool tick_resume_check_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
 extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
@@ -95,7 +98,8 @@ static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
 static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
 static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
-static inline int tick_resume_broadcast(void) { return 0; }
+static inline void tick_resume_broadcast(void) { }
+static inline bool tick_resume_check_broadcast(void) { return false; }
 static inline void tick_broadcast_init(void) { }
 static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
 

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

* [tip:timers/core] arm/bL_switcher: Kill tick suspend hackery
  2015-03-25 12:11   ` [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery Rafael J. Wysocki
  2015-03-25 12:34     ` Nicolas Pitre
@ 2015-04-02 12:30     ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 106+ messages in thread
From: tip-bot for Thomas Gleixner @ 2015-04-02 12:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, nicolas.pitre, tglx, rmk+kernel, rafael.j.wysocki,
	mingo, hpa, peterz

Commit-ID:  7270d11c56f594af4d166b2988421cd8ed933dc1
Gitweb:     http://git.kernel.org/tip/7270d11c56f594af4d166b2988421cd8ed933dc1
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Wed, 25 Mar 2015 13:11:52 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Apr 2015 14:23:00 +0200

arm/bL_switcher: Kill tick suspend hackery

Use the new tick_suspend/resume_local() and get rid of the
homebrewn implementation of these in the ARM bL switcher.  The
check for the cpumask is completely pointless.  There is no harm
to suspend a per cpu tick device unconditionally.  If that's a
real issue then we fix it proper at the core level and not with
some completely undocumented hacks in some random core code.

Move the tick internals to the core code, now that this nuisance
is gone.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[ rjw: Rebase, changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Link: http://lkml.kernel.org/r/1655112.Ws17YsMfN7@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/arm/common/bL_switcher.c | 16 ++--------------
 include/linux/clockchips.h    |  6 ------
 include/linux/tick.h          | 19 ++++---------------
 kernel/time/tick-common.c     |  2 +-
 kernel/time/tick-internal.h   |  5 +++++
 kernel/time/tick-sched.h      | 10 ++++++++++
 6 files changed, 22 insertions(+), 36 deletions(-)

diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index d4f970a..37dc0fe 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -151,8 +151,6 @@ static int bL_switch_to(unsigned int new_cluster_id)
 	unsigned int mpidr, this_cpu, that_cpu;
 	unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
 	struct completion inbound_alive;
-	struct tick_device *tdev;
-	enum clock_event_state tdev_state;
 	long volatile *handshake_ptr;
 	int ipi_nr, ret;
 
@@ -219,13 +217,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
 	/* redirect GIC's SGIs to our counterpart */
 	gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
 
-	tdev = tick_get_device(this_cpu);
-	if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
-		tdev = NULL;
-	if (tdev) {
-		tdev_state = tdev->evtdev->state;
-		clockevents_set_state(tdev->evtdev, CLOCK_EVT_STATE_SHUTDOWN);
-	}
+	tick_suspend_local();
 
 	ret = cpu_pm_enter();
 
@@ -251,11 +243,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
 
 	ret = cpu_pm_exit();
 
-	if (tdev) {
-		clockevents_set_state(tdev->evtdev, tdev_state);
-		clockevents_program_event(tdev->evtdev,
-					  tdev->evtdev->next_event, 1);
-	}
+	tick_resume_local();
 
 	trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
 	local_fiq_enable();
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 50ce975..3ac7e2d 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -198,12 +198,6 @@ clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 				      freq, minsec);
 }
 
-/* Should be core only, but is abused by arm bl_switcher */
-extern void clockevents_set_state(struct clock_event_device *dev,
-				 enum clock_event_state state);
-extern int clockevents_program_event(struct clock_event_device *dev,
-				     ktime_t expires, bool force);
-
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
diff --git a/include/linux/tick.h b/include/linux/tick.h
index a3d4d28..589868b 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -11,30 +11,19 @@
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
-/* ARM BL switcher abuse support */
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-enum tick_device_mode {
-	TICKDEV_MODE_PERIODIC,
-	TICKDEV_MODE_ONESHOT,
-};
-
-struct tick_device {
-	struct clock_event_device *evtdev;
-	enum tick_device_mode mode;
-};
-extern struct tick_device *tick_get_device(int cpu);
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void __init tick_init(void);
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
-/* Should be core only, but XEN resume magic requires this */
+/* Should be core only, but ARM BL switcher requires it */
+extern void tick_suspend_local(void);
+/* Should be core only, but XEN resume magic and ARM BL switcher require it */
 extern void tick_resume_local(void);
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
 static inline void tick_init(void) { }
 static inline void tick_freeze(void) { }
 static inline void tick_unfreeze(void) { }
+static inline void tick_suspend_local(void) { }
 static inline void tick_resume_local(void) { }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index da796d6..e28ba5c 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -380,7 +380,7 @@ void tick_shutdown(unsigned int *cpup)
  *
  * No locks required. Nothing can change the per cpu device.
  */
-static void tick_suspend_local(void)
+void tick_suspend_local(void)
 {
 	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 6ba7bce..5fc2daf 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -28,6 +28,7 @@ extern bool tick_check_replacement(struct clock_event_device *curdev,
 				   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
 extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
 
 extern int clockevents_tick_resume(struct clock_event_device *dev);
 /* Check, if the device is functional or a dummy for broadcast */
@@ -39,6 +40,10 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
 extern void clockevents_shutdown(struct clock_event_device *dev);
 extern void clockevents_exchange_device(struct clock_event_device *old,
 					struct clock_event_device *new);
+extern void clockevents_set_state(struct clock_event_device *dev,
+				 enum clock_event_state state);
+extern int clockevents_program_event(struct clock_event_device *dev,
+				     ktime_t expires, bool force);
 extern void clockevents_handle_noop(struct clock_event_device *dev);
 extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h
index 9307432..28b5da3 100644
--- a/kernel/time/tick-sched.h
+++ b/kernel/time/tick-sched.h
@@ -3,6 +3,16 @@
 
 #include <linux/hrtimer.h>
 
+enum tick_device_mode {
+	TICKDEV_MODE_PERIODIC,
+	TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+	struct clock_event_device *evtdev;
+	enum tick_device_mode mode;
+};
+
 enum tick_nohz_mode {
 	NOHZ_MODE_INACTIVE,
 	NOHZ_MODE_LOWRES,

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

* [tip:timers/core] timers/PM: Fix up tick_unfreeze()
  2015-04-03 13:21       ` [PATCH][fix for tip/timers/core] timers / PM: Fix up tick_unfreeze() Rafael J. Wysocki
@ 2015-04-03 13:18         ` tip-bot for Rafael J. Wysocki
  2015-04-03 13:31         ` [PATCH][cleanup for tip/timers/core] timers / PM: Drop unnecessary braces from tick_freeze() Rafael J. Wysocki
  1 sibling, 0 replies; 106+ messages in thread
From: tip-bot for Rafael J. Wysocki @ 2015-04-03 13:18 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: rafael.j.wysocki, mingo, tglx, hpa, linux-kernel

Commit-ID:  422fe7502e3f16dc1c680f22d31f59f022edc10d
Gitweb:     http://git.kernel.org/tip/422fe7502e3f16dc1c680f22d31f59f022edc10d
Author:     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
AuthorDate: Fri, 3 Apr 2015 15:21:51 +0200
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Fri, 3 Apr 2015 15:15:51 +0200

timers/PM: Fix up tick_unfreeze()

A recent conflict resolution has left tick_resume() in
tick_unfreeze() which leads to an unbalanced execution of
tick_resume_broadcast() every time that function runs.

Fix that by replacing the tick_resume() in tick_unfreeze()
with tick_resume_local() as appropriate.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: boris.ostrovsky@oracle.com
Cc: david.vrabel@citrix.com
Cc: konrad.wilk@oracle.com
Cc: peterz@infradead.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/8099075.V0LvN3pQAV@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/tick-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index fac3e98..ad66a51 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -482,7 +482,7 @@ void tick_unfreeze(void)
 	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_resume();
 	else
-		tick_resume();
+		tick_resume_local();
 
 	tick_freeze_depth--;
 

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

* [tip:timers/core] timers/PM: Drop unnecessary braces from tick_freeze()
  2015-04-03 13:31         ` [PATCH][cleanup for tip/timers/core] timers / PM: Drop unnecessary braces from tick_freeze() Rafael J. Wysocki
@ 2015-04-03 13:18           ` tip-bot for Rafael J. Wysocki
  0 siblings, 0 replies; 106+ messages in thread
From: tip-bot for Rafael J. Wysocki @ 2015-04-03 13:18 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: mingo, hpa, tglx, linux-kernel, rafael.j.wysocki

Commit-ID:  def747087e83aa5f6a71582cfa71e18341988688
Gitweb:     http://git.kernel.org/tip/def747087e83aa5f6a71582cfa71e18341988688
Author:     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
AuthorDate: Fri, 3 Apr 2015 15:31:32 +0200
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Fri, 3 Apr 2015 15:15:52 +0200

timers/PM: Drop unnecessary braces from tick_freeze()

Some braces in tick_freeze() are not necessary, so drop them.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: peterz@infradead.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1534128.H5hN3KBFB4@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/time/tick-common.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index ad66a51..3ae6afa 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -457,11 +457,10 @@ void tick_freeze(void)
 	raw_spin_lock(&tick_freeze_lock);
 
 	tick_freeze_depth++;
-	if (tick_freeze_depth == num_online_cpus()) {
+	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_suspend();
-	} else {
+	else
 		tick_suspend_local();
-	}
 
 	raw_spin_unlock(&tick_freeze_lock);
 }

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

* [PATCH][fix for tip/timers/core] timers / PM: Fix up tick_unfreeze()
  2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
@ 2015-04-03 13:21       ` Rafael J. Wysocki
  2015-04-03 13:18         ` [tip:timers/core] timers/PM: " tip-bot for Rafael J. Wysocki
  2015-04-03 13:31         ` [PATCH][cleanup for tip/timers/core] timers / PM: Drop unnecessary braces from tick_freeze() Rafael J. Wysocki
  0 siblings, 2 replies; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-04-03 13:21 UTC (permalink / raw)
  To: peterz, mingo
  Cc: rafael.j.wysocki, konrad.wilk, boris.ostrovsky, tglx,
	david.vrabel, linux-kernel, hpa, Linux PM list

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

A recent conflict resolution has left tick_resume() in
tick_unfreeze() which leads to an unbalanced execution of
tick_resume_broadcast() every time that function runs.

Fix that by replacing the tick_resume() in tick_unfreeze()
with tick_resume_local() as appropriate.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/tick-common.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -482,7 +482,7 @@ void tick_unfreeze(void)
 	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_resume();
 	else
-		tick_resume();
+		tick_resume_local();
 
 	tick_freeze_depth--;
 


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

* [PATCH][cleanup for tip/timers/core] timers / PM: Drop unnecessary braces from tick_freeze()
  2015-04-03 13:21       ` [PATCH][fix for tip/timers/core] timers / PM: Fix up tick_unfreeze() Rafael J. Wysocki
  2015-04-03 13:18         ` [tip:timers/core] timers/PM: " tip-bot for Rafael J. Wysocki
@ 2015-04-03 13:31         ` Rafael J. Wysocki
  2015-04-03 13:18           ` [tip:timers/core] timers/PM: " tip-bot for Rafael J. Wysocki
  1 sibling, 1 reply; 106+ messages in thread
From: Rafael J. Wysocki @ 2015-04-03 13:31 UTC (permalink / raw)
  To: peterz, mingo; +Cc: rafael.j.wysocki, tglx, linux-kernel, hpa, Linux PM list

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Some braces in tick_freeze() are not necessary, so drop them.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/time/tick-common.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux-pm/kernel/time/tick-common.c
===================================================================
--- linux-pm.orig/kernel/time/tick-common.c
+++ linux-pm/kernel/time/tick-common.c
@@ -457,11 +457,10 @@ void tick_freeze(void)
 	raw_spin_lock(&tick_freeze_lock);
 
 	tick_freeze_depth++;
-	if (tick_freeze_depth == num_online_cpus()) {
+	if (tick_freeze_depth == num_online_cpus())
 		timekeeping_suspend();
-	} else {
+	else
 		tick_suspend_local();
-	}
 
 	raw_spin_unlock(&tick_freeze_lock);
 }


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

end of thread, other threads:[~2015-04-03 13:19 UTC | newest]

Thread overview: 106+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-16 12:14 [PATCH 00/35] Some kernel/time cleanups Peter Zijlstra
2015-02-16 12:14 ` [PATCH 01/35] ACPI/acpi_pad: Remove the local apic nonsense Peter Zijlstra
2015-02-16 18:54   ` Rafael J. Wysocki
2015-02-18  6:16     ` Rafael J. Wysocki
2015-02-16 12:14 ` [PATCH 02/35] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Peter Zijlstra
2015-02-16 12:14 ` [PATCH 03/35] tick: Cleanup internal header files Peter Zijlstra
2015-02-16 12:14 ` [PATCH 04/35] tick: Cleanup internal header file Peter Zijlstra
2015-02-16 12:14 ` [PATCH 05/35] tick: Move core only declarations and functions to core Peter Zijlstra
2015-02-16 12:14 ` [PATCH 06/35] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Peter Zijlstra
2015-02-16 12:14 ` [PATCH 07/35] clockevents: Make suspend/resume calls explicit Peter Zijlstra
2015-02-16 19:07   ` Rafael J. Wysocki
2015-02-16 12:14 ` [PATCH 08/35] tick: Make tick_resume_broadcast_oneshot static Peter Zijlstra
2015-02-16 12:14 ` [PATCH 09/35] tick/xen: Provide and use tick_resume_local() Peter Zijlstra
2015-02-16 16:37   ` David Vrabel
2015-02-16 12:14 ` [PATCH 10/35] clockevents: Make tick handover explicit Peter Zijlstra
2015-02-16 12:14 ` [PATCH 11/35] clockevents: Cleanup dead cpu explicitely Peter Zijlstra
2015-02-16 12:14 ` [PATCH 12/35] clockevents: Provide explicit broadcast control function Peter Zijlstra
2015-02-23 18:08   ` Daniel Lezcano
2015-02-24  0:38   ` Tony Lindgren
2015-02-16 12:14 ` [PATCH 13/35] x86, amd_idle: Use explicit broadcast control functions Peter Zijlstra
2015-02-16 12:14 ` [PATCH 14/35] ACPI / PAD: Use explicit broadcast control function Peter Zijlstra
2015-02-16 12:14 ` [PATCH 15/35] ACPI/ processor_idle: Use explicit broadcast controll function Peter Zijlstra
2015-02-16 12:14 ` [PATCH 16/35] cpuidle: Use explicit broadcast control function Peter Zijlstra
2015-02-23 18:11   ` Daniel Lezcano
2015-02-16 12:14 ` [PATCH 17/35] intel_idle: " Peter Zijlstra
2015-02-16 12:14 ` [PATCH 18/35] ARM: OMAP: " Peter Zijlstra
2015-02-24  0:40   ` Tony Lindgren
2015-02-16 12:14 ` [PATCH 19/35] clockevents: Remove the broadcast control leftovers Peter Zijlstra
2015-02-16 12:14 ` [PATCH 20/35] clockevents: Provide explicit broadcast oneshot control function Peter Zijlstra
2015-02-24  0:41   ` Tony Lindgren
2015-02-16 12:14 ` [PATCH 21/35] x86, amd_idle: Use explicit broadcast oneshot control functions Peter Zijlstra
2015-02-16 12:14 ` [PATCH 22/35] ACPI / PAD: Use explicit broadcast oneshot control function Peter Zijlstra
2015-02-16 12:14 ` [PATCH 23/35] ACPI/ processor_idle: Use explicit broadcast oneshot controll function Peter Zijlstra
2015-02-16 12:14 ` [PATCH 24/35] intel_idle: Use explicit broadcast oneshot control function Peter Zijlstra
2015-02-16 12:15 ` [PATCH 25/35] ARM: OMAP: " Peter Zijlstra
2015-02-24  0:41   ` Tony Lindgren
2015-02-16 12:15 ` [PATCH 26/35] ARM: tegra: " Peter Zijlstra
2015-02-16 12:15 ` [PATCH 27/35] sched/idle: " Peter Zijlstra
2015-02-21  0:56   ` Nicolas Pitre
2015-02-21 11:19     ` Peter Zijlstra
2015-02-16 12:15 ` [PATCH 28/35] clockevents: Remove the broadcast oneshot control leftovers Peter Zijlstra
2015-02-16 12:15 ` [PATCH 29/35] tick/timekeeping: Make PM_SLEEP related code conditional Peter Zijlstra
2015-02-16 12:15 ` [PATCH 30/35] timekeeping: Get rid of stale comment Peter Zijlstra
2015-02-16 12:15 ` [PATCH 31/35] clockevents: Consolidate tick_shutdown() Peter Zijlstra
2015-02-16 12:15 ` [PATCH 32/35] clockevents: Fix cpu down race for hrtimer based broadcasting Peter Zijlstra
2015-02-17  4:03   ` Preeti U Murthy
2015-02-17 10:39     ` Peter Zijlstra
2015-02-18  3:10       ` Preeti U Murthy
2015-02-18 13:06         ` Peter Zijlstra
2015-02-19  7:01           ` Preeti U Murthy
2015-02-19  9:53             ` Peter Zijlstra
2015-02-19 17:51   ` Nicolas Pitre
2015-02-21 12:46     ` Peter Zijlstra
2015-02-21 17:45       ` Nicolas Pitre
2015-02-23 16:14         ` Peter Zijlstra
2015-02-23 16:32           ` Nicolas Pitre
2015-02-23 17:33             ` Nicolas Pitre
2015-02-26  5:31               ` Preeti U Murthy
2015-02-27  8:49                 ` Preeti U Murthy
2015-03-02 14:56                   ` Peter Zijlstra
2015-03-05  4:20                     ` Preeti U Murthy
2015-03-29  6:45                       ` Ingo Molnar
2015-03-16  4:52                     ` Preeti U Murthy
2015-03-25  5:32                       ` Preeti U Murthy
2015-02-16 12:15 ` [PATCH 33/35] tick: Make hrtimer broadcasting opt-in Peter Zijlstra
2015-02-17  3:06   ` Preeti U Murthy
2015-02-17 10:04   ` Lorenzo Pieralisi
2015-02-16 12:15 ` [PATCH 34/35] tick: Provide tick_suspend_local() Peter Zijlstra
2015-02-17 14:31   ` Lorenzo Pieralisi
2015-02-17 17:55     ` Nicolas Pitre
2015-02-17 21:29       ` Nicolas Pitre
2015-02-18 13:35     ` Peter Zijlstra
2015-02-18 16:22       ` Rafael J. Wysocki
2015-02-18 16:38       ` Lorenzo Pieralisi
2015-02-16 12:15 ` [PATCH 35/35] arm: bl_switcher: Kill tick suspend hackery Peter Zijlstra
2015-02-16 19:14 ` [PATCH 00/35] Some kernel/time cleanups Rafael J. Wysocki
2015-03-25 12:04 ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
2015-03-25 12:05   ` [PATCH 01/09] clockevents: Remove CONFIG_GENERIC_CLOCKEVENTS_BUILD Rafael J. Wysocki
2015-04-02 12:28     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-03-25 12:06   ` [PATCH 02/09] tick: Move clocksource related stuff to timekeeping.h Rafael J. Wysocki
2015-04-02 12:28     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-03-25 12:06   ` [PATCH 03/09] tick: Simplify tick-internal.h Rafael J. Wysocki
2015-04-02 12:29     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-03-25 12:07   ` [PATCH 04/09] tick: Move core only declarations and functions to core Rafael J. Wysocki
2015-04-02 12:29     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-03-25 12:08   ` [PATCH 05/09] clockevents: Remove extra local_irq_save in clockevents_exchange_device() Rafael J. Wysocki
2015-04-02 12:29     ` [tip:timers/core] clockevents: Remove extra local_irq_save() " tip-bot for Thomas Gleixner
2015-03-25 12:09   ` [PATCH 06/09] clockevents: Make suspend/resume calls explicit Rafael J. Wysocki
2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-03-25 12:09   ` [PATCH 07/09] tick: Make tick_resume_broadcast_oneshot static Rafael J. Wysocki
2015-04-02 12:30     ` [tip:timers/core] tick: Make tick_resume_broadcast_oneshot() static tip-bot for Thomas Gleixner
2015-03-25 12:11   ` [PATCH 08/09] tick/xen: Provide and use tick_suspend_local() and tick_resume_local() Rafael J. Wysocki
2015-03-25 20:13     ` Konrad Rzeszutek Wilk
2015-03-25 20:57       ` Rafael J. Wysocki
2015-03-25 20:44         ` Konrad Rzeszutek Wilk
2015-03-25 21:36           ` Rafael J. Wysocki
2015-04-02 12:30     ` [tip:timers/core] " tip-bot for Thomas Gleixner
2015-04-03 13:21       ` [PATCH][fix for tip/timers/core] timers / PM: Fix up tick_unfreeze() Rafael J. Wysocki
2015-04-03 13:18         ` [tip:timers/core] timers/PM: " tip-bot for Rafael J. Wysocki
2015-04-03 13:31         ` [PATCH][cleanup for tip/timers/core] timers / PM: Drop unnecessary braces from tick_freeze() Rafael J. Wysocki
2015-04-03 13:18           ` [tip:timers/core] timers/PM: " tip-bot for Rafael J. Wysocki
2015-03-25 12:11   ` [PATCH 09/09] arm: bl_switcher: Kill tick suspend hackery Rafael J. Wysocki
2015-03-25 12:34     ` Nicolas Pitre
2015-04-02 12:30     ` [tip:timers/core] arm/bL_switcher: " tip-bot for Thomas Gleixner
2015-03-25 12:13   ` [PATCH 00/09] Some kernel/time cleanups (related to timer_suspend/resume) Rafael J. Wysocki
2015-03-31 22:45   ` [GIT PULL] kernel/time cleanups (related to tick_suspend/resume) Rafael J. Wysocki

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