Driver does not unregister typec structures (typec_mux_dev and typec_switch_desc) during removal leading to leaks. Fix this by moving typec registering parts to separate function and using devm interface to release them. This also makes code a bit simpler: - Smaller probe() function with less error paths and no #ifdefs, - No need to store typec_mux_dev and typec_switch_desc in driver state container structure.
Cc: stable@vger.kernel.org Fixes: 10f514bd172a ("ASoC: codecs: Add WCD939x Codec driver") Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
---
Not tested on hardware. --- sound/soc/codecs/wcd939x.c | 113 ++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 47 deletions(-)
diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c index 72d8a6a35052..28cb74f6f330 100644 --- a/sound/soc/codecs/wcd939x.c +++ b/sound/soc/codecs/wcd939x.c @@ -181,8 +181,6 @@ struct wcd939x_priv { /* typec handling */ bool typec_analog_mux; #if IS_ENABLED(CONFIG_TYPEC) - struct typec_mux_dev *typec_mux; - struct typec_switch_dev *typec_sw; enum typec_orientation typec_orientation; unsigned long typec_mode; struct typec_switch *typec_switch; @@ -3519,6 +3517,68 @@ static const struct component_master_ops wcd939x_comp_ops = { .unbind = wcd939x_unbind, };
+static void __maybe_unused wcd939x_typec_mux_unregister(void *data) +{ + struct typec_mux_dev *typec_mux = data; + + typec_mux_unregister(typec_mux); +} + +static void __maybe_unused wcd939x_typec_switch_unregister(void *data) +{ + struct typec_switch_dev *typec_sw = data; + + typec_switch_unregister(typec_sw); +} + +static int wcd939x_add_typec(struct wcd939x_priv *wcd939x, struct device *dev) +{ +#if IS_ENABLED(CONFIG_TYPEC) + int ret; + struct typec_mux_dev *typec_mux; + struct typec_switch_dev *typec_sw; + struct typec_mux_desc mux_desc = { + .drvdata = wcd939x, + .fwnode = dev_fwnode(dev), + .set = wcd939x_typec_mux_set, + }; + struct typec_switch_desc sw_desc = { + .drvdata = wcd939x, + .fwnode = dev_fwnode(dev), + .set = wcd939x_typec_switch_set, + }; + + /* + * Is USBSS is used to mux analog lines, + * register a typec mux/switch to get typec events + */ + if (!wcd939x->typec_analog_mux) + return 0; + + typec_mux = typec_mux_register(dev, &mux_desc); + if (IS_ERR(typec_mux)) + return dev_err_probe(dev, PTR_ERR(typec_mux), + "failed to register typec mux\n"); + + ret = devm_add_action_or_reset(dev, wcd939x_typec_mux_unregister, + typec_mux); + if (ret) + return ret; + + typec_sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(typec_sw)) + return dev_err_probe(dev, PTR_ERR(typec_sw), + "failed to register typec switch\n"); + + ret = devm_add_action_or_reset(dev, wcd939x_typec_switch_unregister, + typec_sw); + if (ret) + return ret; +#endif + + return 0; +} + static int wcd939x_add_slave_components(struct wcd939x_priv *wcd939x, struct device *dev, struct component_match **matchptr) @@ -3567,42 +3627,13 @@ static int wcd939x_probe(struct platform_device *pdev) return -EINVAL; }
-#if IS_ENABLED(CONFIG_TYPEC) - /* - * Is USBSS is used to mux analog lines, - * register a typec mux/switch to get typec events - */ - if (wcd939x->typec_analog_mux) { - struct typec_mux_desc mux_desc = { - .drvdata = wcd939x, - .fwnode = dev_fwnode(dev), - .set = wcd939x_typec_mux_set, - }; - struct typec_switch_desc sw_desc = { - .drvdata = wcd939x, - .fwnode = dev_fwnode(dev), - .set = wcd939x_typec_switch_set, - }; - - wcd939x->typec_mux = typec_mux_register(dev, &mux_desc); - if (IS_ERR(wcd939x->typec_mux)) { - ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_mux), - "failed to register typec mux\n"); - goto err_disable_regulators; - } - - wcd939x->typec_sw = typec_switch_register(dev, &sw_desc); - if (IS_ERR(wcd939x->typec_sw)) { - ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_sw), - "failed to register typec switch\n"); - goto err_unregister_typec_mux; - } - } -#endif /* CONFIG_TYPEC */ + ret = wcd939x_add_typec(wcd939x, dev); + if (ret) + goto err_disable_regulators;
ret = wcd939x_add_slave_components(wcd939x, dev, &match); if (ret) - goto err_unregister_typec_switch; + goto err_disable_regulators;
wcd939x_reset(wcd939x);
@@ -3619,18 +3650,6 @@ static int wcd939x_probe(struct platform_device *pdev)
return 0;
-#if IS_ENABLED(CONFIG_TYPEC) -err_unregister_typec_mux: - if (wcd939x->typec_analog_mux) - typec_mux_unregister(wcd939x->typec_mux); -#endif /* CONFIG_TYPEC */ - -err_unregister_typec_switch: -#if IS_ENABLED(CONFIG_TYPEC) - if (wcd939x->typec_analog_mux) - typec_switch_unregister(wcd939x->typec_sw); -#endif /* CONFIG_TYPEC */ - err_disable_regulators: regulator_bulk_disable(WCD939X_MAX_SUPPLY, wcd939x->supplies); regulator_bulk_free(WCD939X_MAX_SUPPLY, wcd939x->supplies);
On 01/07/2024 14:26, Krzysztof Kozlowski wrote:
Driver does not unregister typec structures (typec_mux_dev and typec_switch_desc) during removal leading to leaks. Fix this by moving typec registering parts to separate function and using devm interface to release them. This also makes code a bit simpler:
- Smaller probe() function with less error paths and no #ifdefs,
- No need to store typec_mux_dev and typec_switch_desc in driver state container structure.
Cc: stable@vger.kernel.org Fixes: 10f514bd172a ("ASoC: codecs: Add WCD939x Codec driver") Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
Not tested on hardware.
sound/soc/codecs/wcd939x.c | 113 ++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 47 deletions(-)
<snip>
Looks good!
Reviewed-by: Neil Armstrong neil.armstrong@linaro.org
On Mon, 01 Jul 2024 14:26:16 +0200, Krzysztof Kozlowski wrote:
Driver does not unregister typec structures (typec_mux_dev and typec_switch_desc) during removal leading to leaks. Fix this by moving typec registering parts to separate function and using devm interface to release them. This also makes code a bit simpler:
- Smaller probe() function with less error paths and no #ifdefs,
- No need to store typec_mux_dev and typec_switch_desc in driver state container structure.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: codecs: wcd939x: Fix typec mux and switch leak during device removal commit: 9f3ae72c5dbca9ba558c752f1ef969ed6908be01
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
linux-stable-mirror@lists.linaro.org