From: Dominik Brodowski <linux-X3ehHDuj6sIIGcDfoQAp7BvVK+yQ3ZXh@public.gmane.org>
To: Len Brown <len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Jos Delbar <jos.delbar-Cru1EgDzd7c@public.gmane.org>,
ACPI Developers
<acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>,
Robert Moore
<robert.moore-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
James P Ketrenos
<james.p.ketrenos-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: Re: Re: Linux ACPI processor driver patch: user-definable power state limit
Date: Sat, 6 Nov 2004 00:54:03 +0100 [thread overview]
Message-ID: <20041105235403.GA21880@dominikbrodowski.de> (raw)
In-Reply-To: <1099696293.13834.1639.camel@d845pe>
[ACPI-PROCESSOR] Dynamic limitation of available C-State types
Some drivers and/or some operations need to disable certain types of ACPI
CPU power states (a.k.a. C-States). Drivers which have requirements >= 99%
of the time should do:
1.) during module_init, get a struct acpi_cstate_limit *acpi_set_cstate_limit
and pass the appropriate limit to acpi_set_cstate_limit().
2.) pass the aquired struct acpi_cstate_limit * to acpi_remove_cstate_limit() in
module_exit.
A driver with dynamic requirements can do the following
1.) get a struct acpi_cstate_limit *acpi_set_cstate_limit(0);
[zero means no limit!]
2.) a critical section should be marked like:
acpi_modify_cstate_limit(cstate_limit, NEW_LIMIT);
/* no C3 may be going on here... */
...
/* the CPU can sleep safely again */
acpi_modify_cstate_limit(cstate_limit, 0);
3.) pass the aquired struct acpi_cstate_limit * to acpi_remove_cstate_limit() in
module_exit.
Signed-off-by: Dominik Brodowski <linux-JhLEnvuH02M@public.gmane.org>
diff -ruN linux-original/drivers/acpi/processor.c linux/drivers/acpi/processor.c
--- linux-original/drivers/acpi/processor.c 2004-11-05 23:59:49.586947488 +0100
+++ linux/drivers/acpi/processor.c 2004-11-06 00:46:45.852810000 +0100
@@ -44,6 +44,7 @@
#include <linux/seq_file.h>
#include <linux/dmi.h>
#include <linux/moduleparam.h>
+#include <linux/list.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -304,6 +305,80 @@
Power Management
-------------------------------------------------------------------------- */
+/* others shall not modify anything in here directly, so the layout isn't
+ * exported anywhere else
+ */
+struct acpi_cstate_limit {
+ struct list_head list;
+ unsigned int limit;
+};
+
+static unsigned int cstate_limit;
+static LIST_HEAD(cstate_limit_list);
+static spinlock_t cstate_limit_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void acpi_update_cstate_limit(void)
+{
+ struct acpi_cstate_limit *cur;
+ unsigned int new_limit = 0;
+
+ list_for_each_entry(cur, &cstate_limit_list, list) {
+ if (cur->limit > new_limit)
+ new_limit = cur->limit;
+ }
+ cstate_limit = new_limit;
+}
+
+struct acpi_cstate_limit *acpi_set_cstate_limit(unsigned int limit)
+{
+ struct acpi_cstate_limit *data;
+ unsigned long flags;
+
+ might_sleep();
+
+ data = kmalloc(sizeof(struct acpi_cstate_limit), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ data->limit = limit;
+
+ spin_lock_irqsave(&cstate_limit_lock, flags);
+ list_add(&data->list, &cstate_limit_list);
+ acpi_update_cstate_limit();
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+
+ return data;
+}
+
+int acpi_modify_cstate_limit(struct acpi_cstate_limit *data, unsigned int limit)
+{
+ unsigned long flags;
+ if (!data)
+ return -ENODEV;
+
+ spin_lock_irqsave(&cstate_limit_lock, flags);
+ data->limit = limit;
+ acpi_update_cstate_limit();
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(acpi_modify_cstate_limit);
+
+void acpi_remove_cstate_limit(struct acpi_cstate_limit *data)
+{
+ unsigned long flags;
+ if (!data)
+ return;
+
+ spin_lock_irqsave(&cstate_limit_lock, flags);
+ list_del(&data->list);
+ acpi_update_cstate_limit();
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+}
+EXPORT_SYMBOL(acpi_remove_cstate_limit);
+
+
static inline u32
ticks_elapsed (
u32 t1,
@@ -359,6 +434,8 @@
int next_state = 0;
int sleep_ticks = 0;
u32 t1, t2 = 0;
+ unsigned long flags;
+
pr = processors[smp_processor_id()];
if (!pr)
@@ -419,6 +496,21 @@
}
}
+ /* Dynamic limitation? */
+ spin_lock_irqsave(&cstate_limit_lock, flags);
+ if ((cstate_limit) && (cstate_limit <= pr->power.state)) {
+ next_state = cstate_limit;
+ while (next_state > 1) {
+ if (!pr->power.states[next_state].valid)
+ next_state--;
+ }
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+ local_irq_enable();
+ goto end;
+ }
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+
+
cx->usage++;
/*
@@ -487,6 +579,7 @@
next_state = pr->power.state;
+
/*
* Promotion?
* ----------
@@ -494,7 +587,7 @@
* and promote when the count threshold is reached. Note that bus
* mastering activity may prevent promotions.
*/
- if (cx->promotion.state) {
+ if (cx->promotion.state && !t2) {
if (sleep_ticks > cx->promotion.threshold.ticks) {
cx->promotion.count++;
cx->demotion.count = 0;
@@ -537,8 +630,16 @@
* If we're going to start using a new Cx state we must clean up
* from the previous and prepare to use the new.
*/
- if (next_state != pr->power.state)
- acpi_processor_power_activate(pr, next_state);
+ if (next_state != pr->power.state) {
+ /* Dynamic limitation? */
+ spin_lock_irqsave(&cstate_limit_lock, flags);
+ if (cstate_limit && (cstate_limit >= next_state)) {
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+ } else {
+ spin_unlock_irqrestore(&cstate_limit_lock, flags);
+ acpi_processor_power_activate(pr, next_state);
+ }
+ }
return;
}
diff -ruN linux-original/include/acpi/processor.h linux/include/acpi/processor.h
--- linux-original/include/acpi/processor.h 2004-11-05 23:59:51.923592264 +0100
+++ linux/include/acpi/processor.h 2004-11-06 00:46:39.284808488 +0100
@@ -44,6 +44,13 @@
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
};
+struct acpi_cstate_limit;
+
+struct acpi_cstate_limit* acpi_set_cstate_limit(unsigned int limit);
+int acpi_modify_cstate_limit(struct acpi_cstate_limit *data, unsigned int limit);
+void acpi_remove_cstate_limit(struct acpi_cstate_limit *data);
+
+
/* Performance Management */
struct acpi_pct_register {
-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
next prev parent reply other threads:[~2004-11-05 23:54 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-10-10 16:56 Linux ACPI processor driver patch: user-definable power state limit Brown, Len
[not found] ` <F7DC2337C7631D4386A2DF6E8FB22B3001A193B6-N2PTB0HCzHKkrb+BlOpmy7fspsVTdybXVpNB7YpNyf8@public.gmane.org>
2004-10-11 21:35 ` Jos Delbar
[not found] ` <200410112335.19159.jos.delbar-Cru1EgDzd7c@public.gmane.org>
2004-10-19 17:19 ` Len Brown
2004-11-05 19:45 ` Len Brown
2004-11-05 22:54 ` Dominik Brodowski
[not found] ` <20041105225438.GA8262-X3ehHDuj6sIIGcDfoQAp7BvVK+yQ3ZXh@public.gmane.org>
2004-11-05 23:11 ` Len Brown
2004-11-05 23:41 ` Dominik Brodowski
[not found] ` <20041105234120.GA20761-X3ehHDuj6sIIGcDfoQAp7BvVK+yQ3ZXh@public.gmane.org>
2004-11-06 0:25 ` Len Brown
2004-11-06 0:29 ` Dominik Brodowski
[not found] ` <20041106002935.GA30467-X3ehHDuj6sIIGcDfoQAp7BvVK+yQ3ZXh@public.gmane.org>
2004-11-06 0:44 ` Len Brown
2004-11-06 13:15 ` Jos Delbar
2004-11-05 23:54 ` Dominik Brodowski [this message]
[not found] ` <20041105235403.GA21880-X3ehHDuj6sIIGcDfoQAp7BvVK+yQ3ZXh@public.gmane.org>
2004-11-06 0:33 ` Len Brown
2004-11-05 23:39 ` Jos Delbar
[not found] ` <200411060039.28067.jos.delbar-Cru1EgDzd7c@public.gmane.org>
2004-11-05 23:55 ` Dominik Brodowski
2004-11-05 22:58 ` Len Brown
2004-11-05 23:21 ` Jos Delbar
[not found] ` <200411060021.49794.jos.delbar-Cru1EgDzd7c@public.gmane.org>
2004-11-06 1:01 ` Len Brown
2004-11-06 2:59 ` Len Brown
-- strict thread matches above, loose matches on Subject: below --
2004-10-10 7:14 Brown, Len
[not found] <200408071959.10529.jos.delbar@ugent.be>
2004-10-09 5:52 ` Len Brown
2004-10-09 18:56 ` Dominik Brodowski
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=20041105235403.GA21880@dominikbrodowski.de \
--to=linux-x3ehhduj6siigcdfoqap7bvvk+yq3zxh@public.gmane.org \
--cc=acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=james.p.ketrenos-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=jos.delbar-Cru1EgDzd7c@public.gmane.org \
--cc=len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=robert.moore-ral2JQCrhuEAvxtiuMwx3w@public.gmane.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox