diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-14 22:18:04 +0200 | 
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-14 22:18:04 +0200 | 
| commit | ee42f75dba3c66e559a13ac86ad1889d2a396378 (patch) | |
| tree | c2e234d229ff467999cfb366f1edef80ea243433 | |
| parent | d4e4ab86bcba5a72779c43dc1459f71fea3d89c8 (diff) | |
| parent | 9aadfa8fd9f8d311ba3014bf76e4d8aeee515533 (diff) | |
Merge back earlier 'pm-cpuidle' material.
| -rw-r--r-- | arch/arm/mach-davinci/cpuidle.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-ux500/Makefile | 1 | ||||
| -rw-r--r-- | drivers/cpuidle/Kconfig | 20 | ||||
| -rw-r--r-- | drivers/cpuidle/Kconfig.arm | 29 | ||||
| -rw-r--r-- | drivers/cpuidle/Makefile | 9 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle-ux500.c (renamed from arch/arm/mach-ux500/cpuidle.c) | 19 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 94 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/ladder.c | 12 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 12 | ||||
| -rw-r--r-- | drivers/cpuidle/sysfs.c | 101 | ||||
| -rw-r--r-- | drivers/mfd/db8500-prcmu.c | 4 | ||||
| -rw-r--r-- | include/linux/cpuidle.h | 9 | 
12 files changed, 188 insertions, 124 deletions
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 36aef3a7dedb..f1ac1c94ac0f 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = {  	.states[1]		= {  		.enter			= davinci_enter_idle,  		.exit_latency		= 10, -		.target_residency	= 100000, +		.target_residency	= 10000,  		.flags			= CPUIDLE_FLAG_TIME_VALID,  		.name			= "DDR SR",  		.desc			= "WFI and DDR Self Refresh", diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b180..fe1f3e26b88b 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -4,7 +4,6 @@  obj-y				:= cpu.o devices.o devices-common.o \  				   id.o usb.o timer.o pm.o -obj-$(CONFIG_CPU_IDLE)          += cpuidle.o  obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o  obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o  obj-$(CONFIG_MACH_MOP500)	+= board-mop500.o board-mop500-sdi.o \ diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 0e2cd5cab4d0..b3fb81d7cf04 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -1,5 +1,6 @@ +menu "CPU Idle" -menuconfig CPU_IDLE +config CPU_IDLE  	bool "CPU idle PM support"  	default y if ACPI || PPC_PSERIES  	select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) @@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU  	bool "Menu governor (for tickless system)"  	default y -config CPU_IDLE_CALXEDA -	bool "CPU Idle Driver for Calxeda processors" -	depends on ARCH_HIGHBANK -	select ARM_CPU_SUSPEND -	help -	  Select this to enable cpuidle on Calxeda processors. - -config CPU_IDLE_ZYNQ -	bool "CPU Idle Driver for Xilinx Zynq processors" -	depends on ARCH_ZYNQ -	help -	  Select this to enable cpuidle on Xilinx Zynq processors. +menu "ARM CPU Idle Drivers" +depends on ARM +source "drivers/cpuidle/Kconfig.arm" +endmenu  endif  config ARCH_NEEDS_CPU_IDLE_COUPLED  	def_bool n +endmenu diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm new file mode 100644 index 000000000000..b3302193c15a --- /dev/null +++ b/drivers/cpuidle/Kconfig.arm @@ -0,0 +1,29 @@ +# +# ARM CPU Idle drivers +# + +config ARM_HIGHBANK_CPUIDLE +	bool "CPU Idle Driver for Calxeda processors" +	depends on ARCH_HIGHBANK +	select ARM_CPU_SUSPEND +	help +	  Select this to enable cpuidle on Calxeda processors. + +config ARM_KIRKWOOD_CPUIDLE +	bool "CPU Idle Driver for Marvell Kirkwood SoCs" +	depends on ARCH_KIRKWOOD +	help +	  This adds the CPU Idle driver for Marvell Kirkwood SoCs. + +config ARM_ZYNQ_CPUIDLE +	bool "CPU Idle Driver for Xilinx Zynq processors" +	depends on ARCH_ZYNQ +	help +	  Select this to enable cpuidle on Xilinx Zynq processors. + +config ARM_U8500_CPUIDLE +	bool "Cpu Idle Driver for the ST-E u8500 processors" +	depends on ARCH_U8500 +	help +	  Select this to enable cpuidle for ST-E u8500 processors + diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 8767a7b3eb91..0b9d200c7e45 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -5,6 +5,9 @@  obj-y += cpuidle.o driver.o governor.o sysfs.o governors/  obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o -obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o -obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o -obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o +################################################################################## +# ARM SoC drivers +obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o +obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)	+= cpuidle-kirkwood.o +obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)		+= cpuidle-zynq.o +obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o diff --git a/arch/arm/mach-ux500/cpuidle.c b/drivers/cpuidle/cpuidle-ux500.c index a45dd09daed9..e0564652af35 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -16,13 +16,11 @@  #include <linux/smp.h>  #include <linux/mfd/dbx500-prcmu.h>  #include <linux/platform_data/arm-ux500-pm.h> +#include <linux/platform_device.h>  #include <asm/cpuidle.h>  #include <asm/proc-fns.h> -#include "db8500-regs.h" -#include "id.h" -  static atomic_t master = ATOMIC_INIT(0);  static DEFINE_SPINLOCK(master_lock); @@ -113,11 +111,8 @@ static struct cpuidle_driver ux500_idle_driver = {  	.state_count = 2,  }; -int __init ux500_idle_init(void) +static int __init dbx500_cpuidle_probe(struct platform_device *pdev)  { -	if (!(cpu_is_u8500_family() || cpu_is_ux540_family())) -		return -ENODEV; -  	/* Configure wake up reasons */  	prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |  			     PRCMU_WAKEUP(ABB)); @@ -125,4 +120,12 @@ int __init ux500_idle_init(void)  	return cpuidle_register(&ux500_idle_driver, NULL);  } -device_initcall(ux500_idle_init); +static struct platform_driver dbx500_cpuidle_plat_driver = { +	.driver = { +		.name = "cpuidle-dbx500", +		.owner = THIS_MODULE, +	}, +	.probe = dbx500_cpuidle_probe, +}; + +module_platform_driver(dbx500_cpuidle_plat_driver); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fdc432f18022..d75040ddd2b3 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -42,8 +42,6 @@ void disable_cpuidle(void)  	off = 1;  } -static int __cpuidle_register_device(struct cpuidle_device *dev); -  /**   * cpuidle_play_dead - cpu off-lining   * @@ -278,7 +276,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}   */  int cpuidle_enable_device(struct cpuidle_device *dev)  { -	int ret, i; +	int ret;  	struct cpuidle_driver *drv;  	if (!dev) @@ -292,15 +290,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)  	if (!drv || !cpuidle_curr_governor)  		return -EIO; +	if (!dev->registered) +		return -EINVAL; +  	if (!dev->state_count)  		dev->state_count = drv->state_count; -	if (dev->registered == 0) { -		ret = __cpuidle_register_device(dev); -		if (ret) -			return ret; -	} -  	poll_idle_init(drv);  	ret = cpuidle_add_device_sysfs(dev); @@ -311,12 +306,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)  	    (ret = cpuidle_curr_governor->enable(drv, dev)))  		goto fail_sysfs; -	for (i = 0; i < dev->state_count; i++) { -		dev->states_usage[i].usage = 0; -		dev->states_usage[i].time = 0; -	} -	dev->last_residency = 0; -  	smp_wmb();  	dev->enabled = 1; @@ -360,6 +349,23 @@ void cpuidle_disable_device(struct cpuidle_device *dev)  EXPORT_SYMBOL_GPL(cpuidle_disable_device); +static void __cpuidle_unregister_device(struct cpuidle_device *dev) +{ +	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); + +	list_del(&dev->device_list); +	per_cpu(cpuidle_devices, dev->cpu) = NULL; +	module_put(drv->owner); +} + +static int __cpuidle_device_init(struct cpuidle_device *dev) +{ +	memset(dev->states_usage, 0, sizeof(dev->states_usage)); +	dev->last_residency = 0; + +	return 0; +} +  /**   * __cpuidle_register_device - internal register function called before register   * and enable routines @@ -377,24 +383,15 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)  	per_cpu(cpuidle_devices, dev->cpu) = dev;  	list_add(&dev->device_list, &cpuidle_detected_devices); -	ret = cpuidle_add_sysfs(dev); -	if (ret) -		goto err_sysfs;  	ret = cpuidle_coupled_register_device(dev); -	if (ret) -		goto err_coupled; +	if (ret) { +		__cpuidle_unregister_device(dev); +		return ret; +	}  	dev->registered = 1;  	return 0; - -err_coupled: -	cpuidle_remove_sysfs(dev); -err_sysfs: -	list_del(&dev->device_list); -	per_cpu(cpuidle_devices, dev->cpu) = NULL; -	module_put(drv->owner); -	return ret;  }  /** @@ -403,25 +400,44 @@ err_sysfs:   */  int cpuidle_register_device(struct cpuidle_device *dev)  { -	int ret; +	int ret = -EBUSY;  	if (!dev)  		return -EINVAL;  	mutex_lock(&cpuidle_lock); -	if ((ret = __cpuidle_register_device(dev))) { -		mutex_unlock(&cpuidle_lock); -		return ret; -	} +	if (dev->registered) +		goto out_unlock; + +	ret = __cpuidle_device_init(dev); +	if (ret) +		goto out_unlock; + +	ret = __cpuidle_register_device(dev); +	if (ret) +		goto out_unlock; + +	ret = cpuidle_add_sysfs(dev); +	if (ret) +		goto out_unregister; + +	ret = cpuidle_enable_device(dev); +	if (ret) +		goto out_sysfs; -	cpuidle_enable_device(dev);  	cpuidle_install_idle_handler(); +out_unlock:  	mutex_unlock(&cpuidle_lock); -	return 0; +	return ret; +out_sysfs: +	cpuidle_remove_sysfs(dev); +out_unregister: +	__cpuidle_unregister_device(dev); +	goto out_unlock;  }  EXPORT_SYMBOL_GPL(cpuidle_register_device); @@ -432,8 +448,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);   */  void cpuidle_unregister_device(struct cpuidle_device *dev)  { -	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); -  	if (dev->registered == 0)  		return; @@ -442,14 +456,12 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)  	cpuidle_disable_device(dev);  	cpuidle_remove_sysfs(dev); -	list_del(&dev->device_list); -	per_cpu(cpuidle_devices, dev->cpu) = NULL; + +	__cpuidle_unregister_device(dev);  	cpuidle_coupled_unregister_device(dev);  	cpuidle_resume_and_unlock(); - -	module_put(drv->owner);  }  EXPORT_SYMBOL_GPL(cpuidle_unregister_device); diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 9b784051ec12..9f08e8cce1af 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -192,14 +192,4 @@ static int __init init_ladder(void)  	return cpuidle_register_governor(&ladder_governor);  } -/** - * exit_ladder - exits the governor - */ -static void __exit exit_ladder(void) -{ -	cpuidle_unregister_governor(&ladder_governor); -} - -MODULE_LICENSE("GPL"); -module_init(init_ladder); -module_exit(exit_ladder); +postcore_initcall(init_ladder); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index bc580b67a652..cbbb73b37a6d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -442,14 +442,4 @@ static int __init init_menu(void)  	return cpuidle_register_governor(&menu_governor);  } -/** - * exit_menu - exits the governor - */ -static void __exit exit_menu(void) -{ -	cpuidle_unregister_governor(&menu_governor); -} - -MODULE_LICENSE("GPL"); -module_init(init_menu); -module_exit(exit_menu); +postcore_initcall(init_menu); diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 428754af6236..8739cc05228c 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -11,8 +11,10 @@  #include <linux/sysfs.h>  #include <linux/slab.h>  #include <linux/cpu.h> +#include <linux/completion.h>  #include <linux/capability.h>  #include <linux/device.h> +#include <linux/kobject.h>  #include "cpuidle.h" @@ -33,7 +35,8 @@ static ssize_t show_available_governors(struct device *dev,  	mutex_lock(&cpuidle_lock);  	list_for_each_entry(tmp, &cpuidle_governors, governor_list) { -		if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2)) +		if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - +				    CPUIDLE_NAME_LEN - 2))  			goto out;  		i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);  	} @@ -166,13 +169,28 @@ 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 attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr) -static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf) + +struct cpuidle_device_kobj { +	struct cpuidle_device *dev; +	struct completion kobj_unregister; +	struct kobject kobj; +}; + +static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj) +{ +	struct cpuidle_device_kobj *kdev = +		container_of(kobj, struct cpuidle_device_kobj, kobj); + +	return kdev->dev; +} + +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_attr * cattr = attr_to_cpuidleattr(attr); +	struct cpuidle_device *dev = to_cpuidle_device(kobj); +	struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);  	if (cattr->show) {  		mutex_lock(&cpuidle_lock); @@ -182,12 +200,12 @@ static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char  	return ret;  } -static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr, -		     const char * buf, size_t count) +static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr, +			     const char *buf, size_t count)  {  	int ret = -EIO; -	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); -	struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr); +	struct cpuidle_device *dev = to_cpuidle_device(kobj); +	struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);  	if (cattr->store) {  		mutex_lock(&cpuidle_lock); @@ -204,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = {  static void cpuidle_sysfs_release(struct kobject *kobj)  { -	struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); +	struct cpuidle_device_kobj *kdev = +		container_of(kobj, struct cpuidle_device_kobj, kobj); -	complete(&dev->kobj_unregister); +	complete(&kdev->kobj_unregister);  }  static struct kobj_type ktype_cpuidle = { @@ -237,8 +256,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \  #define define_store_state_ull_function(_name) \  static ssize_t store_state_##_name(struct cpuidle_state *state, \ -		struct cpuidle_state_usage *state_usage, \ -		const char *buf, size_t size) \ +				   struct cpuidle_state_usage *state_usage, \ +				   const char *buf, size_t size)	\  { \  	unsigned long long value; \  	int err; \ @@ -256,14 +275,16 @@ static ssize_t store_state_##_name(struct cpuidle_state *state, \  #define define_show_state_ull_function(_name) \  static ssize_t show_state_##_name(struct cpuidle_state *state, \ -			struct cpuidle_state_usage *state_usage, char *buf) \ +				  struct cpuidle_state_usage *state_usage, \ +				  char *buf)				\  { \  	return sprintf(buf, "%llu\n", state_usage->_name);\  }  #define define_show_state_str_function(_name) \  static ssize_t show_state_##_name(struct cpuidle_state *state, \ -			struct cpuidle_state_usage *state_usage, char *buf) \ +				  struct cpuidle_state_usage *state_usage, \ +				  char *buf)				\  { \  	if (state->_name[0] == '\0')\  		return sprintf(buf, "<null>\n");\ @@ -309,8 +330,9 @@ struct cpuidle_state_kobj {  #define kobj_to_state(k) (kobj_to_state_obj(k)->state)  #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)  #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) + +static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr, +				  char * buf)  {  	int ret = -EIO;  	struct cpuidle_state *state = kobj_to_state(kobj); @@ -323,8 +345,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj,  	return ret;  } -static ssize_t cpuidle_state_store(struct kobject *kobj, -	struct attribute *attr, const char *buf, size_t size) +static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr, +				   const char *buf, size_t size)  {  	int ret = -EIO;  	struct cpuidle_state *state = kobj_to_state(kobj); @@ -371,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)  {  	int i, ret = -ENOMEM;  	struct cpuidle_state_kobj *kobj; +	struct cpuidle_device_kobj *kdev = device->kobj_dev;  	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);  	/* state statistics */ @@ -383,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)  		init_completion(&kobj->kobj_unregister);  		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, -					   &device->kobj, "state%d", i); +					   &kdev->kobj, "state%d", i);  		if (ret) {  			kfree(kobj);  			goto error_state; @@ -449,8 +472,8 @@ static void cpuidle_driver_sysfs_release(struct kobject *kobj)  	complete(&driver_kobj->kobj_unregister);  } -static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr, -				   char * buf) +static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr, +				   char *buf)  {  	int ret = -EIO;  	struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj); @@ -500,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = {  static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)  {  	struct cpuidle_driver_kobj *kdrv; +	struct cpuidle_device_kobj *kdev = dev->kobj_dev;  	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);  	int ret; @@ -511,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)  	init_completion(&kdrv->kobj_unregister);  	ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle, -				   &dev->kobj, "driver"); +				   &kdev->kobj, "driver");  	if (ret) {  		kfree(kdrv);  		return ret; @@ -580,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device)   */  int cpuidle_add_sysfs(struct cpuidle_device *dev)  { +	struct cpuidle_device_kobj *kdev;  	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);  	int error; -	init_completion(&dev->kobj_unregister); +	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); +	if (!kdev) +		return -ENOMEM; +	kdev->dev = dev; +	dev->kobj_dev = kdev; -	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj, -				     "cpuidle"); -	if (!error) -		kobject_uevent(&dev->kobj, KOBJ_ADD); -	return error; +	init_completion(&kdev->kobj_unregister); + +	error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj, +				   "cpuidle"); +	if (error) { +		kfree(kdev); +		return error; +	} + +	kobject_uevent(&kdev->kobj, KOBJ_ADD); + +	return 0;  }  /** @@ -598,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)   */  void cpuidle_remove_sysfs(struct cpuidle_device *dev)  { -	kobject_put(&dev->kobj); -	wait_for_completion(&dev->kobj_unregister); +	struct cpuidle_device_kobj *kdev = dev->kobj_dev; + +	kobject_put(&kdev->kobj); +	wait_for_completion(&kdev->kobj_unregister); +	kfree(kdev);  } diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 3c157faee645..0d68eb1a5ec5 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3094,6 +3094,10 @@ static struct mfd_cell db8500_prcmu_devs[] = {  		.pdata_size = sizeof(db8500_cpufreq_table),  	},  	{ +		.name = "cpuidle-dbx500", +		.of_compatible = "stericsson,cpuidle-dbx500", +	}, +	{  		.name = "db8500-thermal",  		.num_resources = ARRAY_SIZE(db8500_thsens_resources),  		.resources = db8500_thsens_resources, diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 0bc4b74668e9..781addc66f03 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -13,8 +13,6 @@  #include <linux/percpu.h>  #include <linux/list.h> -#include <linux/kobject.h> -#include <linux/completion.h>  #include <linux/hrtimer.h>  #define CPUIDLE_STATE_MAX	10 @@ -61,6 +59,10 @@ struct cpuidle_state {  #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) +struct cpuidle_device_kobj; +struct cpuidle_state_kobj; +struct cpuidle_driver_kobj; +  struct cpuidle_device {  	unsigned int		registered:1;  	unsigned int		enabled:1; @@ -71,9 +73,8 @@ struct cpuidle_device {  	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];  	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];  	struct cpuidle_driver_kobj *kobj_driver; +	struct cpuidle_device_kobj *kobj_dev;  	struct list_head 	device_list; -	struct kobject		kobj; -	struct completion	kobj_unregister;  #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED  	int			safe_state_index;  | 
