Re: [v9 PATCH 4/9]: x86: refactor x86 idle power management code and remove all instances of pm_idle.

2009-10-26 Thread Arun R Bharadwaj
* Pavel Machek pa...@ucw.cz [2009-10-23 18:07:11]:

 On Fri 2009-10-16 15:13:08, Arun R Bharadwaj wrote:
  * Arun R Bharadwaj a...@linux.vnet.ibm.com [2009-10-16 15:08:50]:
  
  This patch cleans up x86 of all instances of pm_idle.
  
  pm_idle which was earlier called from cpu_idle() idle loop
  is replaced by cpuidle_idle_call.
  
  x86 also registers to cpuidle when the idle routine is selected,
  by populating the cpuidle_device data structure for each cpu.
  
  This is replicated for apm module and for xen, which also used pm_idle.
  
  
  Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com
  ---
   arch/x86/kernel/apm_32.c  |   55 -
   arch/x86/kernel/process.c |   90 
  --
   arch/x86/kernel/process_32.c  |3 -
   arch/x86/kernel/process_64.c  |3 -
   arch/x86/xen/setup.c  |   40 ++
   drivers/acpi/processor_core.c |9 ++--
   drivers/cpuidle/cpuidle.c |   16 +--
   7 files changed, 182 insertions(+), 34 deletions(-)
 ...
  +static int local_idle_loop(struct cpuidle_device *dev, struct 
  cpuidle_state *st)
  +{
  +   ktime_t t1, t2;
  +   s64 diff;
  +   int ret;
  +
  +   t1 = ktime_get();
  +   local_idle();
  +   t2 = ktime_get();
  +
  +   diff = ktime_to_us(ktime_sub(t2, t1));
  +   if (diff  INT_MAX)
  +   diff = INT_MAX;
  +   ret = (int) diff;
  +
  +   return ret;
  +}
 
 So we get this routine essentially 3 times. Is there no way to share
 the code?
 

We can move this code to a common place, but that would mean exporting
the idle function pointer to be called from within this routine, which
is exactly what we wanted to avoid.

Any suggestions are welcome.

arun

 -- 
 (english) http://www.livejournal.com/~pavelmachek
 (cesky, pictures) 
 http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [v9 PATCH 4/9]: x86: refactor x86 idle power management code and remove all instances of pm_idle.

2009-10-26 Thread Pavel Machek

   +static int local_idle_loop(struct cpuidle_device *dev, struct 
   cpuidle_state *st)
   +{
   + ktime_t t1, t2;
   + s64 diff;
   + int ret;
   +
   + t1 = ktime_get();
   + local_idle();
   + t2 = ktime_get();
   +
   + diff = ktime_to_us(ktime_sub(t2, t1));
   + if (diff  INT_MAX)
   + diff = INT_MAX;
   + ret = (int) diff;
   +
   + return ret;
   +}
  
  So we get this routine essentially 3 times. Is there no way to share
  the code?
  
 
 We can move this code to a common place, but that would mean exporting
 the idle function pointer to be called from within this routine, which
 is exactly what we wanted to avoid.
 
 Any suggestions are welcome.

You can just pass idle routine as a parameter...?

int common_idle_loop(struct cpuidle_device *dev, struct cpuidle_state
*st, void *idle(void))

...?
Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [v9 PATCH 4/9]: x86: refactor x86 idle power management code and remove all instances of pm_idle.

2009-10-26 Thread Arun R Bharadwaj
* Pavel Machek pa...@ucw.cz [2009-10-26 08:58:31]:

 
+static int local_idle_loop(struct cpuidle_device *dev, struct 
cpuidle_state *st)
+{
+   ktime_t t1, t2;
+   s64 diff;
+   int ret;
+
+   t1 = ktime_get();
+   local_idle();
+   t2 = ktime_get();
+
+   diff = ktime_to_us(ktime_sub(t2, t1));
+   if (diff  INT_MAX)
+   diff = INT_MAX;
+   ret = (int) diff;
+
+   return ret;
+}
   
   So we get this routine essentially 3 times. Is there no way to share
   the code?
   
  
  We can move this code to a common place, but that would mean exporting
  the idle function pointer to be called from within this routine, which
  is exactly what we wanted to avoid.
  
  Any suggestions are welcome.
 
 You can just pass idle routine as a parameter...?
 
 int common_idle_loop(struct cpuidle_device *dev, struct cpuidle_state
 *st, void *idle(void))
 
 ...?
   Pavel

Yes, this should be fine. I was trying to avoid passing the void
function pointer around but i guess this reduces considerable code
size.

thanks!
arun
 -- 
 (english) http://www.livejournal.com/~pavelmachek
 (cesky, pictures) 
 http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [v9 PATCH 4/9]: x86: refactor x86 idle power management code and remove all instances of pm_idle.

2009-10-23 Thread Pavel Machek
On Fri 2009-10-16 15:13:08, Arun R Bharadwaj wrote:
 * Arun R Bharadwaj a...@linux.vnet.ibm.com [2009-10-16 15:08:50]:
 
 This patch cleans up x86 of all instances of pm_idle.
 
 pm_idle which was earlier called from cpu_idle() idle loop
 is replaced by cpuidle_idle_call.
 
 x86 also registers to cpuidle when the idle routine is selected,
 by populating the cpuidle_device data structure for each cpu.
 
 This is replicated for apm module and for xen, which also used pm_idle.
 
 
 Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com
 ---
  arch/x86/kernel/apm_32.c  |   55 -
  arch/x86/kernel/process.c |   90 
 --
  arch/x86/kernel/process_32.c  |3 -
  arch/x86/kernel/process_64.c  |3 -
  arch/x86/xen/setup.c  |   40 ++
  drivers/acpi/processor_core.c |9 ++--
  drivers/cpuidle/cpuidle.c |   16 +--
  7 files changed, 182 insertions(+), 34 deletions(-)
