|
40 | 40 |
|
41 | 41 | typedef int (*pm_callback_t)(struct device *); |
42 | 42 |
|
43 | | -#define list_for_each_entry_rcu_locked(pos, head, member) \ |
44 | | - list_for_each_entry_rcu(pos, head, member, \ |
45 | | - device_links_read_lock_held()) |
46 | | - |
47 | 43 | /* |
48 | 44 | * The entries in the dpm_list list are in a depth first order, simply |
49 | 45 | * because children are guaranteed to be discovered after parents, and |
@@ -281,7 +277,7 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async) |
281 | 277 | * callbacks freeing the link objects for the links in the list we're |
282 | 278 | * walking. |
283 | 279 | */ |
284 | | - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) |
| 280 | + dev_for_each_link_to_supplier(link, dev) |
285 | 281 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
286 | 282 | dpm_wait(link->supplier, async); |
287 | 283 |
|
@@ -338,7 +334,7 @@ static void dpm_wait_for_consumers(struct device *dev, bool async) |
338 | 334 | * continue instead of trying to continue in parallel with its |
339 | 335 | * unregistration). |
340 | 336 | */ |
341 | | - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) |
| 337 | + dev_for_each_link_to_consumer(link, dev) |
342 | 338 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
343 | 339 | dpm_wait(link->consumer, async); |
344 | 340 |
|
@@ -675,7 +671,7 @@ static void dpm_async_resume_subordinate(struct device *dev, async_func_t func) |
675 | 671 | idx = device_links_read_lock(); |
676 | 672 |
|
677 | 673 | /* Start processing the device's "async" consumers. */ |
678 | | - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) |
| 674 | + dev_for_each_link_to_consumer(link, dev) |
679 | 675 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
680 | 676 | dpm_async_with_cleanup(link->consumer, func); |
681 | 677 |
|
@@ -724,8 +720,20 @@ static void device_resume_noirq(struct device *dev, pm_message_t state, bool asy |
724 | 720 | if (dev->power.syscore || dev->power.direct_complete) |
725 | 721 | goto Out; |
726 | 722 |
|
727 | | - if (!dev->power.is_noirq_suspended) |
| 723 | + if (!dev->power.is_noirq_suspended) { |
| 724 | + /* |
| 725 | + * This means that system suspend has been aborted in the noirq |
| 726 | + * phase before invoking the noirq suspend callback for the |
| 727 | + * device, so if device_suspend_late() has left it in suspend, |
| 728 | + * device_resume_early() should leave it in suspend either in |
| 729 | + * case the early resume of it depends on the noirq resume that |
| 730 | + * has not run. |
| 731 | + */ |
| 732 | + if (dev_pm_skip_suspend(dev)) |
| 733 | + dev->power.must_resume = false; |
| 734 | + |
728 | 735 | goto Out; |
| 736 | + } |
729 | 737 |
|
730 | 738 | if (!dpm_wait_for_superior(dev, async)) |
731 | 739 | goto Out; |
@@ -1330,7 +1338,7 @@ static void dpm_async_suspend_superior(struct device *dev, async_func_t func) |
1330 | 1338 | idx = device_links_read_lock(); |
1331 | 1339 |
|
1332 | 1340 | /* Start processing the device's "async" suppliers. */ |
1333 | | - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) |
| 1341 | + dev_for_each_link_to_supplier(link, dev) |
1334 | 1342 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
1335 | 1343 | dpm_async_with_cleanup(link->supplier, func); |
1336 | 1344 |
|
@@ -1384,7 +1392,7 @@ static void dpm_superior_set_must_resume(struct device *dev) |
1384 | 1392 |
|
1385 | 1393 | idx = device_links_read_lock(); |
1386 | 1394 |
|
1387 | | - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) |
| 1395 | + dev_for_each_link_to_supplier(link, dev) |
1388 | 1396 | link->supplier->power.must_resume = true; |
1389 | 1397 |
|
1390 | 1398 | device_links_read_unlock(idx); |
@@ -1813,7 +1821,7 @@ static void dpm_clear_superiors_direct_complete(struct device *dev) |
1813 | 1821 |
|
1814 | 1822 | idx = device_links_read_lock(); |
1815 | 1823 |
|
1816 | | - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { |
| 1824 | + dev_for_each_link_to_supplier(link, dev) { |
1817 | 1825 | spin_lock_irq(&link->supplier->power.lock); |
1818 | 1826 | link->supplier->power.direct_complete = false; |
1819 | 1827 | spin_unlock_irq(&link->supplier->power.lock); |
@@ -2065,7 +2073,7 @@ static bool device_prepare_smart_suspend(struct device *dev) |
2065 | 2073 |
|
2066 | 2074 | idx = device_links_read_lock(); |
2067 | 2075 |
|
2068 | | - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { |
| 2076 | + dev_for_each_link_to_supplier(link, dev) { |
2069 | 2077 | if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) |
2070 | 2078 | continue; |
2071 | 2079 |
|
|
0 commit comments