These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / serial / usb_wwan.c
index 2f805cb..be9cb61 100644 (file)
 #include <linux/serial.h>
 #include "usb-wwan.h"
 
+/*
+ * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
+ * in CDC ACM.
+ */
+static int usb_wwan_send_setup(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct usb_wwan_port_private *portdata;
+       int val = 0;
+       int ifnum;
+       int res;
+
+       portdata = usb_get_serial_port_data(port);
+
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
+
+       ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+       res = usb_autopm_get_interface(serial->interface);
+       if (res)
+               return res;
+
+       res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x22, 0x21, val, ifnum, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+
+       usb_autopm_put_interface(port->serial->interface);
+
+       return res;
+}
+
 void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct usb_wwan_port_private *portdata;
@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 
        intfdata = usb_get_serial_data(port->serial);
 
-       if (!intfdata->send_setup)
+       if (!intfdata->use_send_setup)
                return;
 
        portdata = usb_get_serial_port_data(port);
@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
        portdata->rts_state = on;
        portdata->dtr_state = on;
 
-       intfdata->send_setup(port);
+       usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_dtr_rts);
 
@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
        portdata = usb_get_serial_port_data(port);
        intfdata = usb_get_serial_data(port->serial);
 
-       if (!intfdata->send_setup)
+       if (!intfdata->use_send_setup)
                return -EINVAL;
 
        /* FIXME: what locks portdata fields ? */
@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return intfdata->send_setup(port);
+       return usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_tiocmset);
 
@@ -282,7 +316,7 @@ static void usb_wwan_indat_callback(struct urb *urb)
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err) {
-               if (err != -EPERM) {
+               if (err != -EPERM && err != -ENODEV) {
                        dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
                                __func__, err);
                        /* busy also in error unless we are killed */