public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [v12 PATCH 1/8]: cpuidle: cleanup cpuidle.h header file.
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
@ 2010-04-15 11:05 ` Arun R Bharadwaj
  2010-04-15 11:06 ` [v12 PATCH 2/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c Arun R Bharadwaj
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:05 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, linux-kernel, Arun Bharadwaj

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch re-designs the data structures used in cpuidle infrastructure.
Currently, we have a per-cpu device structure. Each cpu needs to register
under cpuidle as a cpuidle_device. This is not desirable and hence the
per-cpu registration is removed by this patch.

This patch introduces a cpuidle_subsystem structure. This needs a one-time
registration to cpuidle. Also the current design has an array of the idle states
for each of the CPUs. This is changed to have a global array of idle states.
The statistics data like 'usage' and 'time' which were earlier part of the
cpuidle_states structure is biforcated to form a new structure cpuidle_stats,
which is per-cpu.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 drivers/cpuidle/cpuidle.h |    6 +--
 include/linux/cpuidle.h   |   70 ++++++++++++++++++++--------------------------
 2 files changed, 33 insertions(+), 43 deletions(-)

Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -20,8 +20,7 @@
 #define CPUIDLE_STATE_MAX	8
 #define CPUIDLE_NAME_LEN	16
 #define CPUIDLE_DESC_LEN	32
-
-struct cpuidle_device;
+#define	CPUIDLE_MAX_CPUS	128
 
 
 /****************************
@@ -38,11 +37,11 @@ struct cpuidle_state {
 	unsigned int	power_usage; /* in mW */
 	unsigned int	target_residency; /* in US */
 
-	unsigned long long	usage;
-	unsigned long long	time; /* in US */
+	int			state_index;
+	unsigned long long	*usage;
+	unsigned long long	*time;
 
-	int (*enter)	(struct cpuidle_device *dev,
-			 struct cpuidle_state *state);
+	int (*enter)	(struct cpuidle_state *state);
 };
 
 /* Idle State Flags */
@@ -76,30 +75,31 @@ cpuidle_set_statedata(struct cpuidle_sta
 }
 
 struct cpuidle_state_kobj {
+	int	cpuid;
 	struct cpuidle_state *state;
 	struct completion kobj_unregister;
 	struct kobject kobj;
 };
 
-struct cpuidle_device {
-	unsigned int		registered:1;
-	unsigned int		enabled:1;
-	unsigned int		cpu;
-
-	int			last_residency;
-	int			state_count;
-	struct cpuidle_state	states[CPUIDLE_STATE_MAX];
+struct cpuidle_stats {
+	unsigned long long	usage[CPUIDLE_STATE_MAX];
+	unsigned long long	time[CPUIDLE_STATE_MAX]; /* in US */
 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-	struct cpuidle_state	*last_state;
-
-	struct list_head 	device_list;
 	struct kobject		kobj;
 	struct completion	kobj_unregister;
-	void			*governor_data;
+};
+
+struct cpuidle_subsystem {
+	unsigned int		registered:1;
+	int			state_count;
+	int			last_residency[CPUIDLE_MAX_CPUS];
+	struct cpuidle_state	*last_state[CPUIDLE_MAX_CPUS];
+	struct cpuidle_state	states[CPUIDLE_STATE_MAX];
 	struct cpuidle_state	*safe_state;
 };
 
-DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+extern struct cpuidle_subsystem cpuidle_subsys;
+DECLARE_PER_CPU(struct cpuidle_stats, stats);
 
 /**
  * cpuidle_get_last_residency - retrieves the last state's residency time
@@ -107,9 +107,9 @@ DECLARE_PER_CPU(struct cpuidle_device *,
  *
  * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set
  */
-static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
+static inline int cpuidle_get_last_residency(int cpu)
 {
-	return dev->last_residency;
+	return cpuidle_subsys.last_residency[cpu];
 }
 
 
@@ -123,32 +123,23 @@ struct cpuidle_driver {
 };
 
 #ifdef CONFIG_CPU_IDLE
-
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
-extern int cpuidle_register_device(struct cpuidle_device *dev);
-extern void cpuidle_unregister_device(struct cpuidle_device *dev);
+extern int cpuidle_register_subsystem(int state_count);
+extern void cpuidle_unregister_subsystem(void);
 
 extern void cpuidle_pause_and_lock(void);
 extern void cpuidle_resume_and_unlock(void);
-extern int cpuidle_enable_device(struct cpuidle_device *dev);
-extern void cpuidle_disable_device(struct cpuidle_device *dev);
-
 #else
-
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return 0;}
 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
-static inline int cpuidle_register_device(struct cpuidle_device *dev)
+static inline int cpuidle_register_subsystem(int state_count)
 {return 0;}
-static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
-
+static inline void cpuidle_unregister_subsystem(void)
+{ }
 static inline void cpuidle_pause_and_lock(void) { }
 static inline void cpuidle_resume_and_unlock(void) { }
-static inline int cpuidle_enable_device(struct cpuidle_device *dev)
-{return 0;}
-static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
-
 #endif
 
 /******************************
@@ -160,11 +151,11 @@ struct cpuidle_governor {
 	struct list_head 	governor_list;
 	unsigned int		rating;
 
-	int  (*enable)		(struct cpuidle_device *dev);
-	void (*disable)		(struct cpuidle_device *dev);
+	int  (*enable)		(int cpu);
+	void (*disable)		(int cpu);
 
-	int  (*select)		(struct cpuidle_device *dev);
-	void (*reflect)		(struct cpuidle_device *dev);
+	int  (*select)		(int cpu);
+	void (*reflect)		(int cpu);
 
 	struct module 		*owner;
 };
@@ -187,5 +178,6 @@ static inline void cpuidle_unregister_go
 #else
 #define CPUIDLE_DRIVER_STATE_START	0
 #endif
+extern void cpuidle_idle_call(void);
 
 #endif /* _LINUX_CPUIDLE_H */
Index: linux.trees.git/drivers/cpuidle/cpuidle.h
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.h
+++ linux.trees.git/drivers/cpuidle/cpuidle.h
@@ -11,12 +11,10 @@
 extern struct cpuidle_governor *cpuidle_curr_governor;
 extern struct cpuidle_driver *cpuidle_curr_driver;
 extern struct list_head cpuidle_governors;
-extern struct list_head cpuidle_detected_devices;
 extern struct mutex cpuidle_lock;
 extern spinlock_t cpuidle_driver_lock;
 
 /* idle loop */
-extern void cpuidle_install_idle_handler(void);
 extern void cpuidle_uninstall_idle_handler(void);
 
 /* governors */
