openwrt/target/linux/generic/patches-4.4/099-0003-net-qmi_wwan-should-hold-RTNL-while-changing-netdev-.patch
Koen Vandeputte 3b227103e6 kernel: backport raw-ip mode for newer QMI LTE modems
Backport support for raw-ip mode including all known fixes afterwards.

Newer LTE modems only tend to support this mode, which was only
introduced in kernel 4.5.

Also backport support for the Quectel EC2x LTE modem series which is
a very popular device.

No custom changes were needed in order to apply these patches.

Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
2018-02-18 09:34:32 +01:00

108 lines
3.6 KiB
Diff

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