diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2014-03-11 05:03:40 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-03-14 15:56:55 -0400 |
commit | e512e001dafa54e5ac7244416e340750a4356b41 (patch) | |
tree | 270d1e579183a1c5e3ea65b6b42cfbb580b3570b /sound/soc/generic | |
parent | 12ffa6fc1958879a81b6af1624c1a2edd83ec04a (diff) |
ASoC: simple-card: Fix the reference count of device nodes
The reference count of some device nodes is not correctly reset
at end of card probe.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/generic')
-rw-r--r-- | sound/soc/generic/simple-card.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 5dd47691ba41..dcf37fb69b35 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -105,12 +105,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
105 | /* get dai->name */ | 105 | /* get dai->name */ |
106 | ret = snd_soc_of_get_dai_name(np, name); | 106 | ret = snd_soc_of_get_dai_name(np, name); |
107 | if (ret < 0) | 107 | if (ret < 0) |
108 | goto parse_error; | 108 | return ret; |
109 | 109 | ||
110 | /* parse TDM slot */ | 110 | /* parse TDM slot */ |
111 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | 111 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); |
112 | if (ret) | 112 | if (ret) |
113 | goto parse_error; | 113 | return ret; |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * bitclock-inversion, frame-inversion | 116 | * bitclock-inversion, frame-inversion |
@@ -130,7 +130,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
130 | clk = of_clk_get(np, 0); | 130 | clk = of_clk_get(np, 0); |
131 | if (IS_ERR(clk)) { | 131 | if (IS_ERR(clk)) { |
132 | ret = PTR_ERR(clk); | 132 | ret = PTR_ERR(clk); |
133 | goto parse_error; | 133 | return ret; |
134 | } | 134 | } |
135 | 135 | ||
136 | dai->sysclk = clk_get_rate(clk); | 136 | dai->sysclk = clk_get_rate(clk); |
@@ -144,12 +144,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
144 | dai->sysclk = clk_get_rate(clk); | 144 | dai->sysclk = clk_get_rate(clk); |
145 | } | 145 | } |
146 | 146 | ||
147 | ret = 0; | 147 | return 0; |
148 | |||
149 | parse_error: | ||
150 | of_node_put(node); | ||
151 | |||
152 | return ret; | ||
153 | } | 148 | } |
154 | 149 | ||
155 | static int asoc_simple_card_parse_of(struct device_node *node, | 150 | static int asoc_simple_card_parse_of(struct device_node *node, |
@@ -187,22 +182,26 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
187 | /* CPU sub-node */ | 182 | /* CPU sub-node */ |
188 | ret = -EINVAL; | 183 | ret = -EINVAL; |
189 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); | 184 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); |
190 | if (np) | 185 | if (np) { |
191 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, | 186 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, |
192 | &priv->cpu_dai, | 187 | &priv->cpu_dai, |
193 | &dai_link->cpu_of_node, | 188 | &dai_link->cpu_of_node, |
194 | &dai_link->cpu_dai_name); | 189 | &dai_link->cpu_dai_name); |
190 | of_node_put(np); | ||
191 | } | ||
195 | if (ret < 0) | 192 | if (ret < 0) |
196 | return ret; | 193 | return ret; |
197 | 194 | ||
198 | /* CODEC sub-node */ | 195 | /* CODEC sub-node */ |
199 | ret = -EINVAL; | 196 | ret = -EINVAL; |
200 | np = of_get_child_by_name(node, "simple-audio-card,codec"); | 197 | np = of_get_child_by_name(node, "simple-audio-card,codec"); |
201 | if (np) | 198 | if (np) { |
202 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, | 199 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, |
203 | &priv->codec_dai, | 200 | &priv->codec_dai, |
204 | &dai_link->codec_of_node, | 201 | &dai_link->codec_of_node, |
205 | &dai_link->codec_dai_name); | 202 | &dai_link->codec_dai_name); |
203 | of_node_put(np); | ||
204 | } | ||
206 | if (ret < 0) | 205 | if (ret < 0) |
207 | return ret; | 206 | return ret; |
208 | 207 | ||
@@ -248,6 +247,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
248 | return 0; | 247 | return 0; |
249 | } | 248 | } |
250 | 249 | ||
250 | /* update the reference count of the devices nodes at end of probe */ | ||
251 | static int asoc_simple_card_unref(struct platform_device *pdev) | ||
252 | { | ||
253 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
254 | struct snd_soc_dai_link *dai_link; | ||
255 | struct device_node *np; | ||
256 | int num_links; | ||
257 | |||
258 | for (num_links = 0, dai_link = card->dai_link; | ||
259 | num_links < card->num_links; | ||
260 | num_links++, dai_link++) { | ||
261 | np = (struct device_node *) dai_link->cpu_of_node; | ||
262 | if (np) | ||
263 | of_node_put(np); | ||
264 | np = (struct device_node *) dai_link->codec_of_node; | ||
265 | if (np) | ||
266 | of_node_put(np); | ||
267 | } | ||
268 | return 0; | ||
269 | } | ||
270 | |||
251 | static int asoc_simple_card_probe(struct platform_device *pdev) | 271 | static int asoc_simple_card_probe(struct platform_device *pdev) |
252 | { | 272 | { |
253 | struct simple_card_data *priv; | 273 | struct simple_card_data *priv; |
@@ -275,7 +295,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
275 | if (ret < 0) { | 295 | if (ret < 0) { |
276 | if (ret != -EPROBE_DEFER) | 296 | if (ret != -EPROBE_DEFER) |
277 | dev_err(dev, "parse error %d\n", ret); | 297 | dev_err(dev, "parse error %d\n", ret); |
278 | return ret; | 298 | goto err; |
279 | } | 299 | } |
280 | } else { | 300 | } else { |
281 | struct asoc_simple_card_info *cinfo; | 301 | struct asoc_simple_card_info *cinfo; |
@@ -318,7 +338,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
318 | 338 | ||
319 | snd_soc_card_set_drvdata(&priv->snd_card, priv); | 339 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
320 | 340 | ||
321 | return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); | 341 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
342 | |||
343 | err: | ||
344 | asoc_simple_card_unref(pdev); | ||
345 | return ret; | ||
322 | } | 346 | } |
323 | 347 | ||
324 | static const struct of_device_id asoc_simple_of_match[] = { | 348 | static const struct of_device_id asoc_simple_of_match[] = { |