From: Thomas Renninger <trenn@suse.de>
To: Tony Lindgren <tony@atomide.com>
Cc: Frank Sorenson <frank@tuxrocks.com>,
linux-kernel@vger.kernel.org,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Pavel Machek <pavel@suse.cz>,
Arjan van de Ven <arjan@infradead.org>,
Martin Schwidefsky <schwidefsky@de.ibm.com>,
Andrea Arcangeli <andrea@suse.de>,
George Anzinger <george@mvista.com>,
Thomas Gleixner <tglx@linutronix.de>,
john stultz <johnstul@us.ibm.com>,
Zwane Mwaikambo <zwane@arm.linux.org.uk>,
Lee Revell <rlrevell@joe-job.com>,
ML ACPI-devel <acpi-devel@lists.sourceforge.net>,
Bodo Bauer <bb@suse.de>, Andi Kleen <ak@suse.de>
Subject: Re: [PATCH] Updated: Dynamic Tick version 050408-1 - C-state measures
Date: Tue, 19 Apr 2005 16:56:56 +0200 [thread overview]
Message-ID: <42651C38.6090807@suse.de> (raw)
In-Reply-To: <20050408115535.GI4477@atomide.com>
[-- Attachment #1: Type: text/plain, Size: 3036 bytes --]
Here are some figures (I used your pmstats):
The machine is a Pentium M 2.00 GHz, supporting C0-C4 processor power states.
The machine run at 2.00 GHz all the time.
A lot of modules (pcmcia, usb, ...) where loaded, services that could
produce load where stopped -> processor is mostly idle.
_____________________________________________________________________________________
*Running with 1000Hz:*
_No processor module:_
Average current the last 100 seconds: *2289mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/1000_HZ_No_module_loaded)
_passing bm_history=0xFFFFFFFF (default) to processor module:_
Average current the last 470 seconds: *1986mA* (also measured better values ~1800, does battery level play a role?!?)
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/1000_HZ_bm_history_FFFFFFFF)
_passing bm_history=0xFF to processor module:_
Average current the last 190 seconds: *1757mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/1000_HZ_bm_history_FF)
(Usage count could be bogus, as some invokations could not succeed if bm has currently been active).
_____________________________________________________________________________________
*Running with CONFIG_NO_IDLE_HZ:*
Patched with http://www.muru.com/linux/dyntick/patches/patch-dynamic-tick-2.6.12-rc2-050408-1.gz
(With the c-state patch attached applied)
_No processor module:_
Average current the last 80 seconds: *2262mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/tony_dyn_tick_No_module_loaded)
idle_ms == 40, bm_promote_bs == 30
Average current the last 160 seconds: *1507mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/tony_dyn_tick_processor_idle_40_bm_30)
idle_ms == 100, bm_promote_bs == 30
Average current the last 80 seconds: *1466mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/tony_dyn_tick_processor_idle_100_bm_30)
idle_ms == 40, bm_promote_bs == 50
Average current the last 150 seconds: *1481mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/tony_dyn_tick_processor_idle_40_bm_30)
idle_ms == 40, bm_promote_bs == 10
Average current the last 330 seconds: *1474mA*
(cmp. ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/measures_C4_machine/tony_dyn_tick_processor_idle_40_bm_10)
Hmm, parameters do not influence at all ... (idle_ms should only comes in when switching between idle/not idle).
_____________________________________________________________________________________
The measures are based on the /proc/acpi/battery/*/* info and are not very accurate, but could give an overall picture.
Thomas
P.S.: Not tested, because I have no x86_64 C3 machine, but the patch should also work reliable with Andi's dyn_tick patch
for x86_64 machines.
Tony: I modified your pmstats to produce an average current value: ftp://ftp.suse.com/pub/people/trenn/dyn_tick_c_states/pmstats
[-- Attachment #2: dynamic_tick_cstate_patch_final.diff --]
[-- Type: text/x-patch, Size: 10275 bytes --]
Patch not enough tested, yet.
Should behave the same if compile with !CONFIG_IDLE_HZ.
If CONFIG_IDLE_HZ is set, the c-state will be evaluated on
three control values (averages of the last 4 measures):
a) idle_ms -> if machine was active for longer than this
value (avg), the machine is assumed to not be idle
and C1 will be triggered.
b) bm_promote_ms -> if the avg bus master activity is below
this threshold, C2 is invoked.
c) sleep_avg (no module param) -> the average sleep time of the
last four C2 (or higher) invokations.
If a and b does not apply, a C-state will be searched that has
the highest latency, but still has a latency below the latest
C2 (or higher) sleeping time and average sleeping time value.
ToDo:
Test on other machines (only C2 or C0 support).
Discuss and enhance algorithm.
If it is used this way, average calculations could get MMX optimised.
--- linux-2.6.12-rc2.orig/drivers/acpi/processor_idle.c 2005-04-19 15:03:13.000000000 +0200
+++ linux-2.6.12-rc2/drivers/acpi/processor_idle.c 2005-04-19 15:17:56.000000000 +0200
@@ -60,6 +60,22 @@
static unsigned int nocst = 0;
module_param(nocst, uint, 0000);
+static unsigned int idle_ms = 40;
+module_param(idle_ms, uint, 0644);
+MODULE_PARM_DESC(idle_ms, "Promote to lower state if machine stays shorter than x ms not in idle func (avg) [40].");
+
+static unsigned int bm_promote_ms = 30;
+module_param(bm_promote_ms, uint, 0644);
+MODULE_PARM_DESC(bm_promote_ms, "Promote to lower state if avg bm is less than x ms [30].");
+
+//#define DEBUG 1
+#ifdef DEBUG
+#define myPrintk(string, args...) printk(KERN_INFO ""string, ##args);
+#else
+#define myPrintk(string, args...) {};
+#endif
+
+
/*
* bm_history -- bit-mask with a bit per jiffy of bus-master activity
* 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
@@ -162,6 +178,88 @@
return;
}
+u16 calc_average (u64 last_measures){
+ int x;
+ u16 ret = 0;
+ for (x = 0; x < sizeof(u64)*8; x+=16){
+ ret += (last_measures >> x) & (u64)0xFFFF;
+// myPrintk (KERN_INFO "x: %d - ret: %X - last_measures: %X - result %X\n", x, ret, (u64)last_measures, (last_measures >> x) & (u64)0xFFFF);
+ }
+/* divide by four -> average bm activity for the last 4 times */
+ ret >>= 2;
+ return ret;
+}
+
+/*
+ * check BM Activity
+ * -----------------
+ * Check for bus mastering activity and save history in
+ * pr->power.bm_activity
+ *
+ * return 0 -> no bm activity for long time
+ * return 1 -> we currently have bus master activity
+ *
+ */
+
+static void check_bm_activity(struct acpi_processor *pr) {
+ u32 bm_status = 0;
+ unsigned long diff = jiffies - pr->power.bm_check_timestamp;
+
+#ifndef CONFIG_NO_IDLE_HZ
+ if (diff > 32)
+ diff = 32;
+ while (diff) {
+ /* if we didn't get called, assume there was busmaster activity */
+ diff--;
+ if (diff)
+ pr->power.bm_activity |= 0x1;
+ pr->power.bm_activity <<= 1;
+ }
+
+ acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
+ &bm_status, ACPI_MTX_DO_NOT_LOCK);
+ if (bm_status) {
+ pr->power.bm_activity++;
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
+ 1, ACPI_MTX_DO_NOT_LOCK);
+ }
+ /*
+ * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
+ * the true state of bus mastering activity; forcing us to
+ * manually check the BMIDEA bit of each IDE channel.
+ */
+ else if (errata.piix4.bmisx) {
+ if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
+ || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+ pr->power.bm_activity++;
+ }
+ pr->power.bm_check_timestamp = jiffies;
+
+#else
+ if (diff > 0xFFFF)
+ diff = 0xFFFF;
+ acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
+ &bm_status, ACPI_MTX_DO_NOT_LOCK);
+// myPrintk (KERN_INFO "bm_status - %d, diff: %lu - bm_avg_ms: %X\n",
+// bm_status, diff, pr->power.bm_avg_ms);
+ if (bm_status) {
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
+ 1, ACPI_MTX_DO_NOT_LOCK);
+ /* we had an active bus master -> get timestamp */
+ pr->power.bm_check_timestamp = jiffies;
+ pr->power.bm_last_measures <<= 16;
+ }
+ /* just OR, even if !bm_status, shouldn't matter */
+ pr->power.bm_last_measures |= diff;
+
+// myPrintk (KERN_INFO "diff: %lu - Avg: bm_last_measures: %#16X\n", diff, (u64)pr->power.bm_last_measures);
+
+ pr->power.bm_avg_ms = calc_average (pr->power.bm_last_measures);
+
+
+// printk (KERN_INFO "Avg: bm_avg_ms: %lu ms \n", (unsigned long)pr->power.bm_avg_ms);
+#endif
+}
static void acpi_processor_idle (void)
{
@@ -171,6 +269,12 @@
int sleep_ticks = 0;
u32 t1, t2 = 0;
+#ifdef CONFIG_NO_IDLE_HZ
+ struct acpi_processor_cx *temp_state = NULL;
+ int i = 0;
+ unsigned long diff = jiffies - pr->power.active_timestamp;
+#endif
+
pr = processors[_smp_processor_id()];
if (!pr)
return;
@@ -191,9 +295,27 @@
}
cx = pr->power.state;
+
+#ifdef CONFIG_NO_IDLE_HZ
+ /* keep track of bm activity */
+ check_bm_activity(pr);
+
+ unsigned long diff = jiffies - pr->power.active_timestamp;
+ if (diff > 0xFFFF)
+ diff = 0xFFFF;
+ pr->power.active_last_measures <<= 16;
+ pr->power.active_last_measures |= (u16)diff;
+ pr->power.active_avg_ms = calc_average(pr->power.active_last_measures);
+ if (pr->power.active_avg_ms > idle_ms){
+ printk (KERN_INFO "We were not idle for %d ms (4 times avg) -> goto C1\n", pr->power.active_avg_ms);
+ next_state = &pr->power.states[ACPI_STATE_C1];
+ goto end;
+ }
+#endif
if (!cx)
goto easy_out;
-
+
+#ifndef CONFIG_NO_IDLE_HZ
/*
* Check BM Activity
* -----------------
@@ -201,40 +323,8 @@
* for demotion.
*/
if (pr->flags.bm_check) {
- u32 bm_status = 0;
- unsigned long diff = jiffies - pr->power.bm_check_timestamp;
-
- if (diff > 32)
- diff = 32;
-
- while (diff) {
- /* if we didn't get called, assume there was busmaster activity */
- diff--;
- if (diff)
- pr->power.bm_activity |= 0x1;
- pr->power.bm_activity <<= 1;
- }
-
- acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
- &bm_status, ACPI_MTX_DO_NOT_LOCK);
- if (bm_status) {
- pr->power.bm_activity++;
- acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
- 1, ACPI_MTX_DO_NOT_LOCK);
- }
- /*
- * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
- * the true state of bus mastering activity; forcing us to
- * manually check the BMIDEA bit of each IDE channel.
- */
- else if (errata.piix4.bmisx) {
- if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
- || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
- pr->power.bm_activity++;
- }
-
- pr->power.bm_check_timestamp = jiffies;
-
+
+ check_bm_activity(pr);
/*
* Apply bus mastering demotion policy. Automatically demote
* to avoid a faulty transition. Note that the processor
@@ -253,6 +343,8 @@
goto end;
}
}
+#endif
+ cx->usage++;
cx->usage++;
@@ -278,7 +370,7 @@
* go to an ISR rather than here. Need to instrument
* base interrupt handler.
*/
- sleep_ticks = 0xFFFFFFFF;
+ sleep_ticks = 0xFFFFFFF;
break;
case ACPI_STATE_C2:
@@ -320,8 +412,51 @@
return;
}
+ if (sleep_ticks <= 0)
+ cx->failed++;
+
+#ifdef CONFIG_NO_IDLE_HZ
+ pr->power.sleep_last_measures <<= 16;
+ pr->power.sleep_last_measures |= sleep_ticks;
+ pr->power.sleep_avg_ticks = calc_average(pr->power.sleep_last_measures);
+#endif
+
next_state = pr->power.state;
+#ifdef CONFIG_NO_IDLE_HZ
+
+ /* use C1/C2 if we have to much bus master activity */
+ if (bm_promote_ms >= pr->power.bm_avg_ms){
+ myPrintk ("pr->power.bm_avg_ms: %d\n", (int)pr->power.bm_avg_ms);
+ next_state = &pr->power.states[ACPI_STATE_C2];
+ if (next_state == NULL || !next_state->valid){
+ next_state = &pr->power.states[ACPI_STATE_C1];
+ if (next_state == NULL || !next_state->valid)
+ goto easy_out;
+
+ }
+ goto end;
+ }
+
+
+ /* goto sleep state which latency fits best to avg sleep time
+ of the last 4 sleep cycles */
+ for (i=ACPI_STATE_C2; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ temp_state = &pr->power.states[i];
+ if (temp_state == NULL || !temp_state->valid)
+ break;
+ myPrintk ("pr->power.sleep_avg_ticks: %d - temp_state->promotion.threshold.ticks: %d"
+ " - sleep_ticks; %d\n",
+ pr->power.sleep_avg_ticks, temp_state->promotion.threshold.ticks, sleep_ticks);
+ if (temp_state->promotion.state &&
+ sleep_ticks > temp_state->promotion.threshold.ticks &&
+ pr->power.sleep_avg_ticks > temp_state->promotion.threshold.ticks){
+ next_state = temp_state->promotion.state;
+ }
+ else
+ break;
+ }
+#else
/*
* Promotion?
* ----------
@@ -330,6 +465,7 @@
* mastering activity may prevent promotions.
* Do not promote above max_cstate.
*/
+
if (cx->promotion.state &&
((cx->promotion.state - pr->power.states) <= max_cstate)) {
if (sleep_ticks > cx->promotion.threshold.ticks) {
@@ -366,6 +502,7 @@
}
}
}
+#endif
end:
/*
@@ -384,7 +521,9 @@
*/
if (next_state != pr->power.state)
acpi_processor_power_activate(pr, next_state);
-
+#ifdef CONFIG_NO_IDLE_HZ
+ pr->power.active_timestamp = jiffies;
+#endif
return;
easy_out:
@@ -393,6 +532,9 @@
pm_idle_save();
else
safe_halt();
+#ifdef CONFIG_NO_IDLE_HZ
+ pr->power.active_timestamp = jiffies;
+#endif
return;
}
@@ -910,6 +1052,9 @@
seq_printf(seq, "latency[%03d] usage[%08d]\n",
pr->power.states[i].latency,
pr->power.states[i].usage);
+ seq_printf(seq, " failed[%08d]\n",
+ pr->power.states[i].failed);
+
}
end:
--- linux-2.6.12-rc2.orig/include/acpi/processor.h 2005-04-19 15:03:44.000000000 +0200
+++ linux-2.6.12-rc2/include/acpi/processor.h 2005-04-19 15:17:56.000000000 +0200
@@ -48,6 +48,7 @@
u32 latency_ticks;
u32 power;
u32 usage;
+ u32 failed;
struct acpi_processor_cx_policy promotion;
struct acpi_processor_cx_policy demotion;
};
@@ -55,8 +56,16 @@
struct acpi_processor_power {
struct acpi_processor_cx *state;
unsigned long bm_check_timestamp;
- u32 default_state;
u32 bm_activity;
+#ifdef CONFIG_NO_IDLE_HZ
+ u16 bm_avg_ms;
+ u64 bm_last_measures;
+ u16 sleep_avg_ticks;
+ u64 sleep_last_measures;
+ unsigned long active_timestamp;
+ u16 active_avg_ms;
+ u64 active_last_measures;
+#endif
int count;
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
};
next prev parent reply other threads:[~2005-04-19 14:56 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-04-06 8:30 [PATCH] Dynamic Tick version 050406-1 Tony Lindgren
2005-04-06 21:16 ` Frank Sorenson
2005-04-07 8:21 ` Tony Lindgren
2005-04-07 9:26 ` Alexander Nyberg
2005-04-08 6:22 ` Tony Lindgren
2005-04-07 21:35 ` Frank Sorenson
2005-04-07 22:20 ` Frank Sorenson
2005-04-08 6:25 ` Tony Lindgren
2005-04-08 7:50 ` [PATCH] Updated: Dynamic Tick version 050408-1 Tony Lindgren
2005-04-08 8:49 ` Frank Sorenson
2005-04-08 9:17 ` Tony Lindgren
2005-04-08 21:42 ` Frank Sorenson
2005-04-09 8:09 ` Tony Lindgren
2005-04-08 11:33 ` Thomas Renninger
2005-04-08 11:55 ` Tony Lindgren
2005-04-08 12:58 ` Thomas Renninger
2005-04-09 8:22 ` Tony Lindgren
2005-04-19 14:56 ` Thomas Renninger [this message]
2005-04-19 15:27 ` [PATCH] Updated: Dynamic Tick version 050408-1 - C-state measures Dominik Brodowski
2005-04-19 21:03 ` Thomas Renninger
2005-04-20 11:44 ` Dominik Brodowski
2005-04-20 11:57 ` Pavel Machek
2005-04-20 12:01 ` Dominik Brodowski
2005-04-20 12:08 ` Pavel Machek
2005-04-20 12:13 ` Dominik Brodowski
2005-04-20 12:24 ` Thomas Renninger
2005-04-19 21:09 ` Pavel Machek
2005-04-20 20:01 ` Tony Lindgren
2005-04-21 7:54 ` Thomas Renninger
2005-04-08 10:28 ` [PATCH] Updated: Dynamic Tick version 050408-1 Pavel Machek
2005-04-08 10:54 ` Tony Lindgren
2005-04-08 12:24 ` Pavel Machek
2005-04-09 9:56 ` Pavel Machek
2005-04-14 19:41 ` Tony Lindgren
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=42651C38.6090807@suse.de \
--to=trenn@suse.de \
--cc=acpi-devel@lists.sourceforge.net \
--cc=ak@suse.de \
--cc=andrea@suse.de \
--cc=arjan@infradead.org \
--cc=bb@suse.de \
--cc=benh@kernel.crashing.org \
--cc=frank@tuxrocks.com \
--cc=george@mvista.com \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pavel@suse.cz \
--cc=rlrevell@joe-job.com \
--cc=schwidefsky@de.ibm.com \
--cc=tglx@linutronix.de \
--cc=tony@atomide.com \
--cc=zwane@arm.linux.org.uk \
/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.