Skip to content

Commit 0679963

Browse files
committed
PM: sleep: Make async suspend handle suppliers like parents
Avoid starting "async" suspend processing upfront for devices that have consumers and start "async" suspend processing for a device's suppliers right after suspending the device itself. Suggested-by: Saravana Kannan <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Ulf Hansson <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent ed18738 commit 0679963

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

drivers/base/power/main.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,10 +1276,15 @@ static bool dpm_leaf_device(struct device *dev)
12761276
return false;
12771277
}
12781278

1279-
return true;
1279+
/*
1280+
* Since this function is required to run under dpm_list_mtx, the
1281+
* list_empty() below will only return true if the device's list of
1282+
* consumers is actually empty before calling it.
1283+
*/
1284+
return list_empty(&dev->links.consumers);
12801285
}
12811286

1282-
static void dpm_async_suspend_parent(struct device *dev, async_func_t func)
1287+
static bool dpm_async_suspend_parent(struct device *dev, async_func_t func)
12831288
{
12841289
guard(mutex)(&dpm_list_mtx);
12851290

@@ -1291,11 +1296,31 @@ static void dpm_async_suspend_parent(struct device *dev, async_func_t func)
12911296
* deleted before it.
12921297
*/
12931298
if (!device_pm_initialized(dev))
1294-
return;
1299+
return false;
12951300

12961301
/* Start processing the device's parent if it is "async". */
12971302
if (dev->parent)
12981303
dpm_async_with_cleanup(dev->parent, func);
1304+
1305+
return true;
1306+
}
1307+
1308+
static void dpm_async_suspend_superior(struct device *dev, async_func_t func)
1309+
{
1310+
struct device_link *link;
1311+
int idx;
1312+
1313+
if (!dpm_async_suspend_parent(dev, func))
1314+
return;
1315+
1316+
idx = device_links_read_lock();
1317+
1318+
/* Start processing the device's "async" suppliers. */
1319+
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
1320+
if (READ_ONCE(link->status) != DL_STATE_DORMANT)
1321+
dpm_async_with_cleanup(link->supplier, func);
1322+
1323+
device_links_read_unlock(idx);
12991324
}
13001325

13011326
/**
@@ -1419,7 +1444,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state, bool asy
14191444
if (error || async_error)
14201445
return error;
14211446

1422-
dpm_async_suspend_parent(dev, async_suspend_noirq);
1447+
dpm_async_suspend_superior(dev, async_suspend_noirq);
14231448

14241449
return 0;
14251450
}
@@ -1615,7 +1640,7 @@ static int device_suspend_late(struct device *dev, pm_message_t state, bool asyn
16151640
if (error || async_error)
16161641
return error;
16171642

1618-
dpm_async_suspend_parent(dev, async_suspend_late);
1643+
dpm_async_suspend_superior(dev, async_suspend_late);
16191644

16201645
return 0;
16211646
}
@@ -1906,7 +1931,7 @@ static int device_suspend(struct device *dev, pm_message_t state, bool async)
19061931
if (error || async_error)
19071932
return error;
19081933

1909-
dpm_async_suspend_parent(dev, async_suspend);
1934+
dpm_async_suspend_superior(dev, async_suspend);
19101935

19111936
return 0;
19121937
}

0 commit comments

Comments
 (0)