diff options
author | David Brownell <david-b@pacbell.net> | 2007-05-25 20:40:14 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-06-08 16:24:30 -0700 |
commit | 01ee7d7032204b383b2fba73021e7acbc776184b (patch) | |
tree | 2a5681e94df6ee18287a962394e9e8565e27f5bc /drivers/usb/gadget/rndis.c | |
parent | 97cb95d1c4b724bc3bedd16dd022fbd3c2d61283 (diff) | |
download | blackbird-op-linux-01ee7d7032204b383b2fba73021e7acbc776184b.tar.gz blackbird-op-linux-01ee7d7032204b383b2fba73021e7acbc776184b.zip |
USB: usb gadgets avoid le{16,32}_to_cpup()
It turns out that le16_to_cpup() and le32_to_cpup() aren't always safe
to call with pointers into packed structures, since those are inlined
functions and GCC may lose the "packed" attribute. So those references
can become unaligned kernel accesses, which are evil on some hardware.
This patch updates uses of those routines in the gadget stack. The
references into packed structures can just use leXX_to_cpu(*x), which
in most cases is more natural. Some other uses in RNDIS, mostly in
debug code, were wrong in the first place; those use get_unaligned().
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/rndis.c')
-rw-r--r-- | drivers/usb/gadget/rndis.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6ec8cf1a3ccb..708657c89132 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -186,10 +186,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, DEBUG("query OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { DEBUG ("%03d: %08x %08x %08x %08x\n", i, - le32_to_cpup((__le32 *)&buf[i]), - le32_to_cpup((__le32 *)&buf[i + 4]), - le32_to_cpup((__le32 *)&buf[i + 8]), - le32_to_cpup((__le32 *)&buf[i + 12])); + le32_to_cpu(get_unaligned((__le32 *) + &buf[i])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 4])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 8])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 12]))); } } @@ -665,7 +669,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, break; case OID_PNP_QUERY_POWER: DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, - le32_to_cpup((__le32 *) buf) - 1); + le32_to_cpu(get_unaligned((__le32 *)buf)) - 1); /* only suspend is a real power state, and * it can't be entered by OID_PNP_SET_POWER... */ @@ -704,10 +708,14 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, DEBUG("set OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { DEBUG ("%03d: %08x %08x %08x %08x\n", i, - le32_to_cpup((__le32 *)&buf[i]), - le32_to_cpup((__le32 *)&buf[i + 4]), - le32_to_cpup((__le32 *)&buf[i + 8]), - le32_to_cpup((__le32 *)&buf[i + 12])); + le32_to_cpu(get_unaligned((__le32 *) + &buf[i])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 4])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 8])), + le32_to_cpu(get_unaligned((__le32 *) + &buf[i + 12]))); } } @@ -721,7 +729,8 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * PROMISCUOUS, DIRECTED, * MULTICAST, ALL_MULTICAST, BROADCAST */ - *params->filter = (u16) le32_to_cpup((__le32 *)buf); + *params->filter = (u16) le32_to_cpu(get_unaligned( + (__le32 *)buf)); DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, *params->filter); @@ -771,7 +780,7 @@ update_linkstate: * resuming, Windows forces a reset, and then SET_POWER D0. * FIXME ... then things go batty; Windows wedges itself. */ - i = le32_to_cpup((__force __le32 *)buf); + i = le32_to_cpu(get_unaligned((__le32 *)buf)); DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); switch (i) { case NdisDeviceStateD0: @@ -1058,8 +1067,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf) return -ENOMEM; tmp = (__le32 *) buf; - MsgType = le32_to_cpup(tmp++); - MsgLength = le32_to_cpup(tmp++); + MsgType = le32_to_cpu(get_unaligned(tmp++)); + MsgLength = le32_to_cpu(get_unaligned(tmp++)); if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; |