Re: [PATCH v2] ASoC: generic: keep fallback dai_name stable across rebind
From: Cássio Gabriel Monteiro Pires
Date: Fri Mar 27 2026 - 13:07:19 EST
On 3/27/26 02:22, Cássio Gabriel Monteiro Pires wrote:
> On 3/27/26 01:11, Cássio Gabriel wrote:
>> simple_parse_dai() and graph_util_parse_dai() first try to identify a
>> DAI via dai_args. When that works the card can rebind without relying on
>> dlc->dai_name.
>>
>> The fallback path still calls snd_soc_get_dlc(), which returns a
>> borrowed dai_name pointer. If the CPU or codec component is unbound
>> while the sound card stays registered, the generic card keeps that
>> pointer and the next rebind may compare stale memory while matching the
>> DAI.
>>
>> Stage the fallback result in a temporary dai_link_component and move
>> only a card-owned copy of dai_name into the live link component. Use
>> devm_kstrdup_const() so static names are reused and dynamic ones remain
>> valid for the lifetime of the card device.
>>
>> Signed-off-by: Cássio Gabriel <cassiogabrielcontato@xxxxxxxxx>
>> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
>> ---
>> Changes in v2:
>> - Rework simple_parse_dai() and graph_util_parse_dai() to use if/else
>> instead of a non-error goto.
>> - Move the fallback snd_soc_get_dlc() handling into the else branch.
>> - Link to v1: https://patch.msgid.link/20260326-asoc-generic-fallback-dai-name-rebind-v1-1-ac9da3cbd606@xxxxxxxxx
>> ---
>> sound/soc/generic/simple-card-utils.c | 52 ++++++++++++++++-------------------
>> sound/soc/generic/simple-card.c | 46 ++++++++++++++-----------------
>> 2 files changed, 44 insertions(+), 54 deletions(-)
>>
>> diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
>> index da6353594d61..e5cb602fd248 100644
>> --- a/sound/soc/generic/simple-card-utils.c
>> +++ b/sound/soc/generic/simple-card-utils.c
>> @@ -1128,7 +1128,9 @@ int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
>> struct device *dev = simple_priv_to_dev(priv);
>> struct device_node *node;
>> struct of_phandle_args args = {};
>> + struct snd_soc_dai_link_component resolved_dlc = {};
>> struct snd_soc_dai *dai;
>> + const char *fallback_dai_name;
>> int ret;
>>
>> if (!ep)
>> @@ -1152,39 +1154,31 @@ int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
>> dlc->of_node = node;
>> dlc->dai_name = dai_name;
>> dlc->dai_args = dai_args;
>> + } else {
>> + /* Get dai->name */
>> + args.np = node;
>> + args.args[0] = graph_get_dai_id(ep);
>> + args.args_count = (of_graph_get_endpoint_count(node) > 1);
>>
>> - goto parse_dai_end;
>> - }
>> + ret = snd_soc_get_dlc(&args, &resolved_dlc);
>> + if (ret < 0)
>> + goto err;
>>
>> - /* Get dai->name */
>> - args.np = node;
>> - args.args[0] = graph_get_dai_id(ep);
>> - args.args_count = (of_graph_get_endpoint_count(node) > 1);
>> + /* Keep fallback dai_name valid across component rebind */
>> + fallback_dai_name = resolved_dlc.dai_name;
>> + if (fallback_dai_name) {
>> + fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name,
>> + GFP_KERNEL);
>> + ret = -ENOMEM;
>> + if (!fallback_dai_name)
>> + goto err;
>> + }
>>
>> - /*
>> - * FIXME
>> - *
>> - * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
>> - * If user unbinded CPU or Codec driver, but not for Sound Card,
>> - * dlc->dai_name is keeping unbinded CPU or Codec
>> - * driver's pointer.
>> - *
>> - * If user re-bind CPU or Codec driver again, ALSA SoC will try
>> - * to rebind Card via snd_soc_try_rebind_card(), but because of
>> - * above reason, it might can't bind Sound Card.
>> - * Because Sound Card is pointing to released dai_name pointer.
>> - *
>> - * To avoid this rebind Card issue,
>> - * 1) It needs to alloc memory to keep dai_name eventhough
>> - * CPU or Codec driver was unbinded, or
>> - * 2) user need to rebind Sound Card everytime
>> - * if he unbinded CPU or Codec.
>> - */
>> - ret = snd_soc_get_dlc(&args, dlc);
>> - if (ret < 0)
>> - goto err;
>> + dlc->of_node = resolved_dlc.of_node;
>> + dlc->dai_name = fallback_dai_name;
>> + dlc->dai_args = resolved_dlc.dai_args;
>> + }
>>
>> -parse_dai_end:
>> if (is_single_link)
>> *is_single_link = of_graph_get_endpoint_count(node) == 1;
>> ret = 0;
>> diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
>> index 9937a991846e..b24ba1330896 100644
>> --- a/sound/soc/generic/simple-card.c
>> +++ b/sound/soc/generic/simple-card.c
>> @@ -69,7 +69,9 @@ static int simple_parse_dai(struct simple_util_priv *priv,
>> {
>> struct device *dev = simple_priv_to_dev(priv);
>> struct of_phandle_args args;
>> + struct snd_soc_dai_link_component resolved_dlc = {};
>> struct snd_soc_dai *dai;
>> + const char *fallback_dai_name;
>> int ret;
>>
>> if (!node)
>> @@ -94,34 +96,28 @@ static int simple_parse_dai(struct simple_util_priv *priv,
>> dlc->dai_args = snd_soc_copy_dai_args(dev, &args);
>> if (!dlc->dai_args)
>> goto end;
>> + } else {
>> + ret = snd_soc_get_dlc(&args, &resolved_dlc);
>> + if (ret < 0)
>> + goto end;
>>
>> - goto parse_dai_end;
>> - }
>> + /* Keep fallback dai_name valid across component rebind */
>> + fallback_dai_name = resolved_dlc.dai_name;
>> + if (fallback_dai_name) {
>> + fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name,
>> + GFP_KERNEL);
>> + ret = -ENOMEM;
>> + if (!fallback_dai_name) {
>> + of_node_put(resolved_dlc.of_node);
>> + goto end;
>> + }
>> + }
>>
>> - /*
>> - * FIXME
>> - *
>> - * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
>> - * If user unbinded CPU or Codec driver, but not for Sound Card,
>> - * dlc->dai_name is keeping unbinded CPU or Codec
>> - * driver's pointer.
>> - *
>> - * If user re-bind CPU or Codec driver again, ALSA SoC will try
>> - * to rebind Card via snd_soc_try_rebind_card(), but because of
>> - * above reason, it might can't bind Sound Card.
>> - * Because Sound Card is pointing to released dai_name pointer.
>> - *
>> - * To avoid this rebind Card issue,
>> - * 1) It needs to alloc memory to keep dai_name eventhough
>> - * CPU or Codec driver was unbinded, or
>> - * 2) user need to rebind Sound Card everytime
>> - * if he unbinded CPU or Codec.
>> - */
>> - ret = snd_soc_get_dlc(&args, dlc);
>> - if (ret < 0)
>> - goto end;
>> + dlc->of_node = resolved_dlc.of_node;
>> + dlc->dai_name = fallback_dai_name;
>> + dlc->dai_args = resolved_dlc.dai_args;
>> + }
>>
>> -parse_dai_end:
>> if (is_single_link)
>> *is_single_link = !args.args_count;
>> ret = 0;
>>
>> ---
>> base-commit: d084fd53a2fd5748d4317635b1c1a7dba7edf583
>> change-id: 20260326-asoc-generic-fallback-dai-name-rebind-6381a1c807fd
>>
>> Best regards,
>> --
>> Cássio Gabriel <cassiogabrielcontato@xxxxxxxxx>
>>
>
> I forgot to add the 'Suggested-by' tag attributing
> the suggestion made by Kuninori. I apologize.
>
> Should I send a v3 patch adding the tag?
I'm going to send a v3 patch with the tag added.
--
Thanks,
Cássio