aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-06-01 16:53:07 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 16:47:43 -0400
commit203652192634c1fce5e79df0a8ff2fabfaefd3ab (patch)
tree9c2ee78c04b0750220fa34e7adc541c16bf21e90 /drivers
parent60af22d2ed490554cc92c8d0fed0b5b9cf687568 (diff)
tty: untangle locking of wait_until_sent
Some wait_until_sent versions require the big tty mutex, others don't and some callers of wait_until_sent already hold it while other don't. That leads to recursive use of the BTM in these functions, which we're trying to get rid of. This turns all cleans up the locking there so that the driver's wait_until_sent function never takes the BTM itself if it is already called with that lock held. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/amiserial.c11
-rw-r--r--drivers/serial/68360serial.c2
-rw-r--r--drivers/serial/crisv10.c2
-rw-r--r--drivers/serial/serial_core.c31
4 files changed, 31 insertions, 15 deletions
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 1b21a7adeb58..8228e61bb54d 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
1528{ 1528{
1529 struct async_struct * info = tty->driver_data; 1529 struct async_struct * info = tty->driver_data;
1530 unsigned long orig_jiffies, char_time; 1530 unsigned long orig_jiffies, char_time;
1531 int tty_was_locked = tty_locked();
1531 int lsr; 1532 int lsr;
1532 1533
1533 if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) 1534 if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
@@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
1538 1539
1539 orig_jiffies = jiffies; 1540 orig_jiffies = jiffies;
1540 1541
1541 tty_lock_nested(); /* tty_wait_until_sent is called from lots of places */ 1542 /*
1543 * tty_wait_until_sent is called from lots of places,
1544 * with or without the BTM.
1545 */
1546 if (!tty_was_locked)
1547 tty_lock();
1542 /* 1548 /*
1543 * Set the check interval to be 1/5 of the estimated time to 1549 * Set the check interval to be 1/5 of the estimated time to
1544 * send a single character, and make it at least 1. The check 1550 * send a single character, and make it at least 1. The check
@@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
1579 break; 1585 break;
1580 } 1586 }
1581 __set_current_state(TASK_RUNNING); 1587 __set_current_state(TASK_RUNNING);
1582 tty_unlock(); 1588 if (!tty_was_locked)
1589 tty_unlock();
1583#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT 1590#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
1584 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); 1591 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
1585#endif 1592#endif
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 16f5f2fab032..edcf1cc089d1 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
1705 printk("jiff=%lu...", jiffies); 1705 printk("jiff=%lu...", jiffies);
1706#endif 1706#endif
1707 1707
1708 tty_lock_nested(); /* always held already since we come from ->close */
1709 /* We go through the loop at least once because we can't tell 1708 /* We go through the loop at least once because we can't tell
1710 * exactly when the last character exits the shifter. There can 1709 * exactly when the last character exits the shifter. There can
1711 * be at least two characters waiting to be sent after the buffers 1710 * be at least two characters waiting to be sent after the buffers
@@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
1734 bdp--; 1733 bdp--;
1735 } while (bdp->status & BD_SC_READY); 1734 } while (bdp->status & BD_SC_READY);
1736 current->state = TASK_RUNNING; 1735 current->state = TASK_RUNNING;
1737 tty_unlock();
1738#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT 1736#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
1739 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); 1737 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
1740#endif 1738#endif
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 94bfb9f238e1..8e356c5eeae0 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3935,7 +3935,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
3935 * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO 3935 * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
3936 * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) 3936 * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
3937 */ 3937 */
3938 tty_lock_nested(); /* locked already when coming from close */
3939 orig_jiffies = jiffies; 3938 orig_jiffies = jiffies;
3940 while (info->xmit.head != info->xmit.tail || /* More in send queue */ 3939 while (info->xmit.head != info->xmit.tail || /* More in send queue */
3941 (*info->ostatusadr & 0x007f) || /* more in FIFO */ 3940 (*info->ostatusadr & 0x007f) || /* more in FIFO */
@@ -3952,7 +3951,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
3952 curr_time_usec - info->last_tx_active_usec; 3951 curr_time_usec - info->last_tx_active_usec;
3953 } 3952 }
3954 set_current_state(TASK_RUNNING); 3953 set_current_state(TASK_RUNNING);
3955 tty_unlock();
3956} 3954}
3957 3955
3958/* 3956/*
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 851d7c29132b..cd8511298bcb 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -60,7 +60,7 @@ static struct lock_class_key port_lock_key;
60 60
61static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, 61static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
62 struct ktermios *old_termios); 62 struct ktermios *old_termios);
63static void uart_wait_until_sent(struct tty_struct *tty, int timeout); 63static void __uart_wait_until_sent(struct uart_port *port, int timeout);
64static void uart_change_pm(struct uart_state *state, int pm_state); 64static void uart_change_pm(struct uart_state *state, int pm_state);
65 65
66/* 66/*
@@ -1322,8 +1322,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
1322 tty->closing = 1; 1322 tty->closing = 1;
1323 spin_unlock_irqrestore(&port->lock, flags); 1323 spin_unlock_irqrestore(&port->lock, flags);
1324 1324
1325 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) 1325 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
1326 tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); 1326 /*
1327 * hack: open-coded tty_wait_until_sent to avoid
1328 * recursive tty_lock
1329 */
1330 long timeout = msecs_to_jiffies(port->closing_wait);
1331 if (wait_event_interruptible_timeout(tty->write_wait,
1332 !tty_chars_in_buffer(tty), timeout) >= 0)
1333 __uart_wait_until_sent(uport, timeout);
1334 }
1327 1335
1328 /* 1336 /*
1329 * At this point, we stop accepting input. To do this, we 1337 * At this point, we stop accepting input. To do this, we
@@ -1339,7 +1347,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
1339 * has completely drained; this is especially 1347 * has completely drained; this is especially
1340 * important if there is a transmit FIFO! 1348 * important if there is a transmit FIFO!
1341 */ 1349 */
1342 uart_wait_until_sent(tty, uport->timeout); 1350 __uart_wait_until_sent(uport, uport->timeout);
1343 } 1351 }
1344 1352
1345 uart_shutdown(tty, state); 1353 uart_shutdown(tty, state);
@@ -1373,17 +1381,13 @@ done:
1373 mutex_unlock(&port->mutex); 1381 mutex_unlock(&port->mutex);
1374} 1382}
1375 1383
1376static void uart_wait_until_sent(struct tty_struct *tty, int timeout) 1384static void __uart_wait_until_sent(struct uart_port *port, int timeout)
1377{ 1385{
1378 struct uart_state *state = tty->driver_data;
1379 struct uart_port *port = state->uart_port;
1380 unsigned long char_time, expire; 1386 unsigned long char_time, expire;
1381 1387
1382 if (port->type == PORT_UNKNOWN || port->fifosize == 0) 1388 if (port->type == PORT_UNKNOWN || port->fifosize == 0)
1383 return; 1389 return;
1384 1390
1385 tty_lock_nested(); /* already locked when coming from close */
1386
1387 /* 1391 /*
1388 * Set the check interval to be 1/5 of the estimated time to 1392 * Set the check interval to be 1/5 of the estimated time to
1389 * send a single character, and make it at least 1. The check 1393 * send a single character, and make it at least 1. The check
@@ -1429,6 +1433,15 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
1429 break; 1433 break;
1430 } 1434 }
1431 set_current_state(TASK_RUNNING); /* might not be needed */ 1435 set_current_state(TASK_RUNNING); /* might not be needed */
1436}
1437
1438static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
1439{
1440 struct uart_state *state = tty->driver_data;
1441 struct uart_port *port = state->uart_port;
1442
1443 tty_lock();
1444 __uart_wait_until_sent(port, timeout);
1432 tty_unlock(); 1445 tty_unlock();
1433} 1446}
1434 1447