diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 145 |
1 files changed, 78 insertions, 67 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 9dac516df006..3d923065d9a2 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
@@ -1229,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1229 | struct serial_struct __user *new_info) | 1228 | struct serial_struct __user *new_info) |
1230 | { | 1229 | { |
1231 | struct mxser_port *info = tty->driver_data; | 1230 | struct mxser_port *info = tty->driver_data; |
1231 | struct tty_port *port = &info->port; | ||
1232 | struct serial_struct new_serial; | 1232 | struct serial_struct new_serial; |
1233 | speed_t baud; | 1233 | speed_t baud; |
1234 | unsigned long sl_flags; | 1234 | unsigned long sl_flags; |
@@ -1244,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1244 | new_serial.port != info->ioaddr) | 1244 | new_serial.port != info->ioaddr) |
1245 | return -EINVAL; | 1245 | return -EINVAL; |
1246 | 1246 | ||
1247 | flags = info->port.flags & ASYNC_SPD_MASK; | 1247 | flags = port->flags & ASYNC_SPD_MASK; |
1248 | 1248 | ||
1249 | if (!capable(CAP_SYS_ADMIN)) { | 1249 | if (!capable(CAP_SYS_ADMIN)) { |
1250 | if ((new_serial.baud_base != info->baud_base) || | 1250 | if ((new_serial.baud_base != info->baud_base) || |
@@ -1258,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1258 | * OK, past this point, all the error checking has been done. | 1258 | * OK, past this point, all the error checking has been done. |
1259 | * At this point, we start making changes..... | 1259 | * At this point, we start making changes..... |
1260 | */ | 1260 | */ |
1261 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | 1261 | port->flags = ((port->flags & ~ASYNC_FLAGS) | |
1262 | (new_serial.flags & ASYNC_FLAGS)); | 1262 | (new_serial.flags & ASYNC_FLAGS)); |
1263 | info->port.close_delay = new_serial.close_delay * HZ / 100; | 1263 | port->close_delay = new_serial.close_delay * HZ / 100; |
1264 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1264 | port->closing_wait = new_serial.closing_wait * HZ / 100; |
1265 | tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) | 1265 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1266 | ? 1 : 0; | 1266 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
1267 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | ||
1268 | (new_serial.baud_base != info->baud_base || | 1267 | (new_serial.baud_base != info->baud_base || |
1269 | new_serial.custom_divisor != | 1268 | new_serial.custom_divisor != |
1270 | info->custom_divisor)) { | 1269 | info->custom_divisor)) { |
1270 | if (new_serial.custom_divisor == 0) | ||
1271 | return -EINVAL; | ||
1271 | baud = new_serial.baud_base / new_serial.custom_divisor; | 1272 | baud = new_serial.baud_base / new_serial.custom_divisor; |
1272 | tty_encode_baud_rate(tty, baud, baud); | 1273 | tty_encode_baud_rate(tty, baud, baud); |
1273 | } | 1274 | } |
@@ -1277,18 +1278,16 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1277 | 1278 | ||
1278 | process_txrx_fifo(info); | 1279 | process_txrx_fifo(info); |
1279 | 1280 | ||
1280 | if (info->port.flags & ASYNC_INITIALIZED) { | 1281 | if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
1281 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { | 1282 | if (flags != (port->flags & ASYNC_SPD_MASK)) { |
1282 | spin_lock_irqsave(&info->slock, sl_flags); | 1283 | spin_lock_irqsave(&info->slock, sl_flags); |
1283 | mxser_change_speed(tty, NULL); | 1284 | mxser_change_speed(tty, NULL); |
1284 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1285 | spin_unlock_irqrestore(&info->slock, sl_flags); |
1285 | } | 1286 | } |
1286 | } else { | 1287 | } else { |
1287 | mutex_lock(&info->port.mutex); | 1288 | retval = mxser_activate(port, tty); |
1288 | retval = mxser_activate(&info->port, tty); | ||
1289 | if (retval == 0) | 1289 | if (retval == 0) |
1290 | set_bit(ASYNCB_INITIALIZED, &info->port.flags); | 1290 | set_bit(ASYNCB_INITIALIZED, &port->flags); |
1291 | mutex_unlock(&info->port.mutex); | ||
1292 | } | 1291 | } |
1293 | return retval; | 1292 | return retval; |
1294 | } | 1293 | } |
@@ -1478,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs) | |||
1478 | 1477 | ||
1479 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1478 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) |
1480 | { | 1479 | { |
1481 | struct mxser_port *port; | 1480 | struct mxser_port *ip; |
1481 | struct tty_port *port; | ||
1482 | struct tty_struct *tty; | 1482 | struct tty_struct *tty; |
1483 | int result, status; | 1483 | int result, status; |
1484 | unsigned int i, j; | 1484 | unsigned int i, j; |
@@ -1494,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1494 | 1494 | ||
1495 | case MOXA_CHKPORTENABLE: | 1495 | case MOXA_CHKPORTENABLE: |
1496 | result = 0; | 1496 | result = 0; |
1497 | lock_kernel(); | ||
1498 | for (i = 0; i < MXSER_BOARDS; i++) | 1497 | for (i = 0; i < MXSER_BOARDS; i++) |
1499 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | 1498 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) |
1500 | if (mxser_boards[i].ports[j].ioaddr) | 1499 | if (mxser_boards[i].ports[j].ioaddr) |
1501 | result |= (1 << i); | 1500 | result |= (1 << i); |
1502 | unlock_kernel(); | ||
1503 | return put_user(result, (unsigned long __user *)argp); | 1501 | return put_user(result, (unsigned long __user *)argp); |
1504 | case MOXA_GETDATACOUNT: | 1502 | case MOXA_GETDATACOUNT: |
1505 | lock_kernel(); | 1503 | /* The receive side is locked by port->slock but it isn't |
1504 | clear that an exact snapshot is worth copying here */ | ||
1506 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | 1505 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) |
1507 | ret = -EFAULT; | 1506 | ret = -EFAULT; |
1508 | unlock_kernel(); | ||
1509 | return ret; | 1507 | return ret; |
1510 | case MOXA_GETMSTATUS: { | 1508 | case MOXA_GETMSTATUS: { |
1511 | struct mxser_mstatus ms, __user *msu = argp; | 1509 | struct mxser_mstatus ms, __user *msu = argp; |
1512 | lock_kernel(); | ||
1513 | for (i = 0; i < MXSER_BOARDS; i++) | 1510 | for (i = 0; i < MXSER_BOARDS; i++) |
1514 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1511 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
1515 | port = &mxser_boards[i].ports[j]; | 1512 | ip = &mxser_boards[i].ports[j]; |
1513 | port = &ip->port; | ||
1516 | memset(&ms, 0, sizeof(ms)); | 1514 | memset(&ms, 0, sizeof(ms)); |
1517 | 1515 | ||
1518 | if (!port->ioaddr) | 1516 | mutex_lock(&port->mutex); |
1517 | if (!ip->ioaddr) | ||
1519 | goto copy; | 1518 | goto copy; |
1520 | 1519 | ||
1521 | tty = tty_port_tty_get(&port->port); | 1520 | tty = tty_port_tty_get(port); |
1522 | 1521 | ||
1523 | if (!tty || !tty->termios) | 1522 | if (!tty || !tty->termios) |
1524 | ms.cflag = port->normal_termios.c_cflag; | 1523 | ms.cflag = ip->normal_termios.c_cflag; |
1525 | else | 1524 | else |
1526 | ms.cflag = tty->termios->c_cflag; | 1525 | ms.cflag = tty->termios->c_cflag; |
1527 | tty_kref_put(tty); | 1526 | tty_kref_put(tty); |
1528 | status = inb(port->ioaddr + UART_MSR); | 1527 | spin_lock_irq(&ip->slock); |
1528 | status = inb(ip->ioaddr + UART_MSR); | ||
1529 | spin_unlock_irq(&ip->slock); | ||
1529 | if (status & UART_MSR_DCD) | 1530 | if (status & UART_MSR_DCD) |
1530 | ms.dcd = 1; | 1531 | ms.dcd = 1; |
1531 | if (status & UART_MSR_DSR) | 1532 | if (status & UART_MSR_DSR) |
@@ -1533,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1533 | if (status & UART_MSR_CTS) | 1534 | if (status & UART_MSR_CTS) |
1534 | ms.cts = 1; | 1535 | ms.cts = 1; |
1535 | copy: | 1536 | copy: |
1536 | if (copy_to_user(msu, &ms, sizeof(ms))) { | 1537 | mutex_unlock(&port->mutex); |
1537 | unlock_kernel(); | 1538 | if (copy_to_user(msu, &ms, sizeof(ms))) |
1538 | return -EFAULT; | 1539 | return -EFAULT; |
1539 | } | ||
1540 | msu++; | 1540 | msu++; |
1541 | } | 1541 | } |
1542 | unlock_kernel(); | ||
1543 | return 0; | 1542 | return 0; |
1544 | } | 1543 | } |
1545 | case MOXA_ASPP_MON_EXT: { | 1544 | case MOXA_ASPP_MON_EXT: { |
@@ -1551,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1551 | if (!me) | 1550 | if (!me) |
1552 | return -ENOMEM; | 1551 | return -ENOMEM; |
1553 | 1552 | ||
1554 | lock_kernel(); | ||
1555 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { | 1553 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
1556 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { | 1554 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
1557 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | 1555 | if (p >= ARRAY_SIZE(me->rx_cnt)) { |
1558 | i = MXSER_BOARDS; | 1556 | i = MXSER_BOARDS; |
1559 | break; | 1557 | break; |
1560 | } | 1558 | } |
1561 | port = &mxser_boards[i].ports[j]; | 1559 | ip = &mxser_boards[i].ports[j]; |
1562 | if (!port->ioaddr) | 1560 | port = &ip->port; |
1561 | |||
1562 | mutex_lock(&port->mutex); | ||
1563 | if (!ip->ioaddr) { | ||
1564 | mutex_unlock(&port->mutex); | ||
1563 | continue; | 1565 | continue; |
1566 | } | ||
1564 | 1567 | ||
1565 | status = mxser_get_msr(port->ioaddr, 0, p); | 1568 | spin_lock_irq(&ip->slock); |
1569 | status = mxser_get_msr(ip->ioaddr, 0, p); | ||
1566 | 1570 | ||
1567 | if (status & UART_MSR_TERI) | 1571 | if (status & UART_MSR_TERI) |
1568 | port->icount.rng++; | 1572 | ip->icount.rng++; |
1569 | if (status & UART_MSR_DDSR) | 1573 | if (status & UART_MSR_DDSR) |
1570 | port->icount.dsr++; | 1574 | ip->icount.dsr++; |
1571 | if (status & UART_MSR_DDCD) | 1575 | if (status & UART_MSR_DDCD) |
1572 | port->icount.dcd++; | 1576 | ip->icount.dcd++; |
1573 | if (status & UART_MSR_DCTS) | 1577 | if (status & UART_MSR_DCTS) |
1574 | port->icount.cts++; | 1578 | ip->icount.cts++; |
1575 | 1579 | ||
1576 | port->mon_data.modem_status = status; | 1580 | ip->mon_data.modem_status = status; |
1577 | me->rx_cnt[p] = port->mon_data.rxcnt; | 1581 | me->rx_cnt[p] = ip->mon_data.rxcnt; |
1578 | me->tx_cnt[p] = port->mon_data.txcnt; | 1582 | me->tx_cnt[p] = ip->mon_data.txcnt; |
1579 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; | 1583 | me->up_rxcnt[p] = ip->mon_data.up_rxcnt; |
1580 | me->up_txcnt[p] = port->mon_data.up_txcnt; | 1584 | me->up_txcnt[p] = ip->mon_data.up_txcnt; |
1581 | me->modem_status[p] = | 1585 | me->modem_status[p] = |
1582 | port->mon_data.modem_status; | 1586 | ip->mon_data.modem_status; |
1583 | tty = tty_port_tty_get(&port->port); | 1587 | spin_unlock_irq(&ip->slock); |
1588 | |||
1589 | tty = tty_port_tty_get(&ip->port); | ||
1584 | 1590 | ||
1585 | if (!tty || !tty->termios) { | 1591 | if (!tty || !tty->termios) { |
1586 | cflag = port->normal_termios.c_cflag; | 1592 | cflag = ip->normal_termios.c_cflag; |
1587 | iflag = port->normal_termios.c_iflag; | 1593 | iflag = ip->normal_termios.c_iflag; |
1588 | me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); | 1594 | me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); |
1589 | } else { | 1595 | } else { |
1590 | cflag = tty->termios->c_cflag; | 1596 | cflag = tty->termios->c_cflag; |
1591 | iflag = tty->termios->c_iflag; | 1597 | iflag = tty->termios->c_iflag; |
@@ -1604,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1604 | if (iflag & (IXON | IXOFF)) | 1610 | if (iflag & (IXON | IXOFF)) |
1605 | me->flowctrl[p] |= 0x0C; | 1611 | me->flowctrl[p] |= 0x0C; |
1606 | 1612 | ||
1607 | if (port->type == PORT_16550A) | 1613 | if (ip->type == PORT_16550A) |
1608 | me->fifo[p] = 1; | 1614 | me->fifo[p] = 1; |
1609 | 1615 | ||
1610 | opmode = inb(port->opmode_ioaddr) >> | 1616 | opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); |
1611 | ((p % 4) * 2); | ||
1612 | opmode &= OP_MODE_MASK; | 1617 | opmode &= OP_MODE_MASK; |
1613 | me->iftype[p] = opmode; | 1618 | me->iftype[p] = opmode; |
1619 | mutex_unlock(&port->mutex); | ||
1614 | } | 1620 | } |
1615 | } | 1621 | } |
1616 | unlock_kernel(); | ||
1617 | if (copy_to_user(argp, me, sizeof(*me))) | 1622 | if (copy_to_user(argp, me, sizeof(*me))) |
1618 | ret = -EFAULT; | 1623 | ret = -EFAULT; |
1619 | kfree(me); | 1624 | kfree(me); |
@@ -1650,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1650 | unsigned int cmd, unsigned long arg) | 1655 | unsigned int cmd, unsigned long arg) |
1651 | { | 1656 | { |
1652 | struct mxser_port *info = tty->driver_data; | 1657 | struct mxser_port *info = tty->driver_data; |
1658 | struct tty_port *port = &info->port; | ||
1653 | struct async_icount cnow; | 1659 | struct async_icount cnow; |
1654 | unsigned long flags; | 1660 | unsigned long flags; |
1655 | void __user *argp = (void __user *)arg; | 1661 | void __user *argp = (void __user *)arg; |
@@ -1674,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1674 | opmode != RS422_MODE && | 1680 | opmode != RS422_MODE && |
1675 | opmode != RS485_4WIRE_MODE) | 1681 | opmode != RS485_4WIRE_MODE) |
1676 | return -EFAULT; | 1682 | return -EFAULT; |
1677 | lock_kernel(); | ||
1678 | mask = ModeMask[p]; | 1683 | mask = ModeMask[p]; |
1679 | shiftbit = p * 2; | 1684 | shiftbit = p * 2; |
1685 | spin_lock_irq(&info->slock); | ||
1680 | val = inb(info->opmode_ioaddr); | 1686 | val = inb(info->opmode_ioaddr); |
1681 | val &= mask; | 1687 | val &= mask; |
1682 | val |= (opmode << shiftbit); | 1688 | val |= (opmode << shiftbit); |
1683 | outb(val, info->opmode_ioaddr); | 1689 | outb(val, info->opmode_ioaddr); |
1684 | unlock_kernel(); | 1690 | spin_unlock_irq(&info->slock); |
1685 | } else { | 1691 | } else { |
1686 | lock_kernel(); | ||
1687 | shiftbit = p * 2; | 1692 | shiftbit = p * 2; |
1693 | spin_lock_irq(&info->slock); | ||
1688 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 1694 | opmode = inb(info->opmode_ioaddr) >> shiftbit; |
1695 | spin_unlock_irq(&info->slock); | ||
1689 | opmode &= OP_MODE_MASK; | 1696 | opmode &= OP_MODE_MASK; |
1690 | unlock_kernel(); | ||
1691 | if (put_user(opmode, (int __user *)argp)) | 1697 | if (put_user(opmode, (int __user *)argp)) |
1692 | return -EFAULT; | 1698 | return -EFAULT; |
1693 | } | 1699 | } |
@@ -1700,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1700 | 1706 | ||
1701 | switch (cmd) { | 1707 | switch (cmd) { |
1702 | case TIOCGSERIAL: | 1708 | case TIOCGSERIAL: |
1703 | lock_kernel(); | 1709 | mutex_lock(&port->mutex); |
1704 | retval = mxser_get_serial_info(tty, argp); | 1710 | retval = mxser_get_serial_info(tty, argp); |
1705 | unlock_kernel(); | 1711 | mutex_unlock(&port->mutex); |
1706 | return retval; | 1712 | return retval; |
1707 | case TIOCSSERIAL: | 1713 | case TIOCSSERIAL: |
1708 | lock_kernel(); | 1714 | mutex_lock(&port->mutex); |
1709 | retval = mxser_set_serial_info(tty, argp); | 1715 | retval = mxser_set_serial_info(tty, argp); |
1710 | unlock_kernel(); | 1716 | mutex_unlock(&port->mutex); |
1711 | return retval; | 1717 | return retval; |
1712 | case TIOCSERGETLSR: /* Get line status register */ | 1718 | case TIOCSERGETLSR: /* Get line status register */ |
1713 | return mxser_get_lsr_info(info, argp); | 1719 | return mxser_get_lsr_info(info, argp); |
@@ -1753,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1753 | case MOXA_HighSpeedOn: | 1759 | case MOXA_HighSpeedOn: |
1754 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1760 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1755 | case MOXA_SDS_RSTICOUNTER: | 1761 | case MOXA_SDS_RSTICOUNTER: |
1756 | lock_kernel(); | 1762 | spin_lock_irq(&info->slock); |
1757 | info->mon_data.rxcnt = 0; | 1763 | info->mon_data.rxcnt = 0; |
1758 | info->mon_data.txcnt = 0; | 1764 | info->mon_data.txcnt = 0; |
1759 | unlock_kernel(); | 1765 | spin_unlock_irq(&info->slock); |
1760 | return 0; | 1766 | return 0; |
1761 | 1767 | ||
1762 | case MOXA_ASPP_OQUEUE:{ | 1768 | case MOXA_ASPP_OQUEUE:{ |
1763 | int len, lsr; | 1769 | int len, lsr; |
1764 | 1770 | ||
1765 | lock_kernel(); | ||
1766 | len = mxser_chars_in_buffer(tty); | 1771 | len = mxser_chars_in_buffer(tty); |
1772 | spin_lock(&info->slock); | ||
1767 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 1773 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; |
1774 | spin_unlock_irq(&info->slock); | ||
1768 | len += (lsr ? 0 : 1); | 1775 | len += (lsr ? 0 : 1); |
1769 | unlock_kernel(); | ||
1770 | 1776 | ||
1771 | return put_user(len, (int __user *)argp); | 1777 | return put_user(len, (int __user *)argp); |
1772 | } | 1778 | } |
1773 | case MOXA_ASPP_MON: { | 1779 | case MOXA_ASPP_MON: { |
1774 | int mcr, status; | 1780 | int mcr, status; |
1775 | 1781 | ||
1776 | lock_kernel(); | 1782 | spin_lock(&info->slock); |
1777 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1783 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1778 | mxser_check_modem_status(tty, info, status); | 1784 | mxser_check_modem_status(tty, info, status); |
1779 | 1785 | ||
1780 | mcr = inb(info->ioaddr + UART_MCR); | 1786 | mcr = inb(info->ioaddr + UART_MCR); |
1787 | spin_unlock(&info->slock); | ||
1788 | |||
1781 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1789 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
1782 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 1790 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; |
1783 | else | 1791 | else |
@@ -1792,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1792 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 1800 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; |
1793 | else | 1801 | else |
1794 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 1802 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; |
1795 | unlock_kernel(); | 1803 | |
1796 | if (copy_to_user(argp, &info->mon_data, | 1804 | if (copy_to_user(argp, &info->mon_data, |
1797 | sizeof(struct mxser_mon))) | 1805 | sizeof(struct mxser_mon))) |
1798 | return -EFAULT; | 1806 | return -EFAULT; |
@@ -1951,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1951 | { | 1959 | { |
1952 | struct mxser_port *info = tty->driver_data; | 1960 | struct mxser_port *info = tty->driver_data; |
1953 | unsigned long orig_jiffies, char_time; | 1961 | unsigned long orig_jiffies, char_time; |
1962 | unsigned long flags; | ||
1954 | int lsr; | 1963 | int lsr; |
1955 | 1964 | ||
1956 | if (info->type == PORT_UNKNOWN) | 1965 | if (info->type == PORT_UNKNOWN) |
@@ -1990,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1990 | timeout, char_time); | 1999 | timeout, char_time); |
1991 | printk("jiff=%lu...", jiffies); | 2000 | printk("jiff=%lu...", jiffies); |
1992 | #endif | 2001 | #endif |
1993 | lock_kernel(); | 2002 | spin_lock_irqsave(&info->slock, flags); |
1994 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 2003 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
1995 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2004 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1996 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 2005 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); |
1997 | #endif | 2006 | #endif |
2007 | spin_unlock_irqrestore(&info->slock, flags); | ||
1998 | schedule_timeout_interruptible(char_time); | 2008 | schedule_timeout_interruptible(char_time); |
2009 | spin_lock_irqsave(&info->slock, flags); | ||
1999 | if (signal_pending(current)) | 2010 | if (signal_pending(current)) |
2000 | break; | 2011 | break; |
2001 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 2012 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
2002 | break; | 2013 | break; |
2003 | } | 2014 | } |
2015 | spin_unlock_irqrestore(&info->slock, flags); | ||
2004 | set_current_state(TASK_RUNNING); | 2016 | set_current_state(TASK_RUNNING); |
2005 | unlock_kernel(); | ||
2006 | 2017 | ||
2007 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2018 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
2008 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 2019 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |