Blob Blame History Raw
From 7b0b644b9aa2de5032db0f468fddca091d0b7b90 Mon Sep 17 00:00:00 2001
From: Karoly Pados <pados@pados.hu>
Date: Sun, 17 Feb 2019 18:59:01 +0100
Subject: [PATCH] USB: serial: cp210x: fix GPIO in autosuspend
Git-commit: 7b0b644b9aa2de5032db0f468fddca091d0b7b90
Patch-mainline: v5.0
References: bsc#1120902

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 <pados@pados.hu>
Fixes: cf5276ce7867 ("USB: serial: cp210x: Adding GPIO support for CP2105")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/usb/serial/cp210x.c |   20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -1312,8 +1312,14 @@ static int cp210x_gpio_get(struct gpio_c
 	int result;
 	u8 buf;
 
+	result = usb_autopm_get_interface(serial->interface);
+	if (result)
+		return result;
+
 	result = cp210x_read_vendor_block(serial, REQTYPE_INTERFACE_TO_HOST,
-					  CP210X_READ_LATCH, &buf, sizeof(buf));
+				  	CP210X_READ_LATCH, &buf, sizeof(buf));
+	
+	usb_autopm_put_interface(serial->interface);
 	if (result < 0)
 		return result;
 
@@ -1324,6 +1330,7 @@ static void cp210x_gpio_set(struct gpio_
 {
 	struct usb_serial *serial = gpiochip_get_data(gc);
 	struct cp210x_gpio_write buf;
+	int result;
 
 	if (value == 1)
 		buf.state = BIT(gpio);
@@ -1332,8 +1339,13 @@ static void cp210x_gpio_set(struct gpio_
 
 	buf.mask = BIT(gpio);
 
+	result = usb_autopm_get_interface(serial->interface);
+	if (result)
+		return;
+
 	cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE,
 				  CP210X_WRITE_LATCH, &buf, sizeof(buf));
+	usb_autopm_put_interface(serial->interface);
 }
 
 static int cp210x_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio)
@@ -1520,6 +1532,10 @@ static int cp210x_attach(struct usb_seri
 
 	usb_set_serial_data(serial, priv);
 
+	result = usb_autopm_get_interface(serial->interface);
+	if (result)
+		goto out;
+
 	if (priv->partnum == CP210X_PARTNUM_CP2105) {
 		result = cp2105_shared_gpio_init(serial);
 		if (result < 0) {
@@ -1527,6 +1543,8 @@ static int cp210x_attach(struct usb_seri
 				"GPIO initialisation failed, continuing without GPIO support\n");
 		}
 	}
+	usb_autopm_put_interface(serial->interface);
+out:
 
 	return 0;
 }