If the card registration fails, typically because of deferred probes, the device properties added for headset codecs are not removed, which leads to kernel oopses in driver bind/unbind tests. We already clean-up the device properties when the card is removed, this code can be moved as a helper and called upon card registration errors.
Unified · Split
| @@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = { · 1397 unmodified lines | ||
| 1398 | 1398 | .late_probe = sof_sdw_card_late_probe, |
| 1399 | 1399 | }; |
| 1400 | 1400 | |
| 1401 | +static void mc_dailink_exit_loop(struct snd_soc_card *card) | |
| 1402 | +{ | |
| 1403 | + struct snd_soc_dai_link *link; | |
| 1404 | + int ret; | |
| 1405 | + int i, j; | |
| 1406 | + | |
| 1407 | + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { | |
| 1408 | + if (!codec_info_list[i].exit) | |
| 1409 | + continue; | |
| 1410 | + /* | |
| 1411 | + * We don't need to call .exit function if there is no matched | |
| 1412 | + * dai link found. | |
| 1413 | + */ | |
| 1414 | + for_each_card_prelinks(card, j, link) { | |
| 1415 | + if (!strcmp(link->codecs[0].dai_name, | |
| 1416 | + codec_info_list[i].dai_name)) { | |
| 1417 | + ret = codec_info_list[i].exit(card, link); | |
| 1418 | + if (ret) | |
| 1419 | + dev_warn(card->dev, | |
| 1420 | + "codec exit failed %d\n", | |
| 1421 | + ret); | |
| 1422 | + break; | |
| 1423 | + } | |
| 1424 | + } | |
| 1425 | + } | |
| 1426 | +} | |
| 1427 | + | |
| 1401 | 1428 | static int mc_probe(struct platform_device *pdev) |
| 1402 | 1429 | { |
| 1403 | 1430 | struct snd_soc_card *card = &card_sof_sdw; |
| @@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev) · 58 unmodified lines | ||
| 1462 | 1489 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
| 1463 | 1490 | if (ret) { |
| 1464 | 1491 | dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); |
| 1492 | + mc_dailink_exit_loop(card); | |
| 1465 | 1493 | return ret; |
| 1466 | 1494 | } |
| 1467 | 1495 | |
| @@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 1473 | 1501 | static int mc_remove(struct platform_device *pdev) |
| 1474 | 1502 | { |
| 1475 | 1503 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 1476 | − struct snd_soc_dai_link *link; | |
| 1477 | − int ret; | |
| 1478 | − int i, j; | |
| 1479 | 1504 | |
| 1480 | − for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { | |
| 1481 | − if (!codec_info_list[i].exit) | |
| 1482 | − continue; | |
| 1483 | − /* | |
| 1484 | − * We don't need to call .exit function if there is no matched | |
| 1485 | − * dai link found. | |
| 1486 | − */ | |
| 1487 | − for_each_card_prelinks(card, j, link) { | |
| 1488 | − if (!strcmp(link->codecs[0].dai_name, | |
| 1489 | − codec_info_list[i].dai_name)) { | |
| 1490 | − ret = codec_info_list[i].exit(card, link); | |
| 1491 | − if (ret) | |
| 1492 | − dev_warn(&pdev->dev, | |
| 1493 | − "codec exit failed %d\n", | |
| 1494 | − ret); | |
| 1495 | − break; | |
| 1496 | − } | |
| 1497 | − } | |
| 1498 | − } | |
| 1505 | + mc_dailink_exit_loop(card); | |
| 1499 | 1506 | |
| 1500 | 1507 | return 0; |
| 1501 | 1508 | } |