lkml.org 
[lkml]   [2016]   [May]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 31/36] usb: serial: ti_usb_3410_5052: Use a mutex to protect shadow mcr
Date
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 <m.othacehe@gmail.com>
---
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
\
 
 \ /
  Last update: 2016-05-12 11:21    [W:0.231 / U:0.316 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site