[haiku-commits] haiku: hrev44860 - src/add-ons/kernel/drivers/power/x86_cpuidle src/add-ons/kernel/generic/cpuidle headers/os/drivers

  • From: fredrik.holmqvist@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 18 Nov 2012 17:43:52 +0100 (CET)

hrev44860 adds 17 changesets to branch 'master'
old head: 8a6451b9fdd949f67cdef090635ce610d1216cce
new head: 5e520ef3995c81a6e1d4ba7ef094c18b4eeaeef3
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5e520ef+^8a6451b

----------------------------------------------------------------------------

2195811: idle: introduce cpuidle generic module
  
  This module will load the various lowlevel cpuidle modules' implementations
  during initialiation. If it finds one available module, it will change
  the global gCpuIdleFunc as its own better one.
  
  When idle, cpuidle module will select the best cstate and enter it by
  calling the lowlevel module's implementation.
  
  Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

251f971: cpuidle: add intel native cpuidle module
  
  Currently, it only supports intel sandy bridge processors.
  
  Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

32c4d58: driver: add cpuidle device driver
  
  Currently, it's only used to load generic cpuidle module. But in the
  future, we will add some features such as stats reporting etc.
  
  Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

5ae9700: enable cpuidle module and device driver
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

66b0c86: cpuidle: rename CpuidleStats to CpuidleStat
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

76877c9: intel_cpuidle: apply strict cpu checking to see it's snb or not
  
  we need to check cpu vendor, family, and model
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

e467ba9: cpuidle: add stats reporting support
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

69f69b0: cpuidle: we should exit when cStateCount is less than 3
  
  If only C0, C1 are available, it doesn't make any sense to enable
  cpuidle
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

57311e7: acpi: add ACPI_ALLOCATE_LOCAL_BUFFER to ACPI.h
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

71d9d37: cpuidle: move generic cpuidle to generic
  
  After this change, low level cpuidle drivers load the generic cpuidle
  module if they can support the underlying platform.
  
  change the intel cpuidle driver accordingly, now it's loaded by acpi
  bus manager during boot, although it doesn't depend on acpi
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

0a0af89: acpi: export read_bit_register and write_bit_register
  
  acpi cpuidle needs such acpi functions
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

0138a95: cpuidle: implement acpi cpuidle driver
  
  we prefer intel native cpuidle driver on newer intel platforms --
  sandybridge or later. we'll fall back to acpi cpuidle driver for other
  platforms.
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

be9a02c: cpuidle: remove drivers/cpuidle
  
  Since generic cpuidle module is loaded by lowlevel cpuidle drivers which
  are loaded dynamically during boot, we don't need drivers/cpuidle any
  more
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

8073227: x86_cpuidle: use module_dependencies rather than get_module()
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

5554814: x86_cpuidle: coding style fix according to Jerome
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

553f1eb: Add disabled cpuidle driver and module to haikuImage.
  
  CPU idle still needs some polish, but it should work on
  newer cpus.

                         [ Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx> ]

5e520ef: Merge branch 'cpu_idle'
  
  * cpu_idle:
    Add disabled cpuidle driver and module to haikuImage.
    x86_cpuidle: coding style fix according to Jerome
    x86_cpuidle: use module_dependencies rather than get_module()
    cpuidle: remove drivers/cpuidle
    cpuidle: implement acpi cpuidle driver
    acpi: export read_bit_register and write_bit_register
    cpuidle: move generic cpuidle to generic
    acpi: add ACPI_ALLOCATE_LOCAL_BUFFER to ACPI.h
    cpuidle: we should exit when cStateCount is less than 3
    cpuidle: add stats reporting support
    intel_cpuidle: apply strict cpu checking to see it's snb or not
    cpuidle: rename CpuidleStats to CpuidleStat
    enable cpuidle module and device driver
    driver: add cpuidle device driver
    cpuidle: add intel native cpuidle module
    idle: introduce cpuidle generic module

                         [ Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx> ]

----------------------------------------------------------------------------

12 files changed, 939 insertions(+), 2 deletions(-)
build/jam/HaikuImage                             |   3 +-
headers/os/drivers/ACPI.h                        |   5 +
headers/os/drivers/cpuidle.h                     |  57 ++
.../kernel/bus_managers/acpi/BusManager.cpp      |  18 +-
src/add-ons/kernel/drivers/power/Jamfile         |   1 +
.../kernel/drivers/power/x86_cpuidle/Jamfile     |  10 +
.../drivers/power/x86_cpuidle/acpi_cpuidle.cpp   | 583 +++++++++++++++++++
.../drivers/power/x86_cpuidle/intel_cpuidle.cpp  | 121 ++++
.../drivers/power/x86_cpuidle/x86_cpuidle.h      |  30 +
src/add-ons/kernel/generic/Jamfile               |   1 +
src/add-ons/kernel/generic/cpuidle/Jamfile       |   7 +
src/add-ons/kernel/generic/cpuidle/cpuidle.cpp   | 105 ++++

############################################################################

Commit:      2195811a847b0a573b017750eefda19abcf0a6ec
URL:         http://cgit.haiku-os.org/haiku/commit/?id=2195811
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Wed Jul  4 15:28:43 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:17 2012 UTC

idle: introduce cpuidle generic module

This module will load the various lowlevel cpuidle modules' implementations
during initialiation. If it finds one available module, it will change
the global gCpuIdleFunc as its own better one.

