aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-09-04 00:44:06 +0200
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-09-04 15:54:12 +0200
commit9cfdc6e9ff4ecd8423e397bb3f70a95667b6414a (patch)
tree55cd4add0e6b6ff9bf2ce58775854a95a6f869e5
parentceae25e408adf982c40e223609e50f962fac4486 (diff)
downloadkernel_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.c46
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);