diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index c16b58adbdfe1f15089bce16ed9e30a30714ee8c..68d45e2e2cd48761a91dd585de09adaf983e9013 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -420,6 +420,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); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index fe7506aae13ca1ea7c7d09500398ba968768d45d..6dbc19de3ac6deda0aba1695165733631bfb7df1 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -123,6 +123,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); @@ -141,6 +145,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); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 63375f80e241ef6c7aa4084ae458adca8b4cd6f7..c3aaa32299986cfee4cc34f6d64518f8600729aa 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -681,6 +681,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; @@ -760,6 +764,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); diff --git a/include/linux/device.h b/include/linux/device.h index 2bcd6f4974b999795cb5763796905b17b8f34727..2c2c2aee89946749c8c4f3ed3aa8ce901c447b43 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1214,6 +1214,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 diff --git a/include/linux/pm.h b/include/linux/pm.h index e723b78d835706f2af7e06dc2e0379e9406a981c..e573f956ed8bc47678150dcea1a16baf4767e281 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -591,6 +591,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;