RE: [PATCH] acpi cpuidle driver should handle max_cstate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2007-04-03 at 09:49 +0800, Pallipadi, Venkatesh wrote:
>  
> >-----Original Message-----
> >From: Li, Shaohua 
> >Sent: Monday, April 02, 2007 6:34 PM
> >To: Pallipadi, Venkatesh
> >Cc: linux acpi; Brown, Len; Adam Belay
> >Subject: RE: [PATCH] acpi cpuidle driver should handle max_cstate
> >
> >On Tue, 2007-04-03 at 00:44 +0800, Pallipadi, Venkatesh wrote:
> >>  
> >Ok, updated it.
> >
> >Signed-off-by: Shaohua Li <shaohua.li@xxxxxxxxx>
> >
> >Index: linux/drivers/acpi/processor_idle.c
> >===================================================================
> >--- linux.orig/drivers/acpi/processor_idle.c	2007-04-03 
> >08:47:05.000000000 +0800
> >+++ linux/drivers/acpi/processor_idle.c	2007-04-03 
> >08:50:50.000000000 +0800
> >@@ -75,7 +75,30 @@ ACPI_MODULE_NAME("processor_idle");
> > #define C2_OVERHEAD			1	/* 1us */
> > #define C3_OVERHEAD			1	/* 1us */
> > 
> >-module_param(max_cstate, uint, 0644);
> >+void acpi_max_cstate_changed(void)
> >+{
> >+	int cpu;
> >+	/* Driver will reset devices' max cstate limit */
> >+	lock_cpu_hotplug();
> >+	for_each_online_cpu(cpu)
> >+		cpuidle_force_redetect(&per_cpu(cpuidle_devices, cpu));
> >+	unlock_cpu_hotplug();
> >+}
> 
> No hotplug lock in cpuidle please. Either we have to add a
> force_allcpu_redetect function or we can use the previous patch.
Ok, I added a new routine to redetect all cpus. please see attached
patches.

Signed-off-by: Shaohua Li <shaohua.li@xxxxxxxxx>
Index: rc4-mm1/drivers/acpi/osl.c
===================================================================
--- rc4-mm1.orig/drivers/acpi/osl.c	2007-04-03 10:41:49.000000000 +0800
+++ rc4-mm1/drivers/acpi/osl.c	2007-04-03 11:05:24.000000000 +0800
@@ -997,6 +997,16 @@ unsigned int max_cstate = ACPI_PROCESSOR
 
 EXPORT_SYMBOL(max_cstate);
 
+void (*acpi_do_set_cstate_limit)(void);
+EXPORT_SYMBOL(acpi_do_set_cstate_limit);
+
+void acpi_set_cstate_limit(unsigned int new_limit)
+{
+	max_cstate = new_limit;
+	if (acpi_do_set_cstate_limit)
+		acpi_do_set_cstate_limit();
+}
+
 /*
  * Acquire a spinlock.
  *
Index: rc4-mm1/drivers/acpi/processor_core.c
===================================================================
--- rc4-mm1.orig/drivers/acpi/processor_core.c	2007-04-03 10:41:49.000000000 +0800
+++ rc4-mm1/drivers/acpi/processor_core.c	2007-04-03 11:05:24.000000000 +0800
@@ -1030,11 +1030,13 @@ static int __init acpi_processor_init(vo
 	acpi_processor_ppc_init();
 
 	cpuidle_register_driver(&acpi_idle_driver);
+	acpi_do_set_cstate_limit = acpi_max_cstate_changed;
 	return 0;
 }
 
 static void __exit acpi_processor_exit(void)
 {
+	acpi_do_set_cstate_limit = NULL;
 	cpuidle_unregister_driver(&acpi_idle_driver);
 
 	acpi_processor_ppc_exit();
Index: rc4-mm1/drivers/acpi/processor_idle.c
===================================================================
--- rc4-mm1.orig/drivers/acpi/processor_idle.c	2007-04-03 11:03:20.000000000 +0800
+++ rc4-mm1/drivers/acpi/processor_idle.c	2007-04-03 11:06:46.000000000 +0800
@@ -75,7 +75,26 @@ ACPI_MODULE_NAME("processor_idle");
 #define C2_OVERHEAD			1	/* 1us */
 #define C3_OVERHEAD			1	/* 1us */
 
-module_param(max_cstate, uint, 0644);
+void acpi_max_cstate_changed(void)
+{
+	/* Driver will reset devices' max cstate limit */
+	cpuidle_force_redetect_devices(&acpi_idle_driver);
+}
+
+static int change_max_cstate(const char *val, struct kernel_param *kp)
+{
+	int max;
+
+	max = simple_strtol(val, NULL, 0);
+	if (!max)
+		return -EINVAL;
+	max_cstate = max;
+	if (acpi_do_set_cstate_limit)
+		acpi_do_set_cstate_limit();
+	return 0;
+}
+
+module_param_call(max_cstate, change_max_cstate, param_get_uint, &max_cstate, 0644);
 
 static unsigned int nocst __read_mostly;
 module_param(nocst, uint, 0000);
@@ -1054,7 +1073,7 @@ static int acpi_idle_init(struct cpuidle
 		return -EINVAL;
 	}
 
-	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
 		cx = &pr->power.states[i];
 		state = &dev->states[count];
 
