aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-08-01 14:08:07 +0200
committerMark Brown <broonie@linaro.org>2013-08-01 19:24:28 +0100
commit2c75bdf3fd935119cf8681ac0df2b4a5edd5167d (patch)
tree9cd5658af2854651f974ad35895f54c1addd9191 /sound/soc/soc-dapm.c
parent9356e9d51c80114fce2d7d8be99bce1d7e19d063 (diff)
ASoC: dapm: Fix kcontrol path list corruption
When calling krealloc for the kcontrol data the items in the path list that point back to the head of the list will now point to freed memory, which causes the list to become corrupted. To fix this, instead of resizing the whole data struct, only resize the widget list. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index b4fae871785..5f64c16336a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -177,7 +177,7 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
struct dapm_kcontrol_data {
unsigned int value;
struct list_head paths;
- struct snd_soc_dapm_widget_list wlist;
+ struct snd_soc_dapm_widget_list *wlist;
};
static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
@@ -185,7 +185,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
{
struct dapm_kcontrol_data *data;
- data = kzalloc(sizeof(*data) + sizeof(widget), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(widget->dapm->dev,
"ASoC: can't allocate kcontrol data for %s\n",
@@ -193,8 +193,6 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
return -ENOMEM;
}
- data->wlist.widgets[0] = widget;
- data->wlist.num_widgets = 1;
INIT_LIST_HEAD(&data->paths);
kcontrol->private_data = data;
@@ -205,6 +203,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
{
struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
+ kfree(data->wlist);
kfree(data);
}
@@ -213,25 +212,30 @@ static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
{
struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
- return &data->wlist;
+ return data->wlist;
}
static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget *widget)
{
struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
- struct dapm_kcontrol_data *new_data;
- unsigned int n = data->wlist.num_widgets + 1;
+ struct snd_soc_dapm_widget_list *new_wlist;
+ unsigned int n;
+
+ if (data->wlist)
+ n = data->wlist->num_widgets + 1;
+ else
+ n = 1;
- new_data = krealloc(data, sizeof(*data) + sizeof(widget) * n,
- GFP_KERNEL);
- if (!new_data)
+ new_wlist = krealloc(data->wlist,
+ sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
+ if (!new_wlist)
return -ENOMEM;
- new_data->wlist.widgets[n - 1] = widget;
- new_data->wlist.num_widgets = n;
+ new_wlist->widgets[n - 1] = widget;
+ new_wlist->num_widgets = n;
- kcontrol->private_data = new_data;
+ data->wlist = new_wlist;
return 0;
}
@@ -689,12 +693,12 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
w->name, name, ret);
return ret;
}
- } else {
- ret = dapm_kcontrol_add_widget(kcontrol, w);
- if (ret)
- return ret;
}
+ ret = dapm_kcontrol_add_widget(kcontrol, w);
+ if (ret)
+ return ret;
+
w->kcontrols[kci] = kcontrol;
dapm_kcontrol_add_path(kcontrol, path);