...
 +static int local_idle_loop(struct cpuidle_device *dev, struct cpuidle_state 
 *st)
 +{
 + ktime_t t1, t2;
 + s64 diff;
 + int ret;
 +
 + t1 = ktime_get();
 + local_idle();
 + t2 = ktime_get();
 +
 + diff = ktime_to_us(ktime_sub(t2, t1));
 + if (diff  INT_MAX)
 + diff = INT_MAX;
 + ret = (int) diff;
 +
 + return ret;
 +}

So we get this routine essentially 3 times. Is there no way to share
the code?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[v9 PATCH 4/9]: x86: refactor x86 idle power management code and remove all instances of pm_idle.

2009-10-16 Thread Arun R Bharadwaj
* Arun R Bharadwaj a...@linux.vnet.ibm.com [2009-10-16 15:08:50]:

This patch cleans up x86 of all instances of pm_idle.

pm_idle which was earlier called from cpu_idle() idle loop
is replaced by cpuidle_idle_call.

x86 also registers to cpuidle when the idle routine is selected,
by populating the cpuidle_device data structure for each cpu.

This is replicated for apm module and for xen, which also used pm_idle.


Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com
---
 arch/x86/kernel/apm_32.c  |   55 -
 arch/x86/kernel/process.c |   90 --
 arch/x86/kernel/process_32.c  |3 -
 arch/x86/kernel/process_64.c  |3 -
 arch/x86/xen/setup.c  |   40 ++
 drivers/acpi/processor_core.c |9 ++--
 drivers/cpuidle/cpuidle.c |   16 +--
 7 files changed, 182 insertions(+), 34 deletions(-)

Index: linux.trees.git/arch/x86/kernel/process.c
===
--- linux.trees.git.orig/arch/x86/kernel/process.c
+++ linux.trees.git/arch/x86/kernel/process.c
@@ -10,6 +10,7 @@
 #include linux/clockchips.h
 #include linux/random.h
 #include linux/user-return-notifier.h
+#include linux/cpuidle.h
 #include trace/events/power.h
 #include asm/system.h
 #include asm/apic.h
@@ -246,12 +247,6 @@ int sys_vfork(struct pt_regs *regs)
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
 
-/*
- * Powermanagement idle function, if any..
- */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
 #ifdef CONFIG_X86_32
 /*
  * This halt magic was a workaround for ancient floppy DMA
@@ -331,17 +326,15 @@ static void do_nothing(void *unused)
 }
 
 /*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
+ * cpu_idle_wait - Required while changing idle routine handler on SMP systems.
  *
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
+ * Caller must have changed idle routine to the new value before the call. Old
+ * value will not be used by any CPU after the return of this function.
  */
 void cpu_idle_wait(void)
 {
smp_mb();
-   /* kick all the CPUs so that they exit out of pm_idle */
+   /* kick all the CPUs so that they exit out of idle loop */
smp_call_function(do_nothing, NULL, 1);
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -520,15 +513,70 @@ static void c1e_idle(void)
default_idle();
 }
 
+static void (*local_idle)(void);
+
+#ifndef CONFIG_CPU_IDLE
+void cpuidle_idle_call(void)
+{
+   if (local_idle)
+   local_idle();
+   else
+   default_idle();
+}
+#endif
+
+DEFINE_PER_CPU(struct cpuidle_device, idle_devices);
+
+struct cpuidle_driver cpuidle_default_driver = {
+   .name = cpuidle_default,
+};
+
+static int local_idle_loop(struct cpuidle_device *dev, struct cpuidle_state 
*st)
+{
+   ktime_t t1, t2;
+   s64 diff;
+   int ret;
+
+   t1 = ktime_get();
+   local_idle();
+   t2 = ktime_get();
+
+   diff = ktime_to_us(ktime_sub(t2, t1));
+   if (diff  INT_MAX)
+   diff = INT_MAX;
+   ret = (int) diff;
+
+   return ret;
+}
+
+static int setup_cpuidle_simple(void)
+{
+   struct cpuidle_device *dev;
+   int cpu;
+
+   if (!cpuidle_curr_driver)
+   cpuidle_register_driver(cpuidle_default_driver);
+
+   for_each_online_cpu(cpu) {
+   dev = per_cpu(idle_devices, cpu);
+   dev-cpu = cpu;
+   dev-states[0].enter = local_idle_loop;
+   dev-state_count = 1;
+   cpuidle_register_device(dev);
+   }
+   return 0;
+}
+device_initcall(setup_cpuidle_simple);
+
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-   if (pm_idle == poll_idle  smp_num_siblings  1) {
+   if (local_idle == poll_idle  smp_num_siblings  1) {
printk(KERN_WARNING WARNING: polling idle and HT enabled,
 performance may degrade.\n);
}
 #endif
-   if (pm_idle)
+   if (local_idle)
return;
 
if (cpu_has(c, X86_FEATURE_MWAIT)  mwait_usable(c)) {
@@ -536,18 +584,20 @@ void __cpuinit select_idle_routine(const
 * One CPU supports mwait = All CPUs supports mwait
 */
printk(KERN_INFO using mwait in idle threads.\n);
-   pm_idle = mwait_idle;
+   local_idle = mwait_idle;
} else if (check_c1e_idle(c)) {
printk(KERN_INFO using C1E aware idle routine\n);
-   pm_idle = c1e_idle;
+   local_idle = c1e_idle;
} else
-   pm_idle = default_idle;
+   local_idle = default_idle;
+
+