diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-09-04 00:44:06 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-09-04 15:54:12 +0200 |
commit | 9cfdc6e9ff4ecd8423e397bb3f70a95667b6414a (patch) | |
tree | 55cd4add0e6b6ff9bf2ce58775854a95a6f869e5 | |
parent | ceae25e408adf982c40e223609e50f962fac4486 (diff) | |
download | kernel_samsung_smdk4412-9cfdc6e9ff4ecd8423e397bb3f70a95667b6414a.zip kernel_samsung_smdk4412-9cfdc6e9ff4ecd8423e397bb3f70a95667b6414a.tar.gz kernel_samsung_smdk4412-9cfdc6e9ff4ecd8423e397bb3f70a95667b6414a.tar.bz2 |
net: usb: qmi_wwan: assume raw IP modeqmi
So far, the driver has assumed that the modem operates in ethernet
mode. While this is true for MDM9x15 in its default mode, it's not
what we want. Android expects RIL data connections to use
point-to-point protocol and integrating dhcp client operations into
the RIL is troublesome. So assume raw IP mode and expect that it's set
in userspace.
Some additional adaptions were necessary to ensure that packets don't
get dropped. They were taken from the rmnet driver while using
the mainline qmi_wwan driver as a reference.
It would be better if it would be possible to switch between the modes
with a sysfs property. This functionality could still be added.
Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 58c83d0..bed34e3 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -10,6 +10,7 @@ #include <linux/netdevice.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/if_arp.h> #include <linux/usb.h> #include <linux/usb/cdc.h> #include <linux/usb/usbnet.h> @@ -57,9 +58,36 @@ static const char qmi_pm_dev[] = "mdm_hsic_pm0"; * corresponding management interface */ +static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + __be16 protocol = 0; + + skb->dev = dev->net; + + /* assumes RAW IP mode! */ + + switch (skb->data[0] & 0xf0) { + case 0x40: + protocol = htons(ETH_P_IP); + break; + case 0x60: + protocol = htons(ETH_P_IPV6); + break; + default: + pr_err("[%s] qmi_wwan L3 protocol decode error: 0x%02x", + dev->net->name, skb->data[0] & 0xf0); + } + + skb->protocol = protocol; + + return 1; +} + int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id *prod) { struct usb_device *udev; + struct usbnet *unet; + struct net_device *net_dev; int status; udev = interface_to_usbdev(intf); @@ -70,6 +98,19 @@ int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id *prod) return -1; } + unet = usb_get_intfdata(intf); + net_dev = unet->net; + /* set RAWIP protocol */ + net_dev->header_ops = 0; /* No header */ + net_dev->type = ARPHRD_RAWIP; + net_dev->hard_header_len = 0; + net_dev->addr_len = 0; + net_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); + /* recalculate buffers after changing hard_header_len */ + usbnet_change_mtu(net_dev, net_dev->mtu); + + /* give margin before send DTR high */ + msleep(20); pr_info("%s: send DTR high to modem\n", __func__); status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_CDC_REQ_SET_CONTROL_LINE_STATE, @@ -382,6 +423,7 @@ static const struct driver_info qmi_wwan_info = { .flags = FLAG_WWAN, .bind = qmi_wwan_bind, .manage_power = qmi_wwan_manage_power, + .rx_fixup = qmi_wwan_rx_fixup, }; static const struct driver_info qmi_wwan_shared = { @@ -398,6 +440,7 @@ static const struct driver_info qmi_wwan_gobi = { .bind = qmi_wwan_bind_gobi, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, + .rx_fixup = qmi_wwan_rx_fixup, }; /* ZTE suck at making USB descriptors */ @@ -407,6 +450,7 @@ static const struct driver_info qmi_wwan_force_int4 = { .bind = qmi_wwan_bind_gobi, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, + .rx_fixup = qmi_wwan_rx_fixup, .data = BIT(4), /* interface whitelist bitmap */ }; @@ -491,7 +535,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ - {QMI_GOBI_DEVICE(0x05c6, 0x904c)}, /* MDM9x15 */ + {QMI_GOBI_DEVICE(0x05c6, 0x904c)}, /* MDM9x15 */ { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); |