mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 13:15:57 +00:00
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 <geert@linux-m68k.org> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://patch.msgid.link/87seps2522.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
8f0defd2e5
commit
139fa599ce
@ -374,12 +374,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
||||
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
||||
{
|
||||
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
|
||||
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
|
||||
struct clk *clk;
|
||||
int i;
|
||||
int ret = 0, i;
|
||||
|
||||
if (enable) {
|
||||
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
|
||||
@ -389,18 +389,33 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
||||
|
||||
for_each_rsnd_clkin(clk, adg, i) {
|
||||
if (enable) {
|
||||
clk_prepare_enable(clk);
|
||||
ret = clk_prepare_enable(clk);
|
||||
|
||||
/*
|
||||
* We shouldn't use clk_get_rate() under
|
||||
* atomic context. Let's keep it when
|
||||
* rsnd_adg_clk_enable() was called
|
||||
*/
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
adg->clkin_rate[i] = clk_get_rate(clk);
|
||||
} else {
|
||||
clk_disable_unprepare(clk);
|
||||
if (adg->clkin_rate[i])
|
||||
clk_disable_unprepare(clk);
|
||||
|
||||
adg->clkin_rate[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rsnd_adg_clk_enable() might return error (_disable() will not).
|
||||
* We need to rollback in such case
|
||||
*/
|
||||
if (ret < 0)
|
||||
rsnd_adg_clk_disable(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
|
||||
@ -753,7 +768,10 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsnd_adg_clk_enable(priv);
|
||||
ret = rsnd_adg_clk_enable(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsnd_adg_clk_dbg_info(priv, NULL);
|
||||
|
||||
return 0;
|
||||
|
@ -2086,9 +2086,7 @@ static int __maybe_unused rsnd_resume(struct device *dev)
|
||||
{
|
||||
struct rsnd_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
rsnd_adg_clk_enable(priv);
|
||||
|
||||
return 0;
|
||||
return rsnd_adg_clk_enable(priv);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rsnd_pm_ops = {
|
||||
|
@ -608,7 +608,7 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
|
||||
struct rsnd_dai_stream *io);
|
||||
#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
|
||||
#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
|
||||
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
|
||||
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
|
||||
void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user