Skip to content

Commit 632d310

Browse files
ppetter1025rafaeljw
authored andcommitted
PM: sleep: Do not wait on SYNC_STATE_ONLY device links
Device links with DL_FLAG_SYNC_STATE_ONLY should not affect system suspend and resume, and functions like device_reorder_to_tail() and device_link_add() don't try to reorder the consumers with that flag. However, dpm_wait_for_consumers() and dpm_wait_for_suppliers() don't check thas flag before triggering dpm_wait(), leading to potential hang during suspend/resume. This can be reproduced on MT8186 Corsola Chromebook with devicetree like: usb-a-connector { compatible = "usb-a-connector"; port { usb_a_con: endpoint { remote-endpoint = <&usb_hs>; }; }; }; usb_host { compatible = "mediatek,mt8186-xhci", "mediatek,mtk-xhci"; port { usb_hs: endpoint { remote-endpoint = <&usb_a_con>; }; }; }; In this case, the two nodes form a cycle and a SYNC_STATE_ONLY devlink between usb_host (supplier) and usb-a-connector (consumer) is created. Address this by exporting device_link_flag_is_sync_state_only() and making dpm_wait_for_consumers() and dpm_wait_for_suppliers() use it when deciding if dpm_wait() should be called. Fixes: 05ef983 ("driver core: Add device link support for SYNC_STATE_ONLY flag") Signed-off-by: Pin-yen Lin <treapking@chromium.org> Link: https://patch.msgid.link/20250926102320.4053167-1-treapking@chromium.org [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 3ce3f56 commit 632d310

3 files changed

Lines changed: 6 additions & 3 deletions

File tree

drivers/base/base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ void device_links_driver_cleanup(struct device *dev);
248248
void device_links_no_driver(struct device *dev);
249249
bool device_links_busy(struct device *dev);
250250
void device_links_unbind_consumers(struct device *dev);
251+
bool device_link_flag_is_sync_state_only(u32 flags);
251252
void fw_devlink_drivers_done(void);
252253
void fw_devlink_probing_done(void);
253254

drivers/base/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ static bool device_is_ancestor(struct device *dev, struct device *target)
287287
#define DL_MARKER_FLAGS (DL_FLAG_INFERRED | \
288288
DL_FLAG_CYCLE | \
289289
DL_FLAG_MANAGED)
290-
static inline bool device_link_flag_is_sync_state_only(u32 flags)
290+
bool device_link_flag_is_sync_state_only(u32 flags)
291291
{
292292
return (flags & ~DL_MARKER_FLAGS) == DL_FLAG_SYNC_STATE_ONLY;
293293
}

drivers/base/power/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async)
278278
* walking.
279279
*/
280280
dev_for_each_link_to_supplier(link, dev)
281-
if (READ_ONCE(link->status) != DL_STATE_DORMANT)
281+
if (READ_ONCE(link->status) != DL_STATE_DORMANT &&
282+
!device_link_flag_is_sync_state_only(link->flags))
282283
dpm_wait(link->supplier, async);
283284

284285
device_links_read_unlock(idx);
@@ -335,7 +336,8 @@ static void dpm_wait_for_consumers(struct device *dev, bool async)
335336
* unregistration).
336337
*/
337338
dev_for_each_link_to_consumer(link, dev)
338-
if (READ_ONCE(link->status) != DL_STATE_DORMANT)
339+
if (READ_ONCE(link->status) != DL_STATE_DORMANT &&
340+
!device_link_flag_is_sync_state_only(link->flags))
339341
dpm_wait(link->consumer, async);
340342

341343
device_links_read_unlock(idx);

0 commit comments

Comments
 (0)