mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ASoC: soc-core: Don't fail if device_link could not be created
@ 2026-06-23 13:58 Richard Fitzgerald
  2026-06-24 12:01 ` Mark Brown
  0 siblings, 1 reply; 2+ messages in thread
From: Richard Fitzgerald @ 2026-06-23 13:58 UTC (permalink / raw)
  To: broonie
  Cc: linux-sound, linux-kernel, patches, m.szyprowski, mripard,
	dave.stevenson, linux-rpi-kernel, florian.fainelli

If device_link_add() fails in snd_soc_bind_card() just skip that
driver pair and carry on.

This means that ASoC must now keep track of which components it was
able to device_link to the card->dev. The new card_device_link member
of struct snd_soc_component is non-NULL if a device_link exists.

The intent of the device link is to ensure that the machine driver
system-suspends before the component drivers, to prevent ASoC
suspend attempting to reconfigure a driver that has already suspended.

It isn't possible to create this device link if the machine driver is
a parent of the component driver or already has a device_link in the
opposite direction. In this case skip the link. A warn is placed in
kernel log since this might indicate a genuine design problem with
those two drivers (this can be downgraded to dbg in future when
people are happy that all these special drivers correctly handle their
reversed shutdown order).

Fixes: 0f54ce994b23 ("ASoC: soc-core: Create device_link to ensure correct suspend order")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/linux-sound/61bd38e7-5eb9-4448-a93f-afa2ccbd1c9d@opensource.cirrus.com/T/#m496fe5a11b0a3649afd2e85da5e1cea82bb16d8a
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
 include/sound/soc-component.h |  4 ++++
 sound/soc/soc-core.c          | 35 +++++++++++++++--------------------
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 11bc9527653f..aa423865dbe7 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -10,6 +10,8 @@
 
 #include <sound/soc.h>
 
+struct device_link;
+
 /*
  * Component probe and remove ordering levels for components with runtime
  * dependencies.
@@ -216,6 +218,8 @@ struct snd_soc_component {
 	struct list_head card_aux_list; /* for auxiliary bound components */
 	struct list_head card_list;
 
+	struct device_link *card_device_link;
+
 	const struct snd_soc_component_driver *driver;
 
 	struct list_head dai_list;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 86b6c752a56b..7817beea5b3b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1980,19 +1980,15 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card)
 	}
 }
 
-static void snd_soc_remove_device_links(struct snd_soc_card *card,
-					struct snd_soc_component *stop_at)
+static void snd_soc_remove_device_links(struct snd_soc_card *card)
 {
 	struct snd_soc_component *component;
 
 	for_each_card_components(card, component) {
-		if (card->dev == component->dev)
-			continue;
-
-		device_link_remove(card->dev, component->dev);
-
-		if (component == stop_at)
-			return;
+		if (component->card_device_link) {
+			device_link_del(component->card_device_link);
+			component->card_device_link = NULL;
+		}
 	}
 }
 
@@ -2001,7 +1997,7 @@ static void snd_soc_unbind_card(struct snd_soc_card *card)
 	if (snd_soc_card_is_instantiated(card)) {
 		card->instantiated = false;
 
-		snd_soc_remove_device_links(card, NULL);
+		snd_soc_remove_device_links(card);
 
 		soc_cleanup_card_resources(card);
 	}
@@ -2012,7 +2008,6 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
 	struct snd_soc_pcm_runtime *rtd;
 	struct snd_soc_component *component;
 	struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
-	struct snd_soc_component *last_devlinked_component = NULL;
 	int ret;
 
 	snd_soc_card_mutex_lock_root(card);
@@ -2141,19 +2136,21 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
 	 * Add device_link from card to component so that system_suspend
 	 * will be done in the correct order. The card must suspend first
 	 * to stop audio activity before the components suspend.
+	 *
+	 * If a driver pair already have a link in the opposite direction
+	 * they must manage their own suspend order.
 	 */
 	for_each_card_components(card, component) {
 		if (card->dev == component->dev)
 			continue;
 
-		if (!device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) {
-			dev_warn(card->dev, "Failed to create device link to %s\n",
+		component->card_device_link = device_link_add(card->dev,
+							      component->dev,
+							      DL_FLAG_STATELESS);
+		if (!component->card_device_link) {
+			dev_warn(card->dev, "Could not create device link to %s\n",
 				 dev_name(component->dev));
-			ret = -EINVAL;
-			goto probe_end;
 		}
-
-		last_devlinked_component = component;
 	}
 
 	ret = snd_soc_card_late_probe(card);
@@ -2185,9 +2182,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
 
 probe_end:
 	if (ret < 0) {
-		if (last_devlinked_component)
-			snd_soc_remove_device_links(card, last_devlinked_component);
-
+		snd_soc_remove_device_links(card);
 		soc_cleanup_card_resources(card);
 	}
 
-- 
2.47.3


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-06-24 15:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-23 13:58 [PATCH] ASoC: soc-core: Don't fail if device_link could not be created Richard Fitzgerald
2026-06-24 12:01 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®