diff options
author | Alan Cox <alan@linux.intel.com> | 2010-06-01 16:52:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 16:47:42 -0400 |
commit | 61cd8a21d8a9fb4b11111270cf2d3aa919c20624 (patch) | |
tree | b390c27925f168a4cec35446b300c4d51657f86d /drivers/serial | |
parent | 8ce73264b75be4d5ed480440ac32dfc1f25ff678 (diff) |
serial: Change the wait for carrier locking
We want to push the lock/unlock into the helper functions so that we
can prepare to move to using the tty_port helper. The expansion initially
comes out a bit ugly but its worth the temporary expansion IMHO just so
we can produce a nice testable series of changes.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/serial_core.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 570dca2935e2..424b1c7e50c4 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -1272,6 +1272,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1272 | struct uart_state *state = tty->driver_data; | 1272 | struct uart_state *state = tty->driver_data; |
1273 | struct tty_port *port; | 1273 | struct tty_port *port; |
1274 | struct uart_port *uport; | 1274 | struct uart_port *uport; |
1275 | unsigned long flags; | ||
1275 | 1276 | ||
1276 | BUG_ON(!kernel_locked()); | 1277 | BUG_ON(!kernel_locked()); |
1277 | 1278 | ||
@@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1284 | pr_debug("uart_close(%d) called\n", uport->line); | 1285 | pr_debug("uart_close(%d) called\n", uport->line); |
1285 | 1286 | ||
1286 | mutex_lock(&port->mutex); | 1287 | mutex_lock(&port->mutex); |
1288 | spin_lock_irqsave(&port->lock, flags); | ||
1287 | 1289 | ||
1288 | if (tty_hung_up_p(filp)) | 1290 | if (tty_hung_up_p(filp)) { |
1291 | spin_unlock_irqrestore(&port->lock, flags); | ||
1289 | goto done; | 1292 | goto done; |
1293 | } | ||
1290 | 1294 | ||
1291 | if ((tty->count == 1) && (port->count != 1)) { | 1295 | if ((tty->count == 1) && (port->count != 1)) { |
1292 | /* | 1296 | /* |
@@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1305 | tty->name, port->count); | 1309 | tty->name, port->count); |
1306 | port->count = 0; | 1310 | port->count = 0; |
1307 | } | 1311 | } |
1308 | if (port->count) | 1312 | if (port->count) { |
1313 | spin_unlock_irqrestore(&port->lock, flags); | ||
1309 | goto done; | 1314 | goto done; |
1315 | } | ||
1310 | 1316 | ||
1311 | /* | 1317 | /* |
1312 | * Now we wait for the transmit buffer to clear; and we notify | 1318 | * Now we wait for the transmit buffer to clear; and we notify |
@@ -1314,6 +1320,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1314 | * setting tty->closing. | 1320 | * setting tty->closing. |
1315 | */ | 1321 | */ |
1316 | tty->closing = 1; | 1322 | tty->closing = 1; |
1323 | spin_unlock_irqrestore(&port->lock, flags); | ||
1317 | 1324 | ||
1318 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 1325 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
1319 | tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); | 1326 | tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); |
@@ -1340,20 +1347,26 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1340 | 1347 | ||
1341 | tty_ldisc_flush(tty); | 1348 | tty_ldisc_flush(tty); |
1342 | 1349 | ||
1343 | tty->closing = 0; | ||
1344 | tty_port_tty_set(port, NULL); | 1350 | tty_port_tty_set(port, NULL); |
1351 | spin_lock_irqsave(&port->lock, flags); | ||
1352 | tty->closing = 0; | ||
1345 | 1353 | ||
1346 | if (port->blocked_open) { | 1354 | if (port->blocked_open) { |
1355 | spin_unlock_irqrestore(&port->lock, flags); | ||
1347 | if (port->close_delay) | 1356 | if (port->close_delay) |
1348 | msleep_interruptible(port->close_delay); | 1357 | msleep_interruptible(port->close_delay); |
1358 | spin_lock_irqsave(&port->lock, flags); | ||
1349 | } else if (!uart_console(uport)) { | 1359 | } else if (!uart_console(uport)) { |
1360 | spin_unlock_irqrestore(&port->lock, flags); | ||
1350 | uart_change_pm(state, 3); | 1361 | uart_change_pm(state, 3); |
1362 | spin_lock_irqsave(&port->lock, flags); | ||
1351 | } | 1363 | } |
1352 | 1364 | ||
1353 | /* | 1365 | /* |
1354 | * Wake up anyone trying to open this port. | 1366 | * Wake up anyone trying to open this port. |
1355 | */ | 1367 | */ |
1356 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1368 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1369 | spin_unlock_irqrestore(&port->lock, flags); | ||
1357 | wake_up_interruptible(&port->open_wait); | 1370 | wake_up_interruptible(&port->open_wait); |
1358 | 1371 | ||
1359 | done: | 1372 | done: |
@@ -1429,6 +1442,7 @@ static void uart_hangup(struct tty_struct *tty) | |||
1429 | { | 1442 | { |
1430 | struct uart_state *state = tty->driver_data; | 1443 | struct uart_state *state = tty->driver_data; |
1431 | struct tty_port *port = &state->port; | 1444 | struct tty_port *port = &state->port; |
1445 | unsigned long flags; | ||
1432 | 1446 | ||
1433 | BUG_ON(!kernel_locked()); | 1447 | BUG_ON(!kernel_locked()); |
1434 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); | 1448 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); |
@@ -1437,8 +1451,10 @@ static void uart_hangup(struct tty_struct *tty) | |||
1437 | if (port->flags & ASYNC_NORMAL_ACTIVE) { | 1451 | if (port->flags & ASYNC_NORMAL_ACTIVE) { |
1438 | uart_flush_buffer(tty); | 1452 | uart_flush_buffer(tty); |
1439 | uart_shutdown(tty, state); | 1453 | uart_shutdown(tty, state); |
1454 | spin_lock_irqsave(&port->lock, flags); | ||
1440 | port->count = 0; | 1455 | port->count = 0; |
1441 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1456 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1457 | spin_unlock_irqrestore(&port->lock, flags); | ||
1442 | tty_port_tty_set(port, NULL); | 1458 | tty_port_tty_set(port, NULL); |
1443 | wake_up_interruptible(&port->open_wait); | 1459 | wake_up_interruptible(&port->open_wait); |
1444 | wake_up_interruptible(&port->delta_msr_wait); | 1460 | wake_up_interruptible(&port->delta_msr_wait); |
@@ -1496,9 +1512,13 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1496 | struct uart_port *uport = state->uart_port; | 1512 | struct uart_port *uport = state->uart_port; |
1497 | struct tty_port *port = &state->port; | 1513 | struct tty_port *port = &state->port; |
1498 | unsigned int mctrl; | 1514 | unsigned int mctrl; |
1515 | unsigned long flags; | ||
1499 | 1516 | ||
1517 | spin_lock_irqsave(&port->lock, flags); | ||
1518 | if (!tty_hung_up_p(filp)) | ||
1519 | port->count--; | ||
1500 | port->blocked_open++; | 1520 | port->blocked_open++; |
1501 | port->count--; | 1521 | spin_unlock_irqrestore(&port->lock, flags); |
1502 | 1522 | ||
1503 | add_wait_queue(&port->open_wait, &wait); | 1523 | add_wait_queue(&port->open_wait, &wait); |
1504 | while (1) { | 1524 | while (1) { |
@@ -1535,23 +1555,26 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1535 | * not set RTS here - we want to make sure we catch | 1555 | * not set RTS here - we want to make sure we catch |
1536 | * the data from the modem. | 1556 | * the data from the modem. |
1537 | */ | 1557 | */ |
1538 | if (port->tty->termios->c_cflag & CBAUD) | 1558 | if (port->tty->termios->c_cflag & CBAUD) { |
1559 | mutex_lock(&port->mutex); | ||
1539 | uart_set_mctrl(uport, TIOCM_DTR); | 1560 | uart_set_mctrl(uport, TIOCM_DTR); |
1561 | mutex_unlock(&port->mutex); | ||
1562 | } | ||
1540 | 1563 | ||
1541 | /* | 1564 | /* |
1542 | * and wait for the carrier to indicate that the | 1565 | * and wait for the carrier to indicate that the |
1543 | * modem is ready for us. | 1566 | * modem is ready for us. |
1544 | */ | 1567 | */ |
1568 | mutex_lock(&port->mutex); | ||
1545 | spin_lock_irq(&uport->lock); | 1569 | spin_lock_irq(&uport->lock); |
1546 | uport->ops->enable_ms(uport); | 1570 | uport->ops->enable_ms(uport); |
1547 | mctrl = uport->ops->get_mctrl(uport); | 1571 | mctrl = uport->ops->get_mctrl(uport); |
1548 | spin_unlock_irq(&uport->lock); | 1572 | spin_unlock_irq(&uport->lock); |
1573 | mutex_unlock(&port->mutex); | ||
1549 | if (mctrl & TIOCM_CAR) | 1574 | if (mctrl & TIOCM_CAR) |
1550 | break; | 1575 | break; |
1551 | 1576 | ||
1552 | mutex_unlock(&port->mutex); | ||
1553 | schedule(); | 1577 | schedule(); |
1554 | mutex_lock(&port->mutex); | ||
1555 | 1578 | ||
1556 | if (signal_pending(current)) | 1579 | if (signal_pending(current)) |
1557 | break; | 1580 | break; |
@@ -1559,8 +1582,11 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1559 | set_current_state(TASK_RUNNING); | 1582 | set_current_state(TASK_RUNNING); |
1560 | remove_wait_queue(&port->open_wait, &wait); | 1583 | remove_wait_queue(&port->open_wait, &wait); |
1561 | 1584 | ||
1562 | port->count++; | 1585 | spin_lock_irqsave(&port->lock, flags); |
1586 | if (!tty_hung_up_p(filp)) | ||
1587 | port->count++; | ||
1563 | port->blocked_open--; | 1588 | port->blocked_open--; |
1589 | spin_unlock_irqrestore(&port->lock, flags); | ||
1564 | 1590 | ||
1565 | if (signal_pending(current)) | 1591 | if (signal_pending(current)) |
1566 | return -ERESTARTSYS; | 1592 | return -ERESTARTSYS; |
@@ -1677,9 +1703,9 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1677 | /* | 1703 | /* |
1678 | * If we succeeded, wait until the port is ready. | 1704 | * If we succeeded, wait until the port is ready. |
1679 | */ | 1705 | */ |
1706 | mutex_unlock(&port->mutex); | ||
1680 | if (retval == 0) | 1707 | if (retval == 0) |
1681 | retval = uart_block_til_ready(filp, state); | 1708 | retval = uart_block_til_ready(filp, state); |
1682 | mutex_unlock(&port->mutex); | ||
1683 | 1709 | ||
1684 | /* | 1710 | /* |
1685 | * If this is the first open to succeed, adjust things to suit. | 1711 | * If this is the first open to succeed, adjust things to suit. |