Power management fixes for 5.19-rc6
- Fix NULL pointer dereference related to printing a diagnostic message in the exynos-bus devfreq driver (Christian Marangi). - Fix race condition in the runtime PM framework which in some cases may cause a supplier device to be suspended when its consumer is still active (Rafael Wysocki). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmLIgKMSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxNgAP/R4t7jx+LyeQbX9JzdY/bA6NTGIdkMbJ RhA9Nc3Sbsb+KXulsccq108O4CZwjiCEngvZHkOJJtzgRzLL7jxV6J63tNfLLS60 oJS4EAOAZ0c1JiO/Fh9G/c6stKdPAajs4PNSHpGcsq8m1e8CktmWPqW40OPD6kDk YbkdMkO/7KJtOBX4IwzF67lYMQsulUGi2TAsq6sxsC00KA2A1CoXTWzoamDKtOD3 8y5JKKRCg7nYhZ7/qxy1zlnhHFJGzVppWbSv98DdZdvsKyizAkk7agBOP4Ld3iPT ZtA1L0Pgjx6qUoQ7D7rUgNrmnHGCk77aluAkg/gtS2GI61bvbtT3apyYusJVC0jg IKI3MHZZTwqdsEyoBxxWXuRciv1HXXrcwSMB3S9pBAwZEES+GwDFO9MwStkAv8zi acceNirUiawODs6qNZjS8Ycsaz56DHCjcsBBCvmP5NnNA8kFdqxB4muz1SRmqubE N9BPNDLFCoZArUkwg35QL9EZZLYjLjf5YtF9Xe3lPCaQdbPaIc+4MfXkEp4HHYC3 V1vvbyZbkq/xSNNCjXRoF4n1x2IZvz7SpsdPjxqADpVNxpL/d/dET8/NBXGxAwJE KLh/iElyuIL17mgqH/fXpYNI6bqphxhe+sasH/nFpKOewdEQDtnYqmz6GQQGH469 /42eiBC4saNB =iyaY -----END PGP SIGNATURE----- Merge tag 'pm-5.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management fixes from Rafael Wysocki: "These fix a NULL pointer dereference in a devfreq driver and a runtime PM framework issue that may cause a supplier device to be suspended before its consumer. Specifics: - Fix NULL pointer dereference related to printing a diagnostic message in the exynos-bus devfreq driver (Christian Marangi) - Fix race condition in the runtime PM framework which in some cases may cause a supplier device to be suspended when its consumer is still active (Rafael Wysocki)" * tag 'pm-5.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM / devfreq: exynos-bus: Fix NULL pointer dereference PM: runtime: Fix supplier device management during consumer probe PM: runtime: Redefine pm_runtime_release_supplier()
This commit is contained in:
commit
3784fad934
@ -486,7 +486,18 @@ static void device_link_release_fn(struct work_struct *work)
|
||||
/* Ensure that all references to the link object have been dropped. */
|
||||
device_link_synchronize_removal();
|
||||
|
||||
pm_runtime_release_supplier(link, true);
|
||||
pm_runtime_release_supplier(link);
|
||||
/*
|
||||
* If supplier_preactivated is set, the link has been dropped between
|
||||
* the pm_runtime_get_suppliers() and pm_runtime_put_suppliers() calls
|
||||
* in __driver_probe_device(). In that case, drop the supplier's
|
||||
* PM-runtime usage counter to remove the reference taken by
|
||||
* pm_runtime_get_suppliers().
|
||||
*/
|
||||
if (link->supplier_preactivated)
|
||||
pm_runtime_put_noidle(link->supplier);
|
||||
|
||||
pm_request_idle(link->supplier);
|
||||
|
||||
put_device(link->consumer);
|
||||
put_device(link->supplier);
|
||||
|
@ -308,13 +308,10 @@ static int rpm_get_suppliers(struct device *dev)
|
||||
/**
|
||||
* pm_runtime_release_supplier - Drop references to device link's supplier.
|
||||
* @link: Target device link.
|
||||
* @check_idle: Whether or not to check if the supplier device is idle.
|
||||
*
|
||||
* Drop all runtime PM references associated with @link to its supplier device
|
||||
* and if @check_idle is set, check if that device is idle (and so it can be
|
||||
* suspended).
|
||||
* Drop all runtime PM references associated with @link to its supplier device.
|
||||
*/
|
||||
void pm_runtime_release_supplier(struct device_link *link, bool check_idle)
|
||||
void pm_runtime_release_supplier(struct device_link *link)
|
||||
{
|
||||
struct device *supplier = link->supplier;
|
||||
|
||||
@ -327,9 +324,6 @@ void pm_runtime_release_supplier(struct device_link *link, bool check_idle)
|
||||
while (refcount_dec_not_one(&link->rpm_active) &&
|
||||
atomic_read(&supplier->power.usage_count) > 0)
|
||||
pm_runtime_put_noidle(supplier);
|
||||
|
||||
if (check_idle)
|
||||
pm_request_idle(supplier);
|
||||
}
|
||||
|
||||
static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
|
||||
@ -337,8 +331,11 @@ static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
|
||||
struct device_link *link;
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
|
||||
device_links_read_lock_held())
|
||||
pm_runtime_release_supplier(link, try_to_suspend);
|
||||
device_links_read_lock_held()) {
|
||||
pm_runtime_release_supplier(link);
|
||||
if (try_to_suspend)
|
||||
pm_request_idle(link->supplier);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpm_put_suppliers(struct device *dev)
|
||||
@ -1771,7 +1768,6 @@ void pm_runtime_get_suppliers(struct device *dev)
|
||||
if (link->flags & DL_FLAG_PM_RUNTIME) {
|
||||
link->supplier_preactivated = true;
|
||||
pm_runtime_get_sync(link->supplier);
|
||||
refcount_inc(&link->rpm_active);
|
||||
}
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
@ -1791,19 +1787,8 @@ void pm_runtime_put_suppliers(struct device *dev)
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
|
||||
device_links_read_lock_held())
|
||||
if (link->supplier_preactivated) {
|
||||
bool put;
|
||||
|
||||
link->supplier_preactivated = false;
|
||||
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
|
||||
put = pm_runtime_status_suspended(dev) &&
|
||||
refcount_dec_not_one(&link->rpm_active);
|
||||
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
|
||||
if (put)
|
||||
pm_runtime_put(link->supplier);
|
||||
pm_runtime_put(link->supplier);
|
||||
}
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
@ -1838,7 +1823,8 @@ void pm_runtime_drop_link(struct device_link *link)
|
||||
return;
|
||||
|
||||
pm_runtime_drop_link_count(link->consumer);
|
||||
pm_runtime_release_supplier(link, true);
|
||||
pm_runtime_release_supplier(link);
|
||||
pm_request_idle(link->supplier);
|
||||
}
|
||||
|
||||
static bool pm_runtime_need_not_resume(struct device *dev)
|
||||
|
@ -447,9 +447,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
max_state = bus->devfreq->profile->max_state;
|
||||
min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
|
||||
max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
|
||||
max_state = bus->devfreq->max_state;
|
||||
min_freq = (bus->devfreq->freq_table[0] / 1000);
|
||||
max_freq = (bus->devfreq->freq_table[max_state - 1] / 1000);
|
||||
pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
|
||||
dev_name(dev), min_freq, max_freq);
|
||||
|
||||
|
@ -88,7 +88,7 @@ extern void pm_runtime_get_suppliers(struct device *dev);
|
||||
extern void pm_runtime_put_suppliers(struct device *dev);
|
||||
extern void pm_runtime_new_link(struct device *dev);
|
||||
extern void pm_runtime_drop_link(struct device_link *link);
|
||||
extern void pm_runtime_release_supplier(struct device_link *link, bool check_idle);
|
||||
extern void pm_runtime_release_supplier(struct device_link *link);
|
||||
|
||||
extern int devm_pm_runtime_enable(struct device *dev);
|
||||
|
||||
@ -314,8 +314,7 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {}
|
||||
static inline void pm_runtime_put_suppliers(struct device *dev) {}
|
||||
static inline void pm_runtime_new_link(struct device *dev) {}
|
||||
static inline void pm_runtime_drop_link(struct device_link *link) {}
|
||||
static inline void pm_runtime_release_supplier(struct device_link *link,
|
||||
bool check_idle) {}
|
||||
static inline void pm_runtime_release_supplier(struct device_link *link) {}
|
||||
|
||||
#endif /* !CONFIG_PM */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user