In file drivers/net/wireless/p54/p54common.c, the statement
priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
generates the sparse warning
.../p54common.c:185:29: warning: cast to restricted __le16
where bootrec->data is u32, and priv->rx_mtu is u16.
What should be done to eliminate this warning?
Thanks,
Larry
Steven Noonan wrote:
> On Thu, Sep 11, 2008 at 7:13 PM, Larry Finger <[email protected]> wrote:
>> In file drivers/net/wireless/p54/p54common.c, the statement
>>
>> priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
>>
>> generates the sparse warning
>>
>> .../p54common.c:185:29: warning: cast to restricted __le16
>>
>> where bootrec->data is u32, and priv->rx_mtu is u16.
>>
>
> (Whoops, didn't CC the mailing lists. Sorry about the double-message, Larry.)
>
> If priv->rx_mtu is u16, I'm surprised it doesn't get noisy about the
> size_t cast. Unless the machine it's being compiled on is 16-bit, that
> should throw a truncation warning, because size_t should be a 32-bit
> integer on 32-bit machines (typically).
>
> I think if you change the (__le16) cast to (__le16 __force) it will
> stop warning you about that particular issue.
This one gets rid of the sparse warning.
priv->rx_mtu = le16_to_cpu((__le16 __force)
bootrec->data[10]);
Thanks,
Larry
On Thu, Sep 11, 2008 at 7:13 PM, Larry Finger <[email protected]> wrote:
> In file drivers/net/wireless/p54/p54common.c, the statement
>
> priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
>
> generates the sparse warning
>
> .../p54common.c:185:29: warning: cast to restricted __le16
>
> where bootrec->data is u32, and priv->rx_mtu is u16.
>
(Whoops, didn't CC the mailing lists. Sorry about the double-message, Larry.)
If priv->rx_mtu is u16, I'm surprised it doesn't get noisy about the
size_t cast. Unless the machine it's being compiled on is 16-bit, that
should throw a truncation warning, because size_t should be a 32-bit
integer on 32-bit machines (typically).
I think if you change the (__le16) cast to (__le16 __force) it will
stop warning you about that particular issue.
- Steven
On Thu, 2008-09-11 at 22:05 -0500, Larry Finger wrote:
> > I would guess you want something like:
> >
> > priv->rx_mtu = le16_to_cpu(((__force __le16 *) bootrec->data)[20]);
> >
> > (__force is what shuts up sparse, and as far as I can see, the size_t
> > cast is useless, since the result will be promoted anyway)
>
> Yes, that one works. As you suspected, this section is parsing data
> from the firmware.
I believe __force should be the last resort. If you want to read a
16-bit little endian value at the given offset, I suggest that you use
le16_to_cpup(), which operates on pointers and does the cast for you.
A better but more elaborate solution would be to define a structure that
would have __le16 rx_mtu at the offset 40. Then you can cast bootrec to
that structure and apply le16_to_cpu() to that field.
--
Regards,
Pavel Roskin
Roland Dreier wrote:
> > In file drivers/net/wireless/p54/p54common.c, the statement
> >
> > priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
>
> [I don't see this code in Linus's tree]
It is in wireless-testing.
>
> the code in question looks buggy to me. Since bootrec->data[10] is u32,
> casting it to a 16-bit type is going to take a different 2 bytes out of
> the 4 bytes depending on the endianness of the system the driver is
> built for. And I assume you are parsing some fixed-layout thing that
> the firmware is giving you or something like that.
>
> I would guess you want something like:
>
> priv->rx_mtu = le16_to_cpu(((__force __le16 *) bootrec->data)[20]);
>
> (__force is what shuts up sparse, and as far as I can see, the size_t
> cast is useless, since the result will be promoted anyway)
Yes, that one works. As you suspected, this section is parsing data
from the firmware.
When I started, there were 18 sparse warnings, and a number of them
were accesses of little-endian variables without an appropriate
leXX_to_cpu() conversion. Obviously, this code has never been tested
on a big-endian machine.
Thanks,
Larry
> In file drivers/net/wireless/p54/p54common.c, the statement
>
> priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
[I don't see this code in Linus's tree]
>
> generates the sparse warning
>
> .../p54common.c:185:29: warning: cast to restricted __le16
>
> where bootrec->data is u32, and priv->rx_mtu is u16.
>
> What should be done to eliminate this warning?
the code in question looks buggy to me. Since bootrec->data[10] is u32,
casting it to a 16-bit type is going to take a different 2 bytes out of
the 4 bytes depending on the endianness of the system the driver is
built for. And I assume you are parsing some fixed-layout thing that
the firmware is giving you or something like that.
I would guess you want something like:
priv->rx_mtu = le16_to_cpu(((__force __le16 *) bootrec->data)[20]);
(__force is what shuts up sparse, and as far as I can see, the size_t
cast is useless, since the result will be promoted anyway)
- R.
Roland Dreier wrote:
> > This one gets rid of the sparse warning.
> >
> > priv->rx_mtu = le16_to_cpu((__le16 __force)
> > bootrec->data[10]);
>
> Yes but does it actually work on both big and little endian systems?
> (See my previous email)
I don't know, but as my previous email stated, the code could not
possibly have worked on a big-endian system before I started the
sparse cleanup. I don't have access to anything but little-endian
hardware.
Larry
On Friday 12 September 2008, Larry Finger wrote:
> Steven Noonan wrote:
> > On Thu, Sep 11, 2008 at 7:13 PM, Larry Finger <[email protected]> wrote:
> >> In file drivers/net/wireless/p54/p54common.c, the statement
> >>
> >> priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
> >>
> >> generates the sparse warning
> >>
> >> .../p54common.c:185:29: warning: cast to restricted __le16
> >>
> >> where bootrec->data is u32, and priv->rx_mtu is u16.
> >>
> >
> > (Whoops, didn't CC the mailing lists. Sorry about the double-message, Larry.)
> >
> > If priv->rx_mtu is u16, I'm surprised it doesn't get noisy about the
> > size_t cast. Unless the machine it's being compiled on is 16-bit, that
> > should throw a truncation warning, because size_t should be a 32-bit
> > integer on 32-bit machines (typically).
> >
> > I think if you change the (__le16) cast to (__le16 __force) it will
> > stop warning you about that particular issue.
>
> This one gets rid of the sparse warning.
>
> priv->rx_mtu = le16_to_cpu((__le16 __force)
> bootrec->data[10]);
I think you should rather fix the type of bootrec->data.
If it is u32, but the data in fact is __le16, please fix the struct instead
of adding dangerous casts.
Note that this is especially dangerous, because you cast between different
typesizes and endianesses at the same time.
> This one gets rid of the sparse warning.
>
> priv->rx_mtu = le16_to_cpu((__le16 __force)
> bootrec->data[10]);
Yes but does it actually work on both big and little endian systems?
(See my previous email)
- R.
On Thu, Sep 11, 2008 at 09:13:20PM -0500, Larry Finger wrote:
> In file drivers/net/wireless/p54/p54common.c, the statement
>
> priv->rx_mtu = (size_t) le16_to_cpu((__le16)bootrec->data[10]);
>
> generates the sparse warning
>
> .../p54common.c:185:29: warning: cast to restricted __le16
>
> where bootrec->data is u32, and priv->rx_mtu is u16.
>
> What should be done to eliminate this warning?
What is the intent?
MTU is 2-byte little-endian starting at 40-th byte?
Oh, and size_t cast is pointless.