ASoC: codecs: wcd939x: Fix typec mux and switch leak during device removal
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: 10f514bd17
("ASoC: codecs: Add WCD939x Codec driver")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patch.msgid.link/20240701122616.414158-1-krzysztof.kozlowski@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
1e0dff741b
commit
9f3ae72c5d
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user