summaryrefslogtreecommitdiff
path: root/packages/linux/linux-ezx/dpm-core-2.6.16.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-ezx/dpm-core-2.6.16.patch')
-rw-r--r--packages/linux/linux-ezx/dpm-core-2.6.16.patch5197
1 files changed, 0 insertions, 5197 deletions
diff --git a/packages/linux/linux-ezx/dpm-core-2.6.16.patch b/packages/linux/linux-ezx/dpm-core-2.6.16.patch
deleted file mode 100644
index d0d34d1225..0000000000
--- a/packages/linux/linux-ezx/dpm-core-2.6.16.patch
+++ /dev/null
@@ -1,5197 +0,0 @@
-This is the Dynamic Power Management Core, as released by the upstream
-project for 2.6.16.
-
-Index: linux-2.6.16/arch/arm/Kconfig
-===================================================================
---- linux-2.6.16.orig/arch/arm/Kconfig 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/arch/arm/Kconfig 2006-04-11 06:34:10.000000000 +0000
-@@ -832,3 +832,5 @@
- source "crypto/Kconfig"
-
- source "lib/Kconfig"
-+
-+source "drivers/dpm/Kconfig"
-Index: linux-2.6.16/arch/i386/Kconfig
-===================================================================
---- linux-2.6.16.orig/arch/i386/Kconfig 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/arch/i386/Kconfig 2006-04-11 06:34:10.000000000 +0000
-@@ -908,6 +908,7 @@
- endmenu
-
- source "arch/i386/kernel/cpu/cpufreq/Kconfig"
-+source "arch/i386/kernel/cpu/dpm/Kconfig"
-
- endmenu
-
-Index: linux-2.6.16/arch/i386/kernel/cpu/Makefile
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/cpu/Makefile 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/cpu/Makefile 2006-04-11 06:34:10.000000000 +0000
-@@ -17,3 +17,4 @@
-
- obj-$(CONFIG_MTRR) += mtrr/
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
-+obj-$(CONFIG_DPM) += dpm/
-Index: linux-2.6.16/arch/i386/kernel/cpu/dpm/Kconfig
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/cpu/dpm/Kconfig 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/cpu/dpm/Kconfig 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,10 @@
-+#
-+# Dynamic Power Management
-+#
-+
-+source "drivers/dpm/Kconfig"
-+
-+config DPM_CENTRINO
-+ tristate "DPM for Intel Centrino Enhanced Speedstep"
-+ depends on DPM
-+ default n
-Index: linux-2.6.16/arch/i386/kernel/cpu/dpm/Makefile
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/cpu/dpm/Makefile 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/cpu/dpm/Makefile 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,3 @@
-+obj-$(CONFIG_DPM) += x86_dpm.o
-+obj-$(CONFIG_DPM_CENTRINO) += centrino_dpm.o
-+
-Index: linux-2.6.16/arch/i386/kernel/cpu/dpm/centrino_dpm.c
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/cpu/dpm/centrino_dpm.c 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/cpu/dpm/centrino_dpm.c 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,133 @@
-+/*
-+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
-+ * terms of the GNU General Public License version 2. This program is
-+ * licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ *
-+ * Based on speedstep-centrino.c by Jeremy Fitzhardinge <jeremy@goop.org>
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/dpm.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+
-+#include <asm/msr.h>
-+#include <asm/processor.h>
-+#include <asm/cpufeature.h>
-+
-+/* Extract clock in kHz from PERF_CTL value */
-+static unsigned extract_clock(unsigned msr)
-+{
-+ msr = (msr >> 8) & 0xff;
-+ return msr * 100000;
-+}
-+
-+/* Return the current CPU frequency in kHz */
-+static unsigned get_cur_freq(void)
-+{
-+ unsigned l, h;
-+
-+ rdmsr(MSR_IA32_PERF_STATUS, l, h);
-+ return extract_clock(l);
-+}
-+
-+static int
-+dpm_centrino_init_opt(struct dpm_opt *opt)
-+{
-+ int v = opt->pp[DPM_MD_V];
-+ int cpu = opt->pp[DPM_MD_CPU_FREQ];
-+
-+ struct dpm_md_opt *md_opt = &opt->md_opt;
-+
-+ md_opt->v = v;
-+ md_opt->cpu = cpu;
-+ return 0;
-+}
-+
-+/* Fully determine the current machine-dependent operating point, and fill in a
-+ structure presented by the caller. This should only be called when the
-+ dpm_sem is held. This call can return an error if the system is currently at
-+ an operating point that could not be constructed by dpm_md_init_opt(). */
-+
-+static int
-+dpm_centrino_get_opt(struct dpm_opt *opt)
-+{
-+ struct dpm_md_opt *md_opt = &opt->md_opt;
-+
-+ md_opt->v = 100; /* TODO. */
-+ md_opt->cpu = get_cur_freq();
-+ return 0;
-+}
-+
-+static int
-+dpm_centrino_set_opt(struct dpm_md_opt *md_opt)
-+{
-+ unsigned int msr = 0, oldmsr, h, mask = 0;
-+
-+ if (md_opt->cpu != -1) {
-+ msr |= ((md_opt->cpu)/100) << 8;
-+ mask |= 0xff00;
-+ }
-+
-+ if (md_opt->v != -1) {
-+ msr |= ((md_opt->v - 700) / 16);
-+ mask |= 0xff;
-+ }
-+
-+ rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-+
-+ if (msr == (oldmsr & mask))
-+ return 0;
-+
-+ /* all but 16 LSB are "reserved", so treat them with
-+ care */
-+ oldmsr &= ~mask;
-+ msr &= mask;
-+ oldmsr |= msr;
-+
-+ wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-+ return 0;
-+}
-+
-+static int dpm_centrino_startup(void)
-+{
-+ struct cpuinfo_x86 *cpu = cpu_data;
-+ unsigned l, h;
-+
-+ if (!cpu_has(cpu, X86_FEATURE_EST))
-+ return -ENODEV;
-+
-+ /* Check to see if Enhanced SpeedStep is enabled, and try to
-+ enable it if not. */
-+ rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-+
-+ if (!(l & (1<<16))) {
-+ l |= (1<<16);
-+ wrmsr(MSR_IA32_MISC_ENABLE, l, h);
-+
-+ /* check to see if it stuck */
-+ rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-+ if (!(l & (1<<16))) {
-+ printk(KERN_INFO "DPM: Couldn't enable Enhanced SpeedStep\n");
-+ return -ENODEV;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int __init dpm_centrino_init(void)
-+{
-+ printk("Dynamic Power Management for Intel Centrino Enhanced SpeedStep.\n");
-+
-+ dpm_bd.startup = dpm_centrino_startup;
-+ dpm_bd.init_opt = dpm_centrino_init_opt;
-+ dpm_bd.get_opt = dpm_centrino_get_opt;
-+ dpm_bd.set_opt = dpm_centrino_set_opt;
-+ return 0;
-+}
-+
-+__initcall(dpm_centrino_init);
-Index: linux-2.6.16/arch/i386/kernel/cpu/dpm/x86_dpm.c
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/cpu/dpm/x86_dpm.c 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/cpu/dpm/x86_dpm.c 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,133 @@
-+/*
-+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
-+ * terms of the GNU General Public License version 2. This program is
-+ * licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/dpm.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+
-+#include <asm/page.h>
-+#include <asm/uaccess.h>
-+
-+struct dpm_bd dpm_bd;
-+
-+static int
-+dpm_x86_init_opt(struct dpm_opt *opt)
-+{
-+ return dpm_bd.init_opt ? dpm_bd.init_opt(opt) : -1;
-+}
-+
-+/* Fully determine the current machine-dependent operating point, and fill in a
-+ structure presented by the caller. This should only be called when the
-+ dpm_sem is held. This call can return an error if the system is currently at
-+ an operating point that could not be constructed by dpm_md_init_opt(). */
-+
-+static unsigned long loops_per_jiffy_ref = 0;
-+
-+static int
-+dpm_x86_get_opt(struct dpm_opt *opt)
-+{
-+ return dpm_bd.get_opt ? dpm_bd.get_opt(opt) : -1;
-+}
-+
-+int
-+dpm_x86_set_opt(struct dpm_opt *cur, struct dpm_opt *new)
-+{
-+ struct cpuinfo_x86 *cpu = cpu_data;
-+
-+ if (! new->md_opt.cpu) {
-+#ifdef CONFIG_PM
-+ pm_suspend(PM_SUSPEND_STANDBY);
-+
-+ /* Here when we wake up. Recursive call to switch back to
-+ * to task state.
-+ */
-+
-+ dpm_set_os(DPM_TASK_STATE);
-+#endif
-+ return 0;
-+ }
-+
-+ if (dpm_bd.set_opt){
-+ dpm_bd.set_opt(&new->md_opt);
-+
-+ }else{
-+ return -1;
-+ }
-+
-+ if (cur->md_opt.cpu && new->md_opt.cpu){
-+ loops_per_jiffy_ref = cpu->loops_per_jiffy;
-+ cpu->loops_per_jiffy =
-+ dpm_compute_lpj(loops_per_jiffy_ref ,
-+ cur->md_opt.cpu,
-+ new->md_opt.cpu);
-+
-+ loops_per_jiffy = cpu->loops_per_jiffy;
-+ if (cpu_khz)
-+ cpu_khz = dpm_compute_lpj(cpu_khz,
-+ cur->md_opt.cpu,
-+ new->md_opt.cpu);
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * idle loop
-+ */
-+
-+static void (*orig_idle)(void);
-+
-+void dpm_x86_idle(void)
-+{
-+ extern void default_idle(void);
-+
-+ if (orig_idle)
-+ orig_idle();
-+ else
-+ default_idle();
-+}
-+
-+/****************************************************************************
-+ * Initialization/Exit
-+ ****************************************************************************/
-+
-+void
-+dpm_x86_startup(void)
-+{
-+ orig_idle = pm_idle;
-+ pm_idle = dpm_idle;
-+
-+ if (dpm_bd.startup)
-+ dpm_bd.startup();
-+}
-+
-+void
-+dpm_x86_cleanup(void)
-+{
-+ pm_idle = orig_idle;
-+
-+ if (dpm_bd.cleanup)
-+ dpm_bd.cleanup();
-+}
-+
-+int __init
-+dpm_x86_init(void)
-+{
-+ printk("Dynamic Power Management for x86.\n");
-+
-+ dpm_md.init_opt = dpm_x86_init_opt;
-+ dpm_md.set_opt = dpm_x86_set_opt;
-+ dpm_md.get_opt = dpm_x86_get_opt;
-+ dpm_md.idle = dpm_x86_idle;
-+ dpm_md.startup = dpm_x86_startup;
-+ dpm_md.cleanup = dpm_x86_cleanup;
-+ return 0;
-+}
-+__initcall(dpm_x86_init);
-Index: linux-2.6.16/arch/i386/kernel/process.c
-===================================================================
---- linux-2.6.16.orig/arch/i386/kernel/process.c 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/arch/i386/kernel/process.c 2006-04-11 06:34:10.000000000 +0000
-@@ -58,6 +58,8 @@
- #include <asm/tlbflush.h>
- #include <asm/cpu.h>
-
-+#include <linux/dpm.h>
-+
- asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
-
- static int hlt_counter;
-@@ -697,6 +699,7 @@
-
- disable_tsc(prev_p, next_p);
-
-+ dpm_set_os(next_p->dpm_state);
- return prev_p;
- }
-
-Index: linux-2.6.16/drivers/Makefile
-===================================================================
---- linux-2.6.16.orig/drivers/Makefile 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/Makefile 2006-04-11 06:34:10.000000000 +0000
-@@ -67,6 +67,7 @@
- obj-$(CONFIG_MCA) += mca/
- obj-$(CONFIG_EISA) += eisa/
- obj-$(CONFIG_CPU_FREQ) += cpufreq/
-+obj-$(CONFIG_DPM) += dpm/
- obj-$(CONFIG_MMC) += mmc/
- obj-$(CONFIG_INFINIBAND) += infiniband/
- obj-$(CONFIG_SGI_SN) += sn/
-Index: linux-2.6.16/drivers/base/core.c
-===================================================================
---- linux-2.6.16.orig/drivers/base/core.c 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/base/core.c 2006-04-11 06:34:10.000000000 +0000
-@@ -282,6 +282,8 @@
- if (parent)
- klist_add_tail(&dev->knode_parent, &parent->klist_children);
-
-+ assert_constraints(dev->constraints);
-+
- /* notify platform of device entry */
- if (platform_notify)
- platform_notify(dev);
-@@ -367,6 +369,8 @@
- klist_del(&dev->knode_parent);
- device_remove_file(dev, &dev->uevent_attr);
-
-+ deassert_constraints(dev->constraints);
-+
- /* Notify the platform of the removal, in case they
- * need to do anything...
- */
-Index: linux-2.6.16/drivers/base/power/Makefile
-===================================================================
---- linux-2.6.16.orig/drivers/base/power/Makefile 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/base/power/Makefile 2006-04-11 06:34:10.000000000 +0000
-@@ -1,4 +1,4 @@
--obj-y := shutdown.o
-+obj-y := shutdown.o power-dpm.o
- obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o
-
- ifeq ($(CONFIG_DEBUG_DRIVER),y)
-Index: linux-2.6.16/drivers/base/power/power-dpm.c
-===================================================================
---- linux-2.6.16.orig/drivers/base/power/power-dpm.c 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/drivers/base/power/power-dpm.c 2006-04-11 06:35:28.000000000 +0000
-@@ -0,0 +1,473 @@
-+/*
-+ * power-dpm.c -- Dynamic Power Management LDM power hooks
-+ *
-+ * (c) 2003 MontaVista Software, Inc. This file is licensed under the
-+ * terms of the GNU General Public License version 2. This program is
-+ * licensed "as is" without any warranty of any kind, whether express or
-+ * implied.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/pm.h>
-+#include <linux/dpm.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+
-+#include "power.h"
-+
-+/*
-+ * power hotplug events
-+ */
-+
-+#define BUFFER_SIZE 1024 /* should be enough memory for the env */
-+#define NUM_ENVP 32 /* number of env pointers */
-+static unsigned long sequence_num;
-+static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
-+
-+void power_event(char *eventstr)
-+{
-+ char *argv [3];
-+ char **envp = NULL;
-+ char *buffer = NULL;
-+ char *scratch;
-+ int i = 0;
-+ int retval;
-+ unsigned long seq;
-+
-+ if (!uevent_helper[0])
-+ return;
-+
-+ envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
-+ if (!envp)
-+ return;
-+ memset (envp, 0x00, NUM_ENVP * sizeof (char *));
-+
-+ buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
-+ if (!buffer)
-+ goto exit;
-+
-+ argv [0] = uevent_helper;
-+ argv [1] = "power";
-+ argv [2] = 0;
-+
-+ /* minimal command environment */
-+ envp [i++] = "HOME=/";
-+ envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+
-+ scratch = buffer;
-+
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "ACTION=event") + 1;
-+
-+ spin_lock(&sequence_lock);
-+ seq = sequence_num++;
-+ spin_unlock(&sequence_lock);
-+
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "EVENT=%s", eventstr) + 1;
-+
-+ pr_debug ("%s: %s %s %s %s %s %s %s\n", __FUNCTION__, argv[0], argv[1],
-+ envp[0], envp[1], envp[2], envp[3], envp[4]);
-+ retval = call_usermodehelper (argv[0], argv, envp, 0);
-+ if (retval)
-+ pr_debug ("%s - call_usermodehelper returned %d\n",
-+ __FUNCTION__, retval);
-+
-+exit:
-+ kfree(buffer);
-+ kfree(envp);
-+ return;
-+}
-+
-+void device_power_event(struct device * dev, char *eventstr)
-+{
-+ char *argv [3];
-+ char **envp = NULL;
-+ char *buffer = NULL;
-+ char *scratch;
-+ int i = 0;
-+ int retval;
-+ unsigned long seq;
-+
-+ if (!uevent_helper[0])
-+ return;
-+
-+ envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
-+ if (!envp)
-+ return;
-+ memset (envp, 0x00, NUM_ENVP * sizeof (char *));
-+
-+ buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
-+ if (!buffer)
-+ goto exit;
-+
-+ argv [0] = uevent_helper;
-+ argv [1] = "power";
-+ argv [2] = 0;
-+
-+ /* minimal command environment */
-+ envp [i++] = "HOME=/";
-+ envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+
-+ scratch = buffer;
-+
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "ACTION=device-event") + 1;
-+
-+ spin_lock(&sequence_lock);
-+ seq = sequence_num++;
-+ spin_unlock(&sequence_lock);
-+
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "DEVICE=%s", dev->bus_id) + 1;
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "EVENT=%s", eventstr) + 1;
-+ envp [i++] = scratch;
-+ scratch += sprintf(scratch, "SUBSYSTEM=power") + 1;
-+
-+ pr_debug ("%s: %s %s %s %s %s %s %s %s %2\n", __FUNCTION__, argv[0], argv[1],
-+ envp[0], envp[1], envp[2], envp[3], envp[4], envp[5],
-+ envp[6]);
-+ retval = call_usermodehelper (argv[0], argv, envp, 0);
-+ if (retval)
-+ pr_debug ("%s - call_usermodehelper returned %d\n",
-+ __FUNCTION__, retval);
-+
-+exit:
-+ kfree(buffer);
-+ kfree(envp);
-+ return;
-+}
-+
-+/*
-+ * Device constraints
-+ */
-+
-+#ifdef CONFIG_DPM
-+LIST_HEAD(dpm_constraints);
-+DECLARE_MUTEX(dpm_constraints_sem);
-+
-+void assert_constraints(struct constraints *constraints)
-+{
-+ if (! constraints || constraints->asserted)
-+ return;
-+
-+ down(&dpm_constraints_sem);
-+ constraints->asserted = 1;
-+ list_add_tail(&constraints->entry, &dpm_constraints);
-+ up(&dpm_constraints_sem);
-+
-+ /* DPM-PM-TODO: Check against DPM state. */
-+
-+}
-+
-+
-+void deassert_constraints(struct constraints *constraints)
-+{
-+ if (! constraints || ! constraints->asserted)
-+ return;
-+
-+ down(&dpm_constraints_sem);
-+ constraints->asserted = 0;
-+ list_del_init(&constraints->entry);
-+ up(&dpm_constraints_sem);
-+}
-+
-+
-+EXPORT_SYMBOL(assert_constraints);
-+EXPORT_SYMBOL(deassert_constraints);
-+
-+static ssize_t
-+constraints_show(struct device * dev, struct device_attribute *attr,
-+ char * buf)
-+{
-+ int i, cnt = 0;
-+
-+ if (dev->constraints) {
-+ for (i = 0; i < dev->constraints->count; i++) {
-+ cnt += sprintf(buf + cnt,"%s: min=%d max=%d\n",
-+ dpm_param_names[dev->constraints->param[i].id],
-+ dev->constraints->param[i].min,
-+ dev->constraints->param[i].max);
-+ }
-+
-+ cnt += sprintf(buf + cnt,"asserted=%s violations=%d\n",
-+ dev->constraints->asserted ?
-+ "yes" : "no", dev->constraints->violations);
-+ } else {
-+ cnt += sprintf(buf + cnt,"none\n");
-+ }
-+
-+ return cnt;
-+}
-+
-+static ssize_t
-+constraints_store(struct device * dev, struct device_attribute *attr,
-+ const char * buf, size_t count)
-+{
-+ int num_args, paramid, min, max;
-+ int cidx;
-+ const char *cp, *paramname;
-+ int paramnamelen;
-+ int provisional = 0;
-+ int ret = 0;
-+
-+ if (!dev->constraints) {
-+ if (! (dev->constraints = kmalloc(sizeof(struct constraints),
-+ GFP_KERNEL)))
-+ return -EINVAL;
-+
-+ memset(dev->constraints, 0,
-+ sizeof(struct constraints));
-+ provisional = 1;
-+ }
-+
-+ cp = buf;
-+ while((cp - buf < count) && *cp && (*cp == ' '))
-+ cp++;
-+
-+ paramname = cp;
-+
-+ while((cp - buf < count) && *cp && (*cp != ' '))
-+ cp++;
-+
-+ paramnamelen = cp - paramname;
-+ num_args = sscanf(cp, "%d %d", &min, &max);
-+
-+ if (num_args != 2) {
-+ printk("DPM: Need 2 integer parameters for constraint min/max.\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ for (paramid = 0; paramid < DPM_PP_NBR; paramid++) {
-+ if (strncmp(paramname, dpm_param_names[paramid], paramnamelen) == 0)
-+ break;
-+ }
-+
-+ if (paramid >= DPM_PP_NBR) {
-+ printk("DPM: Unknown power parameter name in device constraints\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ for (cidx = 0; cidx < dev->constraints->count; cidx++)
-+ /*
-+ * If the new range overlaps an existing range,
-+ * modify the existing one.
-+ */
-+
-+ if ((dev->constraints->param[cidx].id == paramid) &&
-+ ((max == -1) ||
-+ (max >= dev->constraints->param[cidx].min)) &&
-+ ((min == -1) ||
-+ (min <= dev->constraints->param[cidx].max)))
-+ break;
-+
-+ if (cidx >= DPM_CONSTRAINT_PARAMS_MAX) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* Error if max is less than min */
-+ if (max < min) {
-+ printk("DPM: Max value of the constraint should not be less than min\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ dev->constraints->param[cidx].id = paramid;
-+ dev->constraints->param[cidx].max = max;
-+ dev->constraints->param[cidx].min = min;
-+
-+ if (cidx == dev->constraints->count)
-+ dev->constraints->count++;
-+
-+ /* New constraints should start off with same state as power
-+ state */
-+ if (provisional && (dev->power.power_state.event == PM_EVENT_ON))
-+ assert_constraints(dev->constraints);
-+
-+out:
-+
-+ if (provisional && (ret < 0)) {
-+ kfree(dev->constraints);
-+ dev->constraints = NULL;
-+ }
-+
-+ return ret < 0 ? ret : count;
-+}
-+
-+DEVICE_ATTR(constraints,S_IWUSR | S_IRUGO,
-+ constraints_show,constraints_store);
-+
-+#else /* CONFIG_DPM */
-+void assert_constraints(struct constraints *constraints)
-+{
-+}
-+
-+void deassert_constraints(struct constraints *constraints)
-+{
-+}
-+#endif /* CONFIG_DPM */
-+
-+#ifdef CONFIG_DPM
-+
-+/*
-+ * Driver scale callbacks
-+ */
-+
-+static struct notifier_block *dpm_scale_notifier_list[SCALE_MAX];
-+static DECLARE_MUTEX(dpm_scale_sem);
-+
-+/* This function may be called by the platform frequency scaler before
-+ or after a frequency change, in order to let drivers adjust any
-+ clocks or calculations for the new frequency. */
-+
-+void dpm_driver_scale(int level, struct dpm_opt *newop)
-+{
-+ if (down_trylock(&dpm_scale_sem))
-+ return;
-+
-+ notifier_call_chain(&dpm_scale_notifier_list[level], level, newop);
-+ up(&dpm_scale_sem);
-+}
-+
-+void dpm_register_scale(struct notifier_block *nb, int level)
-+{
-+ down(&dpm_scale_sem);
-+ notifier_chain_register(&dpm_scale_notifier_list[level], nb);
-+ up(&dpm_scale_sem);
-+}
-+
-+void dpm_unregister_scale(struct notifier_block *nb, int level)
-+{
-+ down(&dpm_scale_sem);
-+ notifier_chain_unregister(&dpm_scale_notifier_list[level], nb);
-+ up(&dpm_scale_sem);
-+}
-+
-+int dpm_constraint_rejects = 0;
-+
-+
-+int
-+dpm_default_check_constraint(struct constraint_param *param,
-+ struct dpm_opt *opt)
-+{
-+ return (opt->pp[param->id] == -1) ||
-+ ((param->min == -1 || opt->pp[param->id] >= param->min) &&
-+ (param->max == -1 || opt->pp[param->id] <= param->max));
-+}
-+
-+static int
-+dpm_check_a_constraint(struct constraints *constraints, struct dpm_opt *opt)
-+{
-+ int i;
-+ int failid = -1;
-+ int ppconstraint[DPM_PP_NBR];
-+
-+
-+ if (! constraints || !constraints->asserted)
-+ return 1;
-+
-+ /*
-+ * ppconstraint[ppid] == 0 means power param has not been checked
-+ * for a constraint
-+ * == -1 means power param has matched a constraint
-+ * > 0 means constraint #n-1 mismatched
-+ *
-+ * failid == pp id of (a) failed constraint
-+ */
-+
-+ memset(ppconstraint, 0, sizeof(ppconstraint));
-+
-+ for (i = 0; i < constraints->count; i++) {
-+ struct constraint_param *param = &constraints->param[i];
-+
-+ if (! dpm_md_check_constraint(param, opt)) {
-+ if (ppconstraint[param->id] == 0) {
-+ failid = param->id;
-+ ppconstraint[failid] = i+1;
-+ }
-+ } else
-+ ppconstraint[param->id] = -1;
-+ }
-+
-+ if ((failid >= 0) && (ppconstraint[failid] > 0)) {
-+#ifdef CONFIG_DPM_TRACE
-+ struct constraint_param *param =
-+ &constraints->param[ppconstraint[failid]-1];
-+
-+ dpm_trace(DPM_TRACE_CONSTRAINT_ASSERTED,
-+ param->id, param->min, param->max,
-+ opt);
-+#endif
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+int dpm_check_constraints(struct dpm_opt *opt)
-+{
-+ struct list_head * entry;
-+ int valid = 1;
-+
-+ list_for_each(entry,&dpm_constraints) {
-+ struct constraints *constraints =
-+ list_entry(entry, struct constraints, entry);
-+ if (!dpm_check_a_constraint(constraints, opt)) {
-+ constraints->violations++;
-+ dpm_constraint_rejects++;
-+ valid = 0;
-+ }
-+ }
-+
-+ return valid;
-+}
-+
-+int dpm_show_opconstraints(struct dpm_opt *opt, char * buf)
-+{
-+#ifdef CONFIG_PM
-+ struct list_head * entry;
-+ int len = 0;
-+
-+ list_for_each_prev(entry,&dpm_active) {
-+ struct device * dev = to_device(entry);
-+
-+ if (!dpm_check_a_constraint(dev->constraints, opt)) {
-+ len += sprintf(buf + len, "%s/%s\n", dev->bus->name,
-+ dev->bus_id);
-+ }
-+ }
-+
-+ return len;
-+#else /* CONFIG_PM */
-+ return 0;
-+#endif /* CONFIG_PM */
-+}
-+
-+void dpm_force_off_constrainers(struct dpm_opt *opt)
-+{
-+#ifdef CONFIG_PM
-+ struct list_head * entry;
-+
-+ list_for_each_prev(entry,&dpm_active) {
-+ struct device * dev = to_device(entry);
-+
-+ if (!dpm_check_a_constraint(dev->constraints, opt)) {
-+ suspend_device(dev, PMSG_SUSPEND);
-+ }
-+ }
-+#endif
-+}
-+
-+EXPORT_SYMBOL(dpm_force_off_constrainers);
-+#endif /* CONFIG_DPM */
-+
-Index: linux-2.6.16/drivers/base/power/resume.c
-===================================================================
---- linux-2.6.16.orig/drivers/base/power/resume.c 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/base/power/resume.c 2006-04-11 06:34:10.000000000 +0000
-@@ -34,6 +34,8 @@
- if (dev->bus && dev->bus->resume) {
- dev_dbg(dev,"resuming\n");
- error = dev->bus->resume(dev);
-+ if (!error)
-+ assert_constraints(dev->constraints);
- }
- up(&dev->sem);
- return error;
-Index: linux-2.6.16/drivers/base/power/suspend.c
-===================================================================
---- linux-2.6.16.orig/drivers/base/power/suspend.c 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/base/power/suspend.c 2006-04-11 06:34:10.000000000 +0000
-@@ -57,6 +57,9 @@
- if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
- dev_dbg(dev, "suspending\n");
- error = dev->bus->suspend(dev, state);
-+
-+ if (! error)
-+ deassert_constraints(dev->constraints);
- }
- up(&dev->sem);
- return error;
-Index: linux-2.6.16/drivers/base/power/sysfs.c
-===================================================================
---- linux-2.6.16.orig/drivers/base/power/sysfs.c 2006-03-20 05:53:29.000000000 +0000
-+++ linux-2.6.16/drivers/base/power/sysfs.c 2006-04-11 06:34:10.000000000 +0000
-@@ -56,7 +56,6 @@
-
- static DEVICE_ATTR(state, 0644, state_show, state_store);
-
--
- /*
- * wakeup - Report/change current wakeup option for device
- *
-@@ -128,10 +127,14 @@
-
- static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
-
-+extern struct device_attribute dev_attr_constraints;
-
- static struct attribute * power_attrs[] = {
- &dev_attr_state.attr,
- &dev_attr_wakeup.attr,
-+#ifdef CONFIG_DPM
-+ &dev_attr_constraints.attr,
-+#endif
- NULL,
- };
- static struct attribute_group pm_attr_group = {
-Index: linux-2.6.16/drivers/dpm/Kconfig
-===================================================================
---- linux-2.6.16.orig/drivers/dpm/Kconfig 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/drivers/dpm/Kconfig 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,43 @@
-+#
-+# Dynamic Power Management
-+#
-+
-+menu "Dynamic Power Management"
-+
-+config DPM
-+ bool "Dynamic Power Management"
-+ help
-+ Enable Dynamic Power Management, if implemented for your platform.
-+ DPM conserves power by adjusting power parameters according to
-+ system state (such as idle, running a high-power-usage task, etc.)
-+ and enables associated power management features such as device
-+ constraints on power parameters. DPM relies on power policy and
-+ machine-dependent power operating points and such to be configured
-+ from userspace after boot.
-+
-+ If in doubt, say N.
-+
-+config DPM_STATS
-+ bool " Enable DPM Statistics Gathering"
-+ depends on DPM
-+ help
-+ This enables gathering and reporting statistics for DPM.
-+ This can be useful during development of DPM platform code or
-+ in other situations where information on the operation of DPM is
-+ needed.
-+
-+ If in doubt, say N.
-+
-+
-+config DPM_PROCFS
-+ bool " Enable old DPM /proc interface (deprecated)"
-+ depends on DPM && PROC_FS
-+ help
-+ This enables the /proc/driver/dpm interface for controlling
-+ DPM. Please note that it is recommended to use the sysfs
-+ interface instead (which is built automatically).
-+
-+ If in doubt, say N.
-+
-+endmenu
-+
-Index: linux-2.6.16/drivers/dpm/Makefile
-===================================================================
---- linux-2.6.16.orig/drivers/dpm/Makefile 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/drivers/dpm/Makefile 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for the kernel DPM driver.
-+#
-+
-+obj-$(CONFIG_DPM) += dpm.o dpm-idle.o dpm-ui.o
-+obj-$(CONFIG_DPM_PROCFS) += proc.o
-+
-Index: linux-2.6.16/drivers/dpm/dpm-idle.c
-===================================================================
---- linux-2.6.16.orig/drivers/dpm/dpm-idle.c 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16/drivers/dpm/dpm-idle.c 2006-04-11 06:34:10.000000000 +0000
-@@ -0,0 +1,167 @@
-+/*
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Copyright (C) 2002, MontaVista Software <source@mvista.com>.
-+ *
-+ * Based on ibm405lp_dpm.c by Bishop Brock, Copyright (C) 2002,
-+ * International Business Machines Corporation.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/dpm.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/kmod.h>
-+#include <linux/module.h>
-+#include <linux/proc_fs.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardirq.h>
-+#include <asm/page.h>
-+#include <asm/processor.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+
-+/****************************************************************************
-+ * DPM Idle Handler
-+ ****************************************************************************/
-+
-+/*
-+ The idle handler is one of the most important parts of DPM, as very
-+ significant amounts of energy are saved by moving to a low-power idle state
-+ whenever possible. The basic coding of the core of this routine is simply:
-+
-+ dpm_set_os(DPM_IDLE_STATE);
-+ machine-dependent-idle-routine();
-+ dpm_set_os(DPM_IDLE_TASK_STATE);
-+
-+ The added complexity found here is introduced to avoid unnecessary work, and
-+ especially to reduce the latencies associated with going in and out of idle.
-+ Idle power can be greatly reduced by moving to a very low-frequency
-+ operating point, but we also need to be aware of the impact on interrupt
-+ latencies. The DPM implementation of idle attempts to balance these
-+ competing needs.
-+
-+ We support 2 "idle" states: DPM_IDLE_TASK_STATE and DPM_IDLE_STATE. The
-+ idle thread is marked as a "no-state" task, so that operating point changes
-+ are not automatically made when the idle thread is scheduled. The
-+ "idle-task" state is used for the majority of the idle thread. Interrupts
-+ that occur during idle are handled in this state as well. The "idle" state
-+ is only entered from the idle-task state, and only for the express purpose
-+ of allowing an ultra-low-power operating point.
-+
-+ The introduction of the idle-task state supports a stepped voltage and
-+ frequency scaling at idle. On the IBM 405LP we would not want to go from,
-+ e.g., 266/133 @ 1.8 V directly to 8/8 @ 1.0 V and back. Why not? Because
-+ we would get "stuck" at 8MHz even though we need to wake up and resume
-+ useful work, e.g., we would have to set the 266/133 operating point while
-+ running at 8/8. So instead when going idle first step down to idle-task,
-+ e.g., 100/50 @ 1.0 V, and then step down to e.g. 8/8 to halt. The interrupt
-+ that takes us out of idle takes us back to idle-task (100/50) for interrupt
-+ processing and the potential return to 266/133.
-+
-+ The best policies for this implementation will be able to transition between
-+ idle-task and idle without voltage scaling or driver notification. In these
-+ cases the transitions are handled with minimal latency by simple frequency
-+ scaling. */
-+
-+static inline void
-+quick_idle(void)
-+{
-+ dpm_quick_enter_state(DPM_IDLE_STATE);
-+ dpm_md_idle();
-+ dpm_quick_enter_state(DPM_IDLE_TASK_STATE);
-+}
-+
-+static void
-+full_idle(struct dpm_opt *idle_task_opt, struct dpm_opt *idle_opt)
-+{
-+ dpm_quick_enter_state(DPM_IDLE_STATE);
-+#ifdef CONFIG_DPM_STATS
-+ dpm_update_stats(&idle_opt->stats, &idle_task_opt->stats);
-+#endif
-+ dpm_set_opt(idle_opt, DPM_SYNC);
-+ dpm_md_idle();
-+ dpm_set_opt(idle_task_opt, DPM_SYNC);
-+ dpm_quick_enter_state(DPM_IDLE_TASK_STATE);
-+#ifdef CONFIG_DPM_STATS
-+ dpm_update_stats(&idle_task_opt->stats, &idle_opt->stats);
-+#endif
-+}
-+
-+
-+/* If DPM is currently disabled here we simply do the standard
-+ idle wait.
-+
-+ If we're not actually in DPM_IDLE_TASK_STATE, we need to go back and get
-+ into this state. This could happen in rare instances - an interrupt between
-+ dpm_set_os() and the critical section.
-+
-+ If we are not yet at the idle-task operating point, or if there is no
-+ difference between idle-task and idle, we can enter/exit the idle state
-+ quickly since it's only for statistical purposes. This is also true if for
-+ some reason we can't get the DPM lock, since obviously an asynchronous event
-+ is going to have to occur to clear the lock, and this event is going to take
-+ us out of idle.
-+
-+ Otherwise the full idle shutdown is done. */
-+
-+
-+void
-+dpm_idle(void)
-+{
-+ unsigned long flags;
-+ struct dpm_opt *idle_task_opt, *idle_opt;
-+
-+ current->dpm_state = DPM_NO_STATE;
-+ dpm_set_os(DPM_IDLE_TASK_STATE);