From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752907AbcELIyG (ORCPT ); Thu, 12 May 2016 04:54:06 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:36096 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752186AbcELIul (ORCPT ); Thu, 12 May 2016 04:50:41 -0400 From: Mathieu OTHACEHE To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Mathieu OTHACEHE Subject: [PATCH 31/36] usb: serial: ti_usb_3410_5052: Use a mutex to protect shadow mcr Date: Thu, 12 May 2016 10:49:03 +0200 Message-Id: <1463042948-12205-32-git-send-email-m.othacehe@gmail.com> X-Mailer: git-send-email 2.8.2 In-Reply-To: <1463042948-12205-1-git-send-email-m.othacehe@gmail.com> References: <1463042948-12205-1-git-send-email-m.othacehe@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Only shadow msr is accessed from interrupt context. So use the ti_port spinlock to protect only shadow msr. Add a mutex in ti_port to protect mcr from concurrent access. Also move shadow mcr setting out of ti_set_mcr function. Signed-off-by: Mathieu OTHACEHE --- drivers/usb/serial/ti_usb_3410_5052.c | 36 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ae77084..0192be9 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -274,7 +274,8 @@ struct ti_port { u8 tp_shadow_mcr; u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; - spinlock_t tp_lock; + spinlock_t tp_lock; /* Protects tp_msr */ + struct mutex tp_mutex; /* Protects tp_shadow_mcr */ }; struct ti_device { @@ -636,6 +637,8 @@ static int ti_port_probe(struct usb_serial_port *port) return -ENOMEM; spin_lock_init(&tport->tp_lock); + mutex_init(&tport->tp_mutex); + if (port == port->serial->port[0]) tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; else @@ -1017,9 +1020,9 @@ static void ti_set_termios(struct tty_struct *tty, port_number, status); } - /* SET_CONFIG asserts RTS and DTR, reset them correctly */ + mutex_lock(&tport->tp_mutex); mcr = tport->tp_shadow_mcr; - /* if baud rate is B0, clear RTS and DTR */ + if (C_BAUD(tty) == B0) mcr &= ~(TI_MCR_DTR | TI_MCR_RTS); else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) @@ -1030,7 +1033,10 @@ static void ti_set_termios(struct tty_struct *tty, dev_err(&port->dev, "cannot set modem control on port %d: %d\n", port_number, status); + } else { + tport->tp_shadow_mcr = mcr; } + mutex_unlock(&tport->tp_mutex); kfree(config); } @@ -1045,10 +1051,14 @@ static int ti_tiocmget(struct tty_struct *tty) unsigned int mcr; unsigned long flags; + mutex_lock(&tport->tp_mutex); spin_lock_irqsave(&tport->tp_lock, flags); + msr = tport->tp_msr; mcr = tport->tp_shadow_mcr; + spin_unlock_irqrestore(&tport->tp_lock, flags); + mutex_unlock(&tport->tp_mutex); result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0) @@ -1069,10 +1079,10 @@ static int ti_tiocmset(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); + int err; unsigned int mcr; - unsigned long flags; - spin_lock_irqsave(&tport->tp_lock, flags); + mutex_lock(&tport->tp_mutex); mcr = tport->tp_shadow_mcr; if (set & TIOCM_RTS) @@ -1088,9 +1098,14 @@ static int ti_tiocmset(struct tty_struct *tty, mcr &= ~TI_MCR_DTR; if (clear & TIOCM_LOOP) mcr &= ~TI_MCR_LOOP; - spin_unlock_irqrestore(&tport->tp_lock, flags); - return ti_set_mcr(port, mcr); + err = ti_set_mcr(port, mcr); + if (!err) + tport->tp_shadow_mcr = mcr; + + mutex_unlock(&tport->tp_mutex); + + return err; } @@ -1183,18 +1198,11 @@ exit: static int ti_set_mcr(struct usb_serial_port *port, unsigned int mcr) { struct ti_port *tport = usb_get_serial_port_data(port); - unsigned long flags; int status; status = ti_write_byte(port, tport->tp_uart_base_addr + TI_UART_OFFSET_MCR, TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr); - - spin_lock_irqsave(&tport->tp_lock, flags); - if (!status) - tport->tp_shadow_mcr = mcr; - spin_unlock_irqrestore(&tport->tp_lock, flags); - return status; } -- 2.8.2