Index: rc4-mm1/include/linux/acpi.h
===================================================================
--- rc4-mm1.orig/include/linux/acpi.h	2007-04-03 10:41:49.000000000 +0800
+++ rc4-mm1/include/linux/acpi.h	2007-04-03 11:05:24.000000000 +0800
@@ -205,11 +205,8 @@ static inline unsigned int acpi_get_csta
 {
 	return max_cstate;
 }
-static inline void acpi_set_cstate_limit(unsigned int new_limit)
-{
-	max_cstate = new_limit;
-	return;
-}
+extern void (*acpi_do_set_cstate_limit)(void);
+extern void acpi_set_cstate_limit(unsigned int new_limit);
 #else
 static inline unsigned int acpi_get_cstate_limit(void) { return 0; }
 static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; }
Index: rc4-mm1/drivers/cpuidle/driver.c
===================================================================
--- rc4-mm1.orig/drivers/cpuidle/driver.c	2007-03-23 08:58:51.000000000 +0800
+++ rc4-mm1/drivers/cpuidle/driver.c	2007-04-03 11:04:13.000000000 +0800
@@ -160,20 +160,34 @@ void cpuidle_unregister_driver(struct cp
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
 
+static void __cpuidle_force_redetect(struct cpuidle_device *dev)
+{
+	cpuidle_remove_driver_sysfs(dev);
+	cpuidle_curr_driver->redetect(dev);
+	cpuidle_add_driver_sysfs(dev);
+}
+
 /**
  * cpuidle_force_redetect - redetects the idle states of a CPU
  *
  * @dev: the CPU to redetect
+ * @drv: the target driver
  *
  * Generally, the driver will call this when the supported states set has
  * changed. (e.g. as the result of an ACPI transition to battery power)
  */
-int cpuidle_force_redetect(struct cpuidle_device *dev)
+int cpuidle_force_redetect(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv)
 {
 	int uninstalled = 0;
 
 	mutex_lock(&cpuidle_lock);
 
+	if (drv != cpuidle_curr_driver) {
+		mutex_unlock(&cpuidle_lock);
+		return 0;
+	}
+
 	if (!(dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED) ||
 	    !cpuidle_curr_driver->redetect) {
 		mutex_unlock(&cpuidle_lock);
@@ -185,9 +199,7 @@ int cpuidle_force_redetect(struct cpuidl
 		cpuidle_uninstall_idle_handler();
 	}
 
-	cpuidle_remove_driver_sysfs(dev);
-	cpuidle_curr_driver->redetect(dev);
-	cpuidle_add_driver_sysfs(dev);
+	__cpuidle_force_redetect(dev);
 
 	if (cpuidle_device_can_idle(dev)) {
 		cpuidle_rescan_device(dev);
@@ -206,6 +218,42 @@ int cpuidle_force_redetect(struct cpuidl
 EXPORT_SYMBOL_GPL(cpuidle_force_redetect);
 
 /**
+ * cpuidle_force_redetect_devices - redetects the idle states of all CPUs
+ *
+ * @drv: the target driver
+ *
+ * Generally, the driver will call this when the supported states set has
+ * changed. (e.g. as the result of an ACPI transition to battery power)
+ */
+int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
+{
+	struct cpuidle_device *dev;
+	int ret = 0;
+
+	mutex_lock(&cpuidle_lock);
+
+	if (drv != cpuidle_curr_driver)
+		goto out;
+
+	if (!cpuidle_curr_driver->redetect) {
+		ret = -EIO;
+		goto out;
+	}
+
+	cpuidle_uninstall_idle_handler();
+
+	list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+		__cpuidle_force_redetect(dev);
+
+	cpuidle_install_idle_handler();
+out:
+	mutex_unlock(&cpuidle_lock);
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(cpuidle_force_redetect_devices);
+
+/**
  * cpuidle_get_bm_activity - determines if BM activity has occured
  */
 int cpuidle_get_bm_activity(void)
Index: rc4-mm1/include/linux/cpuidle.h
===================================================================
--- rc4-mm1.orig/include/linux/cpuidle.h	2007-04-03 10:42:45.000000000 +0800
+++ rc4-mm1/include/linux/cpuidle.h	2007-04-03 11:04:56.000000000 +0800
@@ -137,14 +137,17 @@ struct cpuidle_driver {
 
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
-extern int cpuidle_force_redetect(struct cpuidle_device *dev);
+extern int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv);
+extern int cpuidle_force_redetect_devices(struct cpuidle_driver *drv);
 
 #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_force_redetect(struct cpuidle_device *dev)
+static inline int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv)
+{return 0;}
+static inline int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
 {return 0;}
 
 #endif
Index: rc4-mm1/drivers/acpi/processor_idle.c
===================================================================
--- rc4-mm1.orig/drivers/acpi/processor_idle.c	2007-04-03 10:42:45.000000000 +0800
+++ rc4-mm1/drivers/acpi/processor_idle.c	2007-04-03 11:03:20.000000000 +0800
@@ -623,7 +623,8 @@ int acpi_processor_cst_has_changed(struc
 		return -ENODEV;
 
 	acpi_processor_get_power_info(pr);
-	return cpuidle_force_redetect(per_cpu(cpuidle_devices, pr->id));
+	return cpuidle_force_redetect(per_cpu(cpuidle_devices, pr->id),
+		&acpi_idle_driver);
 }
 
 /* proc interface */

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux