mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	PM / wakeup: Register wakeup class kobj after device is added
The device_set_wakeup_enable() function can be called on a device that hasn't been registered with device_add() yet. This allows the device to be in a state where wakeup is enabled for it but the device isn't published to userspace in sysfs yet. After commitc8377adfa7("PM / wakeup: Show wakeup sources stats in sysfs"), calling device_set_wakeup_enable() will fail for a device that hasn't been registered with the driver core via device_add(). This is because we try to create sysfs entries for the device and associate a wakeup class kobject with it before the device has been registered. Let's follow a similar approach that device_set_wakeup_capable() takes here and register the wakeup class either from device_set_wakeup_enable() when the device is already registered, or from dpm_sysfs_add() when the device is being registered with the driver core via device_add(). Fixes:c8377adfa7("PM / wakeup: Show wakeup sources stats in sysfs") Reported-by: Qian Cai <cai@lca.pw> Reviewed-by: Tri Vo <trong@android.com> Signed-off-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									ae367b7936
								
							
						
					
					
						commit
						2ca3d1ecb8
					
				
					 4 changed files with 34 additions and 4 deletions
				
			
		| 
						 | 
					@ -157,4 +157,13 @@ extern int wakeup_source_sysfs_add(struct device *parent,
 | 
				
			||||||
				   struct wakeup_source *ws);
 | 
									   struct wakeup_source *ws);
 | 
				
			||||||
extern void wakeup_source_sysfs_remove(struct wakeup_source *ws);
 | 
					extern void wakeup_source_sysfs_remove(struct wakeup_source *ws);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int pm_wakeup_source_sysfs_add(struct device *parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else /* !CONFIG_PM_SLEEP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int pm_wakeup_source_sysfs_add(struct device *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CONFIG_PM_SLEEP */
 | 
					#endif /* CONFIG_PM_SLEEP */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@
 | 
				
			||||||
#include <linux/export.h>
 | 
					#include <linux/export.h>
 | 
				
			||||||
#include <linux/pm_qos.h>
 | 
					#include <linux/pm_qos.h>
 | 
				
			||||||
#include <linux/pm_runtime.h>
 | 
					#include <linux/pm_runtime.h>
 | 
				
			||||||
 | 
					#include <linux/pm_wakeup.h>
 | 
				
			||||||
#include <linux/atomic.h>
 | 
					#include <linux/atomic.h>
 | 
				
			||||||
#include <linux/jiffies.h>
 | 
					#include <linux/jiffies.h>
 | 
				
			||||||
#include "power.h"
 | 
					#include "power.h"
 | 
				
			||||||
| 
						 | 
					@ -667,8 +668,13 @@ int dpm_sysfs_add(struct device *dev)
 | 
				
			||||||
		if (rc)
 | 
							if (rc)
 | 
				
			||||||
			goto err_wakeup;
 | 
								goto err_wakeup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						rc = pm_wakeup_source_sysfs_add(dev);
 | 
				
			||||||
 | 
						if (rc)
 | 
				
			||||||
 | 
							goto err_latency;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 err_latency:
 | 
				
			||||||
 | 
						sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
 | 
				
			||||||
 err_wakeup:
 | 
					 err_wakeup:
 | 
				
			||||||
	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 | 
						sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 | 
				
			||||||
 err_runtime:
 | 
					 err_runtime:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -220,10 +220,12 @@ struct wakeup_source *wakeup_source_register(struct device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ws = wakeup_source_create(name);
 | 
						ws = wakeup_source_create(name);
 | 
				
			||||||
	if (ws) {
 | 
						if (ws) {
 | 
				
			||||||
		ret = wakeup_source_sysfs_add(dev, ws);
 | 
							if (!dev || device_is_registered(dev)) {
 | 
				
			||||||
		if (ret) {
 | 
								ret = wakeup_source_sysfs_add(dev, ws);
 | 
				
			||||||
			wakeup_source_free(ws);
 | 
								if (ret) {
 | 
				
			||||||
			return NULL;
 | 
									wakeup_source_free(ws);
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		wakeup_source_add(ws);
 | 
							wakeup_source_add(ws);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,19 @@ int wakeup_source_sysfs_add(struct device *parent, struct wakeup_source *ws)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(wakeup_source_sysfs_add);
 | 
					EXPORT_SYMBOL_GPL(wakeup_source_sysfs_add);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * pm_wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs
 | 
				
			||||||
 | 
					 * for a device if they're missing.
 | 
				
			||||||
 | 
					 * @parent: Device given wakeup source is associated with
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int pm_wakeup_source_sysfs_add(struct device *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!parent->power.wakeup || parent->power.wakeup->dev)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return wakeup_source_sysfs_add(parent, parent->power.wakeup);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs.
 | 
					 * wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs.
 | 
				
			||||||
 * @ws: Wakeup source to be removed from sysfs.
 | 
					 * @ws: Wakeup source to be removed from sysfs.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue