[bug report] ASoC: rsnd: add null CLOCKIN support
Hello Kuninori Morimoto,
The patch d6956a7dde6f: "ASoC: rsnd: add null CLOCKIN support" from May 24, 2021, leads to the following static checker warning:
sound/soc/sh/rcar/adg.c:435 rsnd_adg_get_clkin() warn: 'clk' isn't an ERR_PTR
sound/soc/sh/rcar/adg.c 423 static int rsnd_adg_get_clkin(struct rsnd_priv *priv) 424 { 425 struct rsnd_adg *adg = priv->adg; 426 struct device *dev = rsnd_priv_to_dev(priv); 427 struct clk *clk; 428 int i; 429 430 for (i = 0; i < CLKMAX; i++) { 431 clk = devm_clk_get(dev, clk_name[i]);
If devm_clk_get() returns NULL that's not an error.
432 433 if (IS_ERR(clk)) 434 clk = rsnd_adg_null_clk_get(priv);
But I think if rsnd_adg_null_clk_get() returns an error then it is an error.
435 if (IS_ERR(clk))
This is impossible.
436 goto err;
So I think it should be:
if (IS_ERR(clk)) { clk = rsnd_adg_null_clk_get(priv); if (!clk) goto err; }
437 438 adg->clk[i] = clk; 439 } 440 441 return 0; 442 443 err: 444 dev_err(dev, "adg clock IN get failed\n"); 445 446 rsnd_adg_null_clk_clean(priv); 447 448 return -EIO; 449 }
regards, dan carpenter
Hi Dan
Thank you for your research.
sound/soc/sh/rcar/adg.c 423 static int rsnd_adg_get_clkin(struct rsnd_priv *priv) 424 { 425 struct rsnd_adg *adg = priv->adg; 426 struct device *dev = rsnd_priv_to_dev(priv); 427 struct clk *clk; 428 int i; 429 430 for (i = 0; i < CLKMAX; i++) { 431 clk = devm_clk_get(dev, clk_name[i]);
If devm_clk_get() returns NULL that's not an error.
432 433 if (IS_ERR(clk)) 434 clk = rsnd_adg_null_clk_get(priv);
But I think if rsnd_adg_null_clk_get() returns an error then it is an error.
435 if (IS_ERR(clk))
This is impossible.
436 goto err;
So I think it should be:
if (IS_ERR(clk)) { clk = rsnd_adg_null_clk_get(priv); if (!clk) goto err; }
Hmm indeed. Thank you for your report, I didn't notice about it. How about this ?
---------- diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 0ebee1ed06a9..2b05a1568ee8 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -393,7 +393,7 @@ static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv, clk = clk_register_fixed_rate(dev, name, parent, 0, 0); if (IS_ERR(clk)) { dev_err(dev, "create null clk error\n"); - return NULL; + return PTR_ERR(clk); }
return clk; @@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv) for (i = 0; i < CLKMAX; i++) { clk = devm_clk_get(dev, clk_name[i]);
- if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) clk = rsnd_adg_null_clk_get(priv); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) goto err;
adg->clk[i] = clk;
Thank you for your help !!
Best regards --- Kuninori Morimoto
On Thu, Jun 10, 2021 at 08:31:25AM +0900, Kuninori Morimoto wrote:
Hi Dan
Thank you for your research.
sound/soc/sh/rcar/adg.c 423 static int rsnd_adg_get_clkin(struct rsnd_priv *priv) 424 { 425 struct rsnd_adg *adg = priv->adg; 426 struct device *dev = rsnd_priv_to_dev(priv); 427 struct clk *clk; 428 int i; 429 430 for (i = 0; i < CLKMAX; i++) { 431 clk = devm_clk_get(dev, clk_name[i]);
If devm_clk_get() returns NULL that's not an error.
432 433 if (IS_ERR(clk)) 434 clk = rsnd_adg_null_clk_get(priv);
But I think if rsnd_adg_null_clk_get() returns an error then it is an error.
435 if (IS_ERR(clk))
This is impossible.
436 goto err;
So I think it should be:
if (IS_ERR(clk)) { clk = rsnd_adg_null_clk_get(priv); if (!clk) goto err; }
Hmm indeed. Thank you for your report, I didn't notice about it. How about this ?
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 0ebee1ed06a9..2b05a1568ee8 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -393,7 +393,7 @@ static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv, clk = clk_register_fixed_rate(dev, name, parent, 0, 0); if (IS_ERR(clk)) { dev_err(dev, "create null clk error\n");
return NULL;
return PTR_ERR(clk);
Yes, I think this part is correct. If an error happens, then it should be reported to the user so they can fix it.
}
return clk; @@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv) for (i = 0; i < CLKMAX; i++) { clk = devm_clk_get(dev, clk_name[i]);
if (IS_ERR(clk))
if (IS_ERR_OR_NULL(clk)) clk = rsnd_adg_null_clk_get(priv);
if (IS_ERR(clk))
if (IS_ERR_OR_NULL(clk)) goto err;
But this is not correct.
If a function like devm_clk_get() returns NULL, then it's not an error, it's something where the user deliberately chose to disable the feature. It shouldn't trigger an error message and the rest of the driver should be written to accomodate it.
adg->clk[i] = clk;
So we should assign the NULL pointer here and add NULL checks to make sure that it doesn't lead to a NULL dereference.
regards, dan carpenter
Hi Dan
Thank you for your feedback
if (IS_ERR(clk)) { dev_err(dev, "create null clk error\n");
return NULL;
return PTR_ERR(clk);
Yes, I think this part is correct. If an error happens, then it should be reported to the user so they can fix it.
Good !
@@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv) for (i = 0; i < CLKMAX; i++) { clk = devm_clk_get(dev, clk_name[i]);
if (IS_ERR(clk))
if (IS_ERR_OR_NULL(clk)) clk = rsnd_adg_null_clk_get(priv);
if (IS_ERR(clk))
if (IS_ERR_OR_NULL(clk)) goto err;
But this is not correct.
If a function like devm_clk_get() returns NULL, then it's not an error, it's something where the user deliberately chose to disable the feature. It shouldn't trigger an error message and the rest of the driver should be written to accomodate it.
adg->clk[i] = clk;
So we should assign the NULL pointer here and add NULL checks to make sure that it doesn't lead to a NULL dereference.
Ah, in this driver, if it got error or NULL clk, it try to call rsnd_adg_null_clk_get() and use null_clk instead of NULL. In other words, all adg->clk[i] should not NULL. If one of them was NULL, it is error for this driver. If so, my suggested code was OK, I hope.
Thank you for your help !!
Best regards --- Kuninori Morimoto
participants (2)
-
Dan Carpenter
-
Kuninori Morimoto