All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Venkatesh Pallipadi" <venkatesh.pallipadi@intel.com>
To: "Ingo Molnar" <mingo@elte.hu>, "H. Peter Anvin" <hpa@zytor.com>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Len Brown" <lenb@kernel.org>,
	"Mark Hounschell" <markh@compro.net>
Cc: linux-kernel@vger.kernel.org, "Rafael J. Wysocki" <rjw@sisk.pl>,
	"Alain Knaff" <alain@knaff.lu>,
	"Linus Torvalds" <torvalds@linux-foundation.org>,
	"Li, Shaohua" <shaohua.li@intel.com>
Subject: [patch 3/4] clockevent: Add tick_check_fallback_timer to look for fallback timer
Date: Thu, 14 Jan 2010 17:40:00 -0800	[thread overview]
Message-ID: <20100115014210.137236000@intel.com> (raw)
In-Reply-To: 20100115013957.027452000@intel.com

[-- Attachment #1: 0004-clockevent-Add-tick_check_fallback_timer-to-look-fo.patch --]
[-- Type: text/plain, Size: 5089 bytes --]

Before switching to braodcast timer, in the event of C3 timer stoppage,
look for any other per cpu timer as a fallback.

This will be used in the following patch where we use HPET MSI as a
fallback timer for LAPIC timer, when C-states are supported.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
---
 include/linux/clockchips.h  |    2 +
 kernel/time/clockevents.c   |   29 +++++++++++++++++++++++++++-
 kernel/time/tick-common.c   |   44 +++++++++++++++++++++++++++++++++++++++++++
 kernel/time/tick-internal.h |    3 ++
 4 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 5352187..791952f 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -51,10 +51,12 @@ enum clock_event_nofitiers {
  * - Clockevent source stops in C3 State and needs broadcast support.
  * - Local APIC timer is used as a dummy device.
  * - Do not use this device as a broadcast device.
+ * - Rating has been reduced for this device as system is C3 capable.
  */
 #define CLOCK_EVT_FEAT_C3STOP		0x000004
 #define CLOCK_EVT_FEAT_DUMMY		0x000008
 #define CLOCK_EVT_FEAT_NO_BROADCAST	0x000010
+#define CLOCK_EVT_FEAT_RATING_REDUCED	0x000020
 
 /**
  * struct clock_event_device - clock event device descriptor
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 6f740d9..6641c97 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -161,7 +161,7 @@ static void clockevents_do_notify(unsigned long reason, void *dev)
  * Called after a notify add to make devices available which were
  * released from the notifier call.
  */
-static void clockevents_notify_released(void)
+void clockevents_notify_released(void)
 {
 	struct clock_event_device *dev;
 
@@ -203,6 +203,33 @@ void clockevents_handle_noop(struct clock_event_device *dev)
 }
 
 /**
+ * clockevents_lookup_newdev - lookup for a higher rated device on this cpu
+ * @cpu:	CPU that the call corresponds to
+ * @rating:	baseline rating (look for higher than this rating)
+ *
+ * Called from the notifier chain. clockevents_lock is held already
+ */
+struct clock_event_device *clockevents_lookup_newdev(int cpu, int rating)
+{
+	struct clock_event_device *dev, *tmp, *found_dev = NULL;
+	int found_rating = 0;
+
+	list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+		if (cpumask_test_cpu(cpu, dev->cpumask) &&
+		    cpumask_weight(dev->cpumask) == 1 &&
+		    dev->rating > found_rating) {
+			found_rating = dev->rating;
+			found_dev = dev;
+		}
+	}
+
+	if (found_rating > rating)
+		return found_dev;
+
+	return NULL;
+}
+
+/**
  * clockevents_exchange_device - release and request clock devices
  * @old:	device to release (can be NULL)
  * @new:	device to request (can be NULL)
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index b6b898d..e9626ad 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -284,6 +284,48 @@ out_bc:
 }
 
 /*
+ * Try to find an alternate timer which does not need broadcast.
+ */
+static void tick_check_fallback_timer(void)
+{
+	struct clock_event_device *curdev;
+	struct clock_event_device *newdev = NULL;
+	struct tick_device *td;
+	int cpu;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&tick_device_lock, flags);
+
+	cpu = smp_processor_id();
+
+	td = &per_cpu(tick_cpu_device, cpu);
+	curdev = td->evtdev;
+
+	/* Check whether current timer is affected by C3 */
+	if (!curdev || !cpumask_equal(curdev->cpumask, cpumask_of(cpu)) ||
+	    !(curdev->features & CLOCK_EVT_FEAT_C3STOP))
+		goto out;
+
+	/* Check if we have already reduced the rating of this device once */
+	if (curdev->features & CLOCK_EVT_FEAT_RATING_REDUCED)
+		goto out;
+
+	curdev->features |= CLOCK_EVT_FEAT_RATING_REDUCED;
+	curdev->rating -= 10;
+	newdev = clockevents_lookup_newdev(cpu, curdev->rating);
+
+out:
+	raw_spin_unlock_irqrestore(&tick_device_lock, flags);
+
+	if (newdev) {
+		tick_check_new_device(newdev);
+		clockevents_notify_released();
+	}
+
+	return;
+}
+
+/*
  * Transfer the do_timer job away from a dying cpu.
  *
  * Called with interrupts disabled.
@@ -365,6 +407,8 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason,
 		return tick_check_new_device(dev);
 
 	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+		tick_check_fallback_timer();
+		/* FALLTHRU */
 	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
 	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
 		tick_broadcast_on_off(reason, dev);
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 290eefb..c72703d 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -14,6 +14,9 @@ extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
+extern struct clock_event_device *clockevents_lookup_newdev(int cpu,
+							    int rating);
+extern void clockevents_notify_released(void);
 
 /*
  * NO_HZ / high resolution timer shared code
-- 
1.6.0.6

-- 


  parent reply	other threads:[~2010-01-15  1:54 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-15  1:39 [patch 0/4] Only use HPET MSI timers on systems with deep C-state support Venkatesh Pallipadi
2010-01-15  1:39 ` [patch 1/4] acpi: acpi_cpu_soft_notify() not getting called on resume Venkatesh Pallipadi
2010-01-15  1:39 ` [patch 2/4] x86: Do not use hpet MSI as clockevent broadcast device Venkatesh Pallipadi
2010-01-15  2:00   ` H. Peter Anvin
2010-01-15  2:07     ` Pallipadi, Venkatesh
2010-01-15  1:40 ` Venkatesh Pallipadi [this message]
2010-01-15  1:40 ` [patch 4/4] x86: Adjust HPET MSI timer rating to work with tick_check_fallback_timer Venkatesh Pallipadi
2010-01-15 21:53 ` [patch 0/4] Only use HPET MSI timers on systems with deep C-state support Mark Hounschell

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=20100115014210.137236000@intel.com \
    --to=venkatesh.pallipadi@intel.com \
    --cc=alain@knaff.lu \
    --cc=hpa@zytor.com \
    --cc=lenb@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=markh@compro.net \
    --cc=mingo@elte.hu \
    --cc=rjw@sisk.pl \
    --cc=shaohua.li@intel.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /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.