PM / core: Add support to skip power management in device/driver model
All device objects in the driver model contain fields that control the handling of various power management activities. However, it's not always useful. There are few instances where pseudo devices are added to the model just to take advantage of many other features like kobjects, udev events, and so on. One such example is cpu devices and their caches. The sysfs for the cpu caches are managed by adding devices with cpu as the parent in cpu_device_create() when secondary cpu is brought online. Generally when the secondary CPUs are hotplugged back in as part of resume from suspend-to-ram, we call cpu_device_create() from the cpu hotplug state machine while the cpu device associated with that CPU is not yet ready to be resumed as the device_resume() call happens bit later. It's not really needed to set the flag is_prepared for cpu devices as they are mostly pseudo device and hotplug framework deals with state machine and not managed through the cpu device. This often results in annoying warning when resuming: Enabling non-boot CPUs ... CPU1: Booted secondary processor cache: parent cpu1 should not be sleeping CPU1 is up CPU2: Booted secondary processor cache: parent cpu2 should not be sleeping CPU2 is up .... and so on. So in order to fix these kind of errors, we could just completely avoid doing any power management related initialisations and operations if they are not used by these devices. Add no_pm flags to indicate that the device doesn't require any sort of PM activities and all of them can be completely skipped. We can use the same flag to also avoid adding not used *power* sysfs entries for these devices. For now, lets use this for cpu cache devices. Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Eugeniu Rosca <erosca@de.adit-jv.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
4a0fa9f9fd
commit
85945c28b5
|
@ -427,6 +427,7 @@ __cpu_device_create(struct device *parent, void *drvdata,
|
|||
dev->parent = parent;
|
||||
dev->groups = groups;
|
||||
dev->release = device_create_release;
|
||||
device_set_pm_not_required(dev);
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
|
||||
|
|
|
@ -124,6 +124,10 @@ void device_pm_unlock(void)
|
|||
*/
|
||||
void device_pm_add(struct device *dev)
|
||||
{
|
||||
/* Skip PM setup/initialization. */
|
||||
if (device_pm_not_required(dev))
|
||||
return;
|
||||
|
||||
pr_debug("PM: Adding info for %s:%s\n",
|
||||
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
|
||||
device_pm_check_callbacks(dev);
|
||||
|
@ -142,6 +146,9 @@ void device_pm_add(struct device *dev)
|
|||
*/
|
||||
void device_pm_remove(struct device *dev)
|
||||
{
|
||||
if (device_pm_not_required(dev))
|
||||
return;
|
||||
|
||||
pr_debug("PM: Removing info for %s:%s\n",
|
||||
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
|
||||
complete_all(&dev->power.completion);
|
||||
|
|
|
@ -653,6 +653,10 @@ int dpm_sysfs_add(struct device *dev)
|
|||
{
|
||||
int rc;
|
||||
|
||||
/* No need to create PM sysfs if explicitly disabled. */
|
||||
if (device_pm_not_required(dev))
|
||||
return 0;
|
||||
|
||||
rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -732,6 +736,8 @@ void rpm_sysfs_remove(struct device *dev)
|
|||
|
||||
void dpm_sysfs_remove(struct device *dev)
|
||||
{
|
||||
if (device_pm_not_required(dev))
|
||||
return;
|
||||
sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
|
||||
dev_pm_qos_constraints_destroy(dev);
|
||||
rpm_sysfs_remove(dev);
|
||||
|
|
|
@ -1165,6 +1165,16 @@ static inline bool device_async_suspend_enabled(struct device *dev)
|
|||
return !!dev->power.async_suspend;
|
||||
}
|
||||
|
||||
static inline bool device_pm_not_required(struct device *dev)
|
||||
{
|
||||
return dev->power.no_pm;
|
||||
}
|
||||
|
||||
static inline void device_set_pm_not_required(struct device *dev)
|
||||
{
|
||||
dev->power.no_pm = true;
|
||||
}
|
||||
|
||||
static inline void dev_pm_syscore_device(struct device *dev, bool val)
|
||||
{
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
@ -592,6 +592,7 @@ struct dev_pm_info {
|
|||
bool is_suspended:1; /* Ditto */
|
||||
bool is_noirq_suspended:1;
|
||||
bool is_late_suspended:1;
|
||||
bool no_pm:1;
|
||||
bool early_init:1; /* Owned by the PM core */
|
||||
bool direct_complete:1; /* Owned by the PM core */
|
||||
u32 driver_flags;
|
||||
|
|
Loading…
Reference in New Issue