linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Tony Breeds <tony@bakeyournoodle.com>
To: <linuxppc-dev@ozlabs.org>, Paul Mackerras <paulus@samba.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Realtime Kernel <linux-rt-users@vger.kernel.org>
Subject: [PATCH v2 3/4] Implement clockevents driver for powerpc
Date: Fri, 21 Sep 2007 13:26:03 +1000	[thread overview]
Message-ID: <20070921032603.0D3EA32C887@thor> (raw)
In-Reply-To: <1190345162.620000.305760830507.qpush@thor>

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>

---
Updated to remove a trivial FIXME left behind

 arch/powerpc/Kconfig       |    3 
 arch/powerpc/kernel/smp.c  |    3 
 arch/powerpc/kernel/time.c |  134 +++++++++++++++++++++++++------------
 include/asm-powerpc/time.h |    1 
 4 files changed, 98 insertions(+), 43 deletions(-)

Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -30,6 +30,9 @@ config GENERIC_TIME
 config GENERIC_TIME_VSYSCALL
 	def_bool y
 
+config GENERIC_CLOCKEVENTS
+	def_bool y
+
 config GENERIC_HARDIRQS
 	bool
 	default y
Index: working/arch/powerpc/kernel/smp.c
===================================================================
--- working.orig/arch/powerpc/kernel/smp.c
+++ working/arch/powerpc/kernel/smp.c
@@ -560,6 +560,8 @@ int __devinit start_secondary(void *unus
 	if (system_state > SYSTEM_BOOTING)
 		snapshot_timebase();
 
+	secondary_cpu_time_init();
+
 	spin_lock(&call_lock);
 	cpu_set(cpu, cpu_online_map);
 	spin_unlock(&call_lock);
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -75,6 +75,7 @@
 
 /* powerpc clocksource/clockevent code */
 
+#include <linux/clockchips.h>
 #include <linux/clocksource.h>
 
 static cycle_t rtc_read(void);
@@ -99,6 +100,27 @@ static struct clocksource clocksource_ti
 	.read         = timebase_read,
 };
 
+#define DECREMENTER_MAX	0x7fffffff
+
+static int decrementer_set_next_event(unsigned long evt,
+				      struct clock_event_device *dev);
+static void decrementer_set_mode(enum clock_event_mode mode,
+				 struct clock_event_device *dev);
+
+static struct clock_event_device decrementer_clockevent = {
+       .name           = "decrementer",
+       .rating         = 200,
+       .shift          = 32,
+       .mult           = 0,	/* To be filled in */
+       .irq            = -1,
+       .set_next_event = decrementer_set_next_event,
+       .set_mode       = decrementer_set_mode,
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+};
+
+static DEFINE_PER_CPU(struct clock_event_device, decrementers);
+void init_decrementer_clockevent(void);
+
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long __initdata iSeries_recal_titan;
 static signed long __initdata iSeries_recal_tb;
@@ -519,10 +541,12 @@ void __init iSeries_time_init_early(void
 void timer_interrupt(struct pt_regs * regs)
 {
 	struct pt_regs *old_regs;
-	int next_dec;
 	int cpu = smp_processor_id();
-	unsigned long ticks;
-	u64 tb_next_jiffy;
+	struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+
+	/* Ensure a positive value is written to the decrementer, or else
+	 * some CPUs will continuue to take decrementer exceptions */
+	set_dec(DECREMENTER_MAX);
 
 #ifdef CONFIG_PPC32
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
@@ -532,7 +556,6 @@ void timer_interrupt(struct pt_regs * re
 	old_regs = set_irq_regs(regs);
 	irq_enter();
 
-	profile_tick(CPU_PROFILING);
 	calculate_steal_time();
 
 #ifdef CONFIG_PPC_ISERIES
@@ -540,44 +563,20 @@ void timer_interrupt(struct pt_regs * re
 		get_lppaca()->int_dword.fields.decr_int = 0;
 #endif
 
-	while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
-	       >= tb_ticks_per_jiffy) {
-		/* Update last_jiffy */
-		per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy;
-		/* Handle RTCL overflow on 601 */
-		if (__USE_RTC() && per_cpu(last_jiffy, cpu) >= 1000000000)
-			per_cpu(last_jiffy, cpu) -= 1000000000;
-
-		/*
-		 * We cannot disable the decrementer, so in the period
-		 * between this cpu's being marked offline in cpu_online_map
-		 * and calling stop-self, it is taking timer interrupts.
-		 * Avoid calling into the scheduler rebalancing code if this
-		 * is the case.
-		 */
-		if (!cpu_is_offline(cpu))
-			account_process_time(regs);
-
-		/*
-		 * No need to check whether cpu is offline here; boot_cpuid
-		 * should have been fixed up by now.
-		 */
-		if (cpu != boot_cpuid)
-			continue;
+	/*
+	 * We cannot disable the decrementer, so in the period
+	 * between this cpu's being marked offline in cpu_online_map
+	 * and calling stop-self, it is taking timer interrupts.
+	 * Avoid calling into the scheduler rebalancing code if this
+	 * is the case.
+	 */
+	if (!cpu_is_offline(cpu))
+		account_process_time(regs);
 
-		write_seqlock(&xtime_lock);
-		tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
-		if (__USE_RTC() && tb_next_jiffy >= 1000000000)
-			tb_next_jiffy -= 1000000000;
-		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
-			tb_last_jiffy = tb_next_jiffy;
-			do_timer(1);
-		}
-		write_sequnlock(&xtime_lock);
-	}
-	
-	next_dec = tb_ticks_per_jiffy - ticks;
-	set_dec(next_dec);
+	if (evt->event_handler)
+		evt->event_handler(evt);
+	else
+		evt->set_next_event(DECREMENTER_MAX, evt);
 
 #ifdef CONFIG_PPC_ISERIES
 	if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
@@ -797,6 +796,53 @@ void __init clocksource_init(void)
 	       clock->name, clock->mult, clock->shift);
 }
 
