aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/lg-vl600.c
diff options
context:
space:
mode:
authorMark Kamichoff <prox@prolixium.com>2011-08-08 01:29:32 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-08 01:29:32 -0400
commit2ae40ee9872953b4f329a54c82970dfb6854e17e (patch)
tree6c76fc8a2965871d5a0aeef5cdaa68ea9083a2b7 /drivers/net/usb/lg-vl600.c
parent8a4cadc708f04a2a463bc3df0f16859b31d4b051 (diff)
net/usb: Add IPv6 support to the LG-VL600 LTE USB modem driver
The LG-VL600 LTE USB modem supports IPv6, but uses and expects an IPv4 ethertype (0x800) for these packets instead of the standard 0x86dd. This patch peeks at the IP version in the L3 header and sets the ethertype appropriately for IPv6 packets. Signed-off-by: Mark Kamichoff <prox@prolixium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/lg-vl600.c')
-rw-r--r--drivers/net/usb/lg-vl600.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c
index 1d83ccfd7277..1e7221951056 100644
--- a/drivers/net/usb/lg-vl600.c
+++ b/drivers/net/usb/lg-vl600.c
@@ -89,6 +89,8 @@ static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
89 * addresses have no meaning, the destination and the source of every 89 * addresses have no meaning, the destination and the source of every
90 * packet depend only on whether it is on the IN or OUT endpoint. */ 90 * packet depend only on whether it is on the IN or OUT endpoint. */
91 dev->net->flags |= IFF_NOARP; 91 dev->net->flags |= IFF_NOARP;
92 /* IPv6 NDP relies on multicast. Enable it by default. */
93 dev->net->flags |= IFF_MULTICAST;
92 94
93 return ret; 95 return ret;
94} 96}
@@ -200,6 +202,14 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
200 } else { 202 } else {
201 memset(ethhdr->h_source, 0, ETH_ALEN); 203 memset(ethhdr->h_source, 0, ETH_ALEN);
202 memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN); 204 memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
205
206 /* Inbound IPv6 packets have an IPv4 ethertype (0x800)
207 * for some reason. Peek at the L3 header to check
208 * for IPv6 packets, and set the ethertype to IPv6
209 * (0x86dd) so Linux can understand it.
210 */
211 if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
212 ethhdr->h_proto = __constant_htons(ETH_P_IPV6);
203 } 213 }
204 214
205 if (count) { 215 if (count) {
@@ -297,6 +307,15 @@ encapsulate:
297 if (skb->len < full_len) /* Pad */ 307 if (skb->len < full_len) /* Pad */
298 skb_put(skb, full_len - skb->len); 308 skb_put(skb, full_len - skb->len);
299 309
310 /* The VL600 wants IPv6 packets to have an IPv4 ethertype
311 * Check if this is an IPv6 packet, and set the ethertype
312 * to 0x800
313 */
314 if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
315 skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
316 skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
317 }
318
300 return skb; 319 return skb;
301} 320}
302 321