@@ -25,8 +23,8 @@ extern int cpuidle_switch_governor(struc
 /* sysfs */
 extern int cpuidle_add_class_sysfs(struct sysdev_class *cls);
 extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
-extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
-extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
+extern int cpuidle_add_state_sysfs(int cpu);
+extern void cpuidle_remove_state_sysfs(int cpu);
 extern int cpuidle_add_sysfs(struct sys_device *sysdev);
 extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 2/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
  2010-04-15 11:05 ` [v12 PATCH 1/8]: cpuidle: cleanup cpuidle.h header file Arun R Bharadwaj
@ 2010-04-15 11:06 ` Arun R Bharadwaj
  2010-04-15 11:07 ` [v12 PATCH 3/8]: cpuidle: cleanup driver/cpuidle/sysfs.c and governor.c Arun R Bharadwaj
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:06 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch cleans up cpuidle.c by doing away with per-cpu
registration for cpuidle. Instead it introduces a single
registration system to register to cpuidle subsystem.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 drivers/cpuidle/cpuidle.c |  269 ++++++++++------------------------------------
 1 file changed, 60 insertions(+), 209 deletions(-)

Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -21,13 +21,10 @@
 
 #include "cpuidle.h"
 
-DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+struct cpuidle_subsystem cpuidle_subsys;
 
 DEFINE_MUTEX(cpuidle_lock);
-LIST_HEAD(cpuidle_detected_devices);
-static void (*pm_idle_old)(void);
-
-static int enabled_devices;
+DEFINE_PER_CPU(struct cpuidle_stats, stats);
 
 #if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
 static void cpuidle_kick_cpus(void)
@@ -40,24 +37,20 @@ static void cpuidle_kick_cpus(void)
 static void cpuidle_kick_cpus(void) {}
 #endif
 
-static int __cpuidle_register_device(struct cpuidle_device *dev);
-
 /**
  * cpuidle_idle_call - the main idle loop
  *
  * NOTE: no locks or semaphores should be used here
  */
-static void cpuidle_idle_call(void)
+void cpuidle_idle_call(void)
 {
-	struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
+	int cpu = smp_processor_id();
 	struct cpuidle_state *target_state;
+	struct cpuidle_stats *state_stats;
 	int next_state;
 
 	/* check if the device is ready */
-	if (!dev || !dev->enabled) {
-		if (pm_idle_old)
-			pm_idle_old();
-		else
+	if (!cpuidle_subsys.registered) {
 #if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
 			default_idle();
 #else
@@ -75,50 +68,36 @@ static void cpuidle_idle_call(void)
 	hrtimer_peek_ahead_timers();
 #endif
 	/* ask the governor for the next state */
-	next_state = cpuidle_curr_governor->select(dev);
+	next_state = cpuidle_curr_governor->select(cpu);
 	if (need_resched()) {
 		local_irq_enable();
 		return;
 	}
 
-	target_state = &dev->states[next_state];
+	target_state = &cpuidle_subsys.states[next_state];
+	state_stats = &per_cpu(stats, cpu);
 
 	/* enter the state and update stats */
-	dev->last_state = target_state;
-	dev->last_residency = target_state->enter(dev, target_state);
-	if (dev->last_state)
-		target_state = dev->last_state;
+	cpuidle_subsys.last_state[cpu] = target_state;
+	cpuidle_subsys.last_residency[cpu] = target_state->enter(target_state);
+	if (cpuidle_subsys.last_state[cpu])
+		target_state = cpuidle_subsys.last_state[cpu];
 
-	target_state->time += (unsigned long long)dev->last_residency;
-	target_state->usage++;
+	state_stats->time[next_state] += (unsigned long long)(cpuidle_subsys.last_residency[cpu]);
+	state_stats->usage[next_state]++;
 
 	/* give the governor an opportunity to reflect on the outcome */
 	if (cpuidle_curr_governor->reflect)
-		cpuidle_curr_governor->reflect(dev);
+		cpuidle_curr_governor->reflect(cpu);
 	trace_power_end(0);
 }
 
 /**
- * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
- */
-void cpuidle_install_idle_handler(void)
-{
-	if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
-		/* Make sure all changes finished before we switch to new idle */
-		smp_wmb();
-		pm_idle = cpuidle_idle_call;
-	}
-}
-
-/**
  * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
  */
 void cpuidle_uninstall_idle_handler(void)
 {
-	if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
-		pm_idle = pm_idle_old;
-		cpuidle_kick_cpus();
-	}
+	cpuidle_kick_cpus();
 }
 
 /**
@@ -137,213 +116,87 @@ EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock
  */
 void cpuidle_resume_and_unlock(void)
 {
-	cpuidle_install_idle_handler();
 	mutex_unlock(&cpuidle_lock);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
-/**
- * cpuidle_enable_device - enables idle PM for a CPU
- * @dev: the CPU
- *
- * This function must be called between cpuidle_pause_and_lock and
- * cpuidle_resume_and_unlock when used externally.
- */
-int cpuidle_enable_device(struct cpuidle_device *dev)
+static void cpuidle_clear_stats(int cpu, int state_count)
 {
-	int ret, i;
-
-	if (dev->enabled)
-		return 0;
-	if (!cpuidle_curr_driver || !cpuidle_curr_governor)
-		return -EIO;
-	if (!dev->state_count)
-		return -EINVAL;
-
-	if (dev->registered == 0) {
-		ret = __cpuidle_register_device(dev);
-		if (ret)
-			return ret;
-	}
+	int i;
 
-	if ((ret = cpuidle_add_state_sysfs(dev)))
-		return ret;
-
-	if (cpuidle_curr_governor->enable &&
-	    (ret = cpuidle_curr_governor->enable(dev)))
-		goto fail_sysfs;
-
-	for (i = 0; i < dev->state_count; i++) {
-		dev->states[i].usage = 0;
-		dev->states[i].time = 0;
+	for (i = 0; i < state_count; i++) {
+		per_cpu(stats, cpu).usage[i] = 0;
+		per_cpu(stats, cpu).time[i] = 0;
+		cpuidle_subsys.states[i].state_index = i;
 	}
-	dev->last_residency = 0;
-	dev->last_state = NULL;
-
-	smp_wmb();
-
-	dev->enabled = 1;
-
-	enabled_devices++;
-	return 0;
-
-fail_sysfs:
-	cpuidle_remove_state_sysfs(dev);
-
-	return ret;
 }
 
-EXPORT_SYMBOL_GPL(cpuidle_enable_device);
-
 /**
- * cpuidle_disable_device - disables idle PM for a CPU
- * @dev: the CPU
- *
- * This function must be called between cpuidle_pause_and_lock and
- * cpuidle_resume_and_unlock when used externally.
+ * cpuidle_register_subsystem - registers a CPU's idle PM feature
+ * @state_count: number of idle states available
  */
-void cpuidle_disable_device(struct cpuidle_device *dev)
+int cpuidle_register_subsystem(int state_count)
 {
-	if (!dev->enabled)
-		return;
-	if (!cpuidle_curr_driver || !cpuidle_curr_governor)
-		return;
-
-	dev->enabled = 0;
-
-	if (cpuidle_curr_governor->disable)
-		cpuidle_curr_governor->disable(dev);
-
-	cpuidle_remove_state_sysfs(dev);
-	enabled_devices--;
-}
-
-EXPORT_SYMBOL_GPL(cpuidle_disable_device);
-
-#ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
-{
-	ktime_t	t1, t2;
-	s64 diff;
-	int ret;
-
-	t1 = ktime_get();
-	local_irq_enable();
-	while (!need_resched())
-		cpu_relax();
-
-	t2 = ktime_get();
-	diff = ktime_to_us(ktime_sub(t2, t1));
-	if (diff > INT_MAX)
-		diff = INT_MAX;
-
-	ret = (int) diff;
-	return ret;
-}
+	int cpu, ret;
+	struct sys_device *sys_dev;
 
-static void poll_idle_init(struct cpuidle_device *dev)
-{
-	struct cpuidle_state *state = &dev->states[0];
-
-	cpuidle_set_statedata(state, NULL);
-
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
-	snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
-	state->exit_latency = 0;
-	state->target_residency = 0;
-	state->power_usage = -1;
-	state->flags = CPUIDLE_FLAG_POLL;
-	state->enter = poll_idle;
-}
-#else
-static void poll_idle_init(struct cpuidle_device *dev) {}
-#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
-
-/**
- * __cpuidle_register_device - internal register function called before register
- * and enable routines
- * @dev: the cpu
- *
- * cpuidle_lock mutex must be held before this is called
- */
-static int __cpuidle_register_device(struct cpuidle_device *dev)
-{
-	int ret;
-	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
-
-	if (!sys_dev)
-		return -EINVAL;
-	if (!try_module_get(cpuidle_curr_driver->owner))
-		return -EINVAL;
-
-	init_completion(&dev->kobj_unregister);
+	cpuidle_pause_and_lock();
 
-	poll_idle_init(dev);
+	cpuidle_subsys.state_count = state_count;
 
-	per_cpu(cpuidle_devices, dev->cpu) = dev;
-	list_add(&dev->device_list, &cpuidle_detected_devices);
-	if ((ret = cpuidle_add_sysfs(sys_dev))) {
-		module_put(cpuidle_curr_driver->owner);
-		return ret;
-	}
-
-	dev->registered = 1;
-	return 0;
-}
+	for_each_online_cpu(cpu) {
+		init_completion(&per_cpu(stats, cpu).kobj_unregister);
+		sys_dev = get_cpu_sysdev(cpu);
 
-/**
- * cpuidle_register_device - registers a CPU's idle PM feature
- * @dev: the cpu
- */
-int cpuidle_register_device(struct cpuidle_device *dev)
-{
-	int ret;
+		cpuidle_clear_stats(cpu, state_count);
+		if ((ret = cpuidle_add_sysfs(sys_dev)))
+			return ret;
 
-	mutex_lock(&cpuidle_lock);
+		if ((ret = cpuidle_add_state_sysfs(cpu)))
+			return ret;
 
-	if ((ret = __cpuidle_register_device(dev))) {
-		mutex_unlock(&cpuidle_lock);
-		return ret;
+		if (cpuidle_curr_governor->enable &&
+			(ret = cpuidle_curr_governor->enable(cpu)))
+			return ret;
 	}
 
-	cpuidle_enable_device(dev);
-	cpuidle_install_idle_handler();
+	cpuidle_subsys.registered = 1;
 
-	mutex_unlock(&cpuidle_lock);
+	cpuidle_resume_and_unlock();
 
 	return 0;
-
 }
 
-EXPORT_SYMBOL_GPL(cpuidle_register_device);
+EXPORT_SYMBOL_GPL(cpuidle_register_subsystem);
 
 /**
- * cpuidle_unregister_device - unregisters a CPU's idle PM feature
- * @dev: the cpu
+ * cpuidle_unregister_subsystem - unregisters a CPU's idle PM feature
  */
-void cpuidle_unregister_device(struct cpuidle_device *dev)
+void cpuidle_unregister_subsystem(void)
 {
-	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
-
-	if (dev->registered == 0)
-		return;
+	int cpu;
+	struct sys_device *sys_dev;
 
 	cpuidle_pause_and_lock();
 
-	cpuidle_disable_device(dev);
+	cpuidle_subsys.registered = 0;
 
-	cpuidle_remove_sysfs(sys_dev);
-	list_del(&dev->device_list);
-	wait_for_completion(&dev->kobj_unregister);
-	per_cpu(cpuidle_devices, dev->cpu) = NULL;
+	for_each_online_cpu(cpu) {
+		sys_dev = get_cpu_sysdev(cpu);
 
-	cpuidle_resume_and_unlock();
+		if (cpuidle_curr_governor->disable)
+			cpuidle_curr_governor->disable(cpu);
 
-	module_put(cpuidle_curr_driver->owner);
+		cpuidle_remove_state_sysfs(cpu);
+		cpuidle_remove_sysfs(sys_dev);
+		wait_for_completion(&per_cpu(stats, cpu).kobj_unregister);
+	}
+
+	cpuidle_resume_and_unlock();
 }
 
-EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
+EXPORT_SYMBOL_GPL(cpuidle_unregister_subsystem);
 
 #ifdef CONFIG_SMP
 
@@ -387,8 +240,6 @@ static int __init cpuidle_init(void)
 {
 	int ret;
 
-	pm_idle_old = pm_idle;
-
 	ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
 	if (ret)
 		return ret;

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 3/8]: cpuidle: cleanup driver/cpuidle/sysfs.c and governor.c
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
  2010-04-15 11:05 ` [v12 PATCH 1/8]: cpuidle: cleanup cpuidle.h header file Arun R Bharadwaj
  2010-04-15 11:06 ` [v12 PATCH 2/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c Arun R Bharadwaj
@ 2010-04-15 11:07 ` Arun R Bharadwaj
  2010-04-15 11:08 ` [v12 PATCH 4/8]: POWER: enable cpuidle for POWER Arun R Bharadwaj
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:07 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch cleans up drivers/cpuidle/sysfs.c to incorporate the new design,
since we are doing away with cpuidle_device structure, this patch moves the
code around a little bit.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 drivers/cpuidle/governor.c         |   20 ++--------
 drivers/cpuidle/governors/ladder.c |   27 ++++++-------
 drivers/cpuidle/governors/menu.c   |   26 +++++--------
 drivers/cpuidle/sysfs.c            |   72 +++++++++++++++++++------------------
 4 files changed, 67 insertions(+), 78 deletions(-)

Index: linux.trees.git/drivers/cpuidle/governor.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/governor.c
+++ linux.trees.git/drivers/cpuidle/governor.c
@@ -43,27 +43,17 @@ static struct cpuidle_governor * __cpuid
  */
 int cpuidle_switch_governor(struct cpuidle_governor *gov)
 {
-	struct cpuidle_device *dev;
-
 	if (gov == cpuidle_curr_governor)
 		return 0;
 
-	cpuidle_uninstall_idle_handler();
-
-	if (cpuidle_curr_governor) {
-		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-			cpuidle_disable_device(dev);
+	if (cpuidle_curr_governor)
 		module_put(cpuidle_curr_governor->owner);
-	}
 
 	cpuidle_curr_governor = gov;
 
 	if (gov) {
 		if (!try_module_get(cpuidle_curr_governor->owner))
 			return -EINVAL;
-		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-			cpuidle_enable_device(dev);
-		cpuidle_install_idle_handler();
 		printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
 	}
 
@@ -81,7 +71,7 @@ int cpuidle_register_governor(struct cpu
 	if (!gov || !gov->select)
 		return -EINVAL;
 
-	mutex_lock(&cpuidle_lock);
+	cpuidle_pause_and_lock();
 	if (__cpuidle_find_governor(gov->name) == NULL) {
 		ret = 0;
 		list_add_tail(&gov->governor_list, &cpuidle_governors);
@@ -89,7 +79,7 @@ int cpuidle_register_governor(struct cpu
 		    cpuidle_curr_governor->rating < gov->rating)
 			cpuidle_switch_governor(gov);
 	}
-	mutex_unlock(&cpuidle_lock);
+	cpuidle_resume_and_unlock();
 
 	return ret;
 }
@@ -126,13 +116,13 @@ void cpuidle_unregister_governor(struct 
 	if (!gov)
 		return;
 
-	mutex_lock(&cpuidle_lock);
+	cpuidle_pause_and_lock();
 	if (gov == cpuidle_curr_governor) {
 		struct cpuidle_governor *new_gov;
 		new_gov = cpuidle_replace_governor(gov->rating);
 		cpuidle_switch_governor(new_gov);
 	}
 	list_del(&gov->governor_list);
-	mutex_unlock(&cpuidle_lock);
+	cpuidle_resume_and_unlock();
 }
 
Index: linux.trees.git/drivers/cpuidle/sysfs.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/sysfs.c
+++ linux.trees.git/drivers/cpuidle/sysfs.c
@@ -156,8 +156,8 @@ void cpuidle_remove_class_sysfs(struct s
 
 struct cpuidle_attr {
 	struct attribute attr;
-	ssize_t (*show)(struct cpuidle_device *, char *);
-	ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
+	ssize_t (*show)(struct cpuidle_stats *, char *);
+	ssize_t (*store)(struct cpuidle_stats *, const char *, size_t count);
 };
 
 #define define_one_ro(_name, show) \
@@ -165,17 +165,17 @@ struct cpuidle_attr {
 #define define_one_rw(_name, show, store) \
 	static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
 
-#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
+#define kobj_to_cpuidlestats(k) container_of(k, struct cpuidle_stats, kobj)
 #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
 static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
 {
 	int ret = -EIO;
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+	struct cpuidle_stats *st = kobj_to_cpuidlestats(kobj);
 	struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
 
 	if (cattr->show) {
 		mutex_lock(&cpuidle_lock);
-		ret = cattr->show(dev, buf);
+		ret = cattr->show(st, buf);
 		mutex_unlock(&cpuidle_lock);
 	}
 	return ret;
@@ -185,12 +185,12 @@ static ssize_t cpuidle_store(struct kobj
 		     const char * buf, size_t count)
 {
 	int ret = -EIO;
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+	struct cpuidle_stats *st = kobj_to_cpuidlestats(kobj);
 	struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
 
 	if (cattr->store) {
 		mutex_lock(&cpuidle_lock);
-		ret = cattr->store(dev, buf, count);
+		ret = cattr->store(st, buf, count);
 		mutex_unlock(&cpuidle_lock);
 	}
 	return ret;
@@ -203,9 +203,9 @@ static const struct sysfs_ops cpuidle_sy
 
 static void cpuidle_sysfs_release(struct kobject *kobj)
 {
-	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+	struct cpuidle_stats *st = kobj_to_cpuidlestats(kobj);
 
-	complete(&dev->kobj_unregister);
+	complete(&st->kobj_unregister);
 }
 
 static struct kobj_type ktype_cpuidle = {
@@ -231,7 +231,7 @@ static ssize_t show_state_##_name(struct
 #define define_show_state_ull_function(_name) \
 static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
 { \
-	return sprintf(buf, "%llu\n", state->_name);\
+	return sprintf(buf, "%llu\n", *state->_name);\
 }
 
 #define define_show_state_str_function(_name) \
@@ -267,15 +267,20 @@ static struct attribute *cpuidle_state_d
 };
 
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
+#define kobj_to_cpuid(k) (kobj_to_state_obj(k)->cpuid)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 static ssize_t cpuidle_state_show(struct kobject * kobj,
 	struct attribute * attr ,char * buf)
 {
 	int ret = -EIO;
+	int cpu = kobj_to_cpuid(kobj);
 	struct cpuidle_state *state = kobj_to_state(kobj);
 	struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
 
+	state->usage = &per_cpu(stats, cpu).usage[state->state_index];
+	state->time = &per_cpu(stats, cpu).time[state->state_index];
+
 	if (cattr->show)
 		ret = cattr->show(state, buf);
 
@@ -299,59 +304,58 @@ static struct kobj_type ktype_state_cpui
 	.release = cpuidle_state_sysfs_release,
 };
 
-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+static void inline cpuidle_free_state_kobj(int cpu, int i)
 {
-	kobject_put(&device->kobjs[i]->kobj);
-	wait_for_completion(&device->kobjs[i]->kobj_unregister);
-	kfree(device->kobjs[i]);
-	device->kobjs[i] = NULL;
+	kobject_put(&per_cpu(stats, cpu).kobjs[i]->kobj);
+	wait_for_completion(&per_cpu(stats, cpu).kobjs[i]->kobj_unregister);
+	kfree(per_cpu(stats, cpu).kobjs[i]);
+	per_cpu(stats, cpu).kobjs[i] = NULL;
 }
 
 /**
  * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
- * @device: the target device
  */
-int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+int cpuidle_add_state_sysfs(int cpu)
 {
 	int i, ret = -ENOMEM;
 	struct cpuidle_state_kobj *kobj;
 
 	/* state statistics */
-	for (i = 0; i < device->state_count; i++) {
+	for (i = 0; i < cpuidle_subsys.state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
-		kobj->state = &device->states[i];
+		kobj->state = &cpuidle_subsys.states[i];
 		init_completion(&kobj->kobj_unregister);
 
-		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
-					   "state%d", i);
+		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+				&per_cpu(stats, cpu).kobj, "state%d", i);
 		if (ret) {
 			kfree(kobj);
 			goto error_state;
 		}
 		kobject_uevent(&kobj->kobj, KOBJ_ADD);
-		device->kobjs[i] = kobj;
+		per_cpu(stats, cpu).kobjs[i] = kobj;
+		kobj->cpuid = cpu;
 	}
 
 	return 0;
 
 error_state:
 	for (i = i - 1; i >= 0; i--)
-		cpuidle_free_state_kobj(device, i);
+		cpuidle_free_state_kobj(cpu, i);
 	return ret;
 }
 
 /**
  * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
- * @device: the target device
  */
-void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
+void cpuidle_remove_state_sysfs(int cpu)
 {
 	int i;
 
-	for (i = 0; i < device->state_count; i++)
-		cpuidle_free_state_kobj(device, i);
+	for (i = 0; i < cpuidle_subsys.state_count; i++)
+		cpuidle_free_state_kobj(cpu, i);
 }
 
 /**
@@ -361,14 +365,14 @@ void cpuidle_remove_state_sysfs(struct c
 int cpuidle_add_sysfs(struct sys_device *sysdev)
 {
 	int cpu = sysdev->id;
-	struct cpuidle_device *dev;
+	struct cpuidle_stats *st;
 	int error;
 
-	dev = per_cpu(cpuidle_devices, cpu);
-	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj,
+	st = &per_cpu(stats, cpu);
+	error = kobject_init_and_add(&st->kobj, &ktype_cpuidle, &sysdev->kobj,
 				     "cpuidle");
 	if (!error)
-		kobject_uevent(&dev->kobj, KOBJ_ADD);
+		kobject_uevent(&st->kobj, KOBJ_ADD);
 	return error;
 }
 
@@ -379,8 +383,8 @@ int cpuidle_add_sysfs(struct sys_device 
 void cpuidle_remove_sysfs(struct sys_device *sysdev)
 {
 	int cpu = sysdev->id;
-	struct cpuidle_device *dev;
+	struct cpuidle_stats *st;
 
-	dev = per_cpu(cpuidle_devices, cpu);
-	kobject_put(&dev->kobj);
+	st = &per_cpu(stats, cpu);
+	kobject_put(&st->kobj);
 }
Index: linux.trees.git/drivers/cpuidle/governors/ladder.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/governors/ladder.c
+++ linux.trees.git/drivers/cpuidle/governors/ladder.c
@@ -60,9 +60,8 @@ static inline void ladder_do_selection(s
 
 /**
  * ladder_select_state - selects the next state to enter
- * @dev: the CPU
  */
-static int ladder_select_state(struct cpuidle_device *dev)
+static int ladder_select_state(int cpu)
 {
 	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
 	struct ladder_device_state *last_state;
@@ -77,15 +76,16 @@ static int ladder_select_state(struct cp
 
 	last_state = &ldev->states[last_idx];
 
-	if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
-		last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+	if (cpuidle_subsys.states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
+		last_residency = cpuidle_get_last_residency(cpu) -
+			cpuidle_subsys.states[last_idx].exit_latency;
 	else
 		last_residency = last_state->threshold.promotion_time + 1;
 
 	/* consider promotion */
-	if (last_idx < dev->state_count - 1 &&
+	if (last_idx < cpuidle_subsys.state_count - 1 &&
 	    last_residency > last_state->threshold.promotion_time &&
-	    dev->states[last_idx + 1].exit_latency <= latency_req) {
+	    cpuidle_subsys.states[last_idx + 1].exit_latency <= latency_req) {
 		last_state->stats.promotion_count++;
 		last_state->stats.demotion_count = 0;
 		if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -96,11 +96,11 @@ static int ladder_select_state(struct cp
 
 	/* consider demotion */
 	if (last_idx > CPUIDLE_DRIVER_STATE_START &&
-	    dev->states[last_idx].exit_latency > latency_req) {
+	    cpuidle_subsys.states[last_idx].exit_latency > latency_req) {
 		int i;
 
 		for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
-			if (dev->states[i].exit_latency <= latency_req)
+			if (cpuidle_subsys.states[i].exit_latency <= latency_req)
 				break;
 		}
 		ladder_do_selection(ldev, last_idx, i);
@@ -123,19 +123,18 @@ static int ladder_select_state(struct cp
 
 /**
  * ladder_enable_device - setup for the governor
- * @dev: the CPU
  */
-static int ladder_enable_device(struct cpuidle_device *dev)
+static int ladder_enable_device(int cpu)
 {
 	int i;
-	struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
+	struct ladder_device *ldev = &per_cpu(ladder_devices, cpu);
 	struct ladder_device_state *lstate;
 	struct cpuidle_state *state;
 
 	ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-	for (i = 0; i < dev->state_count; i++) {
-		state = &dev->states[i];
+	for (i = 0; i < cpuidle_subsys.state_count; i++) {
+		state = &cpuidle_subsys.states[i];
 		lstate = &ldev->states[i];
 
 		lstate->stats.promotion_count = 0;
@@ -144,7 +143,7 @@ static int ladder_enable_device(struct c
 		lstate->threshold.promotion_count = PROMOTION_COUNT;
 		lstate->threshold.demotion_count = DEMOTION_COUNT;
 
-		if (i < dev->state_count - 1)
+		if (i < cpuidle_subsys.state_count - 1)
 			lstate->threshold.promotion_time = state->exit_latency;
 		if (i > 0)
 			lstate->threshold.demotion_time = state->exit_latency;
Index: linux.trees.git/drivers/cpuidle/governors/menu.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/governors/menu.c
+++ linux.trees.git/drivers/cpuidle/governors/menu.c
@@ -168,7 +168,7 @@ static inline int performance_multiplier
 
 static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
-static void menu_update(struct cpuidle_device *dev);
+static void menu_update(int cpu);
 
 /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
 static u64 div_round64(u64 dividend, u32 divisor)
@@ -178,9 +178,8 @@ static u64 div_round64(u64 dividend, u32
 
 /**
  * menu_select - selects the next idle state to enter
- * @dev: the CPU
  */
-static int menu_select(struct cpuidle_device *dev)
+static int menu_select(int cpu)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
@@ -191,7 +190,7 @@ static int menu_select(struct cpuidle_de
 	data->exit_us = 0;
 
 	if (data->needs_update) {
-		menu_update(dev);
+		menu_update(cpu);
 		data->needs_update = 0;
 	}
 
@@ -228,8 +227,8 @@ static int menu_select(struct cpuidle_de
 
 
 	/* find the deepest idle state that satisfies our constraints */
-	for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
-		struct cpuidle_state *s = &dev->states[i];
+	for (i = CPUIDLE_DRIVER_STATE_START; i < cpuidle_subsys.state_count; i++) {
+		struct cpuidle_state *s = &cpuidle_subsys.states[i];
 
 		if (s->target_residency > data->predicted_us)
 			break;
@@ -246,12 +245,11 @@ static int menu_select(struct cpuidle_de
 
 /**
  * menu_reflect - records that data structures need update
- * @dev: the CPU
  *
  * NOTE: it's important to be fast here because this operation will add to
  *       the overall exit latency.
  */
-static void menu_reflect(struct cpuidle_device *dev)
+static void menu_reflect(int cpu)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	data->needs_update = 1;
@@ -259,14 +257,13 @@ static void menu_reflect(struct cpuidle_
 
 /**
  * menu_update - attempts to guess what happened after entry
- * @dev: the CPU
  */
-static void menu_update(struct cpuidle_device *dev)
+static void menu_update(int cpu)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int last_idx = data->last_state_idx;
-	unsigned int last_idle_us = cpuidle_get_last_residency(dev);
-	struct cpuidle_state *target = &dev->states[last_idx];
+	unsigned int last_idle_us = cpuidle_get_last_residency(cpu);
+	struct cpuidle_state *target = &cpuidle_subsys.states[last_idx];
 	unsigned int measured_us;
 	u64 new_factor;
 
@@ -315,11 +312,10 @@ static void menu_update(struct cpuidle_d
 
 /**
  * menu_enable_device - scans a CPU's states and does setup
- * @dev: the CPU
  */
-static int menu_enable_device(struct cpuidle_device *dev)
+static int menu_enable_device(int cpu)
 {
-	struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+	struct menu_device *data = &per_cpu(menu_devices, cpu);
 
 	memset(data, 0, sizeof(struct menu_device));
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 4/8]: POWER: enable cpuidle for POWER.
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
                   ` (2 preceding siblings ...)
  2010-04-15 11:07 ` [v12 PATCH 3/8]: cpuidle: cleanup driver/cpuidle/sysfs.c and governor.c Arun R Bharadwaj
@ 2010-04-15 11:08 ` Arun R Bharadwaj
  2010-04-15 11:09 ` [v12 PATCH 5/8]: pSeries/cpuidle: refactor pseries idle loops Arun R Bharadwaj
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:08 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch enables the cpuidle option in Kconfig for pSeries.

Currently cpuidle infrastructure is enabled only for x86 and ARM.
This code is almost completely borrowed from x86 to enable
cpuidle for pSeries.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig              |    9 +++++++++
 arch/powerpc/include/asm/system.h |    2 ++
 arch/powerpc/kernel/idle.c        |   19 +++++++++++++++++++
 3 files changed, 30 insertions(+)

Index: linux.trees.git/arch/powerpc/Kconfig
===================================================================
--- linux.trees.git.orig/arch/powerpc/Kconfig
+++ linux.trees.git/arch/powerpc/Kconfig
@@ -101,6 +101,9 @@ config ARCH_HAS_ILOG2_U64
 	bool
 	default y if 64BIT
 
+config ARCH_HAS_CPU_IDLE_WAIT
+	def_bool y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -275,6 +278,12 @@ source "kernel/Kconfig.freezer"
 source "arch/powerpc/sysdev/Kconfig"
 source "arch/powerpc/platforms/Kconfig"
 
+menu "Power management options"
+
+source "drivers/cpuidle/Kconfig"
+
+endmenu
+
 menu "Kernel options"
 
 config HIGHMEM
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -551,5 +551,7 @@ extern void account_system_vtime(struct 
 
 extern struct dentry *powerpc_debugfs_root;
 
+void cpu_idle_wait(void);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -102,6 +102,25 @@ void cpu_idle(void)
 	}
 }
 
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs come out of the old
+ * idle loop and start using the new idle loop.
+ * Required while changing idle handler on SMP systems.
+ * Caller must have changed idle handler to the new value before the call.
+ */
+void cpu_idle_wait(void)
+{
+	/* Ensure that new value of idle is set */
+	smp_mb();
+	/* kick all the CPUs so that they exit out of old idle routine */
+	smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 5/8]: pSeries/cpuidle: refactor pseries idle loops.
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
                   ` (3 preceding siblings ...)
  2010-04-15 11:08 ` [v12 PATCH 4/8]: POWER: enable cpuidle for POWER Arun R Bharadwaj
@ 2010-04-15 11:09 ` Arun R Bharadwaj
  2010-04-15 11:10 ` [v12 PATCH 6/8]: POWER: add a default_idle idle loop for POWER Arun R Bharadwaj
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:09 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch removes the routines, pseries_shared_idle_sleep and
pseries_dedicated_idle_sleep, since this is implemented as a part
of arch/powerpc/platform/pseries/processor_idle.c

Also, similar to x86, call cpuidle_idle_call from cpu_idle() idle
loop instead of ppc_md.power_save.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/idle.c             |   58 ++++++++++-----------
 arch/powerpc/platforms/pseries/setup.c |   89 ---------------------------------
 2 files changed, 30 insertions(+), 117 deletions(-)

Index: linux.trees.git/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/setup.c
+++ linux.trees.git/arch/powerpc/platforms/pseries/setup.c
@@ -74,9 +74,6 @@ EXPORT_SYMBOL(CMO_PageSize);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
-static void pseries_shared_idle_sleep(void);
-static void pseries_dedicated_idle_sleep(void);
-
 static struct device_node *pSeries_mpic_node;
 
 static void pSeries_show_cpuinfo(struct seq_file *m)
@@ -296,18 +293,8 @@ static void __init pSeries_setup_arch(vo
 	pSeries_nvram_init();
 
 	/* Choose an idle loop */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+	if (firmware_has_feature(FW_FEATURE_SPLPAR))
 		vpa_init(boot_cpuid);
-		if (get_lppaca()->shared_proc) {
-			printk(KERN_DEBUG "Using shared processor idle loop\n");
-			ppc_md.power_save = pseries_shared_idle_sleep;
-		} else {
-			printk(KERN_DEBUG "Using dedicated idle loop\n");
-			ppc_md.power_save = pseries_dedicated_idle_sleep;
-		}
-	} else {
-		printk(KERN_DEBUG "Using default idle loop\n");
-	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
@@ -495,80 +482,6 @@ static int __init pSeries_probe(void)
 	return 1;
 }
 
-
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-static void pseries_dedicated_idle_sleep(void)
-{ 
-	unsigned int cpu = smp_processor_id();
-	unsigned long start_snooze;
-	unsigned long in_purr, out_purr;
-
-	/*
-	 * Indicate to the HV that we are idle. Now would be
-	 * a good time to find other work to dispatch.
-	 */
-	get_lppaca()->idle = 1;
-	get_lppaca()->donate_dedicated_cpu = 1;
-	in_purr = mfspr(SPRN_PURR);
-
-	/*
-	 * We come in with interrupts disabled, and need_resched()
-	 * has been checked recently.  If we should poll for a little
-	 * while, do so.
-	 */
-	if (__get_cpu_var(smt_snooze_delay)) {
-		start_snooze = get_tb() +
-			__get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec;
-		local_irq_enable();
-		set_thread_flag(TIF_POLLING_NRFLAG);
-
-		while (get_tb() < start_snooze) {
-			if (need_resched() || cpu_is_offline(cpu))
-				goto out;
-			ppc64_runlatch_off();
-			HMT_low();
-			HMT_very_low();
-		}
-
-		HMT_medium();
-		clear_thread_flag(TIF_POLLING_NRFLAG);
-		smp_mb();
-		local_irq_disable();
-		if (need_resched() || cpu_is_offline(cpu))
-			goto out;
-	}
-
-	cede_processor();
-
-out:
-	HMT_medium();
-	out_purr = mfspr(SPRN_PURR);
-	get_lppaca()->wait_state_cycles += out_purr - in_purr;
-	get_lppaca()->donate_dedicated_cpu = 0;
-	get_lppaca()->idle = 0;
-}
-
-static void pseries_shared_idle_sleep(void)
-{
-	/*
-	 * Indicate to the HV that we are idle. Now would be
-	 * a good time to find other work to dispatch.
-	 */
-	get_lppaca()->idle = 1;
-
-	/*
-	 * Yield the processor to the hypervisor.  We return if
-	 * an external interrupt occurs (which are driven prior
-	 * to returning here) or if a prod occurs from another
-	 * processor. When returning here, external interrupts
-	 * are enabled.
-	 */
-	cede_processor();
-
-	get_lppaca()->idle = 0;
-}
-
 static int pSeries_pci_probe_mode(struct pci_bus *bus)
 {
 	if (firmware_has_feature(FW_FEATURE_LPAR))
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -25,6 +25,7 @@
 #include <linux/cpu.h>
 #include <linux/sysctl.h>
 #include <linux/tick.h>
+#include <linux/cpuidle.h>
 
 #include <asm/system.h>
 #include <asm/processor.h>
@@ -46,6 +47,14 @@ static int __init powersave_off(char *ar
 }
 __setup("powersave=off", powersave_off);
 
+#ifndef CONFIG_CPU_IDLE
+void cpuidle_idle_call(void)
+{
+	local_irq_enable();
+	cpu_relax();
+}
+#endif
+
 /*
  * The body of the idle task.
  */
@@ -60,35 +69,26 @@ void cpu_idle(void)
 		while (!need_resched() && !cpu_should_die()) {
 			ppc64_runlatch_off();
 
-			if (ppc_md.power_save) {
-				clear_thread_flag(TIF_POLLING_NRFLAG);
-				/*
-				 * smp_mb is so clearing of TIF_POLLING_NRFLAG
-				 * is ordered w.r.t. need_resched() test.
-				 */
-				smp_mb();
-				local_irq_disable();
-
-				/* Don't trace irqs off for idle */
-				stop_critical_timings();
-
-				/* check again after disabling irqs */
-				if (!need_resched() && !cpu_should_die())
-					ppc_md.power_save();
-
-				start_critical_timings();
-
-				local_irq_enable();
-				set_thread_flag(TIF_POLLING_NRFLAG);
-
-			} else {
-				/*
-				 * Go into low thread priority and possibly
-				 * low power mode.
-				 */
-				HMT_low();
-				HMT_very_low();
-			}
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+			/*
+			 * smp_mb is so clearing of TIF_POLLING_NRFLAG
+			 * is ordered w.r.t. need_resched() test.
+			 */
+			smp_mb();
+			local_irq_disable();
+
+			/* Don't trace irqs off for idle */
+			stop_critical_timings();
+
+			/* check again after disabling irqs */
+			if (!need_resched() && !cpu_should_die())
+				cpuidle_idle_call();
+
+			start_critical_timings();
+
+			local_irq_enable();
+			set_thread_flag(TIF_POLLING_NRFLAG);
+
 		}
 
 		HMT_medium();

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 6/8]: POWER: add a default_idle idle loop for POWER
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
                   ` (4 preceding siblings ...)
  2010-04-15 11:09 ` [v12 PATCH 5/8]: pSeries/cpuidle: refactor pseries idle loops Arun R Bharadwaj
@ 2010-04-15 11:10 ` Arun R Bharadwaj
  2010-04-15 11:11 ` [v12 PATCH 7/8]: pSeries: implement pSeries processor idle module Arun R Bharadwaj
  2010-04-15 11:12 ` [v12 PATCH 8/8]: POWER: Enable default_idle when power_save=off Arun R Bharadwaj
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:10 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

In arch/powerpc/kernel/idle.c create a default_idle() routine by moving
the failover condition of the cpu_idle() idle loop. This is needed by
cpuidle infrastructure to call default_idle when other idle routines
are not yet registered. Functionality remains the same, but the code is
slightly moved around.


Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig              |    3 +++
 arch/powerpc/include/asm/system.h |    1 +
 arch/powerpc/kernel/idle.c        |    6 ++++++
 3 files changed, 10 insertions(+)

Index: linux.trees.git/arch/powerpc/Kconfig
===================================================================
--- linux.trees.git.orig/arch/powerpc/Kconfig
+++ linux.trees.git/arch/powerpc/Kconfig
@@ -104,6 +104,9 @@ config ARCH_HAS_ILOG2_U64
 config ARCH_HAS_CPU_IDLE_WAIT
 	def_bool y
 
+config ARCH_HAS_DEFAULT_IDLE
+	def_bool y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -223,6 +223,7 @@ extern unsigned long klimit;
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
+extern void default_idle(void);
 extern int powersave_nap;	/* set if nap mode can be used in idle loop */
 
 /*
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -121,6 +121,12 @@ void cpu_idle_wait(void)
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
+void default_idle(void)
+{
+	HMT_low();
+	HMT_very_low();
+}
+
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 7/8]: pSeries: implement pSeries processor idle module.
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
                   ` (5 preceding siblings ...)
  2010-04-15 11:10 ` [v12 PATCH 6/8]: POWER: add a default_idle idle loop for POWER Arun R Bharadwaj
@ 2010-04-15 11:11 ` Arun R Bharadwaj
  2010-04-15 11:12 ` [v12 PATCH 8/8]: POWER: Enable default_idle when power_save=off Arun R Bharadwaj
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:11 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch creates arch/powerpc/platforms/pseries/processor_idle.c,
which implements the cpuidle infrastructure for pseries.
It implements a pseries_cpuidle_loop() which would be the main idle loop
called from cpu_idle(). It makes decision of entering either
dedicated_snooze_loop or dedicated_cede_loop for dedicated lpar and
shared_cede_loop for shared lpar processor based on the
decision taken by the cpuidle governor.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/system.h               |    6 
 arch/powerpc/kernel/sysfs.c                     |    2 
 arch/powerpc/platforms/pseries/Makefile         |    1 
 arch/powerpc/platforms/pseries/processor_idle.c |  190 ++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/pseries.h        |    6 
 5 files changed, 205 insertions(+)

Index: linux.trees.git/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/Makefile
+++ linux.trees.git/arch/powerpc/platforms/pseries/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst
 obj-$(CONFIG_PHYP_DUMP)	+= phyp_dump.o
 obj-$(CONFIG_CMM)		+= cmm.o
 obj-$(CONFIG_DTL)		+= dtl.o
+obj-$(CONFIG_CPU_IDLE)		+= processor_idle.o
Index: linux.trees.git/arch/powerpc/platforms/pseries/pseries.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/pseries.h
+++ linux.trees.git/arch/powerpc/platforms/pseries/pseries.h
@@ -10,6 +10,8 @@
 #ifndef _PSERIES_PSERIES_H
 #define _PSERIES_PSERIES_H
 
+#include <linux/cpuidle.h>
+
 extern void __init fw_feature_init(const char *hypertas, unsigned long len);
 
 struct pt_regs;
@@ -40,4 +42,8 @@ extern unsigned long rtas_poweron_auto;
 
 extern void find_udbg_vterm(void);
 
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+extern struct cpuidle_driver pseries_idle_driver;
+
 #endif /* _PSERIES_PSERIES_H */
Index: linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
===================================================================
--- /dev/null
+++ linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
@@ -0,0 +1,190 @@
+/*
+ *  processor_idle - idle state cpuidle driver.
+ *  Adapted from drivers/acpi/processor_idle.c
+ *
+ *  Arun R Bharadwaj <arun@linux.vnet.ibm.com>
+ *
+ *  Copyright (C) 2009 IBM Corporation.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/cpuidle.h>
+
+#include <asm/paca.h>
+#include <asm/reg.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+
+#include "plpar_wrappers.h"
+#include "pseries.h"
+
+MODULE_AUTHOR("Arun R Bharadwaj");
+MODULE_DESCRIPTION("pSeries Idle State Driver");
+MODULE_LICENSE("GPL");
+
+struct cpuidle_driver pseries_idle_driver = {
+	.name =		"pseries_idle",
+	.owner =	THIS_MODULE,
+};
+
+#define IDLE_STATE_COUNT	2
+
+/* pSeries Idle state Flags */
+#define	PSERIES_DEDICATED_SNOOZE	(0x01)
+#define	PSERIES_DEDICATED_CEDE		(0x02)
+#define	PSERIES_SHARED_CEDE		(0x03)
+
+static int pseries_idle_init(struct cpuidle_subsystem *subsys)
+{
+	return cpuidle_register_subsystem(subsys->state_count);
+}
+
+static void shared_cede_loop(void)
+{
+	get_lppaca()->idle = 1;
+	cede_processor();
+	get_lppaca()->idle = 0;
+}
+
+static void dedicated_snooze_loop(void)
+{
+	local_irq_enable();
+	set_thread_flag(TIF_POLLING_NRFLAG);
+	while (!need_resched()) {
+		ppc64_runlatch_off();
+		HMT_low();
+		HMT_very_low();
+	}
+	HMT_medium();
+	clear_thread_flag(TIF_POLLING_NRFLAG);
+	smp_mb();
+	local_irq_disable();
+}
+
+static void dedicated_cede_loop(void)
+{
+	ppc64_runlatch_off();
+	HMT_medium();
+	cede_processor();
+}
+
+static int pseries_cpuidle_loop(struct cpuidle_state *st)
+{
+	unsigned long in_purr, out_purr;
+
+	get_lppaca()->idle = 1;
+	get_lppaca()->donate_dedicated_cpu = 1;
+	in_purr = mfspr(SPRN_PURR);
+
+	if (st->flags & PSERIES_SHARED_CEDE)
+		shared_cede_loop();
+	else if (st->flags & PSERIES_DEDICATED_SNOOZE)
+		dedicated_snooze_loop();
+	else
+		dedicated_cede_loop();
+
+	out_purr = mfspr(SPRN_PURR);
+	get_lppaca()->wait_state_cycles += out_purr - in_purr;
+	get_lppaca()->donate_dedicated_cpu = 0;
+	get_lppaca()->idle = 0;
+	return 0;
+}
+
+static int pseries_setup_cpuidle(struct cpuidle_subsystem *subsys)
+{
+	int i;
+	struct cpuidle_state *state;
+
+	if (get_lppaca()->shared_proc) {
+		state = &subsys->states[0];
+		snprintf(state->name, CPUIDLE_NAME_LEN, "IDLE");
+		state->enter = pseries_cpuidle_loop;
+		strncpy(state->desc, "shared_cede", CPUIDLE_DESC_LEN);
+		state->flags = PSERIES_SHARED_CEDE;
+		state->exit_latency = 0;
+		state->target_residency = 0;
+		subsys->state_count = 1;
+		return 0;
+	}
+
+	for (i = 0; i < IDLE_STATE_COUNT; i++) {
+		state = &subsys->states[i];
+
+		snprintf(state->name, CPUIDLE_NAME_LEN, "CEDE%d", i);
+		state->enter = pseries_cpuidle_loop;
+
+		switch (i) {
+		case 0:
+			strncpy(state->desc, "snooze", CPUIDLE_DESC_LEN);
+			state->flags = PSERIES_DEDICATED_SNOOZE;
+			state->exit_latency = 0;
+			state->target_residency = 0;
+			break;
+
+		case 1:
+			strncpy(state->desc, "cede", CPUIDLE_DESC_LEN);
+			state->flags = PSERIES_DEDICATED_CEDE;
+			state->exit_latency = 1;
+			state->target_residency =
+					__get_cpu_var(smt_snooze_delay);
+			break;
+		}
+	}
+	subsys->state_count = i;
+
+	return 0;
+}
+
+void update_smt_snooze_delay(int snooze)
+{
+	cpuidle_subsys.states[0].target_residency = snooze;
+}
+
+static int __init pseries_processor_idle_init(void)
+{
+	int result;
+	struct cpuidle_subsystem *pseries_subsys = &cpuidle_subsys;
+
+
+	result = cpuidle_register_driver(&pseries_idle_driver);
+
+	if (result < 0)
+		return result;
+
+	printk(KERN_DEBUG "pSeries idle driver registered\n");
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR)) {
+		printk(KERN_DEBUG "Using default idle\n");
+		return 0;
+	}
+
+	pseries_setup_cpuidle(pseries_subsys);
+	pseries_idle_init(pseries_subsys);
+
+	printk(KERN_DEBUG "Using cpuidle idle loop\n");
+
+	return 0;
+}
+
+late_initcall(pseries_processor_idle_init);
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -554,5 +554,11 @@ extern struct dentry *powerpc_debugfs_ro
 
 void cpu_idle_wait(void);
 
