This is a note to let you know that I've just added the patch titled ASoC: codecs: wcd938x: fix resource leaks on bind errors to the 6.1-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: asoc-codecs-wcd938x-fix-resource-leaks-on-bind-errors.patch and it can be found in the queue-6.1 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From da29b94ed3547cee9d510d02eca4009f2de476cf Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan+linaro@xxxxxxxxxx> Date: Tue, 3 Oct 2023 17:55:54 +0200 Subject: ASoC: codecs: wcd938x: fix resource leaks on bind errors From: Johan Hovold <johan+linaro@xxxxxxxxxx> commit da29b94ed3547cee9d510d02eca4009f2de476cf upstream. Add the missing code to release resources on bind errors, including the references taken by wcd938x_sdw_device_get() which also need to be dropped on unbind(). Fixes: 16572522aece ("ASoC: codecs: wcd938x-sdw: add SoundWire driver") Cc: stable@xxxxxxxxxxxxxxx # 5.14 Cc: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx> Signed-off-by: Johan Hovold <johan+linaro@xxxxxxxxxx> Link: https://lore.kernel.org/r/20231003155558.27079-4-johan+linaro@xxxxxxxxxx Signed-off-by: Mark Brown <broonie@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- sound/soc/codecs/wcd938x.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -3441,7 +3441,8 @@ static int wcd938x_bind(struct device *d wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode); if (!wcd938x->rxdev) { dev_err(dev, "could not find slave with matching of node\n"); - return -EINVAL; + ret = -EINVAL; + goto err_unbind; } wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev); wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x; @@ -3449,7 +3450,8 @@ static int wcd938x_bind(struct device *d wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode); if (!wcd938x->txdev) { dev_err(dev, "could not find txslave with matching of node\n"); - return -EINVAL; + ret = -EINVAL; + goto err_put_rxdev; } wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev); wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x; @@ -3460,31 +3462,35 @@ static int wcd938x_bind(struct device *d if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { dev_err(dev, "could not devlink tx and rx\n"); - return -EINVAL; + ret = -EINVAL; + goto err_put_txdev; } if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { dev_err(dev, "could not devlink wcd and tx\n"); - return -EINVAL; + ret = -EINVAL; + goto err_remove_rxtx_link; } if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { dev_err(dev, "could not devlink wcd and rx\n"); - return -EINVAL; + ret = -EINVAL; + goto err_remove_tx_link; } wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL); if (!wcd938x->regmap) { dev_err(dev, "could not get TX device regmap\n"); - return -EINVAL; + ret = -EINVAL; + goto err_remove_rx_link; } ret = wcd938x_irq_init(wcd938x, dev); if (ret) { dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret); - return ret; + goto err_remove_rx_link; } wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq; @@ -3493,17 +3499,33 @@ static int wcd938x_bind(struct device *d ret = wcd938x_set_micbias_data(wcd938x); if (ret < 0) { dev_err(dev, "%s: bad micbias pdata\n", __func__); - return ret; + goto err_remove_rx_link; } ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x, wcd938x_dais, ARRAY_SIZE(wcd938x_dais)); - if (ret) + if (ret) { dev_err(dev, "%s: Codec registration failed\n", __func__); + goto err_remove_rx_link; + } - return ret; + return 0; +err_remove_rx_link: + device_link_remove(dev, wcd938x->rxdev); +err_remove_tx_link: + device_link_remove(dev, wcd938x->txdev); +err_remove_rxtx_link: + device_link_remove(wcd938x->rxdev, wcd938x->txdev); +err_put_txdev: + put_device(wcd938x->txdev); +err_put_rxdev: + put_device(wcd938x->rxdev); +err_unbind: + component_unbind_all(dev, wcd938x); + + return ret; } static void wcd938x_unbind(struct device *dev) @@ -3514,6 +3536,8 @@ static void wcd938x_unbind(struct device device_link_remove(dev, wcd938x->txdev); device_link_remove(dev, wcd938x->rxdev); device_link_remove(wcd938x->rxdev, wcd938x->txdev); + put_device(wcd938x->txdev); + put_device(wcd938x->rxdev); component_unbind_all(dev, wcd938x); } Patches currently in stable-queue which might be from johan+linaro@xxxxxxxxxx are queue-6.1/asoc-codecs-wcd938x-fix-unbind-tear-down-order.patch queue-6.1/asoc-codecs-wcd938x-sdw-fix-use-after-free-on-driver-unbind.patch queue-6.1/asoc-codecs-wcd938x-drop-bogus-bind-error-handling.patch queue-6.1/asoc-codecs-wcd938x-fix-resource-leaks-on-bind-errors.patch queue-6.1/asoc-codecs-wcd938x-sdw-fix-runtime-pm-imbalance-on-probe-errors.patch queue-6.1/regmap-fix-null-deref-on-lookup.patch