+static int decrementer_set_next_event(unsigned long evt,
+				      struct clock_event_device *dev)
+{
+	set_dec(evt);
+	return 0;
+}
+
+static void decrementer_set_mode(enum clock_event_mode mode,
+				 struct clock_event_device *dev)
+{
+	if (mode != CLOCK_EVT_MODE_ONESHOT)
+		decrementer_set_next_event(DECREMENTER_MAX, dev);
+}
+
+static void register_decrementer_clockevent(int cpu)
+{
+	struct clock_event_device *dec = &per_cpu(decrementers, cpu);
+
+	*dec = decrementer_clockevent;
+	dec->cpumask = cpumask_of_cpu(cpu);
+
+	printk(KERN_ERR "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
+	       dec->name, dec->mult, dec->shift, cpu);
+
+	clockevents_register_device(dec);
+}
+
+void init_decrementer_clockevent(void)
+{
+	int cpu = smp_processor_id();
+
+	decrementer_clockevent.mult = div_sc(ppc_tb_freq, NSEC_PER_SEC,
+					     decrementer_clockevent.shift);
+	decrementer_clockevent.max_delta_ns =
+		clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent);
+	decrementer_clockevent.min_delta_ns = 1000;
+
+	register_decrementer_clockevent(cpu);
+}
+
+void secondary_cpu_time_init(void)
+{
+	/* FIME: Should make unrelatred change to move snapshot_timebase
+	 * call here ! */
+	register_decrementer_clockevent(smp_processor_id());
+}
+
 /* This function is only called on the boot processor */
 void __init time_init(void)
 {
@@ -912,8 +958,7 @@ void __init time_init(void)
 #endif
 		clocksource_init();
 
-	/* Not exact, but the timer interrupt takes care of this */
-	set_dec(tb_ticks_per_jiffy);
+	init_decrementer_clockevent();
 }
 
 
Index: working/include/asm-powerpc/time.h
===================================================================
--- working.orig/include/asm-powerpc/time.h
+++ working/include/asm-powerpc/time.h
@@ -245,6 +245,7 @@ extern void snapshot_timebases(void);
 #define snapshot_timebases()			do { } while (0)
 #endif
 
+extern void secondary_cpu_time_init(void);
 extern void iSeries_time_init_early(void);
 
 #endif /* __KERNEL__ */

  parent reply	other threads:[~2007-09-21  3:28 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-21  3:26 [PATCH v2 1/4] Implement {read,update}_persistent_clock Tony Breeds
2007-09-21  3:26 ` [PATCH v2 2/4] Implement generic time of day clocksource for powerpc machines Tony Breeds
2007-09-21  4:05   ` Daniel Walker
2007-09-21  4:59     ` Paul Mackerras
2007-09-21  6:43       ` David Gibson
2007-09-21  4:52   ` Stephen Rothwell
2007-09-21 21:35     ` Tony Breeds
2007-09-21 21:35     ` [PATCH v3 " Tony Breeds
2007-10-03  0:48       ` Paul Mackerras
2007-10-03  4:00         ` Thomas Gleixner
2007-09-21  3:26 ` Tony Breeds [this message]
2007-10-15 17:40   ` [PATCH v2 3/4] Implement clockevents driver for powerpc Sergei Shtylyov
2007-10-15 18:33     ` Sergei Shtylyov
2007-10-15 23:44     ` Paul Mackerras
2007-10-17 14:29       ` Sergei Shtylyov
2007-10-18  0:51         ` Paul Mackerras
2007-10-18 15:11           ` Sergei Shtylyov
2007-10-19  1:53             ` Paul Mackerras
2007-10-19 12:11               ` Sergei Shtylyov
2007-10-19 12:36                 ` Paul Mackerras
2007-10-19 13:35                   ` Sergei Shtylyov
2007-10-24 12:07                     ` Sergei Shtylyov
2007-10-24 23:55                       ` Paul Mackerras
2007-10-17 14:34       ` Sergei Shtylyov
2007-10-18  0:36         ` Paul Mackerras
2007-10-18 14:48           ` Sergei Shtylyov
2007-10-19  0:14             ` Paul Mackerras
2007-10-19  9:22               ` Gabriel Paubert
2007-10-19 11:22                 ` Paul Mackerras
2007-10-19 11:49               ` Sergei Shtylyov
2007-10-19 12:24                 ` Paul Mackerras
2007-09-21  3:26 ` [PATCH v2 4/4] Enable tickless idle and high res timers " Tony Breeds
2007-09-26 19:04 ` [PATCH v2 1/4] Implement {read,update}_persistent_clock Steven Rostedt
2007-09-26 19:39   ` Sergei Shtylyov
2007-09-26 19:44     ` Steven Rostedt
2007-09-26 19:58       ` Thomas Gleixner
2007-10-15 18:05         ` Sergei Shtylyov
2007-10-15 23:46           ` Paul Mackerras
2007-10-16  1:19           ` Benjamin Herrenschmidt
2007-10-17 12:45             ` Sergei Shtylyov
2007-09-27  1:59     ` Benjamin Herrenschmidt
2007-10-15 18:07       ` Sergei Shtylyov
2007-10-15 23:02         ` Benjamin Herrenschmidt
2007-10-17 15:34 ` Sergei Shtylyov
2007-10-18 14:18   ` Sergei Shtylyov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070921032603.0D3EA32C887@thor \
    --to=tony@bakeyournoodle.com \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=paulus@samba.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).