summaryrefslogtreecommitdiff
path: root/target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch')
-rw-r--r--target/linux/generic/patches-4.4/099-0006-net-qmi_wwan-MDM9x30-specific-power-management.patch97
1 files changed, 97 insertions, 0 deletions
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 0000000..c26a86b
--- /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
+