All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@domain.hid>
To: Xenomai-core@domain.hid
Subject: [Xenomai-core] [PATCH] fix hw-timer setup/cleanup for i386
Date: Thu, 11 Oct 2007 22:47:58 +0200	[thread overview]
Message-ID: <470E8BFE.4070804@domain.hid> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 797 bytes --]

This patch for SVN trunk fixes most of the current bugs around hardware
timer takeover and release from/to Linux. Tested and found working here
(including SMP):
- 2.6.22, APIC, highres=off, nohz=off
- 2.6.22, APIC, highres=on, nohz=on
- 2.6.20, APIC

Tests to be done:
- 2.6.22, PIT (currently building...)
- 2.6.20, PIT

Things became quite complex in i386/hal.c now. Some of this complexity
might be avoidable if RTHAL_APIC_TIMER_VECTOR equalled
LOCAL_TIMER_VECTOR. What's the reason for this? Is it something related
to pre-highres times of Linux (ie. 2.6.20 and earlier)? Can we overcome
it, at least for recent kernels?

So, while this patch may work correctly, my feeling is it needs yet
another round of polishing, also looking for now possibly outdated comments.

Jan

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: fix-timers.patch --]
[-- Type: text/x-patch; name="fix-timers.patch", Size: 6346 bytes --]

Index: xenomai/ksrc/arch/i386/hal.c
===================================================================
--- xenomai/ksrc/arch/i386/hal.c	(Revision 3050)
+++ xenomai/ksrc/arch/i386/hal.c	(Arbeitskopie)
@@ -77,7 +77,12 @@ static struct {
 	int count;
 } rthal_linux_irq[IPIPE_NR_XIRQS];
 
-static int rthal_ktimer_oneshot;
+static enum {
+	KTIMER_MODE_UNUSED = 0,
+	KTIMER_MODE_SHUTDOWN,
+	KTIMER_MODE_PERIODIC,
+	KTIMER_MODE_ONESHOT,
+} rthal_ktimer_saved_mode;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
@@ -103,15 +108,24 @@ static inline void rthal_setup_oneshot_a
 	apic_write_around(APIC_LVTT, rthal_set_apic_base(vector));
 }
 
