From 5c4ef9286d53263764a46a7d0f46870ef02bc487 Mon Sep 17 00:00:00 2001 From: Michael Lauer Date: Sat, 20 May 2006 15:49:36 +0000 Subject: linux-ezx: we no longer keep own copies of the patches, refresh defconfigs --- .../linux/linux-ezx/a780-transflash_power.patch | 132 - packages/linux/linux-ezx/defconfig-a780 | 17 +- packages/linux/linux-ezx/defconfig-e680 | 21 +- packages/linux/linux-ezx/dpm-core-2.6.16.patch | 5197 ---- packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch | 2469 -- packages/linux/linux-ezx/exz-platformdevices.patch | 63 - packages/linux/linux-ezx/ezx-kbd.patch | 768 - packages/linux/linux-ezx/ezx-mmc-ro.patch | 24 - packages/linux/linux-ezx/ezx_camera.patch | 26846 ------------------- packages/linux/linux-ezx/ezx_core.patch | 15352 ----------- packages/linux/linux-ezx/ezx_defconfig.patch | 4449 --- packages/linux/linux-ezx/ezx_mtd.patch | 219 - packages/linux/linux-ezx/ezx_pxa_ssp.patch | 780 - packages/linux/linux-ezx/ezx_roflash.patch | 895 - packages/linux/linux-ezx/ezx_serial_emu.patch | 16 - packages/linux/linux-ezx/ezx_sound.patch | 6874 ----- packages/linux/linux-ezx/ezx_ts.patch | 1026 - .../linux-ezx/ezx_usb_gadged_serial_pxa27x.patch | 48 - .../linux/linux-ezx/ezxfb-fix-screensave.patch | 34 - packages/linux/linux-ezx/keypad-module.patch | 249 - packages/linux/linux-ezx/laforge_config.patch | 1302 - packages/linux/linux-ezx/nobody_cared.patch | 13 - packages/linux/linux-ezx/old/.mtn2git_empty | 0 .../linux/linux-ezx/old/ezx_pxamci_debug.patch | 70 - packages/linux/linux-ezx/patch-2.6.16.13 | 4985 ---- packages/linux/linux-ezx/pxa-spi.patch | 1041 - packages/linux/linux-ezx/pxa27x_udc-more.patch | 106 - packages/linux/linux-ezx/pxa7xx_udc.patch | 2738 -- packages/linux/linux-ezx/pxa_mtd_fix.patch | 45 - .../linux-ezx/pxa_serial_bug_workaround.patch | 36 - packages/linux/linux-ezx/pxa_serial_dpm.patch | 25 - packages/linux/linux-ezx/pxamci-4bit.patch | 64 - packages/linux/linux-ezx/pxamci_debug.patch | 15 - packages/linux/linux-ezx/sa1100_rtc.patch | 604 - packages/linux/linux-ezx/ssp_pcap_nobitbang.patch | 321 - 35 files changed, 22 insertions(+), 76822 deletions(-) delete mode 100644 packages/linux/linux-ezx/a780-transflash_power.patch delete mode 100644 packages/linux/linux-ezx/dpm-core-2.6.16.patch delete mode 100644 packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch delete mode 100644 packages/linux/linux-ezx/exz-platformdevices.patch delete mode 100644 packages/linux/linux-ezx/ezx-kbd.patch delete mode 100644 packages/linux/linux-ezx/ezx-mmc-ro.patch delete mode 100644 packages/linux/linux-ezx/ezx_camera.patch delete mode 100644 packages/linux/linux-ezx/ezx_core.patch delete mode 100644 packages/linux/linux-ezx/ezx_defconfig.patch delete mode 100644 packages/linux/linux-ezx/ezx_mtd.patch delete mode 100644 packages/linux/linux-ezx/ezx_pxa_ssp.patch delete mode 100644 packages/linux/linux-ezx/ezx_roflash.patch delete mode 100644 packages/linux/linux-ezx/ezx_serial_emu.patch delete mode 100644 packages/linux/linux-ezx/ezx_sound.patch delete mode 100644 packages/linux/linux-ezx/ezx_ts.patch delete mode 100644 packages/linux/linux-ezx/ezx_usb_gadged_serial_pxa27x.patch delete mode 100644 packages/linux/linux-ezx/ezxfb-fix-screensave.patch delete mode 100644 packages/linux/linux-ezx/keypad-module.patch delete mode 100644 packages/linux/linux-ezx/laforge_config.patch delete mode 100644 packages/linux/linux-ezx/nobody_cared.patch delete mode 100644 packages/linux/linux-ezx/old/.mtn2git_empty delete mode 100644 packages/linux/linux-ezx/old/ezx_pxamci_debug.patch delete mode 100644 packages/linux/linux-ezx/patch-2.6.16.13 delete mode 100644 packages/linux/linux-ezx/pxa-spi.patch delete mode 100644 packages/linux/linux-ezx/pxa27x_udc-more.patch delete mode 100644 packages/linux/linux-ezx/pxa7xx_udc.patch delete mode 100644 packages/linux/linux-ezx/pxa_mtd_fix.patch delete mode 100644 packages/linux/linux-ezx/pxa_serial_bug_workaround.patch delete mode 100644 packages/linux/linux-ezx/pxa_serial_dpm.patch delete mode 100644 packages/linux/linux-ezx/pxamci-4bit.patch delete mode 100644 packages/linux/linux-ezx/pxamci_debug.patch delete mode 100644 packages/linux/linux-ezx/sa1100_rtc.patch delete mode 100644 packages/linux/linux-ezx/ssp_pcap_nobitbang.patch diff --git a/packages/linux/linux-ezx/a780-transflash_power.patch b/packages/linux/linux-ezx/a780-transflash_power.patch deleted file mode 100644 index 4b4d4634b5..0000000000 --- a/packages/linux/linux-ezx/a780-transflash_power.patch +++ /dev/null @@ -1,132 +0,0 @@ -Index: linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx.c -=================================================================== ---- linux-2.6.16.5-ezx.orig/arch/arm/mach-pxa/ezx.c 2006-05-02 19:17:34.000000000 +0200 -+++ linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx.c 2006-05-02 22:30:24.000000000 +0200 -@@ -137,10 +137,63 @@ - /* this is only e680, i guess */ - } - -+#if defined(CONFIG_PXA_EZX_A780) -+static u_int8_t mmc_voltage[] = { -+ [MMC_VDD_160] = 5, -+ [MMC_VDD_170] = 5, -+ [MMC_VDD_180] = 6, -+ [MMC_VDD_190] = 6, -+ [MMC_VDD_200] = 7, -+ [MMC_VDD_210] = 7, -+ [MMC_VDD_220] = 8, -+ [MMC_VDD_230] = 8, -+ [MMC_VDD_240] = 9, -+ [MMC_VDD_250] = 9, -+ [MMC_VDD_260] = 10, -+ [MMC_VDD_270] = 10, -+ [MMC_VDD_280] = 11, -+ [MMC_VDD_290] = 11, -+ [MMC_VDD_300] = 12, -+ [MMC_VDD_310] = 12, -+ [MMC_VDD_320] = 13, -+ [MMC_VDD_330] = 13, -+ [MMC_VDD_340] = 14, -+ [MMC_VDD_350] = 14, -+ [MMC_VDD_360] = 15, -+}; -+#elif defined(CONFIG_PXA_EZX_E680) -+static u_int8_t mmc_voltage[] = { -+ [MMC_VDD_160] = 3, -+ [MMC_VDD_170] = 3, -+ [MMC_VDD_180] = 3, -+ [MMC_VDD_190] = 3, -+ [MMC_VDD_200] = 3, -+ [MMC_VDD_210] = 3, -+ [MMC_VDD_220] = 3, -+ [MMC_VDD_230] = 3, -+ [MMC_VDD_240] = 3, -+ [MMC_VDD_250] = 3, -+ [MMC_VDD_260] = 3, -+ [MMC_VDD_270] = 3, -+ [MMC_VDD_280] = 3, -+ [MMC_VDD_290] = 3, -+ [MMC_VDD_300] = 3, -+ [MMC_VDD_310] = 3, -+ [MMC_VDD_320] = 3, -+ [MMC_VDD_330] = 3, -+ [MMC_VDD_340] = 3, -+ [MMC_VDD_350] = 3, -+ [MMC_VDD_360] = 3, -+ -+}; -+#endif -+ - static void ezx_mci_setpower(struct device *dev, unsigned int vdd) - { -- printk("%s entered\n", __FUNCTION__); -- /* FIXME: implement this */ -+ printk("%s(vdd=%u) entered\n", __FUNCTION__, vdd); -+ if (vdd <= MMC_VDD_360) -+ SSP_PCAP_MMCSD_voltage(mmc_voltage[vdd]); -+ - SSP_PCAP_MMCSD_poweron(); - } - -@@ -152,7 +205,14 @@ - } - - static struct pxamci_platform_data ezx_mci_platform_data = { -- .ocr_mask = MMC_VDD_27_28, //|MMC_VDD_32_33|MMC_VDD_33_34, -+#if defined(CONFIG_PXA_EZX_E680) -+ .ocr_mask = MMC_VDD_27_28, -+#elif defined(CONFIG_PXA_EZX_A780) -+ .ocr_mask = MMC_VDD_160_165|MMC_VDD_18_19|MMC_VDD_20_21 -+ |MMC_VDD_22_23|MMC_VDD_24_25|MMC_VDD_26_27 -+ |MMC_VDD_28_29|MMC_VDD_30_31|MMC_VDD_32_33 -+ |MMC_VDD_34_35|MMC_VDD_35_36, -+#endif - .init = ezx_mci_init, - .get_ro = ezx_mci_get_ro, - .setpower = ezx_mci_setpower, -Index: linux-2.6.16.5-ezx/drivers/misc/ezx/ssp_pcap_main.c -=================================================================== ---- linux-2.6.16.5-ezx.orig/drivers/misc/ezx/ssp_pcap_main.c 2006-05-02 19:17:34.000000000 +0200 -+++ linux-2.6.16.5-ezx/drivers/misc/ezx/ssp_pcap_main.c 2006-05-02 22:29:58.000000000 +0200 -@@ -125,18 +125,41 @@ - - void SSP_PCAP_MMCSD_poweroff(void) - { -+#if defined(CONFIG_PXA_EZX_E680) - SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN); - SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN); -+#else -+ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX3_EN); -+#endif - } - EXPORT_SYMBOL(SSP_PCAP_MMCSD_poweroff); - - void SSP_PCAP_MMCSD_poweron(void) - { -+#if defined(CONFIG_PXA_EZX_E680) - SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN); - SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN); -+#elif defined(CONFIG_PXA_EZX_A780) -+ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX3_EN); -+#endif - } - EXPORT_SYMBOL(SSP_PCAP_MMCSD_poweron); - -+void SSP_PCAP_MMCSD_voltage(unsigned char bits) -+{ -+ unsigned int tmp; -+ SSP_PCAP_read_data_from_PCAP(SSP_PCAP_ADJ_AUX_VREG_REGISTER, &tmp); -+#if defined(CONFIG_PXA_EZX_E680) -+ tmp &= 0xffffff9f; /* zero all vaux2 bits */ -+ tmp |= (bits & 0x3) << 5; -+#elif defined(CONFIG_PXA_EZX_A780) -+ tmp &= 0xfffff0ff; /* zero all vaux3 bits */ -+ tmp |= (bits & 0xf) << 8; -+#endif -+ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUX_VREG_REGISTER, tmp); -+} -+EXPORT_SYMBOL(SSP_PCAP_MMCSD_voltage); -+ - static void accessory_bus_detect_handler(ACCESSORY_TYPE type,ACCESSORY_DEVICE_STATUS status,void* privdata ) - { - sspUsbAccessoryInfo.type = (u32)type; diff --git a/packages/linux/linux-ezx/defconfig-a780 b/packages/linux/linux-ezx/defconfig-a780 index e9dda2b13f..560530a1ce 100644 --- a/packages/linux/linux-ezx/defconfig-a780 +++ b/packages/linux/linux-ezx/defconfig-a780 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.5 -# Thu May 4 17:12:53 2006 +# Linux kernel version: 2.6.16.13 +# Thu May 18 19:40:25 2006 # CONFIG_ARM=y CONFIG_MMU=y @@ -19,7 +19,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # -CONFIG_LOCALVERSION="-ezx3" +CONFIG_LOCALVERSION="-ezx6" # CONFIG_LOCALVERSION_AUTO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -120,7 +120,9 @@ CONFIG_PXA_EZX=y CONFIG_PXA_EZX_A780=y CONFIG_PXA27x=y CONFIG_IWMMXT=y -CONFIG_PXA_SSP=y +CONFIG_PXA_SPI=y +CONFIG_PXA_EZX_PCAP=y +CONFIG_PXA_EZX_PCAP_EMU=m # # Processor Type @@ -169,7 +171,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootfstype=ext3 rootdelay=5 ip=192.168.1.2:192.168.1.10:192.168.1.10:255.255.255.0:ezx:usb0:off console=tty0 console=ttyS2,115200n8" +CONFIG_CMDLINE="mem=32M root=/dev/mmcblk0p1 rootfstype=ext3 rootdelay=1 ip=192.168.1.2:192.168.1.10:192.168.1.10:255.255.255.0:ezx:usb0:off console=ttyS2,115200n8 console=tty0" # CONFIG_XIP_KERNEL is not set # @@ -236,7 +238,7 @@ CONFIG_TCP_CONG_BIC=y # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set -CONFIG_IPV6=y +CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m @@ -692,11 +694,12 @@ CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=m +# CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_TOUCHSCREEN_PCAP=m # CONFIG_INPUT_MISC is not set # diff --git a/packages/linux/linux-ezx/defconfig-e680 b/packages/linux/linux-ezx/defconfig-e680 index d59985244e..560530a1ce 100644 --- a/packages/linux/linux-ezx/defconfig-e680 +++ b/packages/linux/linux-ezx/defconfig-e680 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.5 -# Thu May 4 17:12:53 2006 +# Linux kernel version: 2.6.16.13 +# Thu May 18 19:40:25 2006 # CONFIG_ARM=y CONFIG_MMU=y @@ -19,7 +19,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # -CONFIG_LOCALVERSION="-ezx3" +CONFIG_LOCALVERSION="-ezx6" # CONFIG_LOCALVERSION_AUTO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -116,11 +116,13 @@ CONFIG_PXA_EZX=y # CONFIG_MACH_MAINSTONE is not set # CONFIG_ARCH_PXA_IDP is not set # CONFIG_PXA_SHARPSL is not set -CONFIG_PXA_EZX_E680=y -# CONFIG_PXA_EZX_A780 is not set +# CONFIG_PXA_EZX_E680 is not set +CONFIG_PXA_EZX_A780=y CONFIG_PXA27x=y CONFIG_IWMMXT=y -CONFIG_PXA_SSP=y +CONFIG_PXA_SPI=y +CONFIG_PXA_EZX_PCAP=y +CONFIG_PXA_EZX_PCAP_EMU=m # # Processor Type @@ -169,7 +171,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootfstype=ext3 rootdelay=5 ip=192.168.1.2:192.168.1.10:192.168.1.10:255.255.255.0:ezx:usb0:off console=tty0 console=ttyS2,115200n8" +CONFIG_CMDLINE="mem=32M root=/dev/mmcblk0p1 rootfstype=ext3 rootdelay=1 ip=192.168.1.2:192.168.1.10:192.168.1.10:255.255.255.0:ezx:usb0:off console=ttyS2,115200n8 console=tty0" # CONFIG_XIP_KERNEL is not set # @@ -236,7 +238,7 @@ CONFIG_TCP_CONG_BIC=y # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set -CONFIG_IPV6=y +CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m @@ -692,11 +694,12 @@ CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=m +# CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_TOUCHSCREEN_PCAP=m # CONFIG_INPUT_MISC is not set # 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 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+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 - #include - -+#include -+ - 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 . -+ * -+ * Based on ibm405lp_dpm.c by Bishop Brock, Copyright (C) 2002, -+ * International Business Machines Corporation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/**************************************************************************** -+ * 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); -+ local_irq_save(flags); -+ -+ if (! need_resched()) { -+ if (!dpm_enabled) { -+ dpm_md_idle(); -+ -+ } else if (dpm_active_state != DPM_IDLE_TASK_STATE) { -+ -+ -+ } else { -+ idle_task_opt = dpm_choose_opt(dpm_active_policy, -+ DPM_IDLE_TASK_STATE); -+ idle_opt = dpm_choose_opt(dpm_active_policy, -+ DPM_IDLE_STATE); -+ -+ if (dpm_trylock()) { -+ dpm_md_idle(); -+ } else { -+ -+ if ((dpm_active_opt != idle_task_opt) || -+ (idle_task_opt == idle_opt)) { -+ -+ quick_idle(); -+ dpm_unlock(); -+ } else { -+ dpm_unlock(); -+ full_idle(idle_task_opt, idle_opt); -+ } -+ } -+ } -+ } -+ local_irq_restore(flags); -+} -+ -Index: linux-2.6.16/drivers/dpm/dpm-ui.c -=================================================================== ---- linux-2.6.16.orig/drivers/dpm/dpm-ui.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.16/drivers/dpm/dpm-ui.c 2006-04-11 06:35:40.000000000 +0000 -@@ -0,0 +1,1249 @@ -+/* -+ * drivers/dpm/dpm-ui.c - userspace interface to Dynamic Power Management -+ * -+ * (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 -+#include -+#include -+#include -+ -+/* Common sysfs/proc support */ -+ -+char *dpm_state_names[DPM_STATES] = DPM_STATE_NAMES; -+char *dpm_param_names[DPM_PP_NBR] = DPM_PARAM_NAMES; -+ -+#define MAXTOKENS 80 -+ -+static int -+tokenizer(char **tbuf, const char *userbuf, ssize_t n, char **tokptrs, -+ int maxtoks) -+{ -+ char *cp, *tok; -+ char *whitespace = " \t\r\n"; -+ int ntoks = 0; -+ -+ if (!(cp = kmalloc(n + 1, GFP_KERNEL))) -+ return -ENOMEM; -+ -+ *tbuf = cp; -+ memcpy(cp, userbuf, n); -+ cp[n] = '\0'; -+ -+ do { -+ cp = cp + strspn(cp, whitespace); -+ tok = strsep(&cp, whitespace); -+ if ((*tok == '\0') || (ntoks == maxtoks)) -+ break; -+ tokptrs[ntoks++] = tok; -+ } while(cp); -+ -+ return ntoks; -+} -+ -+ -+/* SysFS Interface */ -+ -+#define dpm_attr(_name,_prefix) \ -+static struct subsys_attribute _prefix##_attr = { \ -+ .attr = { \ -+ .name = __stringify(_name), \ -+ .mode = 0644, \ -+ }, \ -+ .show = _prefix##_show, \ -+ .store = _prefix##_store, \ -+} -+ -+ -+static void dpm_kobj_release(struct kobject *kobj) -+{ -+ /* -+ * No sysfs/kobject state to release, DPM layer will handle the -+ * the containing object. -+ */ -+ -+ return; -+} -+ -+/* -+ * Top-level control -+ */ -+ -+static ssize_t dpm_control_show(struct subsystem * subsys, char * buf) -+{ -+ unsigned long flags; -+ ssize_t len = 0; -+ -+ if (dpm_lock_interruptible()) -+ return -ERESTARTSYS; -+ -+ if (!dpm_enabled) { -+ len += sprintf(buf, "disabled\n"); -+ } else { -+ spin_lock_irqsave(&dpm_policy_lock, flags); -+ len += sprintf(buf,"enabled %s %d %s %s %s\n", -+ dpm_active_policy->name, -+ dpm_active_state, -+ dpm_state_names[dpm_active_state], -+ dpm_classopt_name(dpm_active_policy, -+ dpm_active_state), -+ dpm_active_opt ? dpm_active_opt->name : "[none]"); -+ spin_unlock_irqrestore(&dpm_policy_lock, flags); -+ } -+ -+ dpm_unlock(); -+ return len; -+} -+ -+static ssize_t dpm_control_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ int error = 0; -+ -+ if (strncmp(buf, "init", 4) == 0) { -+ error = dynamicpower_init(); -+ } else if (strncmp(buf, "enable", 6) == 0) { -+ error = dynamicpower_enable(); -+ } else if (strncmp(buf, "disable", 7) == 0) { -+ error = dynamicpower_disable(); -+ } else if (strncmp(buf, "terminate", 9) == 0) { -+ error = dynamicpower_terminate(); -+ } else -+ error = -EINVAL; -+ -+ return error ? error : n; -+} -+ -+dpm_attr(control,dpm_control); -+ -+static struct attribute * g[] = { -+ &dpm_control_attr.attr, -+ NULL, -+}; -+ -+static struct attribute_group dpm_attr_group = { -+ .attrs = g, -+}; -+ -+decl_subsys(dpm, NULL, NULL); -+ -+/* -+ * policy -+ */ -+ -+struct dpm_policy_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct kobject * kobj, char * buf); -+ ssize_t (*store)(struct kobject * kobj, const char * buf, size_t count); -+}; -+ -+#define to_policy(obj) container_of(obj,struct dpm_policy,kobj) -+#define to_policy_attr(_attr) container_of(_attr,struct dpm_policy_attribute,attr) -+ -+static struct kobject dpm_policy_kobj = { -+ .kset = &dpm_subsys.kset, -+}; -+ -+static ssize_t policy_control_show(struct subsystem * subsys, char * buf) -+{ -+ ssize_t len = 0; -+ struct list_head * p; -+ -+ if (dpm_lock_interruptible()) -+ return -ERESTARTSYS; -+ -+ len += sprintf(buf + len, "policies: "); -+ -+ list_for_each(p, &dpm_policies) { -+ len += sprintf(buf + len, "%s ", -+ ((struct dpm_policy *) -+ list_entry(p, struct dpm_policy, list))->name); -+ } -+ -+ len += sprintf(buf + len, "\n"); -+ dpm_unlock(); -+ return len; -+} -+ -+static ssize_t policy_control_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ int error = 0; -+ char *tbuf = NULL; -+ char *token[MAXTOKENS]; -+ int ntoks = tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); -+ -+ if (ntoks <= 0) { -+ error = ntoks; -+ goto out; -+ } -+ -+ if (strcmp(token[0],"create") == 0) { -+ error = dpm_create_policy(token[1], &token[2], ntoks - 2); -+ } else if (strcmp(token[0],"set") == 0) { -+ if (ntoks != 2) -+ printk("dpm: policy set requires 1 policy name argument\n"); -+ else -+ error = dpm_set_policy(token[1]); -+ } else -+ error = -EINVAL; -+ -+ out: -+ if (tbuf) -+ kfree(tbuf); -+ return error ? error : n; -+} -+ -+static ssize_t active_policy_show(struct subsystem * subsys, char * buf) -+{ -+ unsigned long flags; -+ ssize_t len = 0; -+ -+ if (dpm_lock_interruptible()) -+ return -ERESTARTSYS; -+ -+ if (!dpm_enabled || (dpm_active_state == DPM_NO_STATE)) { -+ len += sprintf(buf + len, "[none]\n"); -+ } else { -+ spin_lock_irqsave(&dpm_policy_lock, flags); -+ len += sprintf(buf + len,"%s\n", -+ dpm_active_policy->name); -+ spin_unlock_irqrestore(&dpm_policy_lock, flags); -+ } -+ -+ dpm_unlock(); -+ return len; -+} -+ -+static ssize_t active_policy_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ int error = 0; -+ char *tbuf = NULL; -+ char *token[MAXTOKENS]; -+ int ntoks = tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); -+ -+ if (ntoks <= 0) { -+ error = ntoks; -+ goto out; -+ } -+ -+ error = dpm_set_policy(token[0]); -+ -+ out: -+ if (tbuf) -+ kfree(tbuf); -+ return error ? error : n; -+} -+ -+dpm_attr(control,policy_control); -+dpm_attr(active,active_policy); -+ -+#ifdef CONFIG_DPM_STATS -+static ssize_t policy_stats_show(struct subsystem * subsys, char * buf) -+{ -+ int len = 0; -+ struct dpm_policy *policy; -+ struct list_head *p; -+ unsigned long long total_time; -+ -+ if (dpm_lock_interruptible()) -+ return -ERESTARTSYS; -+ -+ if (!dpm_enabled) { -+ dpm_unlock(); -+ len += sprintf(buf + len, "DPM IS DISABLED\n"); -+ return len; -+ } -+ -+ for (p = dpm_policies.next; p != &dpm_policies; p = p->next) { -+ policy = list_entry(p, struct dpm_policy, list); -+ len += sprintf(buf + len, "policy: %s", policy->name); -+ total_time = policy->stats.total_time; -+ if (policy == dpm_active_policy) -+ total_time += (unsigned long long) dpm_time() - -+ policy->stats.start_time; -+ len += sprintf(buf + len, " ticks: %Lu times: %lu\n", -+ (unsigned long long) dpm_time_to_usec(total_time), -+ policy->stats.count); -+ } -+ -+ dpm_unlock(); -+ return len; -+} -+ -+static ssize_t policy_stats_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ return n; -+} -+ -+dpm_attr(stats, policy_stats); -+#endif /* CONFIG_DPM_STATS */ -+ -+static ssize_t a_policy_control_show(struct kobject * kobj, char * buf) -+{ -+ struct dpm_policy *policy = to_policy(kobj); -+ ssize_t len = 0; -+ int i; -+ -+ len += sprintf(buf + len, "ops/classes: "); -+ -+ for (i = 0; i < DPM_STATES; i++) -+ len += sprintf(buf + len, "%s ", dpm_classopt_name(policy,i)); -+ -+ len += sprintf(buf + len, "\n"); -+ return len; -+} -+ -+static ssize_t a_policy_control_store(struct kobject * kobj, const char * buf, -+ size_t n) -+{ -+ struct dpm_policy *policy = to_policy(kobj); -+ int error = 0; -+ char *tbuf = NULL; -+ char *token[MAXTOKENS]; -+ int ntoks = tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); -+ -+ if (ntoks <= 0) { -+ error = ntoks; -+ goto out; -+ } -+ -+ if (strcmp(token[0],"destroy") == 0) { -+ dpm_destroy_policy(policy->name); -+ } else -+ error = -EINVAL; -+ -+ out: -+ if (tbuf) -+ kfree(tbuf); -+ return error ? error : n; -+} -+ -+#define POLICY_STATE_ATTR(index) \ -+static ssize_t policy_state ## index ## _show(struct kobject * kobj, \ -+ char * buf) \ -+{ \ -+ ssize_t len = 0; \ -+ struct dpm_policy *policy = to_policy(kobj); \ -+ len += sprintf(buf + len, "%s\n", policy->classopt[index].opt ? policy->classopt[index].opt->name :policy->classopt[index].class->name ); \ -+ return len; \ -+} \ -+static ssize_t policy_state ## index ## _store(struct kobject * kobj, \ -+ const char * buf, \ -+ size_t n) \ -+{ \ -+ struct dpm_policy *policy = to_policy(kobj); \ -+ struct dpm_classopt old_classopt; \ -+ int ret; \ -+ \ -+ dpm_lock(); \ -+ old_classopt = policy->classopt[index]; \ -+ if ((ret = dpm_map_policy_state(policy,index,(char *)buf))) \ -+ policy->classopt[index] = old_classopt; \ -+ dpm_unlock(); \ -+ return ret ? -EINVAL : n; \ -+} \ -+static struct dpm_policy_attribute policy_state ## index ## _attr = { \ -+ .attr = { \ -+ .mode = 0644, \ -+ }, \ -+ .show = policy_state ## index ## _show, \ -+ .store = policy_state ## index ## _store, \ -+}; \ -+ -+#define MAX_POLICY_STATES 20 -+POLICY_STATE_ATTR(0); -+POLICY_STATE_ATTR(1); -+POLICY_STATE_ATTR(2); -+POLICY_STATE_ATTR(3); -+POLICY_STATE_ATTR(4); -+POLICY_STATE_ATTR(5); -+POLICY_STATE_ATTR(6); -+POLICY_STATE_ATTR(7); -+POLICY_STATE_ATTR(8); -+POLICY_STATE_ATTR(9); -+POLICY_STATE_ATTR(10); -+POLICY_STATE_ATTR(11); -+POLICY_STATE_ATTR(12); -+POLICY_STATE_ATTR(13); -+POLICY_STATE_ATTR(14); -+POLICY_STATE_ATTR(15); -+POLICY_STATE_ATTR(16); -+POLICY_STATE_ATTR(17); -+POLICY_STATE_ATTR(18); -+POLICY_STATE_ATTR(19); -+ -+static struct dpm_policy_attribute *policy_state_attr[MAX_POLICY_STATES] = { -+ &policy_state0_attr, -+ &policy_state1_attr, -+ &policy_state2_attr, -+ &policy_state3_attr, -+ &policy_state4_attr, -+ &policy_state5_attr, -+ &policy_state6_attr, -+ &policy_state7_attr, -+ &policy_state8_attr, -+ &policy_state9_attr, -+ &policy_state10_attr, -+ &policy_state11_attr, -+ &policy_state12_attr, -+ &policy_state13_attr, -+ &policy_state14_attr, -+ &policy_state15_attr, -+ &policy_state16_attr, -+ &policy_state17_attr, -+ &policy_state18_attr, -+ &policy_state19_attr, -+}; -+ -+static ssize_t -+policy_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) -+{ -+ struct dpm_policy_attribute * policy_attr = to_policy_attr(attr); -+ ssize_t ret = 0; -+ -+ if (policy_attr->show) -+ ret = policy_attr->show(kobj,buf); -+ return ret; -+} -+ -+static ssize_t -+policy_attr_store(struct kobject * kobj, struct attribute * attr, -+ const char * buf, size_t count) -+{ -+ struct dpm_policy_attribute * policy_attr = to_policy_attr(attr); -+ ssize_t ret = 0; -+ -+ if (policy_attr->store) -+ ret = policy_attr->store(kobj,buf,count); -+ return ret; -+} -+ -+static struct dpm_policy_attribute a_policy_control_attr = { -+ .attr = { -+ .name = "control", -+ .mode = 0644, -+ }, -+ .show = a_policy_control_show, -+ .store = a_policy_control_store, -+}; -+ -+static struct sysfs_ops policy_sysfs_ops = { -+ .show = policy_attr_show, -+ .store = policy_attr_store, -+}; -+ -+static struct attribute * policy_default_attrs[] = { -+ &a_policy_control_attr.attr, -+ NULL, -+}; -+ -+static struct kobj_type ktype_policy = { -+ .release = dpm_kobj_release, -+ .sysfs_ops = &policy_sysfs_ops, -+ .default_attrs = policy_default_attrs, -+}; -+ -+void dpm_sysfs_new_policy(struct dpm_policy *policy) -+{ -+ int i; -+ -+ memset(&policy->kobj, 0, sizeof(struct kobject)); -+ policy->kobj.kset = &dpm_subsys.kset, -+ kobject_set_name(&policy->kobj,policy->name); -+ policy->kobj.parent = &dpm_policy_kobj; -+ policy->kobj.ktype = &ktype_policy; -+ kobject_register(&policy->kobj); -+ -+ for (i = 0; (i < DPM_STATES) && (i < MAX_POLICY_STATES); i++) { -+ policy_state_attr[i]->attr.name = dpm_state_names[i]; -+ sysfs_create_file(&policy->kobj, &policy_state_attr[i]->attr); -+ } -+ -+ return; -+} -+ -+void dpm_sysfs_destroy_policy(struct dpm_policy *policy) -+{ -+ kobject_unregister(&policy->kobj); -+ return; -+} -+ -+/* -+ * class -+ */ -+ -+struct dpm_class_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct kobject * kobj, char * buf); -+ ssize_t (*store)(struct kobject * kobj, const char * buf, size_t count); -+}; -+ -+#define to_class(obj) container_of(obj,struct dpm_class,kobj) -+#define to_class_attr(_attr) container_of(_attr,struct dpm_class_attribute,attr) -+ -+static ssize_t class_control_show(struct subsystem * subsys, char * buf) -+{ -+ ssize_t len = 0; -+ struct list_head * p; -+ -+ len += sprintf(buf + len, "classes: "); -+ -+ list_for_each(p, &dpm_classes) { -+ len += sprintf(buf + len, "%s ", -+ ((struct dpm_class *) -+ list_entry(p, struct dpm_class, list))->name); -+ } -+ -+ len += sprintf(buf + len, "\nactive: %s\n", -+ (dpm_enabled && dpm_active_class) ? -+ dpm_active_class->name : "[none]"); -+ return len; -+} -+ -+static ssize_t class_control_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ int error = 0; -+ char *tbuf = NULL; -+ char *token[MAXTOKENS]; -+ int ntoks = tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); -+ -+ if (ntoks <= 0) { -+ error = ntoks; -+ goto out; -+ } -+ -+ if (strcmp(token[0],"create") == 0) { -+ if (ntoks < 3) -+ printk("dpm: class create requires 1 name and at least one operating point argument\n"); -+ else -+ error = dpm_create_class(token[1], &token[2], ntoks-2); -+ } else -+ error = -EINVAL; -+ -+ out: -+ if (tbuf) -+ kfree(tbuf); -+ return error ? error : n; -+} -+ -+static struct kobject dpm_class_kobj = { -+ .kset = &dpm_subsys.kset, -+}; -+ -+dpm_attr(control,class_control); -+ -+static ssize_t a_class_control_show(struct kobject * kobj, char * buf) -+{ -+ ssize_t len = 0; -+ struct dpm_class *class = to_class(kobj); -+ int i; -+ -+ len += sprintf(buf + len, "ops: "); -+ -+ for (i = 0; i < class->nops; i++) -+ len += sprintf(buf + len, "%s ", class->ops[i]->name); -+ -+ -+ len += sprintf(buf + len, "\n"); -+ return len; -+} -+ -+static ssize_t a_class_control_store(struct kobject * kobj, const char * buf, -+ size_t n) -+{ -+ return n; -+} -+ -+static ssize_t -+class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) -+{ -+ struct dpm_class_attribute * class_attr = to_class_attr(attr); -+ ssize_t ret = 0; -+ -+ if (class_attr->show) -+ ret = class_attr->show(kobj,buf); -+ return ret; -+} -+ -+static ssize_t -+class_attr_store(struct kobject * kobj, struct attribute * attr, -+ const char * buf, size_t count) -+{ -+ struct dpm_class_attribute * class_attr = to_class_attr(attr); -+ ssize_t ret = 0; -+ -+ if (class_attr->store) -+ ret = class_attr->store(kobj,buf,count); -+ return ret; -+} -+ -+static struct dpm_class_attribute a_class_control_attr = { -+ .attr = { -+ .name = "control", -+ .mode = 0644, -+ }, -+ .show = a_class_control_show, -+ .store = a_class_control_store, -+}; -+ -+static struct sysfs_ops class_sysfs_ops = { -+ .show = class_attr_show, -+ .store = class_attr_store, -+}; -+ -+static struct attribute * class_default_attrs[] = { -+ &a_class_control_attr.attr, -+ NULL, -+}; -+ -+static struct kobj_type ktype_class = { -+ .release = dpm_kobj_release, -+ .sysfs_ops = &class_sysfs_ops, -+ .default_attrs = class_default_attrs, -+}; -+ -+void dpm_sysfs_new_class(struct dpm_class *class) -+{ -+ memset(&class->kobj, 0, sizeof(struct kobject)); -+ class->kobj.kset = &dpm_subsys.kset, -+ kobject_set_name(&class->kobj,class->name); -+ class->kobj.parent = &dpm_class_kobj; -+ class->kobj.ktype = &ktype_class; -+ kobject_register(&class->kobj); -+ return; -+} -+ -+void dpm_sysfs_destroy_class(struct dpm_class *class) -+{ -+ kobject_unregister(&class->kobj); -+ return; -+} -+ -+ -+/* -+ * op -+ */ -+ -+struct dpm_op_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct kobject * kobj, char * buf); -+ ssize_t (*store)(struct kobject * kobj, const char * buf, size_t count); -+}; -+ -+#define to_op(obj) container_of(obj,struct dpm_opt,kobj) -+#define to_op_attr(_attr) container_of(_attr,struct dpm_op_attribute,attr) -+ -+static ssize_t op_control_show(struct subsystem * subsys, char * buf) -+{ -+ unsigned long flags; -+ ssize_t len = 0; -+ -+ if (dpm_lock_interruptible()) -+ return -ERESTARTSYS; -+ -+ len += sprintf(buf + len, "active: "); -+ -+ if (!dpm_enabled) { -+ len += sprintf(buf + len, "[none]\n"); -+ } else { -+ spin_lock_irqsave(&dpm_policy_lock, flags); -+ len += sprintf(buf + len,"%s\n", -+ dpm_active_opt ? dpm_active_opt->name : "[none]"); -+ spin_unlock_irqrestore(&dpm_policy_lock, flags); -+ } -+ -+ dpm_unlock(); -+ -+ len += sprintf(buf + len, "params: %d\n", DPM_PP_NBR); -+ return len; -+} -+ -+static ssize_t op_control_store(struct subsystem * subsys, const char * buf, -+ size_t n) -+{ -+ int error = 0; -+ char *tbuf = NULL; -+ char *token[MAXTOKENS]; -+ int ntoks = tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); -+ -+ if (ntoks <= 0) { -+ error = ntoks; -+ goto out; -+ } -+ -+ if ((strcmp(token[0],"create") == 0) && (ntoks >= 2)) { -+ dpm_md_pp_t pp[DPM_PP_NBR]; -+ int i; -+ -+ for (i = 0; i < DPM_PP_NBR; i++) { -+ if (i >= ntoks - 2) -+ pp[i] = -1; -+ else -+ pp[i] = simple_strtol(token[i + 2], -+ NULL, 0); -+ } -+ -+ error = dpm_create_opt(token[1], pp, DPM_PP_NBR); -+ } else -+ error = -EINVAL; -+ -+ out: -+ if (tbuf) -+ kfree(tbuf); -+ return error ? error : n; -+ -+} -+ -+dpm_attr(control,op_control); -+ -+