When idle, cpuidle module will select the best cstate and enter it by
calling the lowlevel module's implementation.

Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h
new file mode 100644
index 0000000..67d8f30
--- /dev/null
+++ b/headers/os/drivers/cpuidle.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _CPUIDLE_MODULE_H
+#define _CPUIDLE_MODULE_H
+
+
+#include <module.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CPUIDLE_CSTATE_MAX     8
+#define CSTATE_NAME_LENGTH     32
+#define B_CPUIDLE_MODULE_NAME "idle/generic/cpuidle/v1"
+
+
+struct CpuidleStats {
+       uint64          usageCount;
+       bigtime_t       usageTime;
+};
+
+
+struct CpuidleInfo {
+       int32                   cstateSleep;
+       CpuidleStats    stats[CPUIDLE_CSTATE_MAX];
+};
+
+
+struct CpuidleCstate {
+       char    name[CSTATE_NAME_LENGTH];
+       int32   latency;
+       int32   (*EnterIdle)(int32 state, CpuidleCstate *cstate);
+       void    *pData;
+};
+
+
+struct CpuidleModuleInfo {
+       module_info             info;
+       CpuidleCstate   cStates[CPUIDLE_CSTATE_MAX];
+       int32                   cStateCount;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif         // _CPUIDLE_MODULE_H
diff --git a/src/add-ons/kernel/idle/Jamfile b/src/add-ons/kernel/idle/Jamfile
new file mode 100644
index 0000000..27f0864
--- /dev/null
+++ b/src/add-ons/kernel/idle/Jamfile
@@ -0,0 +1,3 @@
+SubDir HAIKU_TOP src add-ons kernel idle ;
+
+SubInclude HAIKU_TOP src add-ons kernel idle generic ;
diff --git a/src/add-ons/kernel/idle/generic/Jamfile 
b/src/add-ons/kernel/idle/generic/Jamfile
new file mode 100644
index 0000000..f7ff039
--- /dev/null
+++ b/src/add-ons/kernel/idle/generic/Jamfile
@@ -0,0 +1,7 @@
+SubDir HAIKU_TOP src add-ons kernel idle generic ;
+
+UsePrivateKernelHeaders ;
+
+KernelAddon <module>cpuidle :
+       cpuidle.cpp
+       ;
diff --git a/src/add-ons/kernel/idle/generic/cpuidle.cpp 
b/src/add-ons/kernel/idle/generic/cpuidle.cpp
new file mode 100644
index 0000000..4338a16
--- /dev/null
+++ b/src/add-ons/kernel/idle/generic/cpuidle.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <KernelExport.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <smp.h>
+#include <cpuidle.h>
+
+
+static CpuidleInfo sPerCPU[B_MAX_CPU_COUNT];
+static CpuidleModuleInfo *sCpuidleModule;
+
+extern void (*gCpuIdleFunc)(void);
+
+
+/*
+ * next cstate selection algorithm is based on NetBSD's
+ * it's simple, stupid
+ */
+static int32
+SelectCstate(CpuidleInfo *info)
+{
+       static const int32 csFactor = 3;
+
+       for (int32 i = sCpuidleModule->cStateCount - 1; i > 0; i--) {
+               CpuidleCstate *cState = &sCpuidleModule->cStates[i];
+               if (info->cstateSleep > cState->latency * csFactor)
+                       return i;
+       }
+
+       /* Choose C1 if there's no state found */
+       return 1;
+}
+
+
+static inline void
+EnterCstate(int32 state, CpuidleInfo *info)
+{
+       CpuidleCstate *cstate = &sCpuidleModule->cStates[state];
+       bigtime_t now = system_time();
+       if (cstate->EnterIdle(state, cstate) > 0) {
+               bigtime_t diff = system_time() - now;
+               info->cstateSleep = diff;
+               info->stats[state].usageCount++;
+               info->stats[state].usageTime += diff;
+       } else {
+               info->cstateSleep = 0;
+       }
+}
+
+
+static void
+CpuCstateIdle(void)
+{
+       CpuidleInfo *info = &sPerCPU[smp_get_current_cpu()];
+       int32 state = SelectCstate(info);
+       EnterCstate(state, info);
+}
+
+
+static status_t
+std_ops(int32 op, ...)
+{
+       switch (op) {
+               case B_MODULE_INIT:
+               {
+                       dprintf("generic cpuidle init\n");
+                       void *cookie = open_module_list("idle/cpuidles");
+                       if (cookie == NULL)
+                               return B_ERROR;
+
+                       char name[B_FILE_NAME_LENGTH];
+                       size_t nameLength = sizeof(name);
+
+                       while (read_next_module_name(cookie, name, &nameLength) 
== B_OK) {
+                               if (get_module(name, (module_info 
**)&sCpuidleModule) == B_OK) {
+                                       break;
+                               }
+                       }
+
+                       close_module_list(cookie);
+                       if (sCpuidleModule->cStateCount < 2) {
+                               dprintf("no enough available cstates, 
exiting...\n");
+                               put_module(sCpuidleModule->info.name);
+                               return B_ERROR;
+                       } else {
+                               dprintf("using %s\n", 
sCpuidleModule->info.name);
+                               gCpuIdleFunc = CpuCstateIdle;
+                               return B_OK;
+                       }
+               }
+               case B_MODULE_UNINIT:
+                       dprintf("generic cpuidle uninit\n");
+                       put_module(sCpuidleModule->info.name);
+                       return B_OK;
+       }
+
+       return B_ERROR;
+}
+
+
+static module_info sModule = {
+       B_CPUIDLE_MODULE_NAME,
+       0,
+       std_ops
+};
+
+
+module_info *modules[] = {
+       (module_info *)&sModule,
+       NULL
+};

############################################################################

Commit:      251f971259714ef07cc4642f145bfb4ce552eb0e
URL:         http://cgit.haiku-os.org/haiku/commit/?id=251f971
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Wed Jul  4 16:09:35 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:17 2012 UTC

cpuidle: add intel native cpuidle module

Currently, it only supports intel sandy bridge processors.

Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/idle/Jamfile b/src/add-ons/kernel/idle/Jamfile
index 27f0864..878fd5c 100644
--- a/src/add-ons/kernel/idle/Jamfile
+++ b/src/add-ons/kernel/idle/Jamfile
@@ -1,3 +1,4 @@
 SubDir HAIKU_TOP src add-ons kernel idle ;
 
+SubInclude HAIKU_TOP src add-ons kernel idle cpuidles ;
 SubInclude HAIKU_TOP src add-ons kernel idle generic ;
diff --git a/src/add-ons/kernel/idle/cpuidles/Jamfile 
b/src/add-ons/kernel/idle/cpuidles/Jamfile
new file mode 100644
index 0000000..03a6a3c
--- /dev/null
+++ b/src/add-ons/kernel/idle/cpuidles/Jamfile
@@ -0,0 +1,3 @@
+SubDir HAIKU_TOP src add-ons kernel idle cpuidles ;
+
+SubInclude HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ;
diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile 
b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile
new file mode 100644
index 0000000..4b74f09
--- /dev/null
+++ b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile
@@ -0,0 +1,7 @@
+SubDir HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ;
+
+UsePrivateKernelHeaders ;
+
+KernelAddon intel_cpuidle :
+       intel_cpuidle.cpp
+       ;
diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
new file mode 100644
index 0000000..a2bba81
--- /dev/null
+++ b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <KernelExport.h>
+#include <stdio.h>
+
+#include <cpu.h>
+#include <arch_system_info.h>
+#include <cpuidle.h>
+
+
+static status_t std_ops(int32 op, ...);
+
+
+static inline void
+x86_monitor(const void *addr, unsigned long ecx, unsigned long edx)
+{
+       asm volatile("monitor"
+               :: "a" (addr), "c" (ecx), "d"(edx));
+}
+
+
+static inline void
+x86_mwait(unsigned long eax, unsigned long ecx)
+{
+       asm volatile("mwait"
+               :: "a" (eax), "c" (ecx));
+}
+
+
+static void *kMwaitEax[] = {
+       // C0, we never use it
+       (void *)0x00,
+       // MWAIT C1
+       (void *)0x00,
+       // MWAIT C2
+       (void *)0x10,
+       // MWAIT C3
+       (void *)0x20,
+       // MWAIT C4
+       (void *)0x30,
+       // MWAIT C5
+       (void *)0x40,
+       // MWAIT C6, 0x2 is used to fully shrink L2 cache
+       (void *)0x52
+};
+
+
+static int32
+IntelCstateIdleEnter(int32 state, CpuidleCstate *cstate)
+{
+       cpu_ent *cpu = get_cpu_struct();
+       if (cpu->invoke_scheduler)
+               return 0;
+
+       x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
+       if (!cpu->invoke_scheduler)
+               x86_mwait((unsigned long)cstate->pData, 1);
+
+       return state;
+}
+
+
+static CpuidleCstate kSnbcStates[CPUIDLE_CSTATE_MAX] = {
+       {},
+       {
+               "C1-SNB",
+               1,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C3-SNB",
+               80,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C6-SNB",
+               104,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C7-SNB",
+               109,
+               IntelCstateIdleEnter,
+       },
+};
+
+
+static CpuidleModuleInfo sIntelidleModule = {
+       {
+               "idle/cpuidles/intel_cpuidle/v1",
+               0,
+               std_ops
+       },
+
+};
+
+
+static status_t
+std_ops(int32 op, ...)
+{
+       switch (op) {
+               case B_MODULE_INIT:
+               {
+                       cpuid_info cpuid;
+                       get_current_cpuid(&cpuid, 5);
+                       /* ecx[0] monitor/mwait extension supported
+                        * ecx[1] support for treating interrupts as 
break-events for mwait
+                        * edx number of sub-states
+                        */
+                       if (!((cpuid.regs.ecx & 0x1) && (cpuid.regs.ecx & 0x2) 
&&
+                               cpuid.regs.edx)) {
+                               return B_ERROR;
+                       }
+
+                       sIntelidleModule.cStateCount = 1;
+                       for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) {
+                               int32 subStates = (cpuid.regs.edx >> ((i) * 4)) 
& 0xf;
+                               // no sub-states means the state is not 
available
+                               if (!subStates)
+                                       continue;
+                               
sIntelidleModule.cStates[sIntelidleModule.cStateCount] =
+                                       kSnbcStates[i];
+                               
sIntelidleModule.cStates[sIntelidleModule.cStateCount].pData =
+                                       kMwaitEax[i];
+                               sIntelidleModule.cStateCount++;
+                       }
+                       dprintf("intel idle init\n");
+                       return B_OK;
+               }
+               case B_MODULE_UNINIT:
+                       dprintf("intel idle uninit\n");
+                       return B_OK;
+       }
+
+       return B_ERROR;
+}
+
+
+module_info *modules[] = {
+       (module_info *)&sIntelidleModule,
+       NULL
+};

############################################################################

Commit:      32c4d58bd3f0cc284c95103e8c970dda643e57f4
URL:         http://cgit.haiku-os.org/haiku/commit/?id=32c4d58
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Wed Jul  4 16:11:53 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:18 2012 UTC

driver: add cpuidle device driver

Currently, it's only used to load generic cpuidle module. But in the
future, we will add some features such as stats reporting etc.

Signed-off-by: Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/cpuidle/Jamfile 
b/src/add-ons/kernel/drivers/cpuidle/Jamfile
new file mode 100644
index 0000000..50b9290
--- /dev/null
+++ b/src/add-ons/kernel/drivers/cpuidle/Jamfile
@@ -0,0 +1,5 @@
+SubDir HAIKU_TOP src add-ons kernel drivers cpuidle ;
+
+KernelAddon <driver>cpuidle :
+       cpuidle.cpp
+       ;
diff --git a/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp 
b/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
new file mode 100644
index 0000000..9440358
--- /dev/null
+++ b/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <Drivers.h>
+#include <KernelExport.h>
+
+#include <cpuidle.h>
+
+#define DEVICE_NAME "cpuidle"
+
+int32 api_version = B_CUR_DRIVER_API_VERSION;
+
+CpuidleModuleInfo *sCpuidleModule;
+
+static status_t
+cpuidle_open(const char *name, uint32 flags, void **cookie)
+{
+       *cookie = NULL;
+       return B_OK;
+}
+
+
+static status_t
+cpuidle_close(void *cookie)
+{
+       return B_OK;
+}
+
+
+static status_t
+cpuidle_free(void *cookie)
+{
+       return B_OK;
+}
+
+
+static status_t
+cpuidle_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
+{
+       return B_OK;
+}
+
+
+static status_t
+cpuidle_read(void *cookie, off_t pos, void *buffer, size_t *length)
+{
+       *length = 0;
+       return B_OK;
+}
+
+
+static status_t
+cpuidle_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
+{
+       return B_OK;
+}
+
+
+status_t
+init_hardware(void)
+{
+       return B_OK;
+}
+
+
+const char **
+publish_devices(void)
+{
+       static const char *devices[] = {
+               DEVICE_NAME,
+               NULL
+       };
+
+       return devices;
+}
+
+
+device_hooks *
+find_device(const char *name)
+{
+       static device_hooks hooks = {
+               &cpuidle_open,
+               &cpuidle_close,
+               &cpuidle_free,
+               &cpuidle_ioctl,
+               &cpuidle_read,
+               &cpuidle_write,
+       };
+
+
+       return &hooks;
+}
+
+
+status_t
+init_driver(void)
+{
+       status_t err;
+
+       err = get_module(B_CPUIDLE_MODULE_NAME, (module_info 
**)&sCpuidleModule);
+       if (err != B_OK) {
+               dprintf("can't load "B_CPUIDLE_MODULE_NAME"\n");
+       }
+       return B_OK;
+}
+
+
+void
+uninit_driver(void)
+{
+       put_module(B_CPUIDLE_MODULE_NAME);
+}

############################################################################

Commit:      5ae9700a12099acc5a2f68660ea795e3d2d31f83
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5ae9700
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Wed Jul  4 16:13:55 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:18 2012 UTC

enable cpuidle module and device driver

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/Jamfile b/src/add-ons/kernel/Jamfile
index 5a5b275..03f5786 100644
--- a/src/add-ons/kernel/Jamfile
+++ b/src/add-ons/kernel/Jamfile
@@ -8,6 +8,7 @@ SubInclude HAIKU_TOP src add-ons kernel debugger ;
 SubInclude HAIKU_TOP src add-ons kernel drivers ;
 SubInclude HAIKU_TOP src add-ons kernel file_cache ;
 SubInclude HAIKU_TOP src add-ons kernel file_systems ;
+SubInclude HAIKU_TOP src add-ons kernel idle ;
 SubInclude HAIKU_TOP src add-ons kernel interrupt_controllers ;
 SubInclude HAIKU_TOP src add-ons kernel network ;
 SubInclude HAIKU_TOP src add-ons kernel media ;
diff --git a/src/add-ons/kernel/drivers/Jamfile 
b/src/add-ons/kernel/drivers/Jamfile
index ef7c7ee..f23cf48 100644
--- a/src/add-ons/kernel/drivers/Jamfile
+++ b/src/add-ons/kernel/drivers/Jamfile
@@ -4,6 +4,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers bluetooth ;
 SubInclude HAIKU_TOP src add-ons kernel drivers bus ;
 SubInclude HAIKU_TOP src add-ons kernel drivers audio ;
 SubInclude HAIKU_TOP src add-ons kernel drivers common ;
+SubInclude HAIKU_TOP src add-ons kernel drivers cpuidle ;
 SubInclude HAIKU_TOP src add-ons kernel drivers disk ;
 SubInclude HAIKU_TOP src add-ons kernel drivers dvb ;
 SubInclude HAIKU_TOP src add-ons kernel drivers input ;

############################################################################

Commit:      66b0c86ae4a3f29e998114ec4a1a4824922e0d9a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=66b0c86
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Jul  7 11:41:27 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:18 2012 UTC

cpuidle: rename CpuidleStats to CpuidleStat

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h
index 67d8f30..7234429 100644
--- a/headers/os/drivers/cpuidle.h
+++ b/headers/os/drivers/cpuidle.h
@@ -17,15 +17,15 @@ extern "C" {
 #define B_CPUIDLE_MODULE_NAME "idle/generic/cpuidle/v1"
 
 
-struct CpuidleStats {
+struct CpuidleStat {
        uint64          usageCount;
        bigtime_t       usageTime;
 };
 
 
 struct CpuidleInfo {
-       int32                   cstateSleep;
-       CpuidleStats    stats[CPUIDLE_CSTATE_MAX];
+       int32           cstateSleep;
+       CpuidleStat     stats[CPUIDLE_CSTATE_MAX];
 };
 
 

############################################################################

Commit:      76877c9a514e51a6f37ca40c8b09f2fcc32321ff
URL:         http://cgit.haiku-os.org/haiku/commit/?id=76877c9
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Jul  7 11:42:14 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:18 2012 UTC

intel_cpuidle: apply strict cpu checking to see it's snb or not

we need to check cpu vendor, family, and model

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
index a2bba81..6265c73 100644
--- a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
+++ b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
@@ -66,7 +66,7 @@ IntelCstateIdleEnter(int32 state, CpuidleCstate *cstate)
 }
 
 
-static CpuidleCstate kSnbcStates[CPUIDLE_CSTATE_MAX] = {
+static CpuidleCstate sSnbcStates[CPUIDLE_CSTATE_MAX] = {
        {},
        {
                "C1-SNB",
@@ -107,6 +107,15 @@ std_ops(int32 op, ...)
        switch (op) {
                case B_MODULE_INIT:
                {
+                       cpu_ent *cpu = get_cpu_struct();
+                       if (cpu->arch.vendor != VENDOR_INTEL || 
cpu->arch.family != 6)
+                               return B_ERROR;
+
+                       // Calculated Model Value: M = (Extended Model << 4) + 
Model
+                       uint32 model = (cpu->arch.extended_model << 4) + 
cpu->arch.model;
+                       if (model != 0x2a && model != 0x2d)
+                               return B_ERROR;
+
                        cpuid_info cpuid;
                        get_current_cpuid(&cpuid, 5);
                        /* ecx[0] monitor/mwait extension supported
@@ -125,7 +134,7 @@ std_ops(int32 op, ...)
                                if (!subStates)
                                        continue;
                                
sIntelidleModule.cStates[sIntelidleModule.cStateCount] =
-                                       kSnbcStates[i];
+                                       sSnbcStates[i];
                                
sIntelidleModule.cStates[sIntelidleModule.cStateCount].pData =
                                        kMwaitEax[i];
                                sIntelidleModule.cStateCount++;

############################################################################

Commit:      e467ba95b017924b06f2f52a73ab5380d553543a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e467ba9
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Jul  7 13:52:56 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:19 2012 UTC

cpuidle: add stats reporting support

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h
index 7234429..ed79be9 100644
--- a/headers/os/drivers/cpuidle.h
+++ b/headers/os/drivers/cpuidle.h
@@ -44,6 +44,15 @@ struct CpuidleModuleInfo {
 };
 
 
+struct GenCpuidle {
+       module_info     info;
+       int32           (*GetIdleStateCount)(void);
+       char *          (*GetIdleStateName)(int32 state);
+       void            (*GetIdleStateInfo)(int32 cpu, int32 state,
+                                                                       
CpuidleStat *stat);
+};
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/add-ons/kernel/drivers/cpuidle/Jamfile 
b/src/add-ons/kernel/drivers/cpuidle/Jamfile
index 50b9290..ce5f450 100644
--- a/src/add-ons/kernel/drivers/cpuidle/Jamfile
+++ b/src/add-ons/kernel/drivers/cpuidle/Jamfile
@@ -1,5 +1,7 @@
 SubDir HAIKU_TOP src add-ons kernel drivers cpuidle ;
 
+UsePrivateKernelHeaders ;
+
 KernelAddon <driver>cpuidle :
        cpuidle.cpp
        ;
diff --git a/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp 
b/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
index 9440358..82110c9 100644
--- a/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
+++ b/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
@@ -6,6 +6,10 @@
  *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
  */
 
+#include <stdio.h>
+#include <string.h>
+#include <smp.h>
+
 #include <Drivers.h>
 #include <KernelExport.h>
 
@@ -15,7 +19,7 @@
 
 int32 api_version = B_CUR_DRIVER_API_VERSION;
 
-CpuidleModuleInfo *sCpuidleModule;
+static GenCpuidle *sGenCpuidle;
 
 static status_t
 cpuidle_open(const char *name, uint32 flags, void **cookie)
@@ -49,7 +53,36 @@ cpuidle_ioctl(void *cookie, uint32 op, void *buffer, size_t 
length)
 static status_t
 cpuidle_read(void *cookie, off_t pos, void *buffer, size_t *length)
 {
-       *length = 0;
+       if (pos != 0) {
+               *length = 0;
+               return B_OK;
+       }
+       char *str = (char *)buffer;
+       size_t max_len = *length;
+       int32 stateCount = sGenCpuidle->GetIdleStateCount();
+       int32 bytes = snprintf(str, max_len, "C-STATE COUNT: %"B_PRId32"\n", 
stateCount);
+       max_len-= bytes;
+       str += bytes;
+       int32 cpu = smp_get_num_cpus();
+
+       for (int32 i = 0; i < cpu; i++) {
+               bytes = snprintf(str, max_len, "CPU%"B_PRId32"\n", i);
+               max_len-= bytes;
+               str += bytes;
+               for (int32 j = 1; j < stateCount; j++) {
+                       CpuidleStat stat;
+                       bytes = snprintf(str, max_len, "%s\n", 
sGenCpuidle->GetIdleStateName(j));
+                       max_len-= bytes;
+                       str += bytes;
+                       sGenCpuidle->GetIdleStateInfo(i, j, &stat);
+                       bytes = snprintf(str, max_len, "%lld %lldus\n",
+                                                       stat.usageCount, 
stat.usageTime);
+                       max_len-= bytes;
+                       str += bytes;
+               }
+       }
+       *length = strlen((char *)buffer);
+
        return B_OK;
 }
 
@@ -102,7 +135,7 @@ init_driver(void)
 {
        status_t err;
 
-       err = get_module(B_CPUIDLE_MODULE_NAME, (module_info 
**)&sCpuidleModule);
+       err = get_module(B_CPUIDLE_MODULE_NAME, (module_info **)&sGenCpuidle);
        if (err != B_OK) {
                dprintf("can't load "B_CPUIDLE_MODULE_NAME"\n");
        }
diff --git a/src/add-ons/kernel/idle/generic/cpuidle.cpp 
b/src/add-ons/kernel/idle/generic/cpuidle.cpp
index 4338a16..041b729 100644
--- a/src/add-ons/kernel/idle/generic/cpuidle.cpp
+++ b/src/add-ons/kernel/idle/generic/cpuidle.cpp
@@ -106,10 +106,37 @@ std_ops(int32 op, ...)
 }
 
 
-static module_info sModule = {
-       B_CPUIDLE_MODULE_NAME,
-       0,
-       std_ops
+static char *
+GetIdleStateName(int32 state)
+{
+       return sCpuidleModule->cStates[state].name;
+}
+
+
+static int32
+GetIdleStateCount(void)
+{
+       return sCpuidleModule->cStateCount;
+}
+
+
+static void
+GetIdleStateInfo(int32 cpu, int32 state, CpuidleStat *stat)
+{
+       memcpy(stat, &sPerCPU[cpu].stats[state], sizeof(CpuidleStat));
+}
+
+
+static GenCpuidle sModule = {
+       {
+               B_CPUIDLE_MODULE_NAME,
+               0,
+               std_ops
+       },
+
+       GetIdleStateCount,
+       GetIdleStateName,
+       GetIdleStateInfo
 };
 
 

############################################################################

Commit:      69f69b003afc34ed153ac3463e7844f77c29dce2
URL:         http://cgit.haiku-os.org/haiku/commit/?id=69f69b0
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Thu Jul  5 02:42:55 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:19 2012 UTC

cpuidle: we should exit when cStateCount is less than 3

If only C0, C1 are available, it doesn't make any sense to enable
cpuidle

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/idle/generic/cpuidle.cpp 
b/src/add-ons/kernel/idle/generic/cpuidle.cpp
index 041b729..0ce9851 100644
--- a/src/add-ons/kernel/idle/generic/cpuidle.cpp
+++ b/src/add-ons/kernel/idle/generic/cpuidle.cpp
@@ -86,7 +86,7 @@ std_ops(int32 op, ...)
                        }
 
                        close_module_list(cookie);
-                       if (sCpuidleModule->cStateCount < 2) {
+                       if (sCpuidleModule->cStateCount < 3) {
                                dprintf("no enough available cstates, 
exiting...\n");
                                put_module(sCpuidleModule->info.name);
                                return B_ERROR;

############################################################################

Commit:      57311e7bb7302866bdcbb28aea336152c7ae873d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=57311e7
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Aug  4 14:12:45 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:19 2012 UTC

acpi: add ACPI_ALLOCATE_LOCAL_BUFFER to ACPI.h

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/ACPI.h b/headers/os/drivers/ACPI.h
index 221c649..aeea707 100644
--- a/headers/os/drivers/ACPI.h
+++ b/headers/os/drivers/ACPI.h
@@ -133,6 +133,7 @@ typedef struct acpi_data {
 
 enum {
        ACPI_ALLOCATE_BUFFER = -1,
+       ACPI_ALLOCATE_LOCAL_BUFFER = -2,
 };
 
 

############################################################################

Commit:      71d9d375b82be4c5c336831042bc7401b9ed0e07
URL:         http://cgit.haiku-os.org/haiku/commit/?id=71d9d37
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Aug  4 14:12:40 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:19 2012 UTC

cpuidle: move generic cpuidle to generic

After this change, low level cpuidle drivers load the generic cpuidle
module if they can support the underlying platform.

change the intel cpuidle driver accordingly, now it's loaded by acpi
bus manager during boot, although it doesn't depend on acpi

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h
index ed79be9..7649cda 100644
--- a/headers/os/drivers/cpuidle.h
+++ b/headers/os/drivers/cpuidle.h
@@ -14,7 +14,7 @@ extern "C" {
 
 #define CPUIDLE_CSTATE_MAX     8
 #define CSTATE_NAME_LENGTH     32
-#define B_CPUIDLE_MODULE_NAME "idle/generic/cpuidle/v1"
+#define B_CPUIDLE_MODULE_NAME "generic/cpuidle/v1"
 
 
 struct CpuidleStat {
@@ -28,28 +28,25 @@ struct CpuidleInfo {
        CpuidleStat     stats[CPUIDLE_CSTATE_MAX];
 };
 
+struct CpuidleDevice;
 
 struct CpuidleCstate {
        char    name[CSTATE_NAME_LENGTH];
        int32   latency;
-       int32   (*EnterIdle)(int32 state, CpuidleCstate *cstate);
+       int32   (*EnterIdle)(int32 state, CpuidleDevice *device);
        void    *pData;
 };
 
 
-struct CpuidleModuleInfo {
-       module_info             info;
+struct CpuidleDevice {
        CpuidleCstate   cStates[CPUIDLE_CSTATE_MAX];
        int32                   cStateCount;
 };
 
 
-struct GenCpuidle {
+struct CpuidleModuleInfo {
        module_info     info;
-       int32           (*GetIdleStateCount)(void);
-       char *          (*GetIdleStateName)(int32 state);
-       void            (*GetIdleStateInfo)(int32 cpu, int32 state,
-                                                                       
CpuidleStat *stat);
+       status_t        (*AddDevice)(CpuidleDevice *device);
 };
 
 
diff --git a/src/add-ons/kernel/Jamfile b/src/add-ons/kernel/Jamfile
index 03f5786..5a5b275 100644
--- a/src/add-ons/kernel/Jamfile
+++ b/src/add-ons/kernel/Jamfile
@@ -8,7 +8,6 @@ SubInclude HAIKU_TOP src add-ons kernel debugger ;
 SubInclude HAIKU_TOP src add-ons kernel drivers ;
 SubInclude HAIKU_TOP src add-ons kernel file_cache ;
 SubInclude HAIKU_TOP src add-ons kernel file_systems ;
-SubInclude HAIKU_TOP src add-ons kernel idle ;
 SubInclude HAIKU_TOP src add-ons kernel interrupt_controllers ;
 SubInclude HAIKU_TOP src add-ons kernel network ;
 SubInclude HAIKU_TOP src add-ons kernel media ;
diff --git a/src/add-ons/kernel/drivers/power/Jamfile 
b/src/add-ons/kernel/drivers/power/Jamfile
index 56d9143..45feced 100644
--- a/src/add-ons/kernel/drivers/power/Jamfile
+++ b/src/add-ons/kernel/drivers/power/Jamfile
@@ -5,3 +5,4 @@ SubInclude HAIKU_TOP src add-ons kernel drivers power 
acpi_button ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
 SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ;
+SubInclude HAIKU_TOP src add-ons kernel drivers power x86_cpuidle ;
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile
new file mode 100644
index 0000000..5161250
--- /dev/null
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile
@@ -0,0 +1,10 @@
+SubDir HAIKU_TOP src add-ons kernel drivers power x86_cpuidle ;
+
+UsePrivateKernelHeaders ;
+
+KernelAddon x86_cpuidle :
+       acpi_cpuidle.cpp
+       intel_cpuidle.cpp
+       ;
+
+Depends x86_cpuidle : acpi ;
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
new file mode 100644
index 0000000..8064d50
--- /dev/null
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ *
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <KernelExport.h>
+#include <Drivers.h>
+#include <Errors.h>
+#include <smp.h>
+#include <cpu.h>
+#include <arch_system_info.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ACPI.h>
+
+#include "x86_cpuidle.h"
+
+#define ACPI_CPUIDLE_MODULE_NAME "drivers/power/x86_cpuidle/acpi/driver_v1"
+
+struct acpi_cpuidle_driver_info {
+       device_node *node;
+       acpi_device_module_info *acpi;
+       acpi_device acpi_cookie;
+};
+
+static device_manager_info *sDeviceManager;
+static acpi_cpuidle_driver_info *acpi_processor[B_MAX_CPU_COUNT];
+
+
+static status_t
+acpi_cpuidle_init(void)
+{
+       dprintf("acpi_cpuidle_init\n");
+
+       return B_ERROR;
+}
+
+
+static status_t
+acpi_processor_init(acpi_cpuidle_driver_info *device)
+{
+       status_t status = B_ERROR;
+
+       acpi_data buffer;
+       buffer.pointer = NULL;
+       buffer.length = ACPI_ALLOCATE_BUFFER;
+       dprintf("get acpi processor @%p\n", device->acpi_cookie);
+       status = device->acpi->evaluate_method(device->acpi_cookie, NULL, NULL,
+               &buffer);
+       if (status != B_OK) {
+               dprintf("failed to get processor obj\n");
+               return B_IO_ERROR;
+       }
+       acpi_object_type *object = (acpi_object_type *)buffer.pointer;
+       dprintf("acpi cpu%"B_PRId32": P_BLK at %#x/%lu\n",
+                       object->data.processor.cpu_id,
+                       object->data.processor.pblk_address,
+                       object->data.processor.pblk_length);
+       int32 cpuid = object->data.processor.cpu_id;
+       free(buffer.pointer);
+       if (cpuid > smp_get_num_cpus())
+               return B_ERROR;
+
+       if (smp_get_num_cpus() == 1)
+               cpuid = 1;
+
+       acpi_processor[cpuid-1] = device;
+
+       if (cpuid == 1) {
+               if (intel_cpuidle_init() != B_OK)
+                       return acpi_cpuidle_init();
+       }
+
+       return B_OK;
+}
+
+
+static float
+acpi_cpuidle_support(device_node *parent)
+{
+       const char *bus;
+       uint32 device_type;
+
+       dprintf("acpi_cpuidle_support\n");
+       // make sure parent is really the ACPI bus manager
+       if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
+               return -1;
+
+       if (strcmp(bus, "acpi"))
+               return 0.0;
+
+       // check whether it's really a cpu Device
+       if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, 
&device_type, false) != B_OK
+               || device_type != ACPI_TYPE_PROCESSOR) {
+               return 0.0;
+       }
+
+       return 0.6;
+}
+
+
+static status_t
+acpi_cpuidle_register_device(device_node *node)
+{
+       device_attr attrs[] = {
+               { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI CPU 
IDLE" }},
+               { NULL }
+       };
+
+       dprintf("acpi_cpuidle_register_device\n");
+       return sDeviceManager->register_node(node, ACPI_CPUIDLE_MODULE_NAME, 
attrs,
+               NULL, NULL);
+}
+
+
+static status_t
+acpi_cpuidle_init_driver(device_node *node, void **driverCookie)
+{
+       dprintf("acpi_cpuidle_init_driver\n");
+       acpi_cpuidle_driver_info *device;
+       device = (acpi_cpuidle_driver_info *)calloc(1, sizeof(*device));
+       if (device == NULL)
+               return B_NO_MEMORY;
+
+       *driverCookie = device;
+
+       device->node = node;
+
+       device_node *parent;
+       parent = sDeviceManager->get_parent_node(node);
+       sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
+               (void **)&device->acpi_cookie);
+       sDeviceManager->put_node(parent);
+
+       return acpi_processor_init(device);
+}
+
+
+static void
+acpi_cpuidle_uninit_driver(void *driverCookie)
+{
+       dprintf("acpi_cpuidle_uninit_driver");
+       acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info 
*)driverCookie;
+       free(device);
+}
+
+
+module_dependency module_dependencies[] = {
+       { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
+       {}
+};
+
+
+static driver_module_info sAcpiidleModule = {
+       {
+               ACPI_CPUIDLE_MODULE_NAME,
+               0,
+               NULL
+       },
+
+       acpi_cpuidle_support,
+       acpi_cpuidle_register_device,
+       acpi_cpuidle_init_driver,
+       acpi_cpuidle_uninit_driver,
+       NULL,
+       NULL,   // rescan
+       NULL,   // removed
+};
+
+
+module_info *modules[] = {
+       (module_info *)&sAcpiidleModule,
+       NULL
+};
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
new file mode 100644
index 0000000..1032a5d
--- /dev/null
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <KernelExport.h>
+#include <cpu.h>
+#include <arch_system_info.h>
+
+#include <stdio.h>
+
+#include <cpuidle.h>
+
+#include "x86_cpuidle.h"
+
+static CpuidleModuleInfo *sIdle;
+static CpuidleDevice sIntelDevice;
+
+static void *kMwaitEax[] = {
+       // C0, we never use it
+       (void *)0x00,
+       // MWAIT C1
+       (void *)0x00,
+       // MWAIT C2
+       (void *)0x10,
+       // MWAIT C3
+       (void *)0x20,
+       // MWAIT C4
+       (void *)0x30,
+       // MWAIT C5
+       (void *)0x40,
+       // MWAIT C6, 0x2 is used to fully shrink L2 cache
+       (void *)0x52
+};
+
+
+static int32
+IntelCstateIdleEnter(int32 state, CpuidleDevice *device)
+{
+       cpu_ent *cpu = get_cpu_struct();
+       if (cpu->invoke_scheduler)
+               return 0;
+
+       CpuidleCstate *cState = &device->cStates[state];
+       x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
+       if (!cpu->invoke_scheduler)
+               x86_mwait((unsigned long)cState->pData, 1);
+
+       return state;
+}
+
+
+static CpuidleCstate sSnbcStates[CPUIDLE_CSTATE_MAX] = {
+       {},
+       {
+               "C1-SNB",
+               1,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C3-SNB",
+               80,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C6-SNB",
+               104,
+               IntelCstateIdleEnter,
+       },
+       {
+               "C7-SNB",
+               109,
+               IntelCstateIdleEnter,
+       },
+};
+
+
+status_t
+intel_cpuidle_init(void)
+{
+       dprintf("intel idle init\n");
+       if (get_module(B_CPUIDLE_MODULE_NAME, (module_info**)&sIdle) != B_OK)
+               return B_ERROR;
+       cpu_ent *cpu = get_cpu_struct();
+       if (cpu->arch.vendor != VENDOR_INTEL || cpu->arch.family != 6)
+               return B_ERROR;
+
+       // Calculated Model Value: M = (Extended Model << 4) + Model
+       uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model;
+       if (model != 0x2a && model != 0x2d)
+               return B_ERROR;
+
+       cpuid_info cpuid;
+       get_current_cpuid(&cpuid, 5);
+       /* ecx[0] monitor/mwait extension supported
+        * ecx[1] support for treating interrupts as break-events for mwait
+        * edx number of sub-states
+        */
+       if (!((cpuid.regs.ecx & 0x1) && (cpuid.regs.ecx & 0x2) &&
+               cpuid.regs.edx)) {
+               return B_ERROR;
+       }
+
+       sIntelDevice.cStateCount = 1;
+       for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) {
+               int32 subStates = (cpuid.regs.edx >> ((i) * 4)) & 0xf;
+               // no sub-states means the state is not available
+               if (!subStates)
+                       continue;
+               sIntelDevice.cStates[sIntelDevice.cStateCount] =
+                       sSnbcStates[i];
+               sIntelDevice.cStates[sIntelDevice.cStateCount].pData =
+                       kMwaitEax[i];
+               sIntelDevice.cStateCount++;
+       }
+       status_t status = sIdle->AddDevice(&sIntelDevice);
+       if (status == B_OK)
+               dprintf("using intel idle\n");
+       else
+               put_module(B_CPUIDLE_MODULE_NAME);
+       return status;
+}
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h
new file mode 100644
index 0000000..b524ef1
--- /dev/null
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static inline void
+x86_monitor(const void *addr, unsigned long ecx, unsigned long edx)
+{
+       asm volatile("monitor"
+               :: "a" (addr), "c" (ecx), "d"(edx));
+}
+
+static inline void
+x86_mwait(unsigned long eax, unsigned long ecx)
+{
+       asm volatile("mwait"
+               :: "a" (eax), "c" (ecx));
+}
+
+status_t intel_cpuidle_init(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/add-ons/kernel/generic/Jamfile 
b/src/add-ons/kernel/generic/Jamfile
index a2a6bfc..719061b 100644
--- a/src/add-ons/kernel/generic/Jamfile
+++ b/src/add-ons/kernel/generic/Jamfile
@@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel generic ;
 
 SubInclude HAIKU_TOP src add-ons kernel generic ata_adapter ;
 SubInclude HAIKU_TOP src add-ons kernel generic atomizer ;
+SubInclude HAIKU_TOP src add-ons kernel generic cpuidle ;
 SubInclude HAIKU_TOP src add-ons kernel generic dpc ;
 SubInclude HAIKU_TOP src add-ons kernel generic ide_adapter ;
 SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ;
diff --git a/src/add-ons/kernel/generic/cpuidle/Jamfile 
b/src/add-ons/kernel/generic/cpuidle/Jamfile
new file mode 100644
index 0000000..bb7cdd2
--- /dev/null
+++ b/src/add-ons/kernel/generic/cpuidle/Jamfile
@@ -0,0 +1,7 @@
+SubDir HAIKU_TOP src add-ons kernel generic cpuidle ;
+
+UsePrivateKernelHeaders ;
+
+KernelAddon cpuidle :
+       cpuidle.cpp
+       ;
diff --git a/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp 
b/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp
new file mode 100644
index 0000000..cc17be8
--- /dev/null
+++ b/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
+ */
+
+#include <KernelExport.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <smp.h>
+#include <cpuidle.h>
+
+
+static CpuidleInfo sPerCPU[B_MAX_CPU_COUNT];
+static CpuidleDevice *sDevice;
+extern void (*gCpuIdleFunc)(void);
+
+
+/*
+ * next cstate selection algorithm is based on NetBSD's
+ * it's simple, stupid
+ */
+static int32
+SelectCstate(CpuidleInfo *info)
+{
+       static const int32 csFactor = 3;
+
+       for (int32 i = sDevice->cStateCount - 1; i > 0; i--) {
+               CpuidleCstate *cState = &sDevice->cStates[i];
+               if (info->cstateSleep > cState->latency * csFactor)
+                       return i;
+       }
+
+       /* Choose C1 if there's no state found */
+       return 1;
+}
+
+
+static inline void
+EnterCstate(int32 state, CpuidleInfo *info)
+{
+       CpuidleCstate *cstate = &sDevice->cStates[state];
+       bigtime_t now = system_time();
+       int32 finalState = cstate->EnterIdle(state, sDevice);
+       if (finalState > 0) {
+               bigtime_t diff = system_time() - now;
+               info->cstateSleep = diff;
+               info->stats[finalState].usageCount++;
+               info->stats[finalState].usageTime += diff;
+       } else {
+               info->cstateSleep = 0;
+       }
+}
+
+
+static void
+CpuCstateIdle(void)
+{
+       CpuidleInfo *info = &sPerCPU[smp_get_current_cpu()];
+       int32 state = SelectCstate(info);
+       EnterCstate(state, info);
+}
+
+
+static status_t
+std_ops(int32 op, ...)
+{
+       switch (op) {
+               case B_MODULE_INIT:
+                       return B_OK;
+               case B_MODULE_UNINIT:
+                       return B_OK;
+       }
+
+       return B_ERROR;
+}
+
+
+status_t AddDevice(CpuidleDevice *device)
+{
+       sDevice = device;
+       memory_write_barrier();
+       gCpuIdleFunc = CpuCstateIdle;
+       return B_OK;
+}
+
+
+static CpuidleModuleInfo sCpuidleModule = {
+       {
+               B_CPUIDLE_MODULE_NAME,
+               0,
+               std_ops
+       },
+
+       AddDevice,
+};
+
+
+module_info *modules[] = {
+       (module_info *)&sCpuidleModule,
+       NULL
+};
diff --git a/src/add-ons/kernel/idle/Jamfile b/src/add-ons/kernel/idle/Jamfile
deleted file mode 100644
index 878fd5c..0000000
--- a/src/add-ons/kernel/idle/Jamfile
+++ /dev/null
@@ -1,4 +0,0 @@
-SubDir HAIKU_TOP src add-ons kernel idle ;
-
-SubInclude HAIKU_TOP src add-ons kernel idle cpuidles ;
-SubInclude HAIKU_TOP src add-ons kernel idle generic ;
diff --git a/src/add-ons/kernel/idle/cpuidles/Jamfile 
b/src/add-ons/kernel/idle/cpuidles/Jamfile
deleted file mode 100644
index 03a6a3c..0000000
--- a/src/add-ons/kernel/idle/cpuidles/Jamfile
+++ /dev/null
@@ -1,3 +0,0 @@
-SubDir HAIKU_TOP src add-ons kernel idle cpuidles ;
-
-SubInclude HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ;
diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile 
b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile
deleted file mode 100644
index 4b74f09..0000000
--- a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile
+++ /dev/null
@@ -1,7 +0,0 @@
-SubDir HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ;
-
-UsePrivateKernelHeaders ;
-
-KernelAddon intel_cpuidle :
-       intel_cpuidle.cpp
-       ;
diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
deleted file mode 100644
index 6265c73..0000000
--- a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2012, Haiku, Inc. All Rights Reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
- */
-
-#include <KernelExport.h>
-#include <stdio.h>
-
-#include <cpu.h>
-#include <arch_system_info.h>
-#include <cpuidle.h>
-
-
-static status_t std_ops(int32 op, ...);
-
-
-static inline void
-x86_monitor(const void *addr, unsigned long ecx, unsigned long edx)
-{
-       asm volatile("monitor"
-               :: "a" (addr), "c" (ecx), "d"(edx));
-}
-
-
-static inline void
-x86_mwait(unsigned long eax, unsigned long ecx)
-{
-       asm volatile("mwait"
-               :: "a" (eax), "c" (ecx));
-}
-
-
-static void *kMwaitEax[] = {
-       // C0, we never use it
-       (void *)0x00,
-       // MWAIT C1
-       (void *)0x00,
-       // MWAIT C2
-       (void *)0x10,
-       // MWAIT C3
-       (void *)0x20,
-       // MWAIT C4
-       (void *)0x30,
-       // MWAIT C5
-       (void *)0x40,
-       // MWAIT C6, 0x2 is used to fully shrink L2 cache
-       (void *)0x52
-};
-
-
-static int32
-IntelCstateIdleEnter(int32 state, CpuidleCstate *cstate)
-{
-       cpu_ent *cpu = get_cpu_struct();
-       if (cpu->invoke_scheduler)
-               return 0;
-
-       x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
-       if (!cpu->invoke_scheduler)
-               x86_mwait((unsigned long)cstate->pData, 1);
-
-       return state;
-}
-
-
-static CpuidleCstate sSnbcStates[CPUIDLE_CSTATE_MAX] = {
-       {},
-       {
-               "C1-SNB",
-               1,
-               IntelCstateIdleEnter,
-       },
-       {
-               "C3-SNB",
-               80,
-               IntelCstateIdleEnter,
-       },
-       {
-               "C6-SNB",
-               104,
-               IntelCstateIdleEnter,
-       },
-       {
-               "C7-SNB",
-               109,
-               IntelCstateIdleEnter,
-       },
-};
-
-
-static CpuidleModuleInfo sIntelidleModule = {
-       {
-               "idle/cpuidles/intel_cpuidle/v1",
-               0,
-               std_ops
-       },
-
-};
-
-
-static status_t
-std_ops(int32 op, ...)
-{
-       switch (op) {
-               case B_MODULE_INIT:
-               {
-                       cpu_ent *cpu = get_cpu_struct();
-                       if (cpu->arch.vendor != VENDOR_INTEL || 
cpu->arch.family != 6)
-                               return B_ERROR;
-
-                       // Calculated Model Value: M = (Extended Model << 4) + 
Model
-                       uint32 model = (cpu->arch.extended_model << 4) + 
cpu->arch.model;
-                       if (model != 0x2a && model != 0x2d)
-                               return B_ERROR;
-
-                       cpuid_info cpuid;
-                       get_current_cpuid(&cpuid, 5);
-                       /* ecx[0] monitor/mwait extension supported
-                        * ecx[1] support for treating interrupts as 
break-events for mwait
-                        * edx number of sub-states
-                        */
-                       if (!((cpuid.regs.ecx & 0x1) && (cpuid.regs.ecx & 0x2) 
&&
-                               cpuid.regs.edx)) {
-                               return B_ERROR;
-                       }
-
-                       sIntelidleModule.cStateCount = 1;
-                       for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) {
-                               int32 subStates = (cpuid.regs.edx >> ((i) * 4)) 
& 0xf;
-                               // no sub-states means the state is not 
available
-                               if (!subStates)
-                                       continue;
-                               
sIntelidleModule.cStates[sIntelidleModule.cStateCount] =
-                                       sSnbcStates[i];
-                               
sIntelidleModule.cStates[sIntelidleModule.cStateCount].pData =
-                                       kMwaitEax[i];
-                               sIntelidleModule.cStateCount++;
-                       }
-                       dprintf("intel idle init\n");
-                       return B_OK;
-               }
-               case B_MODULE_UNINIT:
-                       dprintf("intel idle uninit\n");
-                       return B_OK;
-       }
-
-       return B_ERROR;
-}
-
-
-module_info *modules[] = {
-       (module_info *)&sIntelidleModule,
-       NULL
-};
diff --git a/src/add-ons/kernel/idle/generic/Jamfile 
b/src/add-ons/kernel/idle/generic/Jamfile
deleted file mode 100644
index f7ff039..0000000
--- a/src/add-ons/kernel/idle/generic/Jamfile
+++ /dev/null
@@ -1,7 +0,0 @@
-SubDir HAIKU_TOP src add-ons kernel idle generic ;
-
-UsePrivateKernelHeaders ;
-
-KernelAddon <module>cpuidle :
-       cpuidle.cpp
-       ;
diff --git a/src/add-ons/kernel/idle/generic/cpuidle.cpp 
b/src/add-ons/kernel/idle/generic/cpuidle.cpp
deleted file mode 100644
index 0ce9851..0000000
--- a/src/add-ons/kernel/idle/generic/cpuidle.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2012, Haiku, Inc. All Rights Reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
- */
-
-#include <KernelExport.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <smp.h>
-#include <cpuidle.h>
-
-
-static CpuidleInfo sPerCPU[B_MAX_CPU_COUNT];
-static CpuidleModuleInfo *sCpuidleModule;
-
-extern void (*gCpuIdleFunc)(void);
-
-
-/*
- * next cstate selection algorithm is based on NetBSD's
- * it's simple, stupid
- */
-static int32
-SelectCstate(CpuidleInfo *info)
-{
-       static const int32 csFactor = 3;
-
-       for (int32 i = sCpuidleModule->cStateCount - 1; i > 0; i--) {
-               CpuidleCstate *cState = &sCpuidleModule->cStates[i];
-               if (info->cstateSleep > cState->latency * csFactor)
-                       return i;
-       }
-
-       /* Choose C1 if there's no state found */
-       return 1;
-}
-
-
-static inline void
-EnterCstate(int32 state, CpuidleInfo *info)
-{
-       CpuidleCstate *cstate = &sCpuidleModule->cStates[state];
-       bigtime_t now = system_time();
-       if (cstate->EnterIdle(state, cstate) > 0) {
-               bigtime_t diff = system_time() - now;
-               info->cstateSleep = diff;
-               info->stats[state].usageCount++;
-               info->stats[state].usageTime += diff;
-       } else {
-               info->cstateSleep = 0;
-       }
-}
-
-
-static void
-CpuCstateIdle(void)
-{
-       CpuidleInfo *info = &sPerCPU[smp_get_current_cpu()];
-       int32 state = SelectCstate(info);
-       EnterCstate(state, info);
-}
-
-
-static status_t
-std_ops(int32 op, ...)
-{
-       switch (op) {
-               case B_MODULE_INIT:
-               {
-                       dprintf("generic cpuidle init\n");
-                       void *cookie = open_module_list("idle/cpuidles");
-                       if (cookie == NULL)
-                               return B_ERROR;
-
-                       char name[B_FILE_NAME_LENGTH];
-                       size_t nameLength = sizeof(name);
-
-                       while (read_next_module_name(cookie, name, &nameLength) 
== B_OK) {
-                               if (get_module(name, (module_info 
**)&sCpuidleModule) == B_OK) {
-                                       break;
-                               }
-                       }
-
-                       close_module_list(cookie);
-                       if (sCpuidleModule->cStateCount < 3) {
-                               dprintf("no enough available cstates, 
exiting...\n");
-                               put_module(sCpuidleModule->info.name);
-                               return B_ERROR;
-                       } else {
-                               dprintf("using %s\n", 
sCpuidleModule->info.name);
-                               gCpuIdleFunc = CpuCstateIdle;
-                               return B_OK;
-                       }
-               }
-               case B_MODULE_UNINIT:
-                       dprintf("generic cpuidle uninit\n");
-                       put_module(sCpuidleModule->info.name);
-                       return B_OK;
-       }
-
-       return B_ERROR;
-}
-
-
-static char *
-GetIdleStateName(int32 state)
-{
-       return sCpuidleModule->cStates[state].name;
-}
-
-
-static int32
-GetIdleStateCount(void)
-{
-       return sCpuidleModule->cStateCount;
-}
-
-
-static void
-GetIdleStateInfo(int32 cpu, int32 state, CpuidleStat *stat)
-{
-       memcpy(stat, &sPerCPU[cpu].stats[state], sizeof(CpuidleStat));
-}
-
-
-static GenCpuidle sModule = {
-       {
-               B_CPUIDLE_MODULE_NAME,
-               0,
-               std_ops
-       },
-
-       GetIdleStateCount,
-       GetIdleStateName,
-       GetIdleStateInfo
-};
-
-
-module_info *modules[] = {
-       (module_info *)&sModule,
-       NULL
-};

############################################################################

Commit:      0a0af8957e4ad48168cb26dba4a058f7eb0e4892
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0a0af89
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Fri Aug 17 11:23:53 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:20 2012 UTC

acpi: export read_bit_register and write_bit_register

acpi cpuidle needs such acpi functions

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/ACPI.h b/headers/os/drivers/ACPI.h
index aeea707..66ce0d0 100644
--- a/headers/os/drivers/ACPI.h
+++ b/headers/os/drivers/ACPI.h
@@ -262,6 +262,10 @@ struct acpi_module_info {
        /* Table Access */
        status_t        (*get_table)(const char *signature, uint32 instance,
                                        void **tableHeader);
+
+       /* Register Access */
+       status_t        (*read_bit_register)(uint32 regid, uint32 *val);
+       status_t        (*write_bit_register)(uint32 regid, uint32 val);
 };
 
 
diff --git a/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp 
b/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp
index 692898b..ea63dba 100644
--- a/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp
+++ b/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp
@@ -715,6 +715,20 @@ get_table(const char* signature, uint32 instance, void** 
tableHeader)
 }
 
 
+status_t
+read_bit_register(uint32 regid, uint32 *val)
+{
+       return AcpiReadBitRegister(regid, (UINT32 *)val);
+}
+
+
+status_t
+write_bit_register(uint32 regid, uint32 val)
+{
+       return AcpiWriteBitRegister(regid, val);
+}
+
+
 struct acpi_module_info gACPIModule = {
        {
                B_ACPI_MODULE_NAME,
@@ -759,5 +773,7 @@ struct acpi_module_info gACPIModule = {
        prepare_sleep_state,
        enter_sleep_state,
        reboot,
-       get_table
+       get_table,
+       read_bit_register,
+       write_bit_register
 };

############################################################################

Commit:      0138a95ebac947f56c39ff2a148d3380ad5db1cc
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0138a95
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sun Aug 19 11:30:23 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:20 2012 UTC

cpuidle: implement acpi cpuidle driver

we prefer intel native cpuidle driver on newer intel platforms --
sandybridge or later. we'll fall back to acpi cpuidle driver for other
platforms.

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
index 8064d50..fb4095c 100644
--- a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
@@ -19,27 +19,433 @@
 #include <string.h>
 
 #include <ACPI.h>
+#include <cpuidle.h>
 
 #include "x86_cpuidle.h"
 
+#define ACPI_PDC_REVID         0x1
+#define ACPI_OSC_QUERY         (1 << 0)
+
+#define ACPI_PDC_P_FFH         (1 << 0)
+#define ACPI_PDC_C_C1_HALT     (1 << 1)
+#define ACPI_PDC_T_FFH         (1 << 2)
+#define ACPI_PDC_SMP_C1PT      (1 << 3)
+#define ACPI_PDC_SMP_C2C3      (1 << 4)
+#define ACPI_PDC_SMP_P_SW      (1 << 5)
+#define ACPI_PDC_SMP_C_SW      (1 << 6)
+#define ACPI_PDC_SMP_T_SW      (1 << 7)
+#define ACPI_PDC_C_C1_FFH      (1 << 8)
+#define ACPI_PDC_C_C2C3_FFH    (1 << 9)
+#define ACPI_PDC_P_HWCOORD     (1 << 11)
+
+// Bus Master check required
+#define ACPI_PDC_GAS_BM                (1 << 1)
+
+#define ACPI_CSTATE_HALT       0x1
+#define ACPI_CSTATE_SYSIO      0x2
+#define ACPI_CSTATE_FFH                0x3
+
+// Bus Master Check
+#define ACPI_FLAG_C_BM         (1 << 0)
+// Bus master arbitration
+#define ACPI_FLAG_C_ARB                (1 << 1)
+
+// Copied from acpica's actypes.h, where's the best place to put?
+#define ACPI_BITREG_BUS_MASTER_STATUS           0x01
+#define ACPI_BITREG_BUS_MASTER_RLD              0x0F
+#define ACPI_BITREG_ARB_DISABLE                 0x13
+
+#define ACPI_STATE_C0                   (uint8) 0
+#define ACPI_STATE_C1                   (uint8) 1
+#define ACPI_STATE_C2                   (uint8) 2
+#define ACPI_STATE_C3                   (uint8) 3
+#define ACPI_C_STATES_MAX               ACPI_STATE_C3
+#define ACPI_C_STATE_COUNT              4
+
+
 #define ACPI_CPUIDLE_MODULE_NAME "drivers/power/x86_cpuidle/acpi/driver_v1"
 
+struct acpicpu_reg {
+       uint8   reg_desc;
+       uint16  reg_reslen;
+       uint8   reg_spaceid;
+       uint8   reg_bitwidth;
+       uint8   reg_bitoffset;
+       uint8   reg_accesssize;
+       uint64  reg_addr;
+} __attribute__((packed));
+
 struct acpi_cpuidle_driver_info {
        device_node *node;
        acpi_device_module_info *acpi;
        acpi_device acpi_cookie;
+       uint32 flags;
+};
+
+struct acpi_cstate_info {
+       uint32 address;
+       uint8 skip_bm_sts;
+       uint8 method;
+       uint8 type;
 };
 
 static device_manager_info *sDeviceManager;
 static acpi_cpuidle_driver_info *acpi_processor[B_MAX_CPU_COUNT];
+static CpuidleModuleInfo *sIdle;
+static CpuidleDevice sAcpiDevice;
+static acpi_module_info *sAcpi;
+
+
+static status_t
+acpi_eval_pdc(acpi_cpuidle_driver_info *device)
+{
+       acpi_objects arg;
+       acpi_object_type obj;
+       uint32 cap[3];
+
+       arg.count = 1;
+       arg.pointer = &obj;
+       cap[0] = 1;
+       cap[1] = 1;
+       cap[2] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
+       cap[2] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
+       cap[2] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
+       cap[2] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD | 
ACPI_PDC_T_FFH;
+       obj.object_type = ACPI_TYPE_BUFFER;
+       obj.data.buffer.length = sizeof(cap);
+       obj.data.buffer.buffer = cap;
+       status_t status = device->acpi->evaluate_method(device->acpi_cookie, 
"_PDC", &arg, NULL);
+       return status;
+}
+
+
+static status_t
+acpi_eval_osc(acpi_cpuidle_driver_info *device)
+{
+       // guid for intel platform
+       dprintf("%s@%p\n", __func__, device->acpi_cookie);
+       static uint8 uuid[] = {
+               0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
+               0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
+       };
+       uint32 cap[2];
+       cap[0] = 0;
+       cap[1] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
+       cap[1] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
+       cap[1] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
+       cap[1] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD | 
ACPI_PDC_T_FFH;
+
+       acpi_objects arg;
+       acpi_object_type obj[4];
+
+       arg.count = 4;
+       arg.pointer = obj;
+
+       obj[0].object_type = ACPI_TYPE_BUFFER;
+       obj[0].data.buffer.length = sizeof(uuid);
+       obj[0].data.buffer.buffer = uuid;
+       obj[1].object_type = ACPI_TYPE_INTEGER;
+       obj[1].data.integer = ACPI_PDC_REVID;
+       obj[2].object_type = ACPI_TYPE_INTEGER;
+       obj[2].data.integer = sizeof(cap)/sizeof(cap[0]);
+       obj[3].object_type = ACPI_TYPE_BUFFER;
+       obj[3].data.buffer.length = sizeof(cap);
+       obj[3].data.buffer.buffer = (void *)cap;
+
+       acpi_data buf;
+       buf.pointer = NULL;
+       buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+       status_t status = device->acpi->evaluate_method(device->acpi_cookie, 
"_OSC", &arg, &buf);
+       if (status != B_OK)
+               return status;
+       acpi_object_type *osc = (acpi_object_type *)buf.pointer;
+       if (osc->object_type != ACPI_TYPE_BUFFER)
+               return B_BAD_TYPE;
+       if (osc->data.buffer.length != sizeof(cap))
+               return B_BUFFER_OVERFLOW;
+       return status;
+}
+
+
+static inline bool
+acpi_cstate_bm_check(void)
+{
+       uint32 val;
+       sAcpi->read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &val);
+       if (!val)
+               return false;
+       sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
+
+       return true;
+}
+
+
+static inline void
+acpi_cstate_ffh_enter(CpuidleCstate *cState)
+{
+       cpu_ent *cpu = get_cpu_struct();
+       if (cpu->invoke_scheduler)
+               return;
+
+       x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
+       if (!cpu->invoke_scheduler)
+               x86_mwait((unsigned long)cState->pData, 1);
+}
+
+
+static inline void
+acpi_cstate_halt(void)
+{
+       cpu_ent *cpu = get_cpu_struct();
+       if (cpu->invoke_scheduler)
+               return;
+       asm("hlt");
+}
+
+
+static void
+acpi_cstate_enter(CpuidleCstate *cState)
+{
+       acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
+       if (ci->method == ACPI_CSTATE_FFH)
+               acpi_cstate_ffh_enter(cState);
+       else if (ci->method == ACPI_CSTATE_SYSIO)
+               in8(ci->address);
+       else
+               acpi_cstate_halt();
+}
+
+
+static int32
+acpi_cstate_idle(int32 state, CpuidleDevice *device)
+{
+       CpuidleCstate *cState = &device->cStates[state];
+       acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
+       if (!ci->skip_bm_sts) {
+               // we fall back to C1 if there's bus master activity
+               if (acpi_cstate_bm_check())
+                       state = 1;
+       }
+       if (ci->type != ACPI_STATE_C3)
+               acpi_cstate_enter(cState);
+
+       // set BM_RLD for Bus Master to activity to wake the system from C3
+       // With Newer chipsets BM_RLD is a NOP Since DMA is automatically 
handled
+       // during C3 State
+       acpi_cpuidle_driver_info *pi = acpi_processor[smp_get_current_cpu()];
+       if (pi->flags & ACPI_FLAG_C_BM)
+               sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
+
+       // disable bus master arbitration during C3
+       if (pi->flags & ACPI_FLAG_C_ARB)
+               sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
+
+       acpi_cstate_enter(cState);
+
+       // clear BM_RLD and re-enable the arbiter
+       if (pi->flags & ACPI_FLAG_C_BM)
+               sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
+
+       if (pi->flags & ACPI_FLAG_C_ARB)
+               sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
+
+       return state;
+}
+
+
+static status_t
+acpi_cstate_add(acpi_object_type *object, CpuidleCstate *cState)
+{
+       acpi_cstate_info *ci = (acpi_cstate_info 
*)malloc(sizeof(acpi_cstate_info));
+       if (!ci)
+               return B_NO_MEMORY;
+
+       if (object->object_type != ACPI_TYPE_PACKAGE) {
+               dprintf("invalid _CST object\n");
+               return B_ERROR;
+       }
+
+       if (object->data.package.count != 4) {
+               dprintf("invalid _CST number\n");
+               return B_ERROR;
+       }
+
+       // type
+       acpi_object_type * pointer = &object->data.package.objects[1];
+       if (pointer->object_type != ACPI_TYPE_INTEGER) {
+               dprintf("invalid _CST elem type\n");
+               return B_ERROR;
+       }
+       uint32 n = pointer->data.integer;
+       if (n < 1 || n > 3) {
+               dprintf("invalid _CST elem value\n");
+               return B_ERROR;
+       }
+       ci->type = n;
+       dprintf("C%" B_PRId32 "\n", n);
+       snprintf(cState->name, sizeof(cState->name), "C%"B_PRId32, n);
+
+       // Latency
+       pointer = &object->data.package.objects[2];
+       if (pointer->object_type != ACPI_TYPE_INTEGER) {
+               dprintf("invalid _CST elem type\n");
+               return B_ERROR;
+       }
+       n = pointer->data.integer;
+       cState->latency = n;
+       dprintf("Latency: %" B_PRId32 "\n", n);
+
+       // power
+       pointer = &object->data.package.objects[3];
+       if (pointer->object_type != ACPI_TYPE_INTEGER) {
+               dprintf("invalid _CST elem type\n");
+               return B_ERROR;
+       }
+       n = pointer->data.integer;
+       dprintf("power: %" B_PRId32 "\n", n);
+
+       // register
+       pointer = &object->data.package.objects[0];
+       if (pointer->object_type != ACPI_TYPE_BUFFER) {
+               dprintf("invalid _CST elem type\n");
+               return B_ERROR;
+       }
+       if (pointer->data.buffer.length < 15) {
+               dprintf("invalid _CST elem length\n");
+               return B_ERROR;
+       }
+
+       struct acpicpu_reg *reg = (struct acpicpu_reg 
*)pointer->data.buffer.buffer;
+       switch (reg->reg_spaceid) {
+               case ACPI_ADR_SPACE_SYSTEM_IO:
+                       dprintf("IO method\n");
+                       if (reg->reg_addr == 0) {
+                               dprintf("illegal address\n");
+                               return B_ERROR;
+                       }
+                       if (reg->reg_bitwidth != 8) {
+                               dprintf("invalid source length\n");
+                               return B_ERROR;
+                       }
+                       ci->address = reg->reg_addr;
+                       ci->method = ACPI_CSTATE_SYSIO;
+                       break;
+               case ACPI_ADR_SPACE_FIXED_HARDWARE:
+               {
+                       dprintf("FFH method\n");
+                       ci->method = ACPI_CSTATE_FFH;
+                       ci->address = reg->reg_addr;
+
+                       // skip checking BM_STS if ACPI_PDC_GAS_BM is cleared
+                       cpu_ent *cpu = get_cpu_struct();
+                       if ((cpu->arch.vendor == VENDOR_INTEL) &&
+                               !(reg->reg_accesssize & ACPI_PDC_GAS_BM))
+                               ci->skip_bm_sts = 1;
+                       break;
+               }
+               default:
+                       dprintf("invalid spaceid %" B_PRId8 "\n", 
reg->reg_spaceid);
+                       break;
+       }
+       cState->pData = ci;
+       cState->EnterIdle = acpi_cstate_idle;
+
+       return B_OK;
+}
+
+
+static void
+acpi_cstate_quirks(acpi_cpuidle_driver_info *device)
+{
+       cpu_ent *cpu = get_cpu_struct();
+       // Calculated Model Value: M = (Extended Model << 4) + Model
+       uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model;
+
+       // On all recent Intel platforms, ARB_DIS is not necessary
+       if (cpu->arch.vendor != VENDOR_INTEL)
+               return;
+       if (cpu->arch.family > 0xf || (cpu->arch.family == 6 && model >= 0xf))
+               device->flags &= ~ACPI_FLAG_C_ARB;
+}
+
+
+static status_t
+acpi_cpuidle_setup(acpi_cpuidle_driver_info *device)
+{
+       // _PDC is deprecated in the ACPI 3.0, we will try _OSC firstly
+       // and fall back to _PDC if _OSC fail
+       status_t status = acpi_eval_osc(device);
+       if (status != B_OK)
+               status = acpi_eval_pdc(device);
+       if (status != B_OK) {
+               dprintf("faile to eval _OSC and _PDC\n");
+               return status;
+       }
+
+       acpi_data buffer;
+       buffer.pointer = NULL;
+       buffer.length = ACPI_ALLOCATE_BUFFER;
+
+       dprintf("evaluate _CST @%p\n", device->acpi_cookie);
+       status = device->acpi->evaluate_method(device->acpi_cookie, "_CST", 
NULL,
+               &buffer);
+       if (status != B_OK) {
+               dprintf("failed to get _CST\n");
+               return B_IO_ERROR;
+       }
+
+       acpi_object_type *object = (acpi_object_type *)buffer.pointer;
+       if (object->object_type != ACPI_TYPE_PACKAGE)
+               dprintf("invalid _CST type\n");
+       if (object->data.package.count < 2)
+               dprintf("invalid _CST count\n");
+
+       acpi_object_type *pointer = object->data.package.objects;
+       if (pointer[0].object_type != ACPI_TYPE_INTEGER)
+               dprintf("invalid _CST type 2\n");
+       uint32 n = pointer[0].data.integer;
+       if (n != object->data.package.count - 1)
+               dprintf("invalid _CST count 2\n");
+       if (n > 8)
+               dprintf("_CST has too many states\n");
+       dprintf("cpuidle found %" B_PRId32 " cstates\n", n);
+       uint32 count = 1;
+       for (uint32 i = 1; i <= n; i++) {
+               pointer = &object->data.package.objects[i];
+               if (acpi_cstate_add(pointer, &sAcpiDevice.cStates[count]) == 
B_OK)
+                       ++count;
+       }
+       sAcpiDevice.cStateCount = count;
+       free(buffer.pointer);
+
+       // TODO we assume BM is a must and ARB_DIS is always available
+       device->flags |= ACPI_FLAG_C_ARB | ACPI_FLAG_C_BM;
+
+       acpi_cstate_quirks(device);
+
+       return B_OK;
+}
 
 
 static status_t
 acpi_cpuidle_init(void)
 {
        dprintf("acpi_cpuidle_init\n");
+       if (get_module(B_CPUIDLE_MODULE_NAME, (module_info**)&sIdle) != B_OK)
+               return B_ERROR;
+       if (get_module(B_ACPI_MODULE_NAME, (module_info**)&sAcpi) != B_OK)
+               return B_ERROR;
+
+       for (int32 i = 0; i < smp_get_num_cpus(); i++)
+               if (acpi_cpuidle_setup(acpi_processor[i]) != B_OK)
+                       return B_ERROR;
 
-       return B_ERROR;
+       status_t status = sIdle->AddDevice(&sAcpiDevice);
+       if (status == B_OK)
+               dprintf("using acpi idle\n");
+       else
+               put_module(B_CPUIDLE_MODULE_NAME);
+       return status;
 }
 
 
@@ -147,6 +553,9 @@ static void
 acpi_cpuidle_uninit_driver(void *driverCookie)
 {
        dprintf("acpi_cpuidle_uninit_driver");
+       put_module(B_CPUIDLE_MODULE_NAME);
+       if (sAcpi)
+               put_module(B_ACPI_MODULE_NAME);
        acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info 
*)driverCookie;
        free(device);
 }

############################################################################

Commit:      be9a02c0db1f0b7b0a75d2d5099371992195bb01
URL:         http://cgit.haiku-os.org/haiku/commit/?id=be9a02c
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Wed Aug 22 10:55:23 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:20 2012 UTC

cpuidle: remove drivers/cpuidle

Since generic cpuidle module is loaded by lowlevel cpuidle drivers which
are loaded dynamically during boot, we don't need drivers/cpuidle any
more

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/Jamfile 
b/src/add-ons/kernel/drivers/Jamfile
index f23cf48..ef7c7ee 100644
--- a/src/add-ons/kernel/drivers/Jamfile
+++ b/src/add-ons/kernel/drivers/Jamfile
@@ -4,7 +4,6 @@ SubInclude HAIKU_TOP src add-ons kernel drivers bluetooth ;
 SubInclude HAIKU_TOP src add-ons kernel drivers bus ;
 SubInclude HAIKU_TOP src add-ons kernel drivers audio ;
 SubInclude HAIKU_TOP src add-ons kernel drivers common ;
-SubInclude HAIKU_TOP src add-ons kernel drivers cpuidle ;
 SubInclude HAIKU_TOP src add-ons kernel drivers disk ;
 SubInclude HAIKU_TOP src add-ons kernel drivers dvb ;
 SubInclude HAIKU_TOP src add-ons kernel drivers input ;
diff --git a/src/add-ons/kernel/drivers/cpuidle/Jamfile 
b/src/add-ons/kernel/drivers/cpuidle/Jamfile
deleted file mode 100644
index ce5f450..0000000
--- a/src/add-ons/kernel/drivers/cpuidle/Jamfile
+++ /dev/null
@@ -1,7 +0,0 @@
-SubDir HAIKU_TOP src add-ons kernel drivers cpuidle ;
-
-UsePrivateKernelHeaders ;
-
-KernelAddon <driver>cpuidle :
-       cpuidle.cpp
-       ;
diff --git a/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp 
b/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
deleted file mode 100644
index 82110c9..0000000
--- a/src/add-ons/kernel/drivers/cpuidle/cpuidle.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2012, Haiku, Inc. All Rights Reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Yongcong Du <ycdu.vmcore@xxxxxxxxx>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <smp.h>
-
-#include <Drivers.h>
-#include <KernelExport.h>
-
-#include <cpuidle.h>
-
-#define DEVICE_NAME "cpuidle"
-
-int32 api_version = B_CUR_DRIVER_API_VERSION;
-
-static GenCpuidle *sGenCpuidle;
-
-static status_t
-cpuidle_open(const char *name, uint32 flags, void **cookie)
-{
-       *cookie = NULL;
-       return B_OK;
-}
-
-
-static status_t
-cpuidle_close(void *cookie)
-{
-       return B_OK;
-}
-
-
-static status_t
-cpuidle_free(void *cookie)
-{
-       return B_OK;
-}
-
-
-static status_t
-cpuidle_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
-{
-       return B_OK;
-}
-
-
-static status_t
-cpuidle_read(void *cookie, off_t pos, void *buffer, size_t *length)
-{
-       if (pos != 0) {
-               *length = 0;
-               return B_OK;
-       }
-       char *str = (char *)buffer;
-       size_t max_len = *length;
-       int32 stateCount = sGenCpuidle->GetIdleStateCount();
-       int32 bytes = snprintf(str, max_len, "C-STATE COUNT: %"B_PRId32"\n", 
stateCount);
-       max_len-= bytes;
-       str += bytes;
-       int32 cpu = smp_get_num_cpus();
-
-       for (int32 i = 0; i < cpu; i++) {
-               bytes = snprintf(str, max_len, "CPU%"B_PRId32"\n", i);
-               max_len-= bytes;
-               str += bytes;
-               for (int32 j = 1; j < stateCount; j++) {
-                       CpuidleStat stat;
-                       bytes = snprintf(str, max_len, "%s\n", 
sGenCpuidle->GetIdleStateName(j));
-                       max_len-= bytes;
-                       str += bytes;
-                       sGenCpuidle->GetIdleStateInfo(i, j, &stat);
-                       bytes = snprintf(str, max_len, "%lld %lldus\n",
-                                                       stat.usageCount, 
stat.usageTime);
-                       max_len-= bytes;
-                       str += bytes;
-               }
-       }
-       *length = strlen((char *)buffer);
-
-       return B_OK;
-}
-
-
-static status_t
-cpuidle_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
-{
-       return B_OK;
-}
-
-
-status_t
-init_hardware(void)
-{
-       return B_OK;
-}
-
-
-const char **
-publish_devices(void)
-{
-       static const char *devices[] = {
-               DEVICE_NAME,
-               NULL
-       };
-
-       return devices;
-}
-
-
-device_hooks *
-find_device(const char *name)
-{
-       static device_hooks hooks = {
-               &cpuidle_open,
-               &cpuidle_close,
-               &cpuidle_free,
-               &cpuidle_ioctl,
-               &cpuidle_read,
-               &cpuidle_write,
-       };
-
-
-       return &hooks;
-}
-
-
-status_t
-init_driver(void)
-{
-       status_t err;
-
-       err = get_module(B_CPUIDLE_MODULE_NAME, (module_info **)&sGenCpuidle);
-       if (err != B_OK) {
-               dprintf("can't load "B_CPUIDLE_MODULE_NAME"\n");
-       }
-       return B_OK;
-}
-
-
-void
-uninit_driver(void)
-{
-       put_module(B_CPUIDLE_MODULE_NAME);
-}

############################################################################

Commit:      8073227c1d0deeb4fc7aece63b893e401f815442
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8073227
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Thu Aug 23 19:50:11 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:20 2012 UTC

x86_cpuidle: use module_dependencies rather than get_module()

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
index fb4095c..dbce64c 100644
--- a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp
@@ -89,11 +89,11 @@ struct acpi_cstate_info {
        uint8 type;
 };
 
-static device_manager_info *sDeviceManager;
 static acpi_cpuidle_driver_info *acpi_processor[B_MAX_CPU_COUNT];
-static CpuidleModuleInfo *sIdle;
 static CpuidleDevice sAcpiDevice;
+static device_manager_info *sDeviceManager;
 static acpi_module_info *sAcpi;
+CpuidleModuleInfo *gIdle;
 
 
 static status_t
@@ -431,20 +431,14 @@ static status_t
 acpi_cpuidle_init(void)
 {
        dprintf("acpi_cpuidle_init\n");
-       if (get_module(B_CPUIDLE_MODULE_NAME, (module_info**)&sIdle) != B_OK)
-               return B_ERROR;
-       if (get_module(B_ACPI_MODULE_NAME, (module_info**)&sAcpi) != B_OK)
-               return B_ERROR;
 
        for (int32 i = 0; i < smp_get_num_cpus(); i++)
                if (acpi_cpuidle_setup(acpi_processor[i]) != B_OK)
                        return B_ERROR;
 
-       status_t status = sIdle->AddDevice(&sAcpiDevice);
+       status_t status = gIdle->AddDevice(&sAcpiDevice);
        if (status == B_OK)
                dprintf("using acpi idle\n");
-       else
-               put_module(B_CPUIDLE_MODULE_NAME);
        return status;
 }
 
@@ -553,9 +547,6 @@ static void
 acpi_cpuidle_uninit_driver(void *driverCookie)
 {
        dprintf("acpi_cpuidle_uninit_driver");
-       put_module(B_CPUIDLE_MODULE_NAME);
-       if (sAcpi)
-               put_module(B_ACPI_MODULE_NAME);
        acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info 
*)driverCookie;
        free(device);
 }
@@ -563,6 +554,8 @@ acpi_cpuidle_uninit_driver(void *driverCookie)
 
 module_dependency module_dependencies[] = {
        { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
+       { B_ACPI_MODULE_NAME, (module_info **)&sAcpi},
+       { B_CPUIDLE_MODULE_NAME, (module_info **)&gIdle },
        {}
 };
 
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
index 1032a5d..069fbc1 100644
--- a/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
@@ -16,7 +16,6 @@
 
 #include "x86_cpuidle.h"
 
-static CpuidleModuleInfo *sIdle;
 static CpuidleDevice sIntelDevice;
 
 static void *kMwaitEax[] = {
@@ -82,8 +81,6 @@ status_t
 intel_cpuidle_init(void)
 {
        dprintf("intel idle init\n");
-       if (get_module(B_CPUIDLE_MODULE_NAME, (module_info**)&sIdle) != B_OK)
-               return B_ERROR;
        cpu_ent *cpu = get_cpu_struct();
        if (cpu->arch.vendor != VENDOR_INTEL || cpu->arch.family != 6)
                return B_ERROR;
@@ -116,10 +113,8 @@ intel_cpuidle_init(void)
                        kMwaitEax[i];
                sIntelDevice.cStateCount++;
        }
-       status_t status = sIdle->AddDevice(&sIntelDevice);
+       status_t status = gIdle->AddDevice(&sIntelDevice);
        if (status == B_OK)
                dprintf("using intel idle\n");
-       else
-               put_module(B_CPUIDLE_MODULE_NAME);
        return status;
 }
diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h
index b524ef1..4b6285c 100644
--- a/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h
+++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h
@@ -6,6 +6,9 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+extern CpuidleModuleInfo *gIdle;
+
 static inline void
 x86_monitor(const void *addr, unsigned long ecx, unsigned long edx)
 {

############################################################################

Commit:      5554814b12e0d7bce167a422b661b70fafb77cc9
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5554814
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Thu Aug 23 20:01:58 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sun Nov 18 16:39:21 2012 UTC

x86_cpuidle: coding style fix according to Jerome

Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp 
b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp
index 069fbc1..7f6fbd6 100644

[ *** diff truncated: 14 lines dropped *** ]


############################################################################

Commit:      553f1ebfc1f6e0cb1cc001ea35cb2b2be77bf366
URL:         http://cgit.haiku-os.org/haiku/commit/?id=553f1eb
Author:      Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Date:        Sat Sep  8 18:55:06 2012 UTC

Add disabled cpuidle driver and module to haikuImage.

CPU idle still needs some polish, but it should work on
newer cpus.

----------------------------------------------------------------------------

############################################################################

Revision:    hrev44860
Commit:      5e520ef3995c81a6e1d4ba7ef094c18b4eeaeef3
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5e520ef
Author:      Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Date:        Sun Nov 18 16:42:43 2012 UTC

Merge branch 'cpu_idle'

* cpu_idle:
  Add disabled cpuidle driver and module to haikuImage.
  x86_cpuidle: coding style fix according to Jerome
  x86_cpuidle: use module_dependencies rather than get_module()
  cpuidle: remove drivers/cpuidle
  cpuidle: implement acpi cpuidle driver
  acpi: export read_bit_register and write_bit_register
  cpuidle: move generic cpuidle to generic
  acpi: add ACPI_ALLOCATE_LOCAL_BUFFER to ACPI.h
  cpuidle: we should exit when cStateCount is less than 3
  cpuidle: add stats reporting support
  intel_cpuidle: apply strict cpu checking to see it's snb or not
  cpuidle: rename CpuidleStats to CpuidleStat
  enable cpuidle module and device driver
  driver: add cpuidle device driver
  cpuidle: add intel native cpuidle module
  idle: introduce cpuidle generic module

----------------------------------------------------------------------------


Other related posts:

  • » [haiku-commits] haiku: hrev44860 - src/add-ons/kernel/drivers/power/x86_cpuidle src/add-ons/kernel/generic/cpuidle headers/os/drivers - fredrik . holmqvist