From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>,
Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>,
"Luiz Fernando N. Capitulino" <lcapitulino@mandriva.com.br>,
Dmitry Nezhevenko <dion@inhex.net>
Subject: [patch 5/6] clockevents: prevent endless loop lockup
Date: Wed, 03 Sep 2008 21:37:14 -0000 [thread overview]
Message-ID: <20080903212753.342810660@linutronix.de> (raw)
In-Reply-To: <20080903212735.713411776@linutronix.de>
[-- Attachment #1: clockevents-prevent-endless-loop-lockup.patch --]
[-- Type: text/plain, Size: 4356 bytes --]
The C1E/HPET bug reports on AMDX2/RS690 systems where tracked down to a
too small value of the HPET minumum delta for programming an event.
The clockevents code needs to enforce an interrupt event on the clock event
device in some cases. The enforcement code was stupid and naive, as it just
added the minimum delta to the current time and tried to reprogram the device.
When the minimum delta is too small, then this loops forever.
Add a sanity check. Allow reprogramming to fail 3 times, then print a warning
and double the minimum delta value to make sure, that this does not happen again.
Use the same function for both tick-oneshot and tick-broadcast code.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/time/tick-broadcast.c | 10 +---------
kernel/time/tick-internal.h | 2 ++
kernel/time/tick-oneshot.c | 36 ++++++++++++++++++++++++++++++------
3 files changed, 33 insertions(+), 15 deletions(-)
Index: linux-2.6/kernel/time/tick-broadcast.c
===================================================================
--- linux-2.6.orig/kernel/time/tick-broadcast.c
+++ linux-2.6/kernel/time/tick-broadcast.c
@@ -372,16 +372,8 @@ cpumask_t *tick_get_broadcast_oneshot_ma
static int tick_broadcast_set_event(ktime_t expires, int force)
{
struct clock_event_device *bc = tick_broadcast_device.evtdev;
- ktime_t now = ktime_get();
- int res;
- for(;;) {
- res = clockevents_program_event(bc, expires, now);
- if (!res || !force)
- return res;
- now = ktime_get();
- expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
- }
+ return tick_dev_program_event(bc, expires, force);
}
int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
Index: linux-2.6/kernel/time/tick-internal.h
===================================================================
--- linux-2.6.orig/kernel/time/tick-internal.h
+++ linux-2.6/kernel/time/tick-internal.h
@@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct
extern void tick_setup_oneshot(struct clock_event_device *newdev,
void (*handler)(struct clock_event_device *),
ktime_t nextevt);
+extern int tick_dev_program_event(struct clock_event_device *dev,
+ ktime_t expires, int force);
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 *));
Index: linux-2.6/kernel/time/tick-oneshot.c
===================================================================
--- linux-2.6.orig/kernel/time/tick-oneshot.c
+++ linux-2.6/kernel/time/tick-oneshot.c
@@ -25,18 +25,42 @@
/**
* tick_program_event internal worker function
*/
-static int __tick_program_event(struct clock_event_device *dev,
- ktime_t expires, int force)
+int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
+ int force)
{
ktime_t now = ktime_get();
+ int i;
- while (1) {
+ for (i = 0;;) {
int ret = clockevents_program_event(dev, expires, now);
if (!ret || !force)
return ret;
+
+ /*
+ * We tried 2 times to program the device with the given
+ * min_delta_ns. If that's not working then we double it
+ * and emit a warning.
+ */
+ if (++i > 2) {
+ printk(KERN_WARNING "CE: __tick_program_event of %s is "
+ "stuck %llx %llx\n", dev->name ? dev->name : "?",
+ now.tv64, expires.tv64);
+ printk(KERN_WARNING
+ "CE: increasing min_delta_ns %ld to %ld nsec\n",
+ dev->min_delta_ns, dev->min_delta_ns << 1);
+ WARN_ON(1);
+
+ /* Double the min. delta and try again */
+ if (!dev->min_delta_ns)
+ dev->min_delta_ns = 5000;
+ else
+ dev->min_delta_ns <<= 1;
+ i = 0;
+ }
+
now = ktime_get();
- expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
+ expires = ktime_add_ns(now, dev->min_delta_ns);
}
}
@@ -47,7 +71,7 @@ int tick_program_event(ktime_t expires,
{
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
- return __tick_program_event(dev, expires, force);
+ return tick_dev_program_event(dev, expires, force);
}
/**
@@ -71,7 +95,7 @@ void tick_setup_oneshot(struct clock_eve
{
newdev->event_handler = handler;
clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
- __tick_program_event(newdev, next_event, 1);
+ tick_dev_program_event(newdev, next_event, 1);
}
/**
--
next prev parent reply other threads:[~2008-09-03 21:38 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-03 21:36 [patch 0/6] final clockevents/hpet fixes Thomas Gleixner
2008-09-03 21:36 ` [patch 1/6] clockevents: Prevent clockevent event_handler ending up handler_noop Thomas Gleixner
2008-09-03 21:36 ` [patch 2/6] clockevents: prevent endless loop in periodic broadcast handler Thomas Gleixner
2008-09-03 21:37 ` [patch 3/6] clockevents: enforce reprogram in oneshot setup Thomas Gleixner
2008-09-03 21:37 ` [patch 4/6] clockevents: prevent multiple init/shutdown Thomas Gleixner
2008-09-03 21:37 ` Thomas Gleixner [this message]
2008-09-03 21:37 ` [patch 6/6] HPET: make minimum reprogramming delta useful Thomas Gleixner
2008-09-03 23:00 ` [patch 0/6] final clockevents/hpet fixes Dmitry Nezhevenko
2008-09-03 23:04 ` Thomas Gleixner
2008-09-03 23:27 ` Dmitry Nezhevenko
2008-09-04 18:33 ` Luiz Fernando N. Capitulino
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=20080903212753.342810660@linutronix.de \
--to=tglx@linutronix.de \
--cc=dion@inhex.net \
--cc=lcapitulino@mandriva.com.br \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=venkatesh.pallipadi@intel.com \
/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
all inboxes | Powered by JetHome®