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/ether.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/ether.c')
-rw-r--r-- | drivers/usb/gadget/ether.c | 56 |
1 files changed, 24 insertions, 32 deletions
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index cff9fb0b73cc..3993156c2e82 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -100,6 +100,8 @@ static const char driver_desc [] = DRIVER_DESC; | |||
100 | 100 | ||
101 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ | 101 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ |
102 | #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ | 102 | #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ |
103 | |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ | ||
104 | |USB_CDC_PACKET_TYPE_PROMISCUOUS \ | ||
103 | |USB_CDC_PACKET_TYPE_DIRECTED) | 105 | |USB_CDC_PACKET_TYPE_DIRECTED) |
104 | 106 | ||
105 | 107 | ||
@@ -322,12 +324,18 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); | |||
322 | /* also defer IRQs on highspeed TX */ | 324 | /* also defer IRQs on highspeed TX */ |
323 | #define TX_DELAY qmult | 325 | #define TX_DELAY qmult |
324 | 326 | ||
325 | #define BITRATE(g) (((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS) | 327 | static inline int BITRATE(struct usb_gadget *g) |
328 | { | ||
329 | return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; | ||
330 | } | ||
326 | 331 | ||
327 | #else /* full speed (low speed doesn't do bulk) */ | 332 | #else /* full speed (low speed doesn't do bulk) */ |
328 | #define qlen(gadget) DEFAULT_QLEN | 333 | #define qlen(gadget) DEFAULT_QLEN |
329 | 334 | ||
330 | #define BITRATE(g) FS_BPS | 335 | static inline int BITRATE(struct usb_gadget *g) |
336 | { | ||
337 | return FS_BPS; | ||
338 | } | ||
331 | #endif | 339 | #endif |
332 | 340 | ||
333 | 341 | ||
@@ -1167,7 +1175,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1167 | eth_reset_config (dev); | 1175 | eth_reset_config (dev); |
1168 | 1176 | ||
1169 | /* default: pass all packets, no multicast filtering */ | 1177 | /* default: pass all packets, no multicast filtering */ |
1170 | dev->cdc_filter = 0x000f; | 1178 | dev->cdc_filter = DEFAULT_FILTER; |
1171 | 1179 | ||
1172 | switch (number) { | 1180 | switch (number) { |
1173 | case DEV_CONFIG_VALUE: | 1181 | case DEV_CONFIG_VALUE: |
@@ -1343,9 +1351,9 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1343 | struct eth_dev *dev = get_gadget_data (gadget); | 1351 | struct eth_dev *dev = get_gadget_data (gadget); |
1344 | struct usb_request *req = dev->req; | 1352 | struct usb_request *req = dev->req; |
1345 | int value = -EOPNOTSUPP; | 1353 | int value = -EOPNOTSUPP; |
1346 | u16 wIndex = ctrl->wIndex; | 1354 | u16 wIndex = (__force u16) ctrl->wIndex; |
1347 | u16 wValue = ctrl->wValue; | 1355 | u16 wValue = (__force u16) ctrl->wValue; |
1348 | u16 wLength = ctrl->wLength; | 1356 | u16 wLength = (__force u16) ctrl->wLength; |
1349 | 1357 | ||
1350 | /* descriptors just go into the pre-allocated ep0 buffer, | 1358 | /* descriptors just go into the pre-allocated ep0 buffer, |
1351 | * while config change events may enable network traffic. | 1359 | * while config change events may enable network traffic. |
@@ -1693,7 +1701,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags) | |||
1693 | 1701 | ||
1694 | /* Some platforms perform better when IP packets are aligned, | 1702 | /* Some platforms perform better when IP packets are aligned, |
1695 | * but on at least one, checksumming fails otherwise. Note: | 1703 | * but on at least one, checksumming fails otherwise. Note: |
1696 | * this doesn't account for variable-sized RNDIS headers. | 1704 | * RNDIS headers involve variable numbers of LE32 values. |
1697 | */ | 1705 | */ |
1698 | skb_reserve(skb, NET_IP_ALIGN); | 1706 | skb_reserve(skb, NET_IP_ALIGN); |
1699 | 1707 | ||
@@ -1730,9 +1738,11 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) | |||
1730 | #ifdef CONFIG_USB_ETH_RNDIS | 1738 | #ifdef CONFIG_USB_ETH_RNDIS |
1731 | /* we know MaxPacketsPerTransfer == 1 here */ | 1739 | /* we know MaxPacketsPerTransfer == 1 here */ |
1732 | if (dev->rndis) | 1740 | if (dev->rndis) |
1733 | rndis_rm_hdr (req->buf, &(skb->len)); | 1741 | status = rndis_rm_hdr (skb); |
1734 | #endif | 1742 | #endif |
1735 | if (ETH_HLEN > skb->len || skb->len > ETH_FRAME_LEN) { | 1743 | if (status < 0 |
1744 | || ETH_HLEN > skb->len | ||
1745 | || skb->len > ETH_FRAME_LEN) { | ||
1736 | dev->stats.rx_errors++; | 1746 | dev->stats.rx_errors++; |
1737 | dev->stats.rx_length_errors++; | 1747 | dev->stats.rx_length_errors++; |
1738 | DEBUG (dev, "rx length %d\n", skb->len); | 1748 | DEBUG (dev, "rx length %d\n", skb->len); |
@@ -2047,38 +2057,20 @@ rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) | |||
2047 | DEBUG ((struct eth_dev *) ep->driver_data, | 2057 | DEBUG ((struct eth_dev *) ep->driver_data, |
2048 | "rndis control ack complete --> %d, %d/%d\n", | 2058 | "rndis control ack complete --> %d, %d/%d\n", |
2049 | req->status, req->actual, req->length); | 2059 | req->status, req->actual, req->length); |
2050 | |||
2051 | usb_ep_free_buffer(ep, req->buf, req->dma, 8); | ||
2052 | usb_ep_free_request(ep, req); | ||
2053 | } | 2060 | } |
2054 | 2061 | ||
2055 | static int rndis_control_ack (struct net_device *net) | 2062 | static int rndis_control_ack (struct net_device *net) |
2056 | { | 2063 | { |
2057 | struct eth_dev *dev = netdev_priv(net); | 2064 | struct eth_dev *dev = netdev_priv(net); |
2058 | u32 length; | 2065 | u32 length; |
2059 | struct usb_request *resp; | 2066 | struct usb_request *resp = dev->stat_req; |
2060 | 2067 | ||
2061 | /* in case RNDIS calls this after disconnect */ | 2068 | /* in case RNDIS calls this after disconnect */ |
2062 | if (!dev->status_ep) { | 2069 | if (!dev->status) { |
2063 | DEBUG (dev, "status ENODEV\n"); | 2070 | DEBUG (dev, "status ENODEV\n"); |
2064 | return -ENODEV; | 2071 | return -ENODEV; |
2065 | } | 2072 | } |
2066 | 2073 | ||
2067 | /* Allocate memory for notification ie. ACK */ | ||
2068 | resp = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC); | ||
2069 | if (!resp) { | ||
2070 | DEBUG (dev, "status ENOMEM\n"); | ||
2071 | return -ENOMEM; | ||
2072 | } | ||
2073 | |||
2074 | resp->buf = usb_ep_alloc_buffer (dev->status_ep, 8, | ||
2075 | &resp->dma, GFP_ATOMIC); | ||
2076 | if (!resp->buf) { | ||
2077 | DEBUG (dev, "status buf ENOMEM\n"); | ||
2078 | usb_ep_free_request (dev->status_ep, resp); | ||
2079 | return -ENOMEM; | ||
2080 | } | ||
2081 | |||
2082 | /* Send RNDIS RESPONSE_AVAILABLE notification; | 2074 | /* Send RNDIS RESPONSE_AVAILABLE notification; |
2083 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too | 2075 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too |
2084 | */ | 2076 | */ |
@@ -2113,7 +2105,7 @@ static void eth_start (struct eth_dev *dev, int gfp_flags) | |||
2113 | if (dev->rndis) { | 2105 | if (dev->rndis) { |
2114 | rndis_set_param_medium (dev->rndis_config, | 2106 | rndis_set_param_medium (dev->rndis_config, |
2115 | NDIS_MEDIUM_802_3, | 2107 | NDIS_MEDIUM_802_3, |
2116 | BITRATE(dev->gadget)); | 2108 | BITRATE(dev->gadget)/100); |
2117 | rndis_send_media_state (dev, 1); | 2109 | rndis_send_media_state (dev, 1); |
2118 | } | 2110 | } |
2119 | #endif | 2111 | #endif |
@@ -2307,8 +2299,8 @@ eth_bind (struct usb_gadget *gadget) | |||
2307 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210); | 2299 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210); |
2308 | } else if (gadget_is_pxa27x(gadget)) { | 2300 | } else if (gadget_is_pxa27x(gadget)) { |
2309 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); | 2301 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); |
2310 | } else if (gadget_is_s3c2410(gadget)) { | 2302 | } else if (gadget_is_s3c2410(gadget)) { |
2311 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212); | 2303 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212); |
2312 | } else if (gadget_is_at91(gadget)) { | 2304 | } else if (gadget_is_at91(gadget)) { |
2313 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213); | 2305 | device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213); |
2314 | } else { | 2306 | } else { |