diff options
Diffstat (limited to 'drivers/char/nozomi.c')
-rw-r--r-- | drivers/char/nozomi.c | 85 |
1 files changed, 45 insertions, 40 deletions
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 9a34a1935283..d6102b644b55 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -353,6 +353,7 @@ struct ctrl_ul { | |||
353 | 353 | ||
354 | /* This holds all information that is needed regarding a port */ | 354 | /* This holds all information that is needed regarding a port */ |
355 | struct port { | 355 | struct port { |
356 | struct tty_port port; | ||
356 | u8 update_flow_control; | 357 | u8 update_flow_control; |
357 | struct ctrl_ul ctrl_ul; | 358 | struct ctrl_ul ctrl_ul; |
358 | struct ctrl_dl ctrl_dl; | 359 | struct ctrl_dl ctrl_dl; |
@@ -365,8 +366,6 @@ struct port { | |||
365 | u8 toggle_ul; | 366 | u8 toggle_ul; |
366 | u16 token_dl; | 367 | u16 token_dl; |
367 | 368 | ||
368 | struct tty_struct *tty; | ||
369 | int tty_open_count; | ||
370 | /* mutex to ensure one access patch to this port */ | 369 | /* mutex to ensure one access patch to this port */ |
371 | struct mutex tty_sem; | 370 | struct mutex tty_sem; |
372 | wait_queue_head_t tty_wait; | 371 | wait_queue_head_t tty_wait; |
@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc) | |||
788 | * Return 1 - send buffer to card and ack. | 787 | * Return 1 - send buffer to card and ack. |
789 | * Return 0 - don't ack, don't send buffer to card. | 788 | * Return 0 - don't ack, don't send buffer to card. |
790 | */ | 789 | */ |
791 | static int send_data(enum port_type index, const struct nozomi *dc) | 790 | static int send_data(enum port_type index, struct nozomi *dc) |
792 | { | 791 | { |
793 | u32 size = 0; | 792 | u32 size = 0; |
794 | const struct port *port = &dc->port[index]; | 793 | struct port *port = &dc->port[index]; |
795 | const u8 toggle = port->toggle_ul; | 794 | const u8 toggle = port->toggle_ul; |
796 | void __iomem *addr = port->ul_addr[toggle]; | 795 | void __iomem *addr = port->ul_addr[toggle]; |
797 | const u32 ul_size = port->ul_size[toggle]; | 796 | const u32 ul_size = port->ul_size[toggle]; |
798 | struct tty_struct *tty = port->tty; | 797 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
799 | 798 | ||
800 | /* Get data from tty and place in buf for now */ | 799 | /* Get data from tty and place in buf for now */ |
801 | size = __kfifo_get(port->fifo_ul, dc->send_buf, | 800 | size = __kfifo_get(port->fifo_ul, dc->send_buf, |
@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) | |||
803 | 802 | ||
804 | if (size == 0) { | 803 | if (size == 0) { |
805 | DBG4("No more data to send, disable link:"); | 804 | DBG4("No more data to send, disable link:"); |
805 | tty_kref_put(tty); | ||
806 | return 0; | 806 | return 0; |
807 | } | 807 | } |
808 | 808 | ||
@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) | |||
815 | if (tty) | 815 | if (tty) |
816 | tty_wakeup(tty); | 816 | tty_wakeup(tty); |
817 | 817 | ||
818 | tty_kref_put(tty); | ||
818 | return 1; | 819 | return 1; |
819 | } | 820 | } |
820 | 821 | ||
@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
826 | u32 offset = 4; | 827 | u32 offset = 4; |
827 | struct port *port = &dc->port[index]; | 828 | struct port *port = &dc->port[index]; |
828 | void __iomem *addr = port->dl_addr[port->toggle_dl]; | 829 | void __iomem *addr = port->dl_addr[port->toggle_dl]; |
829 | struct tty_struct *tty = port->tty; | 830 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
830 | int i; | 831 | int i; |
831 | 832 | ||
832 | if (unlikely(!tty)) { | 833 | if (unlikely(!tty)) { |
@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
870 | } | 871 | } |
871 | 872 | ||
872 | set_bit(index, &dc->flip); | 873 | set_bit(index, &dc->flip); |
873 | 874 | tty_kref_put(tty); | |
874 | return 1; | 875 | return 1; |
875 | } | 876 | } |
876 | 877 | ||
@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) | |||
1276 | 1277 | ||
1277 | exit_handler: | 1278 | exit_handler: |
1278 | spin_unlock(&dc->spin_mutex); | 1279 | spin_unlock(&dc->spin_mutex); |
1279 | for (a = 0; a < NOZOMI_MAX_PORTS; a++) | 1280 | for (a = 0; a < NOZOMI_MAX_PORTS; a++) { |
1280 | if (test_and_clear_bit(a, &dc->flip)) | 1281 | struct tty_struct *tty; |
1281 | tty_flip_buffer_push(dc->port[a].tty); | 1282 | if (test_and_clear_bit(a, &dc->flip)) { |
1283 | tty = tty_port_tty_get(&dc->port[a].port); | ||
1284 | if (tty) | ||
1285 | tty_flip_buffer_push(tty); | ||
1286 | tty_kref_put(tty); | ||
1287 | } | ||
1288 | } | ||
1282 | return IRQ_HANDLED; | 1289 | return IRQ_HANDLED; |
1283 | none: | 1290 | none: |
1284 | spin_unlock(&dc->spin_mutex); | 1291 | spin_unlock(&dc->spin_mutex); |
@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1453 | 1460 | ||
1454 | for (i = 0; i < MAX_PORT; i++) { | 1461 | for (i = 0; i < MAX_PORT; i++) { |
1455 | mutex_init(&dc->port[i].tty_sem); | 1462 | mutex_init(&dc->port[i].tty_sem); |
1456 | dc->port[i].tty_open_count = 0; | 1463 | tty_port_init(&dc->port[i].port); |
1457 | dc->port[i].tty = NULL; | ||
1458 | tty_register_device(ntty_driver, dc->index_start + i, | 1464 | tty_register_device(ntty_driver, dc->index_start + i, |
1459 | &pdev->dev); | 1465 | &pdev->dev); |
1460 | } | 1466 | } |
1461 | |||
1462 | return 0; | 1467 | return 0; |
1463 | 1468 | ||
1464 | err_free_sbuf: | 1469 | err_free_sbuf: |
@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc) | |||
1482 | 1487 | ||
1483 | flush_scheduled_work(); | 1488 | flush_scheduled_work(); |
1484 | 1489 | ||
1485 | for (i = 0; i < MAX_PORT; ++i) | 1490 | for (i = 0; i < MAX_PORT; ++i) { |
1486 | if (dc->port[i].tty && \ | 1491 | struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); |
1487 | list_empty(&dc->port[i].tty->hangup_work.entry)) | 1492 | if (tty && list_empty(&tty->hangup_work.entry)) |
1488 | tty_hangup(dc->port[i].tty); | 1493 | tty_hangup(tty); |
1489 | 1494 | tty_kref_put(tty); | |
1495 | } | ||
1496 | /* Racy below - surely should wait for scheduled work to be done or | ||
1497 | complete off a hangup method ? */ | ||
1490 | while (dc->open_ttys) | 1498 | while (dc->open_ttys) |
1491 | msleep(1); | 1499 | msleep(1); |
1492 | |||
1493 | for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) | 1500 | for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) |
1494 | tty_unregister_device(ntty_driver, i); | 1501 | tty_unregister_device(ntty_driver, i); |
1495 | } | 1502 | } |
@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
1579 | if (mutex_lock_interruptible(&port->tty_sem)) | 1586 | if (mutex_lock_interruptible(&port->tty_sem)) |
1580 | return -ERESTARTSYS; | 1587 | return -ERESTARTSYS; |
1581 | 1588 | ||
1582 | port->tty_open_count++; | 1589 | port->port.count++; |
1583 | dc->open_ttys++; | 1590 | dc->open_ttys++; |
1584 | 1591 | ||
1585 | /* Enable interrupt downlink for channel */ | 1592 | /* Enable interrupt downlink for channel */ |
1586 | if (port->tty_open_count == 1) { | 1593 | if (port->port.count == 1) { |
1594 | /* FIXME: is this needed now ? */ | ||
1587 | tty->low_latency = 1; | 1595 | tty->low_latency = 1; |
1588 | tty->driver_data = port; | 1596 | tty->driver_data = port; |
1589 | port->tty = tty; | 1597 | tty_port_tty_set(&port->port, tty); |
1590 | DBG1("open: %d", port->token_dl); | 1598 | DBG1("open: %d", port->token_dl); |
1591 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1599 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1592 | dc->last_ier = dc->last_ier | port->token_dl; | 1600 | dc->last_ier = dc->last_ier | port->token_dl; |
1593 | writew(dc->last_ier, dc->reg_ier); | 1601 | writew(dc->last_ier, dc->reg_ier); |
1594 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1602 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1595 | } | 1603 | } |
1596 | |||
1597 | mutex_unlock(&port->tty_sem); | 1604 | mutex_unlock(&port->tty_sem); |
1598 | |||
1599 | return 0; | 1605 | return 0; |
1600 | } | 1606 | } |
1601 | 1607 | ||
@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
1606 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1612 | static void ntty_close(struct tty_struct *tty, struct file *file) |
1607 | { | 1613 | { |
1608 | struct nozomi *dc = get_dc_by_tty(tty); | 1614 | struct nozomi *dc = get_dc_by_tty(tty); |
1609 | struct port *port = tty->driver_data; | 1615 | struct port *nport = tty->driver_data; |
1616 | struct tty_port *port = &nport->port; | ||
1610 | unsigned long flags; | 1617 | unsigned long flags; |
1611 | 1618 | ||
1612 | if (!dc || !port) | 1619 | if (!dc || !nport) |
1613 | return; | 1620 | return; |
1614 | 1621 | ||
1615 | if (mutex_lock_interruptible(&port->tty_sem)) | 1622 | /* Users cannot interrupt a close */ |
1616 | return; | 1623 | mutex_lock(&nport->tty_sem); |
1617 | 1624 | ||
1618 | if (!port->tty_open_count) | 1625 | WARN_ON(!port->count); |
1619 | goto exit; | ||
1620 | 1626 | ||
1621 | dc->open_ttys--; | 1627 | dc->open_ttys--; |
1622 | port->tty_open_count--; | 1628 | port->count--; |
1629 | tty_port_tty_set(port, NULL); | ||
1623 | 1630 | ||
1624 | if (port->tty_open_count == 0) { | 1631 | if (port->count == 0) { |
1625 | DBG1("close: %d", port->token_dl); | 1632 | DBG1("close: %d", nport->token_dl); |
1626 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1633 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1627 | dc->last_ier &= ~(port->token_dl); | 1634 | dc->last_ier &= ~(nport->token_dl); |
1628 | writew(dc->last_ier, dc->reg_ier); | 1635 | writew(dc->last_ier, dc->reg_ier); |
1629 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1636 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1630 | } | 1637 | } |
1631 | 1638 | mutex_unlock(&nport->tty_sem); | |
1632 | exit: | ||
1633 | mutex_unlock(&port->tty_sem); | ||
1634 | } | 1639 | } |
1635 | 1640 | ||
1636 | /* | 1641 | /* |
@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1660 | return -EAGAIN; | 1665 | return -EAGAIN; |
1661 | } | 1666 | } |
1662 | 1667 | ||
1663 | if (unlikely(!port->tty_open_count)) { | 1668 | if (unlikely(!port->port.count)) { |
1664 | DBG1(" "); | 1669 | DBG1(" "); |
1665 | goto exit; | 1670 | goto exit; |
1666 | } | 1671 | } |
@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty) | |||
1710 | if (!mutex_trylock(&port->tty_sem)) | 1715 | if (!mutex_trylock(&port->tty_sem)) |
1711 | return 0; | 1716 | return 0; |
1712 | 1717 | ||
1713 | if (!port->tty_open_count) | 1718 | if (!port->port.count) |
1714 | goto exit; | 1719 | goto exit; |
1715 | 1720 | ||
1716 | room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); | 1721 | room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); |
@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) | |||
1866 | goto exit_in_buffer; | 1871 | goto exit_in_buffer; |
1867 | } | 1872 | } |
1868 | 1873 | ||
1869 | if (unlikely(!port->tty_open_count)) { | 1874 | if (unlikely(!port->port.count)) { |
1870 | dev_err(&dc->pdev->dev, "No tty open?\n"); | 1875 | dev_err(&dc->pdev->dev, "No tty open?\n"); |
1871 | rval = -ENODEV; | 1876 | rval = -ENODEV; |
1872 | goto exit_in_buffer; | 1877 | goto exit_in_buffer; |