+#ifdef CONFIG_CPU_IDLE
+extern void update_smt_snooze_delay(int snooze);
+#else
+static inline void update_smt_snooze_delay(int snooze) {}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
Index: linux.trees.git/arch/powerpc/kernel/sysfs.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/sysfs.c
+++ linux.trees.git/arch/powerpc/kernel/sysfs.c
@@ -18,6 +18,7 @@
 #include <asm/machdep.h>
 #include <asm/smp.h>
 #include <asm/pmc.h>
+#include <asm/system.h>
 
 #include "cacheinfo.h"
 
@@ -51,6 +52,7 @@ static ssize_t store_smt_snooze_delay(st
 		return -EINVAL;
 
 	per_cpu(smt_snooze_delay, cpu->sysdev.id) = snooze;
+	update_smt_snooze_delay(snooze);
 
 	return count;
 }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [v12 PATCH 8/8]: POWER: Enable default_idle when power_save=off.
       [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
                   ` (6 preceding siblings ...)
  2010-04-15 11:11 ` [v12 PATCH 7/8]: pSeries: implement pSeries processor idle module Arun R Bharadwaj
@ 2010-04-15 11:12 ` Arun R Bharadwaj
  7 siblings, 0 replies; 8+ messages in thread
From: Arun R Bharadwaj @ 2010-04-15 11:12 UTC (permalink / raw)
  To: peterz
  Cc: Benjamin Herrenschmidt, Ingo Molnar, Vaidyanathan Srinivasan,
	Dipankar Sarma, Balbir Singh, Arun Bharadwaj, linux-kernel

* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2010-04-15 16:30:46]:

This patch enables default_idle when power_save=off kernel boot
option is specified.

Earlier, this was done by setting ppc_md.power_save = NULL and hence
HMT_low() and HMT_very_low() was called. Now this is defined under
default_idle() and hence by setting boot_option_idle_override = 1,
the cpuidle registration stuff does not happen and hence default_idle
is chosen in cpuidle_idle_call.

Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/processor.h            |    2 ++
 arch/powerpc/kernel/idle.c                      |    4 +++-
 arch/powerpc/platforms/pseries/processor_idle.c |    5 +++++
 3 files changed, 10 insertions(+), 1 deletion(-)

Index: linux.trees.git/arch/powerpc/include/asm/processor.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/processor.h
+++ linux.trees.git/arch/powerpc/include/asm/processor.h
@@ -364,6 +364,8 @@ static inline unsigned long get_clean_sp
 }
 #endif
 
+extern int boot_option_idle_override;
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -40,9 +40,11 @@
 #define cpu_should_die()	0
 #endif
 
+int boot_option_idle_override;
+
 static int __init powersave_off(char *arg)
 {
-	ppc_md.power_save = NULL;
+	boot_option_idle_override = 1;
 	return 0;
 }
 __setup("powersave=off", powersave_off);
Index: linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/platforms/pseries/processor_idle.c
+++ linux.trees.git/arch/powerpc/platforms/pseries/processor_idle.c
@@ -167,6 +167,11 @@ static int __init pseries_processor_idle
 	struct cpuidle_subsystem *pseries_subsys = &cpuidle_subsys;
 
 
+	if (boot_option_idle_override) {
+		printk(KERN_DEBUG "Using default idle\n");
+		return 0;
+	}
+
 	result = cpuidle_register_driver(&pseries_idle_driver);
 
 	if (result < 0)

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-04-15 11:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20100415110046.GA16760@linux.vnet.ibm.com>
2010-04-15 11:05 ` [v12 PATCH 1/8]: cpuidle: cleanup cpuidle.h header file Arun R Bharadwaj
2010-04-15 11:06 ` [v12 PATCH 2/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c Arun R Bharadwaj
2010-04-15 11:07 ` [v12 PATCH 3/8]: cpuidle: cleanup driver/cpuidle/sysfs.c and governor.c Arun R Bharadwaj
2010-04-15 11:08 ` [v12 PATCH 4/8]: POWER: enable cpuidle for POWER Arun R Bharadwaj
2010-04-15 11:09 ` [v12 PATCH 5/8]: pSeries/cpuidle: refactor pseries idle loops Arun R Bharadwaj
2010-04-15 11:10 ` [v12 PATCH 6/8]: POWER: add a default_idle idle loop for POWER Arun R Bharadwaj
2010-04-15 11:11 ` [v12 PATCH 7/8]: pSeries: implement pSeries processor idle module Arun R Bharadwaj
2010-04-15 11:12 ` [v12 PATCH 8/8]: POWER: Enable default_idle when power_save=off Arun R Bharadwaj

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox