ASoC: wcd937x: Fix invalid memory access in wcd937x_suspend
Invalid memory access happens in wcd937x_suspend if component bind for slave fails. This is because as part of component_unbind devres_release_group is called which removes every node from list and frees corresponding memory. This results in invalid memory access for wcd937x in wcd937x_suspend. Do kfree and set drvdata to NULL if component_bind fails to resolve the issue. Change-Id: Ia26eb36fe8b92ac0491b03d0d4a2b8def415148b Signed-off-by: Vatsal Bucha <vbucha@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
f53186de04
commit
72753620d0
@@ -2601,7 +2601,7 @@ struct wcd937x_pdata *wcd937x_populate_dt_data(struct device *dev)
|
||||
{
|
||||
struct wcd937x_pdata *pdata = NULL;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(struct wcd937x_pdata),
|
||||
pdata = kzalloc(sizeof(struct wcd937x_pdata),
|
||||
GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
@@ -2665,7 +2665,7 @@ static int wcd937x_bind(struct device *dev)
|
||||
struct wcd937x_pdata *pdata = NULL;
|
||||
struct wcd_ctrl_platform_data *plat_data = NULL;
|
||||
|
||||
wcd937x = devm_kzalloc(dev, sizeof(struct wcd937x_priv), GFP_KERNEL);
|
||||
wcd937x = kzalloc(sizeof(struct wcd937x_priv), GFP_KERNEL);
|
||||
if (!wcd937x)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2684,31 +2684,35 @@ static int wcd937x_bind(struct device *dev)
|
||||
if (!wcd937x->supplies) {
|
||||
dev_err(dev, "%s: Cannot init wcd supplies\n",
|
||||
__func__);
|
||||
return ret;
|
||||
goto err_bind_all;
|
||||
}
|
||||
|
||||
plat_data = dev_get_platdata(dev->parent);
|
||||
if (!plat_data) {
|
||||
dev_err(dev, "%s: platform data from parent is NULL\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_bind_all;
|
||||
}
|
||||
wcd937x->handle = (void *)plat_data->handle;
|
||||
if (!wcd937x->handle) {
|
||||
dev_err(dev, "%s: handle is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_bind_all;
|
||||
}
|
||||
wcd937x->update_wcd_event = plat_data->update_wcd_event;
|
||||
if (!wcd937x->update_wcd_event) {
|
||||
dev_err(dev, "%s: update_wcd_event api is null!\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_bind_all;
|
||||
}
|
||||
wcd937x->register_notifier = plat_data->register_notifier;
|
||||
if (!wcd937x->register_notifier) {
|
||||
dev_err(dev, "%s: register_notifier api is null!\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_bind_all;
|
||||
}
|
||||
|
||||
ret = msm_cdc_enable_static_supplies(dev, wcd937x->supplies,
|
||||
@@ -2717,7 +2721,7 @@ static int wcd937x_bind(struct device *dev)
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: wcd static supply enable failed!\n",
|
||||
__func__);
|
||||
return ret;
|
||||
goto err_bind_all;
|
||||
}
|
||||
|
||||
wcd937x_reset(dev);
|
||||
@@ -2733,7 +2737,7 @@ static int wcd937x_bind(struct device *dev)
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Slave bind failed, ret = %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
goto err_bind_all;
|
||||
}
|
||||
|
||||
ret = wcd937x_parse_port_mapping(dev, "qcom,rx_swr_ch_map", CODEC_RX);
|
||||
@@ -2820,18 +2824,26 @@ err_irq:
|
||||
wcd_irq_exit(&wcd937x->irq_info, wcd937x->virq);
|
||||
err:
|
||||
component_unbind_all(dev, wcd937x);
|
||||
err_bind_all:
|
||||
dev_set_drvdata(dev, NULL);
|
||||
kfree(pdata);
|
||||
kfree(wcd937x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wcd937x_unbind(struct device *dev)
|
||||
{
|
||||
struct wcd937x_priv *wcd937x = dev_get_drvdata(dev);
|
||||
struct wcd937x_pdata *pdata = dev_get_platdata(wcd937x->dev);
|
||||
|
||||
wcd_irq_exit(&wcd937x->irq_info, wcd937x->virq);
|
||||
snd_soc_unregister_component(dev);
|
||||
component_unbind_all(dev, wcd937x);
|
||||
mutex_destroy(&wcd937x->micb_lock);
|
||||
mutex_destroy(&wcd937x->ana_tx_clk_lock);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
kfree(pdata);
|
||||
kfree(wcd937x);
|
||||
}
|
||||
|
||||
static const struct of_device_id wcd937x_dt_match[] = {
|
||||
@@ -2901,6 +2913,8 @@ static int wcd937x_probe(struct platform_device *pdev)
|
||||
static int wcd937x_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_master_del(&pdev->dev, &wcd937x_comp_ops);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user