1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- 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(+)
- --- a/drivers/net/usb/qmi_wwan.c
- +++ b/drivers/net/usb/qmi_wwan.c
- @@ -329,6 +329,20 @@ err:
- 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;
- @@ -386,6 +400,24 @@ static int qmi_wwan_bind(struct usbnet *
- 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,
- @@ -414,6 +446,12 @@ static void qmi_wwan_unbind(struct usbne
- 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;
|