Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966647AbcCPLQJ (ORCPT ); Wed, 16 Mar 2016 07:16:09 -0400 Received: from mx2.suse.de ([195.135.220.15]:47179 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754758AbcCPK7s (ORCPT ); Wed, 16 Mar 2016 06:59:48 -0400 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Konstantin Shkolnyy , Johan Hovold , Oliver Neukum , Jiri Slaby Subject: [PATCH 3.12 04/58] USB: cp210x: flush device queues at close Date: Wed, 16 Mar 2016 11:58:49 +0100 Message-Id: X-Mailer: git-send-email 2.7.3 In-Reply-To: <377b71e18f20d69b0df301ce7040554f40ba9651.1458125909.git.jslaby@suse.cz> References: <377b71e18f20d69b0df301ce7040554f40ba9651.1458125909.git.jslaby@suse.cz> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2198 Lines: 65 From: Konstantin Shkolnyy 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit ebfb319bb601e501f77809a83b0b69b529c22a8d upstream. Flush all device queues at close in order to work around a cp2108 Tx queue bug. Occasionally, writing data and immediately closing the port makes cp2108 stop responding. The device has to be unplugged to clear the error. The failure is induced by shutting down the device while its Tx queue still has unsent data. This condition is avoided by issuing PURGE command from the close() callback. This change is applied to all cp210x devices. Clearing internal queues on close is generally good. Signed-off-by: Konstantin Shkolnyy [johan: amend commit message ] Signed-off-by: Johan Hovold Cc: Oliver Neukum Signed-off-by: Jiri Slaby --- drivers/usb/serial/cp210x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f288f3c1f5e2..9bd71e00954f 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -304,6 +304,14 @@ static struct usb_serial_driver * const serial_drivers[] = { #define CONTROL_WRITE_RTS 0x0200 /* + * CP210X_PURGE - 16 bits passed in wValue of USB request. + * SiLabs app note AN571 gives a strange description of the 4 bits: + * bit 0 or bit 2 clears the transmit queue and 1 or 3 receive. + * writing 1 to all, however, purges cp2108 well enough to avoid the hang. + */ +#define PURGE_ALL 0x000f + +/* * cp210x_get_config * Reads from the CP210x configuration registers * 'size' is specified in bytes. @@ -482,7 +490,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) static void cp210x_close(struct usb_serial_port *port) { + unsigned int purge_ctl; + usb_serial_generic_close(port); + + /* Clear both queues; cp2108 needs this to avoid an occasional hang */ + purge_ctl = PURGE_ALL; + cp210x_set_config(port, CP210X_PURGE, &purge_ctl, 2); + cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); } -- 2.7.3