aboutsummaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/linux/generic/patches-4.4/099-0001-usbnet-allow-mini-drivers-to-consume-L2-headers.patch39
-rw-r--r--target/linux/generic/patches-4.4/099-0002-net-qmi_wwan-support-raw-IP-mode.patch206
-rw-r--r--target/linux/generic/patches-4.4/099-0003-net-qmi_wwan-should-hold-RTNL-while-changing-netdev-.patch107
-rw-r--r--target/linux/generic/patches-4.4/099-0004-usbnet-fix-alignment-for-frames-with-no-ethernet-hea.patch73
-rw-r--r--target/linux/generic/patches-4.4/099-0005-qmi_wwan-Add-missing-skb_reset_mac_header-call.patch81
-rw-r--r--target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch97
-rw-r--r--target/linux/generic/patches-4.4/099-0007-qmi_wwan-add-support-for-Quectel-EC21-and-EC25.patch98
7 files changed, 701 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.4/099-0001-usbnet-allow-mini-drivers-to-consume-L2-headers.patch b/target/linux/generic/patches-4.4/099-0001-usbnet-allow-mini-drivers-to-consume-L2-headers.patch
new file mode 100644
index 0000000000..a1f19ea18e
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0001-usbnet-allow-mini-drivers-to-consume-L2-headers.patch
@@ -0,0 +1,39 @@
+From 81e0ce79f2919dbd5f025894d29aa806af8695c7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Thu, 3 Dec 2015 19:24:20 +0100
+Subject: [PATCH] usbnet: allow mini-drivers to consume L2 headers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Assume the minidriver has taken care of all L2 header parsing
+if it sets skb->protocol. This allows the minidriver to
+support non-ethernet L2 headers, and even operate without
+any L2 header at all.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/usbnet.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 0744bf2ef2d6..0b0ba7ef14e4 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -324,7 +324,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
+ return;
+ }
+
+- skb->protocol = eth_type_trans (skb, dev->net);
++ /* only update if unset to allow minidriver rx_fixup override */
++ if (skb->protocol == 0)
++ skb->protocol = eth_type_trans (skb, dev->net);
++
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += skb->len;
+
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0002-net-qmi_wwan-support-raw-IP-mode.patch b/target/linux/generic/patches-4.4/099-0002-net-qmi_wwan-support-raw-IP-mode.patch
new file mode 100644
index 0000000000..8b5fc374b3
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0002-net-qmi_wwan-support-raw-IP-mode.patch
@@ -0,0 +1,206 @@
+From 32f7adf633b9f99ad5089901bc7ebff57704aaa9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Thu, 3 Dec 2015 19:24:21 +0100
+Subject: [PATCH] net: qmi_wwan: support "raw IP" mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+QMI wwan devices have traditionally emulated ethernet devices
+by default. But they have always had the capability of operating
+without any L2 header at all, transmitting and receiving "raw"
+IP packets over the USB link. This firmware feature used to be
+configurable through the QMI management protocol.
+
+Traditionally there was no way to verify the firmware mode
+without attempting to change it. And the firmware would often
+disallow changes anyway, i.e. due to a session already being
+established. In some cases, this could be a hidden firmware
+internal session, completely outside host control. For these
+reasons, sticking with the "well known" default mode was safest.
+
+But newer generations of QMI hardware and firmware have moved
+towards defaulting to "raw IP" mode instead, followed by an
+increasing number of bugs in the already buggy "802.3" firmware
+implementation. At the same time, the QMI management protocol
+gained the ability to detect the current mode. This has enabled
+the userspace QMI management application to verify the current
+firmware mode without trying to modify it.
+
+Following this development, the latest QMI hardware and firmware
+(the MDM9x30 generation) has dropped support for "802.3" mode
+entirely. Support for "raw IP" framing in the driver is therefore
+necessary for these devices, and to a certain degree to work
+around problems with the previous generation,
+
+This patch adds support for "raw IP" framing for QMI devices,
+changing the netdev from an ethernet device to an ARPHRD_NONE
+p-t-p device when "raw IP" framing is enabled.
+
+The firmware setup is fully delegated to the QMI userspace
+management application, through simple tunneling of the QMI
+protocol. The driver will therefore not know which mode has been
+"negotiated" between firmware and userspace. Allowing userspace
+to inform the driver of the result through a sysfs switch is
+considered a better alternative than to change the well established
+clean delegation of firmware management to userspace.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 98 +++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 97 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index e3727b66d850..98add3bf8821 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -14,6 +14,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/ethtool.h>
+ #include <linux/etherdevice.h>
++#include <linux/if_arp.h>
+ #include <linux/mii.h>
+ #include <linux/usb.h>
+ #include <linux/usb/cdc.h>
+@@ -48,11 +49,93 @@
+ struct qmi_wwan_state {
+ struct usb_driver *subdriver;
+ atomic_t pmcount;
+- unsigned long unused;
++ unsigned long flags;
+ struct usb_interface *control;
+ struct usb_interface *data;
+ };
+
++enum qmi_wwan_flags {
++ QMI_WWAN_FLAG_RAWIP = 1 << 0,
++};
++
++static void qmi_wwan_netdev_setup(struct net_device *net)
++{
++ struct usbnet *dev = netdev_priv(net);
++ struct qmi_wwan_state *info = (void *)&dev->data;
++
++ if (info->flags & QMI_WWAN_FLAG_RAWIP) {
++ net->header_ops = NULL; /* No header */
++ net->type = ARPHRD_NONE;
++ net->hard_header_len = 0;
++ net->addr_len = 0;
++ net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
++ netdev_dbg(net, "mode: raw IP\n");
++ } else if (!net->header_ops) { /* don't bother if already set */
++ ether_setup(net);
++ netdev_dbg(net, "mode: Ethernet\n");
++ }
++
++ /* recalculate buffers after changing hard_header_len */
++ usbnet_change_mtu(net, net->mtu);
++}
++
++static ssize_t raw_ip_show(struct device *d, struct device_attribute *attr, char *buf)
++{
++ struct usbnet *dev = netdev_priv(to_net_dev(d));
++ struct qmi_wwan_state *info = (void *)&dev->data;
++
++ return sprintf(buf, "%c\n", info->flags & QMI_WWAN_FLAG_RAWIP ? 'Y' : 'N');
++}
++
++static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len)
++{
++ struct usbnet *dev = netdev_priv(to_net_dev(d));
++ struct qmi_wwan_state *info = (void *)&dev->data;
++ bool enable;
++ int err;
++
++ if (strtobool(buf, &enable))
++ return -EINVAL;
++
++ /* no change? */
++ if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP))
++ return len;
++
++ /* we don't want to modify a running netdev */
++ if (netif_running(dev->net)) {
++ netdev_err(dev->net, "Cannot change a running device\n");
++ return -EBUSY;
++ }
++
++ /* let other drivers deny the change */
++ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev->net);
++ err = notifier_to_errno(err);
++ if (err) {
++ netdev_err(dev->net, "Type change was refused\n");
++ return err;
++ }
++
++ if (enable)
++ info->flags |= QMI_WWAN_FLAG_RAWIP;
++ else
++ info->flags &= ~QMI_WWAN_FLAG_RAWIP;
++ qmi_wwan_netdev_setup(dev->net);
++ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev->net);
++ return len;
++}
++
++static DEVICE_ATTR_RW(raw_ip);
++
++static struct attribute *qmi_wwan_sysfs_attrs[] = {
++ &dev_attr_raw_ip.attr,
++ NULL,
++};
++
++static struct attribute_group qmi_wwan_sysfs_attr_group = {
++ .name = "qmi",
++ .attrs = qmi_wwan_sysfs_attrs,
++};
++
+ /* default ethernet address used by the modem */
+ static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
+
+@@ -80,6 +163,8 @@ static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
+ */
+ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ {
++ struct qmi_wwan_state *info = (void *)&dev->data;
++ bool rawip = info->flags & QMI_WWAN_FLAG_RAWIP;
+ __be16 proto;
+
+ /* This check is no longer done by usbnet */
+@@ -94,15 +179,25 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ proto = htons(ETH_P_IPV6);
+ break;
+ case 0x00:
++ if (rawip)
++ return 0;
+ if (is_multicast_ether_addr(skb->data))
+ return 1;
+ /* possibly bogus destination - rewrite just in case */
+ skb_reset_mac_header(skb);
+ goto fix_dest;
+ default:
++ if (rawip)
++ return 0;
+ /* pass along other packets without modifications */
+ return 1;
+ }
++ if (rawip) {
++ skb->dev = dev->net; /* normally set by eth_type_trans */
++ skb->protocol = proto;
++ return 1;
++ }
++
+ if (skb_headroom(skb) < ETH_HLEN)
+ return 0;
+ skb_push(skb, ETH_HLEN);
+@@ -326,6 +421,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
+ }
+ dev->net->netdev_ops = &qmi_wwan_netdev_ops;
++ dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
+ err:
+ return status;
+ }
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0003-net-qmi_wwan-should-hold-RTNL-while-changing-netdev-.patch b/target/linux/generic/patches-4.4/099-0003-net-qmi_wwan-should-hold-RTNL-while-changing-netdev-.patch
new file mode 100644
index 0000000000..48f7141efb
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0003-net-qmi_wwan-should-hold-RTNL-while-changing-netdev-.patch
@@ -0,0 +1,107 @@
+From 6c730080e663b1d629f8aa89348291fbcdc46cd9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Sun, 6 Dec 2015 21:25:50 +0100
+Subject: [PATCH] net: qmi_wwan: should hold RTNL while changing netdev type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The notifier calls were thrown in as a last-minute fix for an
+imagined "this device could be part of a bridge" problem. That
+revealed a certain lack of locking. Not to mention testing...
+
+Avoid this splat:
+
+RTNL: assertion failed at net/core/dev.c (1639)
+CPU: 0 PID: 4293 Comm: bash Not tainted 4.4.0-rc3+ #358
+Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 12/19/2011
+ 0000000000000000 ffff8800ad253d60 ffffffff8122f7cf ffff8800ad253d98
+ ffff8800ad253d88 ffffffff813833ab 0000000000000002 ffff880230f48560
+ ffff880230a12900 ffff8800ad253da0 ffffffff813833da 0000000000000002
+Call Trace:
+ [<ffffffff8122f7cf>] dump_stack+0x4b/0x63
+ [<ffffffff813833ab>] call_netdevice_notifiers_info+0x3d/0x59
+ [<ffffffff813833da>] call_netdevice_notifiers+0x13/0x15
+ [<ffffffffa09be227>] raw_ip_store+0x81/0x193 [qmi_wwan]
+ [<ffffffff8131e149>] dev_attr_store+0x20/0x22
+ [<ffffffff811d858b>] sysfs_kf_write+0x49/0x50
+ [<ffffffff811d8027>] kernfs_fop_write+0x10a/0x151
+ [<ffffffff8117249a>] __vfs_write+0x26/0xa5
+ [<ffffffff81085ed4>] ? percpu_down_read+0x53/0x7f
+ [<ffffffff81174c9e>] ? __sb_start_write+0x5f/0xb0
+ [<ffffffff81174c9e>] ? __sb_start_write+0x5f/0xb0
+ [<ffffffff81172c37>] vfs_write+0xa3/0xe7
+ [<ffffffff811734ad>] SyS_write+0x50/0x7e
+ [<ffffffff8145c517>] entry_SYSCALL_64_fastpath+0x12/0x6f
+
+Fixes: 32f7adf633b9 ("net: qmi_wwan: support "raw IP" mode")
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 98add3bf8821..babc84a3946c 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -16,6 +16,7 @@
+ #include <linux/etherdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/mii.h>
++#include <linux/rtnetlink.h>
+ #include <linux/usb.h>
+ #include <linux/usb/cdc.h>
+ #include <linux/usb/usbnet.h>
+@@ -92,7 +93,7 @@ static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, co
+ struct usbnet *dev = netdev_priv(to_net_dev(d));
+ struct qmi_wwan_state *info = (void *)&dev->data;
+ bool enable;
+- int err;
++ int ret;
+
+ if (strtobool(buf, &enable))
+ return -EINVAL;
+@@ -101,18 +102,22 @@ static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, co
+ if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP))
+ return len;
+
++ if (!rtnl_trylock())
++ return restart_syscall();
++
+ /* we don't want to modify a running netdev */
+ if (netif_running(dev->net)) {
+ netdev_err(dev->net, "Cannot change a running device\n");
+- return -EBUSY;
++ ret = -EBUSY;
++ goto err;
+ }
+
+ /* let other drivers deny the change */
+- err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev->net);
+- err = notifier_to_errno(err);
+- if (err) {
++ ret = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev->net);
++ ret = notifier_to_errno(ret);
++ if (ret) {
+ netdev_err(dev->net, "Type change was refused\n");
+- return err;
++ goto err;
+ }
+
+ if (enable)
+@@ -121,7 +126,10 @@ static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, co
+ info->flags &= ~QMI_WWAN_FLAG_RAWIP;
+ qmi_wwan_netdev_setup(dev->net);
+ call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev->net);
+- return len;
++ ret = len;
++err:
++ rtnl_unlock();
++ return ret;
+ }
+
+ static DEVICE_ATTR_RW(raw_ip);
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0004-usbnet-fix-alignment-for-frames-with-no-ethernet-hea.patch b/target/linux/generic/patches-4.4/099-0004-usbnet-fix-alignment-for-frames-with-no-ethernet-hea.patch
new file mode 100644
index 0000000000..2511e0a961
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0004-usbnet-fix-alignment-for-frames-with-no-ethernet-hea.patch
@@ -0,0 +1,73 @@
+From a4abd7a80addb4a9547f7dfc7812566b60ec505c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Wed, 6 Dec 2017 20:21:24 +0100
+Subject: [PATCH] usbnet: fix alignment for frames with no ethernet header
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The qmi_wwan minidriver support a 'raw-ip' mode where frames are
+received without any ethernet header. This causes alignment issues
+because the skbs allocated by usbnet are "IP aligned".
+
+Fix by allowing minidrivers to disable the additional alignment
+offset. This is implemented using a per-device flag, since the same
+minidriver also supports 'ethernet' mode.
+
+Fixes: 32f7adf633b9 ("net: qmi_wwan: support "raw IP" mode")
+Reported-and-tested-by: Jay Foster <jay@systech.com>
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 2 ++
+ drivers/net/usb/usbnet.c | 5 ++++-
+ include/linux/usb/usbnet.h | 1 +
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index c750cf7c042b..304ec6555cd8 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -261,9 +261,11 @@ static void qmi_wwan_netdev_setup(struct net_device *net)
+ net->hard_header_len = 0;
+ net->addr_len = 0;
+ net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
++ set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
+ netdev_dbg(net, "mode: raw IP\n");
+ } else if (!net->header_ops) { /* don't bother if already set */
+ ether_setup(net);
++ clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
+ netdev_dbg(net, "mode: Ethernet\n");
+ }
+
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 80348b6a8646..d56fe32bf48d 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -484,7 +484,10 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
+ return -ENOLINK;
+ }
+
+- skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
++ if (test_bit(EVENT_NO_IP_ALIGN, &dev->flags))
++ skb = __netdev_alloc_skb(dev->net, size, flags);
++ else
++ skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
+ if (!skb) {
+ netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
+diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
+index a69877734c4e..e2ec3582e549 100644
+--- a/include/linux/usb/usbnet.h
++++ b/include/linux/usb/usbnet.h
+@@ -82,6 +82,7 @@ struct usbnet {
+ # define EVENT_RX_KILL 10
+ # define EVENT_LINK_CHANGE 11
+ # define EVENT_SET_RX_MODE 12
++# define EVENT_NO_IP_ALIGN 13
+ };
+
+ static inline struct usb_driver *driver_of(struct usb_interface *intf)
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0005-qmi_wwan-Add-missing-skb_reset_mac_header-call.patch b/target/linux/generic/patches-4.4/099-0005-qmi_wwan-Add-missing-skb_reset_mac_header-call.patch
new file mode 100644
index 0000000000..08408e2414
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0005-qmi_wwan-Add-missing-skb_reset_mac_header-call.patch
@@ -0,0 +1,81 @@
+From 0de0add10e587effa880c741c9413c874f16be91 Mon Sep 17 00:00:00 2001
+From: Kristian Evensen <kristian.evensen@gmail.com>
+Date: Tue, 7 Nov 2017 13:47:56 +0100
+Subject: [PATCH] qmi_wwan: Add missing skb_reset_mac_header-call
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When we receive a packet on a QMI device in raw IP mode, we should call
+skb_reset_mac_header() to ensure that skb->mac_header contains a valid
+offset in the packet. While it shouldn't really matter, the packets have
+no MAC header and the interface is configured as-such, it seems certain
+parts of the network stack expects a "good" value in skb->mac_header.
+
+Without the skb_reset_mac_header() call added in this patch, for example
+shaping traffic (using tc) triggers the following oops on the first
+received packet:
+
+[ 303.642957] skbuff: skb_under_panic: text:8f137918 len:177 put:67 head:8e4b0f00 data:8e4b0eff tail:0x8e4b0fb0 end:0x8e4b1520 dev:wwan0
+[ 303.655045] Kernel bug detected[#1]:
+[ 303.658622] CPU: 1 PID: 1002 Comm: logd Not tainted 4.9.58 #0
+[ 303.664339] task: 8fdf05e0 task.stack: 8f15c000
+[ 303.668844] $ 0 : 00000000 00000001 0000007a 00000000
+[ 303.674062] $ 4 : 8149a2fc 8149a2fc 8149ce20 00000000
+[ 303.679284] $ 8 : 00000030 3878303a 31623465 20303235
+[ 303.684510] $12 : ded731e3 2626a277 00000000 03bd0000
+[ 303.689747] $16 : 8ef62b40 00000043 8f137918 804db5fc
+[ 303.694978] $20 : 00000001 00000004 8fc13800 00000003
+[ 303.700215] $24 : 00000001 8024ab10
+[ 303.705442] $28 : 8f15c000 8fc19cf0 00000043 802cc920
+[ 303.710664] Hi : 00000000
+[ 303.713533] Lo : 74e58000
+[ 303.716436] epc : 802cc920 skb_panic+0x58/0x5c
+[ 303.721046] ra : 802cc920 skb_panic+0x58/0x5c
+[ 303.725639] Status: 11007c03 KERNEL EXL IE
+[ 303.729823] Cause : 50800024 (ExcCode 09)
+[ 303.733817] PrId : 0001992f (MIPS 1004Kc)
+[ 303.737892] Modules linked in: rt2800pci rt2800mmio rt2800lib qcserial ppp_async option usb_wwan rt2x00pci rt2x00mmio rt2x00lib rndis_host qmi_wwan ppp_generic nf_nat_pptp nf_conntrack_pptp nf_conntrack_ipv6 mt76x2i
+Process logd (pid: 1002, threadinfo=8f15c000, task=8fdf05e0, tls=77b3eee4)
+[ 303.962509] Stack : 00000000 80408990 8f137918 000000b1 00000043 8e4b0f00 8e4b0eff 8e4b0fb0
+[ 303.970871] 8e4b1520 8fec1800 00000043 802cd2a4 6e000045 00000043 00000000 8ef62000
+[ 303.979219] 8eef5d00 8ef62b40 8fea7300 8f137918 00000000 00000000 0002bb01 793e5664
+[ 303.987568] 8ef08884 00000001 8fea7300 00000002 8fc19e80 8eef5d00 00000006 00000003
+[ 303.995934] 00000000 8030ba90 00000003 77ab3fd0 8149dc80 8004d1bc 8f15c000 8f383700
+[ 304.004324] ...
+[ 304.006767] Call Trace:
+[ 304.009241] [<802cc920>] skb_panic+0x58/0x5c
+[ 304.013504] [<802cd2a4>] skb_push+0x78/0x90
+[ 304.017783] [<8f137918>] 0x8f137918
+[ 304.021269] Code: 00602825 0c02a3b4 24842888 <000c000d> 8c870060 8c8200a0 0007382b 00070336 8c88005c
+[ 304.031034]
+[ 304.032805] ---[ end trace b778c482b3f0bda9 ]---
+[ 304.041384] Kernel panic - not syncing: Fatal exception in interrupt
+[ 304.051975] Rebooting in 3 seconds..
+
+While the oops is for a 4.9-kernel, I was able to trigger the same oops with
+net-next as of yesterday.
+
+Fixes: 32f7adf633b9 ("net: qmi_wwan: support "raw IP" mode")
+Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index a4f229edcceb..8d4a6f7cba61 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -499,6 +499,7 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ return 1;
+ }
+ if (rawip) {
++ skb_reset_mac_header(skb);
+ skb->dev = dev->net; /* normally set by eth_type_trans */
+ skb->protocol = proto;
+ return 1;
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch b/target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch
new file mode 100644
index 0000000000..c26a86b270
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch
@@ -0,0 +1,97 @@
+From 93725149794d3d418cf1eddcae60c7b536c5faa1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Thu, 3 Dec 2015 19:24:18 +0100
+Subject: [PATCH] net: qmi_wwan: MDM9x30 specific power management
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+MDM9x30 based modems appear to go into a deeper sleep when
+suspended without "Remote Wakeup" enabled. The QMI interface
+will not respond unless a "set DTR" control request is sent
+on resume. The effect is similar to a QMI_CTL SYNC request,
+resetting (some of) the firmware state.
+
+We allow userspace sessions to span multiple character device
+open/close sequences. This means that userspace can depend
+on firmware state while both the netdev and the character
+device are closed. We have disabled "needs_remote_wakeup" at
+this point to allow devices without remote wakeup support to
+be auto-suspended.
+
+To make sure the MDM9x30 keeps firmware state, we need to
+keep "needs_remote_wakeup" always set. We also need to
+issue a "set DTR" request to enable the QMI interface.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 9a5be8b85186..fc9dd452a3b5 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -223,6 +223,20 @@ static int qmi_wwan_register_subdriver(struct usbnet *dev)
+ return rv;
+ }
+
++/* Send CDC SetControlLineState request, setting or clearing the DTR.
++ * "Required for Autoconnect and 9x30 to wake up" according to the
++ * GobiNet driver. The requirement has been verified on an MDM9230
++ * based Sierra Wireless MC7455
++ */
++static int qmi_wwan_change_dtr(struct usbnet *dev, bool on)
++{
++ u8 intf = dev->intf->cur_altsetting->desc.bInterfaceNumber;
++
++ return usbnet_write_cmd(dev, USB_CDC_REQ_SET_CONTROL_LINE_STATE,
++ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
++ on ? 0x01 : 0x00, intf, NULL, 0);
++}
++
+ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+ {
+ int status = -1;
+@@ -280,6 +294,24 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+ usb_driver_release_interface(driver, info->data);
+ }
+
++ /* disabling remote wakeup on MDM9x30 devices has the same
++ * effect as clearing DTR. The device will not respond to QMI
++ * requests until we set DTR again. This is similar to a
++ * QMI_CTL SYNC request, clearing a lot of firmware state
++ * including the client ID allocations.
++ *
++ * Our usage model allows a session to span multiple
++ * open/close events, so we must prevent the firmware from
++ * clearing out state the clients might need.
++ *
++ * MDM9x30 is the first QMI chipset with USB3 support. Abuse
++ * this fact to enable the quirk.
++ */
++ if (le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
++ qmi_wwan_manage_power(dev, 1);
++ qmi_wwan_change_dtr(dev, true);
++ }
++
+ /* Never use the same address on both ends of the link, even if the
+ * buggy firmware told us to. Or, if device is assigned the well-known
+ * buggy firmware MAC address, replace it with a random address,
+@@ -307,6 +339,12 @@ static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
+ if (info->subdriver && info->subdriver->disconnect)
+ info->subdriver->disconnect(info->control);
+
++ /* disable MDM9x30 quirk */
++ if (le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
++ qmi_wwan_change_dtr(dev, false);
++ qmi_wwan_manage_power(dev, 0);
++ }
++
+ /* allow user to unbind using either control or data */
+ if (intf == info->control)
+ other = info->data;
+--
+2.7.4
+
diff --git a/target/linux/generic/patches-4.4/099-0007-qmi_wwan-add-support-for-Quectel-EC21-and-EC25.patch b/target/linux/generic/patches-4.4/099-0007-qmi_wwan-add-support-for-Quectel-EC21-and-EC25.patch
new file mode 100644
index 0000000000..3b8032776a
--- /dev/null
+++ b/target/linux/generic/patches-4.4/099-0007-qmi_wwan-add-support-for-Quectel-EC21-and-EC25.patch
@@ -0,0 +1,98 @@
+From 9a765881bf3dcd32847d7108cf48cb04a4ed993f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Mon, 10 Oct 2016 21:12:49 +0200
+Subject: [PATCH] qmi_wwan: add support for Quectel EC21 and EC25
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Quectel EC21 and EC25 need the same "set DTR" request as devices
+based on the MDM9230 chipset, but has no USB3 support. Our best guess
+is that the "set DTR" functionality depends on chipset and/or
+baseband firmware generation. But USB3 is still an optional feature.
+
+Since we cannot enable this unconditionally for all older devices, and
+there doesn't appear to be anything we can use in the USB descriptors
+to identify these chips, we are forced to use a device specific quirk
+flag.
+
+Reported-and-tested-by: Sebastian Sjoholm <sebastian.sjoholm@gmail.com>
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/usb/qmi_wwan.c | 30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 9d1fce8a6e84..3ff76c6db4f6 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -59,6 +59,10 @@ enum qmi_wwan_flags {
+ QMI_WWAN_FLAG_RAWIP = 1 << 0,
+ };
+
++enum qmi_wwan_quirks {
++ QMI_WWAN_QUIRK_DTR = 1 << 0, /* needs "set DTR" request */
++};
++
+ static void qmi_wwan_netdev_setup(struct net_device *net)
+ {
+ struct usbnet *dev = netdev_priv(net);
+@@ -411,9 +415,14 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+ * clearing out state the clients might need.
+ *
+ * MDM9x30 is the first QMI chipset with USB3 support. Abuse
+- * this fact to enable the quirk.
++ * this fact to enable the quirk for all USB3 devices.
++ *
++ * There are also chipsets with the same "set DTR" requirement
++ * but without USB3 support. Devices based on these chips
++ * need a quirk flag in the device ID table.
+ */
+- if (le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
++ if (dev->driver_info->data & QMI_WWAN_QUIRK_DTR ||
++ le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
+ qmi_wwan_manage_power(dev, 1);
+ qmi_wwan_change_dtr(dev, true);
+ }
+@@ -526,6 +535,16 @@ static const struct driver_info qmi_wwan_info = {
+ .rx_fixup = qmi_wwan_rx_fixup,
+ };
+
++static const struct driver_info qmi_wwan_info_quirk_dtr = {
++ .description = "WWAN/QMI device",
++ .flags = FLAG_WWAN,
++ .bind = qmi_wwan_bind,
++ .unbind = qmi_wwan_unbind,
++ .manage_power = qmi_wwan_manage_power,
++ .rx_fixup = qmi_wwan_rx_fixup,
++ .data = QMI_WWAN_QUIRK_DTR,
++};
++
+ #define HUAWEI_VENDOR_ID 0x12D1
+
+ /* map QMI/wwan function by a fixed interface number */
+@@ -533,6 +552,11 @@ static const struct driver_info qmi_wwan_info = {
+ USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
+ .driver_info = (unsigned long)&qmi_wwan_info
+
++/* devices requiring "set DTR" quirk */
++#define QMI_QUIRK_SET_DTR(vend, prod, num) \
++ USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
++ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr
++
+ /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
+ #define QMI_GOBI1K_DEVICE(vend, prod) \
+ QMI_FIXED_INTF(vend, prod, 3)
+@@ -895,6 +919,8 @@ static const struct usb_device_id products[] = {
+ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
+ {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
++ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0125, 4)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
++ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)}, /* Quectel EC21 Mini PCIe */
+
+ /* 4. Gobi 1000 devices */
+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+--
+2.7.4
+