diff options
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.patch | 97 |
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 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 + |