diff options
author | David Brownell <david-b@pacbell.net> | 2005-04-18 20:39:34 -0400 |
---|---|---|
committer | Greg K-H <gregkh@suse.de> | 2005-04-18 20:39:34 -0400 |
commit | 6cdee106e7571751ecc0e9f96606322f88b64a8d (patch) | |
tree | edc75e42c3f3e9bbfecabc12a51b0f6d1bb37930 /drivers/usb/gadget/rndis.c | |
parent | 1bc3c9e1e44c2059fe2ffa6ff70ad0a925d7b05f (diff) |
[PATCH] usb gadget: ethernet/rndis updates
Updates to the Ethernet/RNDIS gadget driver (mostly for RNDIS):
- Fix brown-paper bag goof with RNDIS packet TX ... the wrong length
field got set, so Windows would ignore data packets it received.
- More consistent handling of CDC output filters (but not yet hooking
things up so RNDIS uses the mechanism).
- Zerocopy RX for RNDIS packets too (saving CPU cycles).
- Use the pre-allocated interrupt/status request and buffer, rather
than allocating and freeing one of each every few seconds (which
could fail).
- Some more "sparse" tweaks, making both dual-speed and single-speed
configurations happier.
- RNDIS speeds are reported in units of 100bps, not bps.
Plus two minor cleanups (whitespace, messaging).
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 | 40 |
1 files changed, 19 insertions, 21 deletions
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6c5197850edc..7457268d5f28 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
38 | #include <asm/byteorder.h> | 38 | #include <asm/byteorder.h> |
39 | #include <asm/system.h> | 39 | #include <asm/system.h> |
40 | #include <asm/unaligned.h> | ||
40 | 41 | ||
41 | 42 | ||
42 | #undef RNDIS_PM | 43 | #undef RNDIS_PM |
@@ -165,7 +166,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
165 | 166 | ||
166 | /* mandatory */ | 167 | /* mandatory */ |
167 | case OID_GEN_LINK_SPEED: | 168 | case OID_GEN_LINK_SPEED: |
168 | DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); | 169 | // DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); |
169 | length = 4; | 170 | length = 4; |
170 | if (rndis_per_dev_params [configNr].media_state | 171 | if (rndis_per_dev_params [configNr].media_state |
171 | == NDIS_MEDIA_STATE_DISCONNECTED) | 172 | == NDIS_MEDIA_STATE_DISCONNECTED) |
@@ -729,7 +730,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
729 | retval = 0; | 730 | retval = 0; |
730 | 731 | ||
731 | /* FIXME use these NDIS_PACKET_TYPE_* bitflags to | 732 | /* FIXME use these NDIS_PACKET_TYPE_* bitflags to |
732 | * filter packets in hard_start_xmit() | 733 | * set the cdc_filter; it's not RNDIS-specific |
733 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: | 734 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: |
734 | * PROMISCUOUS, DIRECTED, | 735 | * PROMISCUOUS, DIRECTED, |
735 | * MULTICAST, ALL_MULTICAST, BROADCAST | 736 | * MULTICAST, ALL_MULTICAST, BROADCAST |
@@ -1194,10 +1195,10 @@ void rndis_add_hdr (struct sk_buff *skb) | |||
1194 | return; | 1195 | return; |
1195 | header = (void *) skb_push (skb, sizeof *header); | 1196 | header = (void *) skb_push (skb, sizeof *header); |
1196 | memset (header, 0, sizeof *header); | 1197 | memset (header, 0, sizeof *header); |
1197 | header->MessageType = __constant_cpu_to_le32 (1); | 1198 | header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG); |
1198 | header->MessageLength = cpu_to_le32(skb->len); | 1199 | header->MessageLength = cpu_to_le32(skb->len); |
1199 | header->DataOffset = __constant_cpu_to_le32 (36); | 1200 | header->DataOffset = __constant_cpu_to_le32 (36); |
1200 | header->OOBDataOffset = cpu_to_le32(skb->len - 44); | 1201 | header->DataLength = cpu_to_le32(skb->len - sizeof *header); |
1201 | } | 1202 | } |
1202 | 1203 | ||
1203 | void rndis_free_response (int configNr, u8 *buf) | 1204 | void rndis_free_response (int configNr, u8 *buf) |
@@ -1253,26 +1254,23 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length) | |||
1253 | return r; | 1254 | return r; |
1254 | } | 1255 | } |
1255 | 1256 | ||
1256 | int rndis_rm_hdr (u8 *buf, u32 *length) | 1257 | int rndis_rm_hdr(struct sk_buff *skb) |
1257 | { | 1258 | { |
1258 | u32 i, messageLen, dataOffset; | 1259 | /* tmp points to a struct rndis_packet_msg_type */ |
1259 | __le32 *tmp; | 1260 | __le32 *tmp = (void *) skb->data; |
1260 | |||
1261 | tmp = (__le32 *) buf; | ||
1262 | 1261 | ||
1263 | if (!buf || !length) return -1; | 1262 | /* MessageType, MessageLength */ |
1264 | if (le32_to_cpup(tmp++) != 1) return -1; | 1263 | if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG) |
1265 | 1264 | != get_unaligned(tmp++)) | |
1266 | messageLen = le32_to_cpup(tmp++); | 1265 | return -EINVAL; |
1267 | dataOffset = le32_to_cpup(tmp++) + 8; | 1266 | tmp++; |
1267 | |||
1268 | /* DataOffset, DataLength */ | ||
1269 | if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++)) | ||
1270 | + 8 /* offset of DataOffset */)) | ||
1271 | return -EOVERFLOW; | ||
1272 | skb_trim(skb, le32_to_cpu(get_unaligned(tmp++))); | ||
1268 | 1273 | ||
1269 | if (messageLen < dataOffset || messageLen > *length) return -1; | ||
1270 | |||
1271 | for (i = dataOffset; i < messageLen; i++) | ||
1272 | buf [i - dataOffset] = buf [i]; | ||
1273 | |||
1274 | *length = messageLen - dataOffset; | ||
1275 | |||
1276 | return 0; | 1274 | return 0; |
1277 | } | 1275 | } |
1278 | 1276 | ||