diff options
| -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); |