+#define RTHAL_SET_ONESHOT_RT		1
+#define RTHAL_SET_ONESHOT_LINUX		2
+#define RTHAL_SET_PERIODIC		3
+
 static void rthal_critical_sync(void)
 {
 	switch (rthal_sync_op) {
-	case 1:
+	case RTHAL_SET_ONESHOT_RT:
 		rthal_setup_oneshot_apic(RTHAL_APIC_TIMER_VECTOR);
 		break;
 
-	case 2:
+	case RTHAL_SET_ONESHOT_LINUX:
+		rthal_setup_oneshot_apic(LOCAL_TIMER_VECTOR);
+		/* We need to keep the timing cycle alive for the kernel. */
+		rthal_trigger_irq(ipipe_apic_vector_irq(LOCAL_TIMER_VECTOR));
+		break;
 
+	case RTHAL_SET_PERIODIC:
 		rthal_setup_periodic_apic(RTHAL_APIC_ICOUNT, LOCAL_TIMER_VECTOR);
 		break;
 	}
@@ -218,13 +232,20 @@ static void rthal_latency_above_max(stru
 
 #endif /* CONFIG_XENO_HW_NMI_DEBUG_LATENCY */
 
-static void rthal_timer_set_oneshot(void)
+static void rthal_timer_set_oneshot(int rt_mode)
 {
 	unsigned long flags;
 
 	flags = rthal_critical_enter(rthal_critical_sync);
-	rthal_sync_op = 1;
-	rthal_setup_oneshot_apic(RTHAL_APIC_TIMER_VECTOR);
+	if (rt_mode) {
+		rthal_sync_op = RTHAL_SET_ONESHOT_RT;
+		rthal_setup_oneshot_apic(RTHAL_APIC_TIMER_VECTOR);
+	} else {
+		rthal_sync_op = RTHAL_SET_ONESHOT_LINUX;
+		rthal_setup_oneshot_apic(LOCAL_TIMER_VECTOR);
+		/* We need to keep the timing cycle alive for the kernel. */
+		rthal_trigger_irq(ipipe_apic_vector_irq(LOCAL_TIMER_VECTOR));
+	}
 	rthal_critical_exit(flags);
 }
 
@@ -233,7 +254,7 @@ static void rthal_timer_set_periodic(voi
 	unsigned long flags;
 
 	flags = rthal_critical_enter(&rthal_critical_sync);
-	rthal_sync_op = 2;
+	rthal_sync_op = RTHAL_SET_PERIODIC;
 	rthal_setup_periodic_apic(RTHAL_APIC_ICOUNT, LOCAL_TIMER_VECTOR);
 	rthal_critical_exit(flags);
 }
@@ -261,13 +282,16 @@ int rthal_timer_request(
 		 * the caller to start an internal timer for emulating
 		 * a periodic tick. */
 		tickval = 1000000000UL / HZ;
-		rthal_ktimer_oneshot = 0;
 		break;
 
-	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_ONESHOT:
+		/* oneshot tick emulation */
+		tickval = 1;
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+		/* we don't need to emulate the tick at all. */
 		tickval = 0;
-		rthal_ktimer_oneshot = 1;
 		break;
 
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -276,6 +300,8 @@ int rthal_timer_request(
 	default:
 		return err;
 	}
+
+	rthal_ktimer_saved_mode = err;
 #else /* !CONFIG_GENERIC_CLOCKEVENTS */
 	/*
 	 * When the local APIC is enabled for kernels lacking generic
@@ -285,7 +311,7 @@ int rthal_timer_request(
 	 * APIC-based timer interrupt instead, i.e. RTHAL_APIC_TIMER_IPI).
 	 */
 	tickval = 0;
-	rthal_ktimer_oneshot = 1;
+	rthal_ktimer_saved_mode = KTIMER_MODE_PERIODIC;
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 	/*
@@ -295,7 +321,7 @@ int rthal_timer_request(
 	if (cpu > 0)
 		goto out;
 
-	rthal_timer_set_oneshot();
+	rthal_timer_set_oneshot(1);
 
 	err = rthal_irq_request(RTHAL_APIC_TIMER_IPI,
 			  (rthal_irq_handler_t) tick_handler, NULL, NULL);
@@ -335,8 +361,10 @@ void rthal_timer_release(int cpu)
 
 	rthal_irq_release(RTHAL_APIC_TIMER_IPI);
 
-	if (!rthal_ktimer_oneshot)
+	if (rthal_ktimer_saved_mode == KTIMER_MODE_PERIODIC)
 		rthal_timer_set_periodic();
+	else if (rthal_ktimer_saved_mode == KTIMER_MODE_ONESHOT)
+		rthal_timer_set_oneshot(0);
 }
 
 #else /* !CONFIG_X86_LOCAL_APIC */
@@ -445,13 +473,16 @@ int rthal_timer_request(
 		 * the caller to start an internal timer for emulating
 		 * a periodic tick. */
 		tickval = 1000000000UL / HZ;
-		rthal_ktimer_oneshot = 0;
 		break;
 
-	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_ONESHOT:
+		/* oneshot tick emulation */
+		tickval = 1;
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+		/* we don't need to emulate the tick at all. */
 		tickval = 0;
-		rthal_ktimer_oneshot = 1;
 		break;
 
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -460,13 +491,15 @@ int rthal_timer_request(
 	default:
 		return err;
 	}
+
+	rthal_ktimer_saved_mode = err;
 #else /* !CONFIG_GENERIC_CLOCKEVENTS */
 	/*
 	 * Out caller has to to emulate the periodic host tick by its
 	 * own means once we will have grabbed the PIT.
 	 */
 	tickval = 1000000000UL / HZ;
-	rthal_ktimer_oneshot = 0;
+	rthal_ktimer_saved_mode = KTIMER_MODE_PERIODIC;
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 	/*
@@ -489,9 +522,9 @@ void rthal_timer_release(int cpu)
 #endif
 	rthal_irq_release(RTHAL_TIMER_IRQ);
 
-	if (!rthal_ktimer_oneshot)
+	if (rthal_ktimer_saved_mode == KTIMER_MODE_PERIODIC)
 		rthal_timer_set_periodic();
-	else
+	else if (rthal_ktimer_saved_mode == KTIMER_MODE_ONESHOT)
 		/* We need to keep the timing cycle alive for the kernel. */
 		rthal_trigger_irq(RTHAL_TIMER_IRQ);
 }
@@ -561,16 +594,7 @@ void rthal_timer_notify_switch(enum cloc
 		 */
 		return;
 
-	switch(mode) {
-	case CLOCK_EVT_MODE_ONESHOT:
-		rthal_ktimer_oneshot = 1;
-		break;
-	case CLOCK_EVT_MODE_PERIODIC:
-		rthal_ktimer_oneshot = 0;
-		break;
-	default:
-		;
-	}
+	rthal_ktimer_saved_mode = mode;
 }
 
 EXPORT_SYMBOL(rthal_timer_notify_switch);
Index: xenomai/ksrc/nucleus/pod.c
===================================================================
--- xenomai/ksrc/nucleus/pod.c	(Revision 3050)
+++ xenomai/ksrc/nucleus/pod.c	(Arbeitskopie)
@@ -3076,10 +3076,10 @@ int xnpod_enable_timesource(void)
 		 * Linux as needed.
 		 */
 
-		if (htickval)
+		if (htickval > 1)
 			xntimer_start(&sched->htimer, htickval, htickval, XN_RELATIVE);
-
-		__setbits(sched->status, XNHTICK);
+		else
+			xntimer_start(&sched->htimer, 0, 0, XN_RELATIVE);
 
 #if defined(CONFIG_XENO_OPT_WATCHDOG)
 		xntimer_start(&sched->wdtimer, 1000000000UL, 1000000000UL, XN_RELATIVE);

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

             reply	other threads:[~2007-10-11 20:47 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-11 20:47 Jan Kiszka [this message]
2007-10-12  8:58 ` [Xenomai-core] [PATCH] fix hw-timer setup/cleanup for i386 Stelian Pop
2007-10-12  9:14   ` Jan Kiszka
2007-10-12 11:00     ` Stelian Pop
2007-10-12 11:15       ` Jan Kiszka
2007-10-12 13:19         ` Stelian Pop
2007-10-12 13:39           ` Jan Kiszka
2007-10-12 13:41           ` Philippe Gerum
2007-10-12 14:26             ` Stelian Pop
2007-10-12 19:53       ` Jan Kiszka
2007-10-12 20:22         ` Stelian Pop
2007-10-12 21:51           ` Stelian Pop
2007-10-12 21:58             ` Philippe Gerum
2007-10-13 14:28               ` Stelian Pop
2007-10-13 14:42                 ` Jan Kiszka
2007-10-13 16:12                   ` Stelian Pop
2007-10-13 16:35                     ` Philippe Gerum
2007-10-13 16:38                     ` Jan Kiszka
2007-10-13 20:55                       ` Stelian Pop
2007-10-13 14:32           ` Stelian Pop
2007-10-12  9:00 ` Jan Kiszka
2007-10-12  9:16 ` Philippe Gerum
2007-10-12  9:47   ` Jan Kiszka
2007-10-12 12:48     ` Philippe Gerum

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=470E8BFE.4070804@domain.hid \
    --to=jan.kiszka@domain.hid \
    --cc=Xenomai-core@domain.hid \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.