* [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
@ 2026-06-11 11:08 Richard Fitzgerald
2026-06-11 19:38 ` Mark Brown
[not found] ` <CGME20260617141046eucas1p2e85629d57bfc17449b135b16f9230d57@eucas1p2.samsung.com>
0 siblings, 2 replies; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-11 11:08 UTC (permalink / raw)
To: broonie; +Cc: linux-sound, linux-kernel, patches
In snd_soc_bind_card() create a device_link from card to all components
to ensure correct order of system_suspend. The card is the consumer and
the components are the supplier, so that the card will system_suspend
before any of the components.
The PM core will normally system_suspend drivers in the opposite order
that they registered. This ensures children are suspended before their
parents, for example users of a bus driver should suspend before the bus
driver suspends.
For ASoC, snd_soc_suspend() shuts down any active audio, which requires
that the components are still able to communicate with their hardware.
Previously there was nothing to ensure this ordering, because there is
(usually) no relationship between a machine driver and component drivers.
If the machine driver registered before the codec drivers, the codec
drivers would be suspended before the machine driver snd_soc_suspend()
runs, so that ASoC is attempting to stop audio on a driver that has
already suspended.
Creating a device_link is safe if there is already a device_link between
those devices because of multiple components sharing the same dev.
device_link_add() kernel doc says:
"if a device link between the given @consumer and @supplier pair
exists already when this function is called for them, the existing link
will be returned regardless of its current type and status ...
The caller of this function is then expected to treat
the link as though it has just been created, so (in particular) if
DL_FLAG_STATELESS was passed in @flags, the link needs to be released
explicitly when not needed any more"
For the same reason it is safe if the codec driver or machine driver
later call device_link_add() to create a link between the same two
devices.
(I have tested creating multiple links between the card->dev and a
component->dev and did not encounter any problems with suspend/resume or
module unloading.)
The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
the probe() function of that device. This isn't guaranteed in ASoC card
binding because of deferred binding. The exact behavior and consequences
of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
So DL_FLAG_STATELESS is used for safety, and the links are removed
explicitly when the card unbinds or if the bind fails.
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
for-next
Changes in V2:
- Use DL_FLAG_STATELESS to avoid unclear/unstated behavior of the
DL_FLAG_AUTOREMOVE_* flags.
- Skip creating a device link for a component that is the same device
as the card.
sound/soc/soc-core.c | 46 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b8c9ddfc4490..ac9b2269c26e 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2138,10 +2138,29 @@ 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)
+{
+ 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;
+ }
+}
+
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);
+
soc_cleanup_card_resources(card);
}
}
@@ -2151,6 +2170,7 @@ 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);
@@ -2275,6 +2295,25 @@ 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.
+ */
+ 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",
+ dev_name(component->dev));
+ ret = -EINVAL;
+ goto probe_end;
+ }
+
+ last_devlinked_component = component;
+ }
+
ret = snd_soc_card_late_probe(card);
if (ret < 0)
goto probe_end;
@@ -2303,8 +2342,13 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
pinctrl_pm_select_sleep_state(component->dev);
probe_end:
- if (ret < 0)
+ if (ret < 0) {
+ if (last_devlinked_component)
+ snd_soc_remove_device_links(card, last_devlinked_component);
+
soc_cleanup_card_resources(card);
+ }
+
if (ret == -EPROBE_DEFER) {
list_add(&card->list, &unbind_card_list);
ret = 0;
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-11 11:08 [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order Richard Fitzgerald
@ 2026-06-11 19:38 ` Mark Brown
[not found] ` <CGME20260617141046eucas1p2e85629d57bfc17449b135b16f9230d57@eucas1p2.samsung.com>
1 sibling, 0 replies; 16+ messages in thread
From: Mark Brown @ 2026-06-11 19:38 UTC (permalink / raw)
To: Richard Fitzgerald; +Cc: linux-sound, linux-kernel, patches
On Thu, 11 Jun 2026 12:08:56 +0100, Richard Fitzgerald wrote:
> ASoC: soc-core: Create device_link to ensure correct suspend order
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2
Thanks!
[1/1] ASoC: soc-core: Create device_link to ensure correct suspend order
https://git.kernel.org/broonie/sound/c/0f54ce994b23
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 16+ messages in thread[parent not found: <CGME20260617141046eucas1p2e85629d57bfc17449b135b16f9230d57@eucas1p2.samsung.com>]
* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
[not found] ` <CGME20260617141046eucas1p2e85629d57bfc17449b135b16f9230d57@eucas1p2.samsung.com>
@ 2026-06-17 14:10 ` Marek Szyprowski
2026-06-18 11:22 ` Richard Fitzgerald
2026-06-20 15:57 ` Richard Fitzgerald
0 siblings, 2 replies; 16+ messages in thread
From: Marek Szyprowski @ 2026-06-17 14:10 UTC (permalink / raw)
To: Richard Fitzgerald, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
Dear All,
On 11.06.2026 13:08, Richard Fitzgerald wrote:
> In snd_soc_bind_card() create a device_link from card to all components
> to ensure correct order of system_suspend. The card is the consumer and
> the components are the supplier, so that the card will system_suspend
> before any of the components.
>
> The PM core will normally system_suspend drivers in the opposite order
> that they registered. This ensures children are suspended before their
> parents, for example users of a bus driver should suspend before the bus
> driver suspends.
>
> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
> that the components are still able to communicate with their hardware.
> Previously there was nothing to ensure this ordering, because there is
> (usually) no relationship between a machine driver and component drivers.
> If the machine driver registered before the codec drivers, the codec
> drivers would be suspended before the machine driver snd_soc_suspend()
> runs, so that ASoC is attempting to stop audio on a driver that has
> already suspended.
>
> Creating a device_link is safe if there is already a device_link between
> those devices because of multiple components sharing the same dev.
> device_link_add() kernel doc says:
>
> "if a device link between the given @consumer and @supplier pair
> exists already when this function is called for them, the existing link
> will be returned regardless of its current type and status ...
> The caller of this function is then expected to treat
> the link as though it has just been created, so (in particular) if
> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
> explicitly when not needed any more"
>
> For the same reason it is safe if the codec driver or machine driver
> later call device_link_add() to create a link between the same two
> devices.
>
> (I have tested creating multiple links between the card->dev and a
> component->dev and did not encounter any problems with suspend/resume or
> module unloading.)
>
> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
> the probe() function of that device. This isn't guaranteed in ASoC card
> binding because of deferred binding. The exact behavior and consequences
> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
> So DL_FLAG_STATELESS is used for safety, and the links are removed
> explicitly when the card unbinds or if the bind fails.
>
> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
> ---
This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
soc-core: Create device_link to ensure correct suspend order"). In my
tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
3 and 4 boards due to an issue with hdmi-audio-codec:
# dmesg | grep vc4
vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
vc4-drm gpu: adev bind failed: -22
vc4-drm gpu: probe with driver vc4-drm failed with error -22
> for-next
>
> Changes in V2:
> - Use DL_FLAG_STATELESS to avoid unclear/unstated behavior of the
> DL_FLAG_AUTOREMOVE_* flags.
>
> - Skip creating a device link for a component that is the same device
> as the card.
>
> sound/soc/soc-core.c | 46 +++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index b8c9ddfc4490..ac9b2269c26e 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -2138,10 +2138,29 @@ 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)
> +{
> + 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;
> + }
> +}
> +
> 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);
> +
> soc_cleanup_card_resources(card);
> }
> }
> @@ -2151,6 +2170,7 @@ 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);
> @@ -2275,6 +2295,25 @@ 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.
> + */
> + 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",
> + dev_name(component->dev));
> + ret = -EINVAL;
> + goto probe_end;
> + }
> +
> + last_devlinked_component = component;
> + }
> +
> ret = snd_soc_card_late_probe(card);
> if (ret < 0)
> goto probe_end;
> @@ -2303,8 +2342,13 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
> pinctrl_pm_select_sleep_state(component->dev);
>
> probe_end:
> - if (ret < 0)
> + if (ret < 0) {
> + if (last_devlinked_component)
> + snd_soc_remove_device_links(card, last_devlinked_component);
> +
> soc_cleanup_card_resources(card);
> + }
> +
> if (ret == -EPROBE_DEFER) {
> list_add(&card->list, &unbind_card_list);
> ret = 0;
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-17 14:10 ` Marek Szyprowski
@ 2026-06-18 11:22 ` Richard Fitzgerald
2026-06-18 12:58 ` Marek Szyprowski
2026-06-20 15:57 ` Richard Fitzgerald
1 sibling, 1 reply; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-18 11:22 UTC (permalink / raw)
To: Marek Szyprowski, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 17/6/26 15:10, Marek Szyprowski wrote:
> Dear All,
>
> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>> In snd_soc_bind_card() create a device_link from card to all components
>> to ensure correct order of system_suspend. The card is the consumer and
>> the components are the supplier, so that the card will system_suspend
>> before any of the components.
>>
>> The PM core will normally system_suspend drivers in the opposite order
>> that they registered. This ensures children are suspended before their
>> parents, for example users of a bus driver should suspend before the bus
>> driver suspends.
>>
>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>> that the components are still able to communicate with their hardware.
>> Previously there was nothing to ensure this ordering, because there is
>> (usually) no relationship between a machine driver and component drivers.
>> If the machine driver registered before the codec drivers, the codec
>> drivers would be suspended before the machine driver snd_soc_suspend()
>> runs, so that ASoC is attempting to stop audio on a driver that has
>> already suspended.
>>
>> Creating a device_link is safe if there is already a device_link between
>> those devices because of multiple components sharing the same dev.
>> device_link_add() kernel doc says:
>>
>> "if a device link between the given @consumer and @supplier pair
>> exists already when this function is called for them, the existing link
>> will be returned regardless of its current type and status ...
>> The caller of this function is then expected to treat
>> the link as though it has just been created, so (in particular) if
>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>> explicitly when not needed any more"
>>
>> For the same reason it is safe if the codec driver or machine driver
>> later call device_link_add() to create a link between the same two
>> devices.
>>
>> (I have tested creating multiple links between the card->dev and a
>> component->dev and did not encounter any problems with suspend/resume or
>> module unloading.)
>>
>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>> the probe() function of that device. This isn't guaranteed in ASoC card
>> binding because of deferred binding. The exact behavior and consequences
>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>> explicitly when the card unbinds or if the bind fails.
>>
>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>> ---
>
>
> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
> soc-core: Create device_link to ensure correct suspend order"). In my
> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
> 3 and 4 boards due to an issue with hdmi-audio-codec:
>
> # dmesg | grep vc4
> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
> vc4-drm gpu: adev bind failed: -22
> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>
Where in device_link_add() does it fail?
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-18 11:22 ` Richard Fitzgerald
@ 2026-06-18 12:58 ` Marek Szyprowski
2026-06-18 13:12 ` Marek Szyprowski
2026-06-18 13:12 ` Richard Fitzgerald
0 siblings, 2 replies; 16+ messages in thread
From: Marek Szyprowski @ 2026-06-18 12:58 UTC (permalink / raw)
To: Richard Fitzgerald, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 18.06.2026 13:22, Richard Fitzgerald wrote:
> On 17/6/26 15:10, Marek Szyprowski wrote:
>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>> In snd_soc_bind_card() create a device_link from card to all components
>>> to ensure correct order of system_suspend. The card is the consumer and
>>> the components are the supplier, so that the card will system_suspend
>>> before any of the components.
>>>
>>> The PM core will normally system_suspend drivers in the opposite order
>>> that they registered. This ensures children are suspended before their
>>> parents, for example users of a bus driver should suspend before the bus
>>> driver suspends.
>>>
>>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>>> that the components are still able to communicate with their hardware.
>>> Previously there was nothing to ensure this ordering, because there is
>>> (usually) no relationship between a machine driver and component drivers.
>>> If the machine driver registered before the codec drivers, the codec
>>> drivers would be suspended before the machine driver snd_soc_suspend()
>>> runs, so that ASoC is attempting to stop audio on a driver that has
>>> already suspended.
>>>
>>> Creating a device_link is safe if there is already a device_link between
>>> those devices because of multiple components sharing the same dev.
>>> device_link_add() kernel doc says:
>>>
>>> "if a device link between the given @consumer and @supplier pair
>>> exists already when this function is called for them, the existing link
>>> will be returned regardless of its current type and status ...
>>> The caller of this function is then expected to treat
>>> the link as though it has just been created, so (in particular) if
>>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>>> explicitly when not needed any more"
>>>
>>> For the same reason it is safe if the codec driver or machine driver
>>> later call device_link_add() to create a link between the same two
>>> devices.
>>>
>>> (I have tested creating multiple links between the card->dev and a
>>> component->dev and did not encounter any problems with suspend/resume or
>>> module unloading.)
>>>
>>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>>> the probe() function of that device. This isn't guaranteed in ASoC card
>>> binding because of deferred binding. The exact behavior and consequences
>>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>>> explicitly when the card unbinds or if the bind fails.
>>>
>>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>>> ---
>>
>>
>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>> soc-core: Create device_link to ensure correct suspend order"). In my
>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>
>> # dmesg | grep vc4
>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>> vc4-drm gpu: adev bind failed: -22
>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>
>
> Where in device_link_add() does it fail?
>
It fails the following check at drivers/base/core.c line 766:
if (!device_pm_initialized(supplier)
|| (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
device_is_dependent(consumer, supplier))) {
link = NULL;
goto out;
}
because device_is_dependent(consumer, supplier) is true for fef00700.hdmi and
hdmi-audio-codec.1.auto.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-18 12:58 ` Marek Szyprowski
@ 2026-06-18 13:12 ` Marek Szyprowski
2026-06-18 13:12 ` Richard Fitzgerald
1 sibling, 0 replies; 16+ messages in thread
From: Marek Szyprowski @ 2026-06-18 13:12 UTC (permalink / raw)
To: Richard Fitzgerald, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 18.06.2026 14:58, Marek Szyprowski wrote:
> On 18.06.2026 13:22, Richard Fitzgerald wrote:
>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>> In snd_soc_bind_card() create a device_link from card to all components
>>>> to ensure correct order of system_suspend. The card is the consumer and
>>>> the components are the supplier, so that the card will system_suspend
>>>> before any of the components.
>>>>
>>>> The PM core will normally system_suspend drivers in the opposite order
>>>> that they registered. This ensures children are suspended before their
>>>> parents, for example users of a bus driver should suspend before the bus
>>>> driver suspends.
>>>>
>>>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>>>> that the components are still able to communicate with their hardware.
>>>> Previously there was nothing to ensure this ordering, because there is
>>>> (usually) no relationship between a machine driver and component drivers.
>>>> If the machine driver registered before the codec drivers, the codec
>>>> drivers would be suspended before the machine driver snd_soc_suspend()
>>>> runs, so that ASoC is attempting to stop audio on a driver that has
>>>> already suspended.
>>>>
>>>> Creating a device_link is safe if there is already a device_link between
>>>> those devices because of multiple components sharing the same dev.
>>>> device_link_add() kernel doc says:
>>>>
>>>> "if a device link between the given @consumer and @supplier pair
>>>> exists already when this function is called for them, the existing link
>>>> will be returned regardless of its current type and status ...
>>>> The caller of this function is then expected to treat
>>>> the link as though it has just been created, so (in particular) if
>>>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>>>> explicitly when not needed any more"
>>>>
>>>> For the same reason it is safe if the codec driver or machine driver
>>>> later call device_link_add() to create a link between the same two
>>>> devices.
>>>>
>>>> (I have tested creating multiple links between the card->dev and a
>>>> component->dev and did not encounter any problems with suspend/resume or
>>>> module unloading.)
>>>>
>>>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>>>> the probe() function of that device. This isn't guaranteed in ASoC card
>>>> binding because of deferred binding. The exact behavior and consequences
>>>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>>>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>>>> explicitly when the card unbinds or if the bind fails.
>>>>
>>>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>>>> ---
>>>
>>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>>> soc-core: Create device_link to ensure correct suspend order"). In my
>>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>>
>>> # dmesg | grep vc4
>>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>>> vc4-drm gpu: adev bind failed: -22
>>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>>
>> Where in device_link_add() does it fail?
>>
> It fails the following check at drivers/base/core.c line 766:
>
> if (!device_pm_initialized(supplier)
> || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
> device_is_dependent(consumer, supplier))) {
> link = NULL;
> goto out;
> }
>
> because device_is_dependent(consumer, supplier) is true for fef00700.hdmi and
> hdmi-audio-codec.1.auto.
This hack fixes VC4 probing (I'm aware that drivers/base/core.c change is not
acceptable):
diff --git a/drivers/base/core.c b/drivers/base/core.c
index bd2ddf2aab50..03e0909d5d68 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -300,7 +300,7 @@ bool device_link_flag_is_sync_state_only(u32 flags)
* Check if @target depends on @dev or any device dependent on it (its child or
* its consumer etc). Return 1 if that is the case or 0 otherwise.
*/
-static int device_is_dependent(struct device *dev, void *target)
+int device_is_dependent(struct device *dev, void *target)
{
struct device_link *link;
int ret;
@@ -330,6 +330,7 @@ static int device_is_dependent(struct device *dev, void *target)
}
return ret;
}
+EXPORT_SYMBOL_GPL(device_is_dependent);
static void device_link_init_status(struct device_link *link,
struct device *consumer,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ac9b2269c26e..ba70befea0e8 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2165,6 +2165,8 @@ static void snd_soc_unbind_card(struct snd_soc_card *card)
}
}
+extern int device_is_dependent(struct device *dev, void *target);
+
static int snd_soc_bind_card(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
@@ -2304,7 +2306,8 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
if (card->dev == component->dev)
continue;
- if (!device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) {
+ if (!device_is_dependent(card->dev, component->dev) &&
+ !device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) {
dev_warn(card->dev, "Failed to create device link to %s\n",
dev_name(component->dev));
ret = -EINVAL;
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-18 12:58 ` Marek Szyprowski
2026-06-18 13:12 ` Marek Szyprowski
@ 2026-06-18 13:12 ` Richard Fitzgerald
2026-06-18 13:22 ` Marek Szyprowski
1 sibling, 1 reply; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-18 13:12 UTC (permalink / raw)
To: Marek Szyprowski, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 18/6/26 13:58, Marek Szyprowski wrote:
> On 18.06.2026 13:22, Richard Fitzgerald wrote:
>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>> In snd_soc_bind_card() create a device_link from card to all components
>>>> to ensure correct order of system_suspend. The card is the consumer and
>>>> the components are the supplier, so that the card will system_suspend
>>>> before any of the components.
>>>>
>>>> The PM core will normally system_suspend drivers in the opposite order
>>>> that they registered. This ensures children are suspended before their
>>>> parents, for example users of a bus driver should suspend before the bus
>>>> driver suspends.
>>>>
>>>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>>>> that the components are still able to communicate with their hardware.
>>>> Previously there was nothing to ensure this ordering, because there is
>>>> (usually) no relationship between a machine driver and component drivers.
>>>> If the machine driver registered before the codec drivers, the codec
>>>> drivers would be suspended before the machine driver snd_soc_suspend()
>>>> runs, so that ASoC is attempting to stop audio on a driver that has
>>>> already suspended.
>>>>
>>>> Creating a device_link is safe if there is already a device_link between
>>>> those devices because of multiple components sharing the same dev.
>>>> device_link_add() kernel doc says:
>>>>
>>>> "if a device link between the given @consumer and @supplier pair
>>>> exists already when this function is called for them, the existing link
>>>> will be returned regardless of its current type and status ...
>>>> The caller of this function is then expected to treat
>>>> the link as though it has just been created, so (in particular) if
>>>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>>>> explicitly when not needed any more"
>>>>
>>>> For the same reason it is safe if the codec driver or machine driver
>>>> later call device_link_add() to create a link between the same two
>>>> devices.
>>>>
>>>> (I have tested creating multiple links between the card->dev and a
>>>> component->dev and did not encounter any problems with suspend/resume or
>>>> module unloading.)
>>>>
>>>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>>>> the probe() function of that device. This isn't guaranteed in ASoC card
>>>> binding because of deferred binding. The exact behavior and consequences
>>>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>>>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>>>> explicitly when the card unbinds or if the bind fails.
>>>>
>>>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>>>> ---
>>>
>>>
>>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>>> soc-core: Create device_link to ensure correct suspend order"). In my
>>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>>
>>> # dmesg | grep vc4
>>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>>> vc4-drm gpu: adev bind failed: -22
>>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>>
>>
>> Where in device_link_add() does it fail?
>>
>
> It fails the following check at drivers/base/core.c line 766:
>
> if (!device_pm_initialized(supplier)
> || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
> device_is_dependent(consumer, supplier))) {
> link = NULL;
> goto out;
> }
>
> because device_is_dependent(consumer, supplier) is true for fef00700.hdmi and
> hdmi-audio-codec.1.auto.
>
>
> Best regards
Is the machine driver the parent of the codec driver?
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-18 13:12 ` Richard Fitzgerald
@ 2026-06-18 13:22 ` Marek Szyprowski
2026-06-19 13:33 ` Richard Fitzgerald
0 siblings, 1 reply; 16+ messages in thread
From: Marek Szyprowski @ 2026-06-18 13:22 UTC (permalink / raw)
To: Richard Fitzgerald, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 18.06.2026 15:12, Richard Fitzgerald wrote:
> On 18/6/26 13:58, Marek Szyprowski wrote:
>> On 18.06.2026 13:22, Richard Fitzgerald wrote:
>>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>>> In snd_soc_bind_card() create a device_link from card to all components
>>>>> to ensure correct order of system_suspend. The card is the consumer and
>>>>> the components are the supplier, so that the card will system_suspend
>>>>> before any of the components.
>>>>>
>>>>> The PM core will normally system_suspend drivers in the opposite order
>>>>> that they registered. This ensures children are suspended before their
>>>>> parents, for example users of a bus driver should suspend before the bus
>>>>> driver suspends.
>>>>>
>>>>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>>>>> that the components are still able to communicate with their hardware.
>>>>> Previously there was nothing to ensure this ordering, because there is
>>>>> (usually) no relationship between a machine driver and component drivers.
>>>>> If the machine driver registered before the codec drivers, the codec
>>>>> drivers would be suspended before the machine driver snd_soc_suspend()
>>>>> runs, so that ASoC is attempting to stop audio on a driver that has
>>>>> already suspended.
>>>>>
>>>>> Creating a device_link is safe if there is already a device_link between
>>>>> those devices because of multiple components sharing the same dev.
>>>>> device_link_add() kernel doc says:
>>>>>
>>>>> "if a device link between the given @consumer and @supplier pair
>>>>> exists already when this function is called for them, the existing link
>>>>> will be returned regardless of its current type and status ...
>>>>> The caller of this function is then expected to treat
>>>>> the link as though it has just been created, so (in particular) if
>>>>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>>>>> explicitly when not needed any more"
>>>>>
>>>>> For the same reason it is safe if the codec driver or machine driver
>>>>> later call device_link_add() to create a link between the same two
>>>>> devices.
>>>>>
>>>>> (I have tested creating multiple links between the card->dev and a
>>>>> component->dev and did not encounter any problems with suspend/resume or
>>>>> module unloading.)
>>>>>
>>>>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>>>>> the probe() function of that device. This isn't guaranteed in ASoC card
>>>>> binding because of deferred binding. The exact behavior and consequences
>>>>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>>>>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>>>>> explicitly when the card unbinds or if the bind fails.
>>>>>
>>>>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>>>>> ---
>>>>
>>>>
>>>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>>>> soc-core: Create device_link to ensure correct suspend order"). In my
>>>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>>>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>>>
>>>> # dmesg | grep vc4
>>>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>>>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>>>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>>>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>>>> vc4-drm gpu: adev bind failed: -22
>>>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>>>
>>>
>>> Where in device_link_add() does it fail?
>>>
>>
>> It fails the following check at drivers/base/core.c line 766:
>>
>> if (!device_pm_initialized(supplier)
>> || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
>> device_is_dependent(consumer, supplier))) {
>> link = NULL;
>> goto out;
>> }
>>
>> because device_is_dependent(consumer, supplier) is true for fef00700.hdmi and
>> hdmi-audio-codec.1.auto.
>>
>>
>> Best regards
>
> Is the machine driver the parent of the codec driver?
Yes, so this change fixes the issue:
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ac9b2269c26e..5e00ad0bc7cf 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2304,7 +2304,8 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
if (card->dev == component->dev)
continue;
- if (!device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) {
+ if (component->dev->parent != card->dev &&
+ !device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) {
dev_warn(card->dev, "Failed to create device link to %s\n",
dev_name(component->dev));
ret = -EINVAL;
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-18 13:22 ` Marek Szyprowski
@ 2026-06-19 13:33 ` Richard Fitzgerald
2026-06-19 15:51 ` Mark Brown
2026-06-19 15:54 ` Charles Keepax
0 siblings, 2 replies; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-19 13:33 UTC (permalink / raw)
To: Marek Szyprowski, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 18/6/26 14:22, Marek Szyprowski wrote:
> On 18.06.2026 15:12, Richard Fitzgerald wrote:
>> On 18/6/26 13:58, Marek Szyprowski wrote:
>>> On 18.06.2026 13:22, Richard Fitzgerald wrote:
>>>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>>>> In snd_soc_bind_card() create a device_link from card to all components
>>>>>> to ensure correct order of system_suspend. The card is the consumer and
>>>>>> the components are the supplier, so that the card will system_suspend
>>>>>> before any of the components.
>>>>>>
>>>>>> The PM core will normally system_suspend drivers in the opposite order
>>>>>> that they registered. This ensures children are suspended before their
>>>>>> parents, for example users of a bus driver should suspend before the bus
>>>>>> driver suspends.
>>>>>>
>>>>>> For ASoC, snd_soc_suspend() shuts down any active audio, which requires
>>>>>> that the components are still able to communicate with their hardware.
>>>>>> Previously there was nothing to ensure this ordering, because there is
>>>>>> (usually) no relationship between a machine driver and component drivers.
>>>>>> If the machine driver registered before the codec drivers, the codec
>>>>>> drivers would be suspended before the machine driver snd_soc_suspend()
>>>>>> runs, so that ASoC is attempting to stop audio on a driver that has
>>>>>> already suspended.
>>>>>>
>>>>>> Creating a device_link is safe if there is already a device_link between
>>>>>> those devices because of multiple components sharing the same dev.
>>>>>> device_link_add() kernel doc says:
>>>>>>
>>>>>> "if a device link between the given @consumer and @supplier pair
>>>>>> exists already when this function is called for them, the existing link
>>>>>> will be returned regardless of its current type and status ...
>>>>>> The caller of this function is then expected to treat
>>>>>> the link as though it has just been created, so (in particular) if
>>>>>> DL_FLAG_STATELESS was passed in @flags, the link needs to be released
>>>>>> explicitly when not needed any more"
>>>>>>
>>>>>> For the same reason it is safe if the codec driver or machine driver
>>>>>> later call device_link_add() to create a link between the same two
>>>>>> devices.
>>>>>>
>>>>>> (I have tested creating multiple links between the card->dev and a
>>>>>> component->dev and did not encounter any problems with suspend/resume or
>>>>>> module unloading.)
>>>>>>
>>>>>> The DL_FLAG_AUTOREMOVE_* flags assume that they are being called from
>>>>>> the probe() function of that device. This isn't guaranteed in ASoC card
>>>>>> binding because of deferred binding. The exact behavior and consequences
>>>>>> of the DL_FLAG_AUTOREMOVE_* are also unclear from the documentation.
>>>>>> So DL_FLAG_STATELESS is used for safety, and the links are removed
>>>>>> explicitly when the card unbinds or if the bind fails.
>>>>>>
>>>>>> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
>>>>>> ---
>>>>>
>>>>>
>>>>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>>>>> soc-core: Create device_link to ensure correct suspend order"). In my
>>>>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>>>>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>>>>
>>>>> # dmesg | grep vc4
>>>>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>>>>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>>>>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>>>>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>>>>> vc4-drm gpu: adev bind failed: -22
>>>>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>>>>
>>>>
>>>> Where in device_link_add() does it fail?
>>>>
>>>
>>> It fails the following check at drivers/base/core.c line 766:
>>>
>>> if (!device_pm_initialized(supplier)
>>> || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
>>> device_is_dependent(consumer, supplier))) {
>>> link = NULL;
>>> goto out;
>>> }
>>>
>>> because device_is_dependent(consumer, supplier) is true for fef00700.hdmi and
>>> hdmi-audio-codec.1.auto.
>>>
>>>
>>> Best regards
>>
>> Is the machine driver the parent of the codec driver?
>
>
> Yes, so this change fixes the issue:
Right. I thought I'd tested that. But I haven't got any hardware that
uses that "for real", so obviously I messed up my testing there.
It makes this whole device_link stuff less useful if you can't use it to
reorder a parent-child suspend order for when the parent-child
relationship isn't relevant to the order they should suspend.
If we skip entries that we can't re-order, is that simply adding
confusing complications and _mostly_ ASoC forces the correct order, but
in some cases it cannot and then it is up to those affected drivers to
figure it out themselves? Can we always guarantee that those drivers
will know which they are, or can it all break subtly because a driver
doesn't know that in some systems it becomes related to some other
driver?
Mark - should we revert this because of too many corner cases in the
device_link code and go back to every codec driver with a system_suspend
installing its own device_link to ensure correct suspend order compared
to the machine driver?
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-19 13:33 ` Richard Fitzgerald
@ 2026-06-19 15:51 ` Mark Brown
2026-06-19 15:54 ` Charles Keepax
1 sibling, 0 replies; 16+ messages in thread
From: Mark Brown @ 2026-06-19 15:51 UTC (permalink / raw)
To: Richard Fitzgerald
Cc: Marek Szyprowski, linux-sound, linux-kernel, patches,
Maxime Ripard, Dave Stevenson, linux-rpi-kernel,
Florian Fainelli
[-- Attachment #1: Type: text/plain, Size: 969 bytes --]
On Fri, Jun 19, 2026 at 02:33:36PM +0100, Richard Fitzgerald wrote:
> It makes this whole device_link stuff less useful if you can't use it to
> reorder a parent-child suspend order for when the parent-child
> relationship isn't relevant to the order they should suspend.
> If we skip entries that we can't re-order, is that simply adding
> confusing complications and _mostly_ ASoC forces the correct order, but
> in some cases it cannot and then it is up to those affected drivers to
> figure it out themselves? Can we always guarantee that those drivers
> will know which they are, or can it all break subtly because a driver
> doesn't know that in some systems it becomes related to some other
> driver?
> Mark - should we revert this because of too many corner cases in the
> device_link code and go back to every codec driver with a system_suspend
> installing its own device_link to ensure correct suspend order compared
> to the machine driver?
I think so.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-19 13:33 ` Richard Fitzgerald
2026-06-19 15:51 ` Mark Brown
@ 2026-06-19 15:54 ` Charles Keepax
2026-06-19 16:04 ` Richard Fitzgerald
1 sibling, 1 reply; 16+ messages in thread
From: Charles Keepax @ 2026-06-19 15:54 UTC (permalink / raw)
To: Richard Fitzgerald
Cc: Marek Szyprowski, broonie, linux-sound, linux-kernel, patches,
Maxime Ripard, Dave Stevenson, linux-rpi-kernel,
Florian Fainelli
On Fri, Jun 19, 2026 at 02:33:36PM +0100, Richard Fitzgerald wrote:
> On 18/6/26 14:22, Marek Szyprowski wrote:
> > On 18.06.2026 15:12, Richard Fitzgerald wrote:
> > > On 18/6/26 13:58, Marek Szyprowski wrote:
> > > > On 18.06.2026 13:22, Richard Fitzgerald wrote:
> > > > > On 17/6/26 15:10, Marek Szyprowski wrote:
> > > > > > On 11.06.2026 13:08, Richard Fitzgerald wrote:
> > > Is the machine driver the parent of the codec driver?
> >
> > Yes, so this change fixes the issue:
>
> Right. I thought I'd tested that. But I haven't got any hardware that
> uses that "for real", so obviously I messed up my testing there.
>
> It makes this whole device_link stuff less useful if you can't use it to
> reorder a parent-child suspend order for when the parent-child
> relationship isn't relevant to the order they should suspend.
Yeah it is pretty confusing situation if the machine driver
is the parent of the codec. What is the correct order for
things to suspend in that case? I feel like probably the parent
child relation takes precedent, but generally not making codecs
children of the machine driver seems prudent.
> If we skip entries that we can't re-order, is that simply adding
> confusing complications and _mostly_ ASoC forces the correct order, but
> in some cases it cannot and then it is up to those affected drivers to
> figure it out themselves? Can we always guarantee that those drivers
> will know which they are, or can it all break subtly because a driver
> doesn't know that in some systems it becomes related to some other
> driver?
I dunno still feels like this change is an improvement to me. The
core DAPM powers down the path, it needs the codecs available to
do that. You fix some subtle issues just not all of them.
> Mark - should we revert this because of too many corner cases in the
> device_link code and go back to every codec driver with a system_suspend
> installing its own device_link to ensure correct suspend order compared
> to the machine driver?
If you go back to this you still have a situation where ASoC
mostly does the right order it just took you more code to get
there. Also I think you would need to install the link from the
machine driver, since the codec driver could be used in
situations where it is or isn't a child of the machine driver, as
you noted earlier.
Personally I would vote for just skipping the case where the
machine driver is a parent of the card.
Thanks,
Charles
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-19 15:54 ` Charles Keepax
@ 2026-06-19 16:04 ` Richard Fitzgerald
2026-06-19 17:19 ` Mark Brown
0 siblings, 1 reply; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-19 16:04 UTC (permalink / raw)
To: Charles Keepax
Cc: Marek Szyprowski, broonie, linux-sound, linux-kernel, patches,
Maxime Ripard, Dave Stevenson, linux-rpi-kernel,
Florian Fainelli
On 19/6/26 16:54, Charles Keepax wrote:
> On Fri, Jun 19, 2026 at 02:33:36PM +0100, Richard Fitzgerald wrote:
>> On 18/6/26 14:22, Marek Szyprowski wrote:
>>> On 18.06.2026 15:12, Richard Fitzgerald wrote:
>>>> On 18/6/26 13:58, Marek Szyprowski wrote:
>>>>> On 18.06.2026 13:22, Richard Fitzgerald wrote:
>>>>>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>>>>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>> Is the machine driver the parent of the codec driver?
>>>
>>> Yes, so this change fixes the issue:
>>
>> Right. I thought I'd tested that. But I haven't got any hardware that
>> uses that "for real", so obviously I messed up my testing there.
>>
>> It makes this whole device_link stuff less useful if you can't use it to
>> reorder a parent-child suspend order for when the parent-child
>> relationship isn't relevant to the order they should suspend.
>
> Yeah it is pretty confusing situation if the machine driver
> is the parent of the codec. What is the correct order for
> things to suspend in that case? I feel like probably the parent
> child relation takes precedent, but generally not making codecs
> children of the machine driver seems prudent.
>
>> If we skip entries that we can't re-order, is that simply adding
>> confusing complications and _mostly_ ASoC forces the correct order, but
>> in some cases it cannot and then it is up to those affected drivers to
>> figure it out themselves? Can we always guarantee that those drivers
>> will know which they are, or can it all break subtly because a driver
>> doesn't know that in some systems it becomes related to some other
>> driver?
>
> I dunno still feels like this change is an improvement to me. The
> core DAPM powers down the path, it needs the codecs available to
> do that. You fix some subtle issues just not all of them.
>
>> Mark - should we revert this because of too many corner cases in the
>> device_link code and go back to every codec driver with a system_suspend
>> installing its own device_link to ensure correct suspend order compared
>> to the machine driver?
>
> If you go back to this you still have a situation where ASoC
> mostly does the right order it just took you more code to get
> there. Also I think you would need to install the link from the
> machine driver, since the codec driver could be used in
> situations where it is or isn't a child of the machine driver, as
> you noted earlier.
>
> Personally I would vote for just skipping the case where the
> machine driver is a parent of the card.
>
> Thanks,
> Charles
We're still in the merge window, so it's not something anyone should be
using on critical hardware or daily driver PCs. We can think about it
for a few days.
We could also deal with the case that card->dev ==
component->dev->parent, then give some time for more people to test and
see if anything else breaks.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-19 16:04 ` Richard Fitzgerald
@ 2026-06-19 17:19 ` Mark Brown
0 siblings, 0 replies; 16+ messages in thread
From: Mark Brown @ 2026-06-19 17:19 UTC (permalink / raw)
To: Richard Fitzgerald
Cc: Charles Keepax, Marek Szyprowski, linux-sound, linux-kernel,
patches, Maxime Ripard, Dave Stevenson, linux-rpi-kernel,
Florian Fainelli
[-- Attachment #1: Type: text/plain, Size: 1818 bytes --]
On Fri, Jun 19, 2026 at 05:04:51PM +0100, Richard Fitzgerald wrote:
> On 19/6/26 16:54, Charles Keepax wrote:
> > On Fri, Jun 19, 2026 at 02:33:36PM +0100, Richard Fitzgerald wrote:
> > > Mark - should we revert this because of too many corner cases in the
> > > device_link code and go back to every codec driver with a system_suspend
> > > installing its own device_link to ensure correct suspend order compared
> > > to the machine driver?
> > If you go back to this you still have a situation where ASoC
> > mostly does the right order it just took you more code to get
> > there. Also I think you would need to install the link from the
> > machine driver, since the codec driver could be used in
> > situations where it is or isn't a child of the machine driver, as
> > you noted earlier.
> > Personally I would vote for just skipping the case where the
> > machine driver is a parent of the card.
> We're still in the merge window, so it's not something anyone should be
> using on critical hardware or daily driver PCs. We can think about it
> for a few days.
> We could also deal with the case that card->dev ==
> component->dev->parent, then give some time for more people to test and
> see if anything else breaks.
Another option is to delay for a further cycle (which was where I was
coming from with the revert comment), though I'm now wondering if we're
more likely to shake stuff out with things sitting in Linus' tree than
we are in -next. It did go into -next fairly late in the cycle, but I
expect more people to test mainline than -next.
I was kind of wondering if it might be more robust to ignore errors from
failing to link thing but since we need to manually remove the links
that's a lot of effort for something ultimately hacky. It would be
nicer to just fix up a few specific cases.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-17 14:10 ` Marek Szyprowski
2026-06-18 11:22 ` Richard Fitzgerald
@ 2026-06-20 15:57 ` Richard Fitzgerald
2026-06-22 7:07 ` Marek Szyprowski
1 sibling, 1 reply; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-20 15:57 UTC (permalink / raw)
To: Marek Szyprowski, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 17/6/26 15:10, Marek Szyprowski wrote:
> Dear All,
>
> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>> In snd_soc_bind_card() create a device_link from card to all components
>> to ensure correct order of system_suspend. The card is the consumer and
>> the components are the supplier, so that the card will system_suspend
>> before any of the components.
>>
<SNIP>
> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
> soc-core: Create device_link to ensure correct suspend order"). In my
> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
> 3 and 4 boards due to an issue with hdmi-audio-codec:
>
> # dmesg | grep vc4
> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
> vc4-drm gpu: adev bind failed: -22
> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>
Marek,
Can you try the patch below?
If this works for you, and passes our tests, and nobody has any
objections, I can send it as a proper patch submission.
---
From 08de5810ef813c9945d01a2ce23cd9dd71cf3d99 Mon Sep 17 00:00:00 2001
From: Richard Fitzgerald <rf@opensource.cirrus.com>
Date: Sat, 20 Jun 2026 14:33:18 +0100
Subject: [PATCH] ASoC: soc-core: Don't fail if device_link could not be
created
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
include/sound/soc-component.h | 4 ++++
sound/soc/soc-core.c | 32 ++++++++++++--------------------
2 files changed, 16 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..8c24049d44d3 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);
@@ -2146,14 +2141,13 @@ static int snd_soc_bind_card(struct snd_soc_card
*card)
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 +2179,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] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-20 15:57 ` Richard Fitzgerald
@ 2026-06-22 7:07 ` Marek Szyprowski
2026-06-23 10:22 ` Richard Fitzgerald
0 siblings, 1 reply; 16+ messages in thread
From: Marek Szyprowski @ 2026-06-22 7:07 UTC (permalink / raw)
To: Richard Fitzgerald, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 20.06.2026 17:57, Richard Fitzgerald wrote:
> On 17/6/26 15:10, Marek Szyprowski wrote:
>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>> In snd_soc_bind_card() create a device_link from card to all components
>>> to ensure correct order of system_suspend. The card is the consumer and
>>> the components are the supplier, so that the card will system_suspend
>>> before any of the components.
>>>
>
> <SNIP>
>
>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>> soc-core: Create device_link to ensure correct suspend order"). In my
>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>
>> # dmesg | grep vc4
>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>> vc4-drm gpu: adev bind failed: -22
>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>
> Marek,
>
> Can you try the patch below?
>
> If this works for you, and passes our tests, and nobody has any
> objections, I can send it as a proper patch submission.
The patch was completely malformed (broken lines, tabs vs. spaces), I had to apply
it manually line by line, but it fixed the issue I've observed:
# dmesg | grep vc4
vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
vc4_hdmi fef00700.hdmi: Could not create device link to hdmi-audio-codec.1.auto
input: vc4-hdmi-0 HDMI Jack as /devices/platform/soc/fef00700.hdmi/sound/card1/input0
vc4-drm gpu: bound fef00700.hdmi (ops vc4_hdmi_ops [vc4])
vc4_hdmi fef05700.hdmi: Could not create device link to hdmi-audio-codec.3.auto
input: vc4-hdmi-1 HDMI Jack as /devices/platform/soc/fef05700.hdmi/sound/card2/input1
vc4-drm gpu: bound fef05700.hdmi (ops vc4_hdmi_ops [vc4])
vc4-drm gpu: bound fe004000.txp (ops vc4_txp_ops [vc4])
vc4-drm gpu: bound fe206000.pixelvalve (ops vc4_crtc_ops [vc4])
vc4-drm gpu: bound fe207000.pixelvalve (ops vc4_crtc_ops [vc4])
vc4-drm gpu: bound fe20a000.pixelvalve (ops vc4_crtc_ops [vc4])
vc4-drm gpu: bound fe216000.pixelvalve (ops vc4_crtc_ops [vc4])
[drm] Initialized vc4 0.0.0 for gpu on minor 1
Feel free to add:
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>
> From 08de5810ef813c9945d01a2ce23cd9dd71cf3d99 Mon Sep 17 00:00:00 2001
> From: Richard Fitzgerald <rf@opensource.cirrus.com>
> Date: Sat, 20 Jun 2026 14:33:18 +0100
> Subject: [PATCH] ASoC: soc-core: Don't fail if device_link could not be
> created
>
> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
> ---
> include/sound/soc-component.h | 4 ++++
> sound/soc/soc-core.c | 32 ++++++++++++--------------------
> 2 files changed, 16 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..8c24049d44d3 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);
> @@ -2146,14 +2141,13 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
> 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 +2179,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
>
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order
2026-06-22 7:07 ` Marek Szyprowski
@ 2026-06-23 10:22 ` Richard Fitzgerald
0 siblings, 0 replies; 16+ messages in thread
From: Richard Fitzgerald @ 2026-06-23 10:22 UTC (permalink / raw)
To: Marek Szyprowski, broonie
Cc: linux-sound, linux-kernel, patches, Maxime Ripard,
Dave Stevenson, linux-rpi-kernel, Florian Fainelli
On 22/6/26 08:07, Marek Szyprowski wrote:
> On 20.06.2026 17:57, Richard Fitzgerald wrote:
>> On 17/6/26 15:10, Marek Szyprowski wrote:
>>> On 11.06.2026 13:08, Richard Fitzgerald wrote:
>>>> In snd_soc_bind_card() create a device_link from card to all components
>>>> to ensure correct order of system_suspend. The card is the consumer and
>>>> the components are the supplier, so that the card will system_suspend
>>>> before any of the components.
>>>>
>>
>> <SNIP>
>>
>>> This patch landed recently in linux-next as commit 0f54ce994b23 ("ASoC:
>>> soc-core: Create device_link to ensure correct suspend order"). In my
>>> tests I found that it breaks probing of VC4 DRM subsystem on Raspberry Pi
>>> 3 and 4 boards due to an issue with hdmi-audio-codec:
>>>
>>> # dmesg | grep vc4
>>> vc4-drm gpu: bound fe400000.hvs (ops vc4_hvs_ops [vc4])
>>> vc4_hdmi fef00700.hdmi: Failed to create device link to hdmi-audio-codec.1.auto
>>> vc4_hdmi fef00700.hdmi: error -EINVAL: Could not register sound card
>>> vc4-drm gpu: failed to bind fef00700.hdmi (ops vc4_hdmi_ops [vc4]): -22
>>> vc4-drm gpu: adev bind failed: -22
>>> vc4-drm gpu: probe with driver vc4-drm failed with error -22
>>>
>> Marek,
>>
>> Can you try the patch below?
>>
>> If this works for you, and passes our tests, and nobody has any
>> objections, I can send it as a proper patch submission.
>
>
> The patch was completely malformed (broken lines, tabs vs. spaces), I had to apply
> it manually line by line, but it fixed the issue I've observed:
Sorry. I forgot that copy-pasting it into an email would do line
wrapping
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-06-23 10:22 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-11 11:08 [PATCH v2] ASoC: soc-core: Create device_link to ensure correct suspend order Richard Fitzgerald
2026-06-11 19:38 ` Mark Brown
[not found] ` <CGME20260617141046eucas1p2e85629d57bfc17449b135b16f9230d57@eucas1p2.samsung.com>
2026-06-17 14:10 ` Marek Szyprowski
2026-06-18 11:22 ` Richard Fitzgerald
2026-06-18 12:58 ` Marek Szyprowski
2026-06-18 13:12 ` Marek Szyprowski
2026-06-18 13:12 ` Richard Fitzgerald
2026-06-18 13:22 ` Marek Szyprowski
2026-06-19 13:33 ` Richard Fitzgerald
2026-06-19 15:51 ` Mark Brown
2026-06-19 15:54 ` Charles Keepax
2026-06-19 16:04 ` Richard Fitzgerald
2026-06-19 17:19 ` Mark Brown
2026-06-20 15:57 ` Richard Fitzgerald
2026-06-22 7:07 ` Marek Szyprowski
2026-06-23 10:22 ` Richard Fitzgerald
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®