Skip to content

Commit 9f3ae72

Browse files
krzkbroonie
authored andcommitted
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: [email protected] Fixes: 10f514b ("ASoC: codecs: Add WCD939x Codec driver") Signed-off-by: Krzysztof Kozlowski <[email protected]> Reviewed-by: Neil Armstrong <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 1e0dff7 commit 9f3ae72

File tree

1 file changed

+66
-47
lines changed

1 file changed

+66
-47
lines changed

sound/soc/codecs/wcd939x.c

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ struct wcd939x_priv {
181181
/* typec handling */
182182
bool typec_analog_mux;
183183
#if IS_ENABLED(CONFIG_TYPEC)
184-
struct typec_mux_dev *typec_mux;
185-
struct typec_switch_dev *typec_sw;
186184
enum typec_orientation typec_orientation;
187185
unsigned long typec_mode;
188186
struct typec_switch *typec_switch;
@@ -3519,6 +3517,68 @@ static const struct component_master_ops wcd939x_comp_ops = {
35193517
.unbind = wcd939x_unbind,
35203518
};
35213519

3520+
static void __maybe_unused wcd939x_typec_mux_unregister(void *data)
3521+
{
3522+
struct typec_mux_dev *typec_mux = data;
3523+
3524+
typec_mux_unregister(typec_mux);
3525+
}
3526+
3527+
static void __maybe_unused wcd939x_typec_switch_unregister(void *data)
3528+
{
3529+
struct typec_switch_dev *typec_sw = data;
3530+
3531+
typec_switch_unregister(typec_sw);
3532+
}
3533+
3534+
static int wcd939x_add_typec(struct wcd939x_priv *wcd939x, struct device *dev)
3535+
{
3536+
#if IS_ENABLED(CONFIG_TYPEC)
3537+
int ret;
3538+
struct typec_mux_dev *typec_mux;
3539+
struct typec_switch_dev *typec_sw;
3540+
struct typec_mux_desc mux_desc = {
3541+
.drvdata = wcd939x,
3542+
.fwnode = dev_fwnode(dev),
3543+
.set = wcd939x_typec_mux_set,
3544+
};
3545+
struct typec_switch_desc sw_desc = {
3546+
.drvdata = wcd939x,
3547+
.fwnode = dev_fwnode(dev),
3548+
.set = wcd939x_typec_switch_set,
3549+
};
3550+
3551+
/*
3552+
* Is USBSS is used to mux analog lines,
3553+
* register a typec mux/switch to get typec events
3554+
*/
3555+
if (!wcd939x->typec_analog_mux)
3556+
return 0;
3557+
3558+
typec_mux = typec_mux_register(dev, &mux_desc);
3559+
if (IS_ERR(typec_mux))
3560+
return dev_err_probe(dev, PTR_ERR(typec_mux),
3561+
"failed to register typec mux\n");
3562+
3563+
ret = devm_add_action_or_reset(dev, wcd939x_typec_mux_unregister,
3564+
typec_mux);
3565+
if (ret)
3566+
return ret;
3567+
3568+
typec_sw = typec_switch_register(dev, &sw_desc);
3569+
if (IS_ERR(typec_sw))
3570+
return dev_err_probe(dev, PTR_ERR(typec_sw),
3571+
"failed to register typec switch\n");
3572+
3573+
ret = devm_add_action_or_reset(dev, wcd939x_typec_switch_unregister,
3574+
typec_sw);
3575+
if (ret)
3576+
return ret;
3577+
#endif
3578+
3579+
return 0;
3580+
}
3581+
35223582
static int wcd939x_add_slave_components(struct wcd939x_priv *wcd939x,
35233583
struct device *dev,
35243584
struct component_match **matchptr)
@@ -3567,42 +3627,13 @@ static int wcd939x_probe(struct platform_device *pdev)
35673627
return -EINVAL;
35683628
}
35693629

3570-
#if IS_ENABLED(CONFIG_TYPEC)
3571-
/*
3572-
* Is USBSS is used to mux analog lines,
3573-
* register a typec mux/switch to get typec events
3574-
*/
3575-
if (wcd939x->typec_analog_mux) {
3576-
struct typec_mux_desc mux_desc = {
3577-
.drvdata = wcd939x,
3578-
.fwnode = dev_fwnode(dev),
3579-
.set = wcd939x_typec_mux_set,
3580-
};
3581-
struct typec_switch_desc sw_desc = {
3582-
.drvdata = wcd939x,
3583-
.fwnode = dev_fwnode(dev),
3584-
.set = wcd939x_typec_switch_set,
3585-
};
3586-
3587-
wcd939x->typec_mux = typec_mux_register(dev, &mux_desc);
3588-
if (IS_ERR(wcd939x->typec_mux)) {
3589-
ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_mux),
3590-
"failed to register typec mux\n");
3591-
goto err_disable_regulators;
3592-
}
3593-
3594-
wcd939x->typec_sw = typec_switch_register(dev, &sw_desc);
3595-
if (IS_ERR(wcd939x->typec_sw)) {
3596-
ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_sw),
3597-
"failed to register typec switch\n");
3598-
goto err_unregister_typec_mux;
3599-
}
3600-
}
3601-
#endif /* CONFIG_TYPEC */
3630+
ret = wcd939x_add_typec(wcd939x, dev);
3631+
if (ret)
3632+
goto err_disable_regulators;
36023633

36033634
ret = wcd939x_add_slave_components(wcd939x, dev, &match);
36043635
if (ret)
3605-
goto err_unregister_typec_switch;
3636+
goto err_disable_regulators;
36063637

36073638
wcd939x_reset(wcd939x);
36083639

@@ -3619,18 +3650,6 @@ static int wcd939x_probe(struct platform_device *pdev)
36193650

36203651
return 0;
36213652

3622-
#if IS_ENABLED(CONFIG_TYPEC)
3623-
err_unregister_typec_mux:
3624-
if (wcd939x->typec_analog_mux)
3625-
typec_mux_unregister(wcd939x->typec_mux);
3626-
#endif /* CONFIG_TYPEC */
3627-
3628-
err_unregister_typec_switch:
3629-
#if IS_ENABLED(CONFIG_TYPEC)
3630-
if (wcd939x->typec_analog_mux)
3631-
typec_switch_unregister(wcd939x->typec_sw);
3632-
#endif /* CONFIG_TYPEC */
3633-
36343653
err_disable_regulators:
36353654
regulator_bulk_disable(WCD939X_MAX_SUPPLY, wcd939x->supplies);
36363655
regulator_bulk_free(WCD939X_MAX_SUPPLY, wcd939x->supplies);

0 commit comments

Comments
 (0)