diff mbox

net: moxa: fix an error code

Message ID 20160302101110.GI5533@mwanda
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Dan Carpenter March 2, 2016, 10:11 a.m. UTC
We accidentally return IS_ERR(priv->base) which is 1 instead of
PTR_ERR(priv->base) which is the error code.

Fixes: 6c821bd9edc9 ('net: Add MOXA ART SoCs ethernet driver')
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Comments

Arnd Bergmann March 2, 2016, 10:52 a.m. UTC | #1
On Wednesday 02 March 2016 13:11:10 Dan Carpenter wrote:
> We accidentally return IS_ERR(priv->base) which is 1 instead of
> PTR_ERR(priv->base) which is the error code.
> 
> Fixes: 6c821bd9edc9 ('net: Add MOXA ART SoCs ethernet driver')
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

nice catch!

> diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
> index 00cfd95..3e67f45 100644
> --- a/drivers/net/ethernet/moxa/moxart_ether.c
> +++ b/drivers/net/ethernet/moxa/moxart_ether.c
> @@ -474,9 +474,9 @@ static int moxart_mac_probe(struct platform_device *pdev)
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	ndev->base_addr = res->start;
>  	priv->base = devm_ioremap_resource(p_dev, res);
> -	ret = IS_ERR(priv->base);
> -	if (ret) {
> +	if (IS_ERR(priv->base)) {
>  		dev_err(p_dev, "devm_ioremap_resource failed\n");
> +		ret = PTR_ERR(priv->base);
>  		goto init_fail;
>  	}

Did you find more of these?

it doesn't matter much either way, but if you do multiple such patches,
I'd suggest using a single PTR_ERR_OR_ZERO() instead of IS_ERR()+PTR_ERR().

I have found a couple of drivers in which that leads to better object
code, and avoids a warning about a possibly uninitialized variable
when the function gets inlined into another one (which won't happen
for this driver).

	Arnd
Dan Carpenter March 2, 2016, 11:21 a.m. UTC | #2
On Wed, Mar 02, 2016 at 11:52:29AM +0100, Arnd Bergmann wrote:
> Did you find more of these?
> 
> it doesn't matter much either way, but if you do multiple such patches,

One or two.  I already sent the fixes.  I think it was applied.

> I'd suggest using a single PTR_ERR_OR_ZERO() instead of IS_ERR()+PTR_ERR().
> 
> I have found a couple of drivers in which that leads to better object
> code, and avoids a warning about a possibly uninitialized variable
> when the function gets inlined into another one (which won't happen
> for this driver).

Huh?  I sent one where I could have done that but I deliberately didn't
because I wanted the uninitialized warning if I made a mistake.  It
sounds like you're working around a GCC bug...

regards,
dan carpenter
Arnd Bergmann March 2, 2016, 11:36 a.m. UTC | #3
On Wednesday 02 March 2016 14:21:29 Dan Carpenter wrote:
> On Wed, Mar 02, 2016 at 11:52:29AM +0100, Arnd Bergmann wrote:
> > Did you find more of these?
> > 
> > it doesn't matter much either way, but if you do multiple such patches,
> 
> One or two.  I already sent the fixes.  I think it was applied.
> 
> > I'd suggest using a single PTR_ERR_OR_ZERO() instead of IS_ERR()+PTR_ERR().
> > 
> > I have found a couple of drivers in which that leads to better object
> > code, and avoids a warning about a possibly uninitialized variable
> > when the function gets inlined into another one (which won't happen
> > for this driver).
> 
> Huh?  I sent one where I could have done that but I deliberately didn't
> because I wanted the uninitialized warning if I made a mistake.  It
> sounds like you're working around a GCC bug...

The uninitialized warning here is about a type mismatch preventing
gcc from noticing that two conditions are the same, I'm not sure
if this is a bug in gcc, or required by the C standard.

I don't think there is a way in which you would hide a correct
warning about an uninitialized warning.

Have a look at
https://git.kernel.org/cgit/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=07cfdc3071432a07713e4d007c2811e0224490b0

in which get_leaf_nr() uses the IS_ERR()/PTR_ERR() combo to return
an error from a pointer, or return success when the pointer was set,
followed by a warning about the use of the pointer in another
function. My original patch avoided the warning by using IS_ERR_VALUE()
in the caller, but in retrospect, IS_ERR_OR_ZERO() would have been
a nicer solution:

@@ -783,12 +783,15 @@ static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
                       u64 *leaf_out)
 {
        __be64 *hash;
+       int error;
 
        hash = gfs2_dir_get_hash_table(dip);
-       if (IS_ERR(hash))
-               return PTR_ERR(hash);
-       *leaf_out = be64_to_cpu(*(hash + index));
-       return 0;
+       error = PTR_ERR_OR_ZERO(hash);
+
+       if (!error)
+               *leaf_out = be64_to_cpu(*(hash + index));
+
+       return error;
 }

