Skip to content

Commit 139fa59

Browse files
morimotobroonie
authored andcommitted
ASoC: rsnd: check rsnd_adg_clk_enable() return value
rsnd_adg_clk_enable() might be failed for some reasons, but it doesn't check return value for now. In such case, we might get below WARNING from clk_disable() during probe or suspend. Check rsnd_adg_clk_enable() return value. clk_multiplier already disabled ... Call trace: clk_core_disable+0xd0/0xd8 (P) clk_disable+0x2c/0x44 rsnd_adg_clk_control+0x80/0xf4 According to Geert, it happened only 7 times during the last 2 years. So I have reproduced the issue and created patch by Intentionally making an error. Link: https://lore.kernel.org/r/CAMuHMdVUKpO2rsia+36BLFFwdMapE8LrYS0duyd0FmrxDvwEfg@mail.gmail.com Reported-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Kuninori Morimoto <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 8f0defd commit 139fa59

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

sound/soc/renesas/rcar/adg.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
374374
return 0;
375375
}
376376

377-
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
377+
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
378378
{
379379
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
380380
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
381381
struct clk *clk;
382-
int i;
382+
int ret = 0, i;
383383

384384
if (enable) {
385385
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
@@ -389,18 +389,33 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
389389

390390
for_each_rsnd_clkin(clk, adg, i) {
391391
if (enable) {
392-
clk_prepare_enable(clk);
392+
ret = clk_prepare_enable(clk);
393393

394394
/*
395395
* We shouldn't use clk_get_rate() under
396396
* atomic context. Let's keep it when
397397
* rsnd_adg_clk_enable() was called
398398
*/
399+
if (ret < 0)
400+
break;
401+
399402
adg->clkin_rate[i] = clk_get_rate(clk);
400403
} else {
401-
clk_disable_unprepare(clk);
404+
if (adg->clkin_rate[i])
405+
clk_disable_unprepare(clk);
406+
407+
adg->clkin_rate[i] = 0;
402408
}
403409
}
410+
411+
/*
412+
* rsnd_adg_clk_enable() might return error (_disable() will not).
413+
* We need to rollback in such case
414+
*/
415+
if (ret < 0)
416+
rsnd_adg_clk_disable(priv);
417+
418+
return ret;
404419
}
405420

406421
static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
@@ -753,7 +768,10 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
753768
if (ret)
754769
return ret;
755770

756-
rsnd_adg_clk_enable(priv);
771+
ret = rsnd_adg_clk_enable(priv);
772+
if (ret)
773+
return ret;
774+
757775
rsnd_adg_clk_dbg_info(priv, NULL);
758776

759777
return 0;

sound/soc/renesas/rcar/core.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,9 +2086,7 @@ static int __maybe_unused rsnd_resume(struct device *dev)
20862086
{
20872087
struct rsnd_priv *priv = dev_get_drvdata(dev);
20882088

2089-
rsnd_adg_clk_enable(priv);
2090-
2091-
return 0;
2089+
return rsnd_adg_clk_enable(priv);
20922090
}
20932091

20942092
static const struct dev_pm_ops rsnd_pm_ops = {

sound/soc/renesas/rcar/rsnd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
608608
struct rsnd_dai_stream *io);
609609
#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
610610
#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
611-
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
611+
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
612612
void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
613613

614614
/*

0 commit comments

Comments
 (0)