Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Add more devm_ functions to fix PM imbalance in

Merge series from Bence Csókás <csokas.bence@prolan.hu>:

The probe() function of the atmel-quadspi driver got quite convoluted,
especially since the addition of SAMA7G5 support, that was forward-ported
from an older vendor kernel. During the port, a bug was introduced, where
the PM get() and put() calls were imbalanced. To alleivate this - and
similar problems in the future - an effort was made to migrate as many
functions as possible, to their devm_ managed counterparts. The few
functions, which did not yet have a devm_ variant, are added in patch 1 of
this series. Patch 2 then uses these APIs to fix the probe() function.

Mark Brown d43eef53 a4ca0245

+52 -13
+44
drivers/base/power/runtime.c
··· 1568 1568 } 1569 1569 EXPORT_SYMBOL_GPL(pm_runtime_enable); 1570 1570 1571 + static void pm_runtime_set_suspended_action(void *data) 1572 + { 1573 + pm_runtime_set_suspended(data); 1574 + } 1575 + 1576 + /** 1577 + * devm_pm_runtime_set_active_enabled - set_active version of devm_pm_runtime_enable. 1578 + * 1579 + * @dev: Device to handle. 1580 + */ 1581 + int devm_pm_runtime_set_active_enabled(struct device *dev) 1582 + { 1583 + int err; 1584 + 1585 + err = pm_runtime_set_active(dev); 1586 + if (err) 1587 + return err; 1588 + 1589 + err = devm_add_action_or_reset(dev, pm_runtime_set_suspended_action, dev); 1590 + if (err) 1591 + return err; 1592 + 1593 + return devm_pm_runtime_enable(dev); 1594 + } 1595 + EXPORT_SYMBOL_GPL(devm_pm_runtime_set_active_enabled); 1596 + 1571 1597 static void pm_runtime_disable_action(void *data) 1572 1598 { 1573 1599 pm_runtime_dont_use_autosuspend(data); ··· 1615 1589 return devm_add_action_or_reset(dev, pm_runtime_disable_action, dev); 1616 1590 } 1617 1591 EXPORT_SYMBOL_GPL(devm_pm_runtime_enable); 1592 + 1593 + static void pm_runtime_put_noidle_action(void *data) 1594 + { 1595 + pm_runtime_put_noidle(data); 1596 + } 1597 + 1598 + /** 1599 + * devm_pm_runtime_get_noresume - devres-enabled version of pm_runtime_get_noresume. 1600 + * 1601 + * @dev: Device to handle. 1602 + */ 1603 + int devm_pm_runtime_get_noresume(struct device *dev) 1604 + { 1605 + pm_runtime_get_noresume(dev); 1606 + 1607 + return devm_add_action_or_reset(dev, pm_runtime_put_noidle_action, dev); 1608 + } 1609 + EXPORT_SYMBOL_GPL(devm_pm_runtime_get_noresume); 1618 1610 1619 1611 /** 1620 1612 * pm_runtime_forbid - Block runtime PM of a device.
+4 -13
drivers/spi/atmel-quadspi.c
··· 1437 1437 1438 1438 pm_runtime_set_autosuspend_delay(&pdev->dev, 500); 1439 1439 pm_runtime_use_autosuspend(&pdev->dev); 1440 - pm_runtime_set_active(&pdev->dev); 1441 - pm_runtime_enable(&pdev->dev); 1442 - pm_runtime_get_noresume(&pdev->dev); 1440 + devm_pm_runtime_set_active_enabled(&pdev->dev); 1441 + devm_pm_runtime_get_noresume(&pdev->dev); 1443 1442 1444 1443 err = atmel_qspi_init(aq); 1445 1444 if (err) 1446 1445 goto dma_release; 1447 1446 1448 1447 err = spi_register_controller(ctrl); 1449 - if (err) { 1450 - pm_runtime_put_noidle(&pdev->dev); 1451 - pm_runtime_disable(&pdev->dev); 1452 - pm_runtime_set_suspended(&pdev->dev); 1453 - pm_runtime_dont_use_autosuspend(&pdev->dev); 1448 + if (err) 1454 1449 goto dma_release; 1455 - } 1450 + 1456 1451 pm_runtime_mark_last_busy(&pdev->dev); 1457 1452 pm_runtime_put_autosuspend(&pdev->dev); 1458 1453 ··· 1526 1531 */ 1527 1532 dev_warn(&pdev->dev, "Failed to resume device on remove\n"); 1528 1533 } 1529 - 1530 - pm_runtime_disable(&pdev->dev); 1531 - pm_runtime_dont_use_autosuspend(&pdev->dev); 1532 - pm_runtime_put_noidle(&pdev->dev); 1533 1534 } 1534 1535 1535 1536 static int __maybe_unused atmel_qspi_suspend(struct device *dev)
+4
include/linux/pm_runtime.h
··· 96 96 extern void pm_runtime_drop_link(struct device_link *link); 97 97 extern void pm_runtime_release_supplier(struct device_link *link); 98 98 99 + int devm_pm_runtime_set_active_enabled(struct device *dev); 99 100 extern int devm_pm_runtime_enable(struct device *dev); 101 + int devm_pm_runtime_get_noresume(struct device *dev); 100 102 101 103 /** 102 104 * pm_suspend_ignore_children - Set runtime PM behavior regarding children. ··· 296 294 static inline void pm_runtime_allow(struct device *dev) {} 297 295 static inline void pm_runtime_forbid(struct device *dev) {} 298 296 297 + static inline int devm_pm_runtime_set_active_enabled(struct device *dev) { return 0; } 299 298 static inline int devm_pm_runtime_enable(struct device *dev) { return 0; } 299 + static inline int devm_pm_runtime_get_noresume(struct device *dev) { return 0; } 300 300 301 301 static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {} 302 302 static inline void pm_runtime_get_noresume(struct device *dev) {}