and I've used that elsewhere now when I ran into this kind of
false positive warning.

	Arnd
Dan Carpenter March 2, 2016, 12:15 p.m. UTC | #4
On Wed, Mar 02, 2016 at 12:36:05PM +0100, Arnd Bergmann wrote:
> The uninitialized warning here is about a type mismatch preventing
> gcc from noticing that two conditions are the same, I'm not sure
> if this is a bug in gcc, or required by the C standard.

I wouldn't call it a bug, because everyone has to make trade offs
between how fast the program runs and how accurate it is.  And trade
offs between how ambitious your warnings are vs how many false positives
you can tolerate.

Anyway, I feel like we should just work around GCC on a case by case
basis instead of always using PTR_ERR_OR_ZERO().  The next version of
GCC will fix some false positives and introduce new ones...  Next time
using PTR_ERR_OR_ZERO() could cause warnings instead of fixing them.

Smatch works in a different way and it parse the code correctly.  But
Smatch is slow and sometimes runs out of memory and gives up trying to
parse large functions.  Smatch sees the two returns and tries to figure
out the implications of each (uninitialized vs initialized).  If you
change the code to:

	error = PTR_ERR_OR_ZERO(hash);

	if (!error)
		*leaf_out = be64_to_cpu(*(hash + index));

	return error;

then Smatch still breaks that up into two separate returns which imply
initialized vs uninitialized.

regards,
dan carpenter
Arnd Bergmann March 2, 2016, 12:42 p.m. UTC | #5
On Wednesday 02 March 2016 15:15:26 Dan Carpenter wrote:
> On Wed, Mar 02, 2016 at 12:36:05PM +0100, Arnd Bergmann wrote:
> > The uninitialized warning here is about a type mismatch preventing
> > gcc from noticing that two conditions are the same, I'm not sure
> > if this is a bug in gcc, or required by the C standard.
> 
> I wouldn't call it a bug, because everyone has to make trade offs
> between how fast the program runs and how accurate it is.  And trade
> offs between how ambitious your warnings are vs how many false positives
> you can tolerate.
> 
> Anyway, I feel like we should just work around GCC on a case by case
> basis instead of always using PTR_ERR_OR_ZERO().  The next version of
> GCC will fix some false positives and introduce new ones...  Next time
> using PTR_ERR_OR_ZERO() could cause warnings instead of fixing them.

It depends on whether we think the PTR_ERR_OR_ZERO() actually makes
the code more readable too. I've actually come to like it now,
the main downside being that it looks a lot like IS_ERR_OR_NULL()
which is very bad style and should be avoided at all cost. ;-)

I can also see how PTR_ERR_OR_ZERO() is easier for the compiler
to understand than IS_ERR()+PTR_ERR() and can't think of a case
where it would result in worse object code or extra (false
positive) warnings.

> Smatch works in a different way and it parse the code correctly.  But
> Smatch is slow and sometimes runs out of memory and gives up trying to
> parse large functions.  Smatch sees the two returns and tries to figure
> out the implications of each (uninitialized vs initialized).  If you
> change the code to:
> 
>         error = PTR_ERR_OR_ZERO(hash);
> 
>         if (!error)
>                 *leaf_out = be64_to_cpu(*(hash + index));
> 
>         return error;
> 
> then Smatch still breaks that up into two separate returns which imply
> initialized vs uninitialized.

Right, so it does the right thing, and it presumably understands
that 'if (error)' is the same as 'if (error < 0)' and
'if (IS_ERR_VALUE(error)', right? I think that is where gcc
gets it wrong.

	Arnd
David Miller March 3, 2016, 10:17 p.m. UTC | #6
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Wed, 2 Mar 2016 13:11:10 +0300

> We accidentally return IS_ERR(priv->base) which is 1 instead of
> PTR_ERR(priv->base) which is the error code.
> 
> Fixes: 6c821bd9edc9 ('net: Add MOXA ART SoCs ethernet driver')
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied, thank you Dan.
diff mbox

Patch

diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 00cfd95..3e67f45 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -474,9 +474,9 @@  static int moxart_mac_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ndev->base_addr = res->start;
 	priv->base = devm_ioremap_resource(p_dev, res);
-	ret = IS_ERR(priv->base);
-	if (ret) {
+	if (IS_ERR(priv->base)) {
 		dev_err(p_dev, "devm_ioremap_resource failed\n");
+		ret = PTR_ERR(priv->base);
 		goto init_fail;
 	}