Current GPIO code in cp210x fails to take USB autosuspend into account,
making it practically impossible to use GPIOs with autosuspend enabled
without user configuration. Fix this like for ftdi_sio in a previous patch.
Tested on a CP2102N.

Signed-off-by: Karoly Pados <pa...@pados.hu>
---
 drivers/usb/serial/cp210x.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index c0777a374a88..8f974eabce63 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -598,9 +598,15 @@ static int cp210x_read_vendor_block(struct usb_serial 
*serial, u8 type, u16 val,
        void *dmabuf;
        int result;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        dmabuf = kmalloc(bufsize, GFP_KERNEL);
-       if (!dmabuf)
+       if (!dmabuf) {
+               usb_autopm_put_interface(serial->interface);
                return -ENOMEM;
+       }
 
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                                 CP210X_VENDOR_SPECIFIC, type, val,
@@ -618,6 +624,7 @@ static int cp210x_read_vendor_block(struct usb_serial 
*serial, u8 type, u16 val,
        }
 
        kfree(dmabuf);
+       usb_autopm_put_interface(serial->interface);
 
        return result;
 }
@@ -702,9 +709,15 @@ static int cp210x_write_vendor_block(struct usb_serial 
*serial, u8 type,
        void *dmabuf;
        int result;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        dmabuf = kmemdup(buf, bufsize, GFP_KERNEL);
-       if (!dmabuf)
+       if (!dmabuf) {
+               usb_autopm_put_interface(serial->interface);
                return -ENOMEM;
+       }
 
        result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                                 CP210X_VENDOR_SPECIFIC, type, val,
@@ -712,6 +725,7 @@ static int cp210x_write_vendor_block(struct usb_serial 
*serial, u8 type,
                                 USB_CTRL_SET_TIMEOUT);
 
        kfree(dmabuf);
+       usb_autopm_put_interface(serial->interface);
 
        if (result == bufsize) {
                result = 0;
@@ -1383,6 +1397,7 @@ static void cp210x_gpio_set(struct gpio_chip *gc, 
unsigned int gpio, int value)
        } else {
                u16 wIndex = buf.state << 8 | buf.mask;
 
+               usb_autopm_get_interface(serial->interface);
                result = usb_control_msg(serial->dev,
                                         usb_sndctrlpipe(serial->dev, 0),
                                         CP210X_VENDOR_SPECIFIC,
@@ -1390,6 +1405,7 @@ static void cp210x_gpio_set(struct gpio_chip *gc, 
unsigned int gpio, int value)
                                         CP210X_WRITE_LATCH,
                                         wIndex,
                                         NULL, 0, USB_CTRL_SET_TIMEOUT);
+               usb_autopm_put_interface(serial->interface);
        }
 
        if (result < 0) {
-- 
2.20.1

Reply via email to