aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/nozomi.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2010-02-08 05:06:45 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:43:20 -0500
commit266794eb71cfee65b38371954b9db2f6dbda207c (patch)
tree1366efced65d8234dc330aff13597f46ac4a18c7 /drivers/char/nozomi.c
parent8b197a5ce7a7218bb9fc721647ba0d5734f27348 (diff)
nozomi: Add tty_port usage
The Nozomi tty handling is very broken on the open/close side (See http://bugzilla.kernel.org/show_bug.cgi?id=13024 for one example). In particular it marks the tty as closed on the first close() not on the last. Most of the logic is pretty solid except for the open/close path so switch to the tty_port helpers and let them do all the heavy lifting. This is also fixes all the POSIX behaviour violations in the open/close paths. Begin by adding the tty port usage Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/nozomi.c')
-rw-r--r--drivers/char/nozomi.c115
1 files changed, 68 insertions, 47 deletions
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 2ad7d37afbd0..cd405bcf53a6 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -371,6 +371,8 @@ struct port {
371 struct mutex tty_sem; 371 struct mutex tty_sem;
372 wait_queue_head_t tty_wait; 372 wait_queue_head_t tty_wait;
373 struct async_icount tty_icount; 373 struct async_icount tty_icount;
374
375 struct nozomi *dc;
374}; 376};
375 377
376/* Private data one for each card in the system */ 378/* Private data one for each card in the system */
@@ -414,6 +416,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
414static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; 416static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
415static struct tty_driver *ntty_driver; 417static struct tty_driver *ntty_driver;
416 418
419static const struct tty_port_operations noz_tty_port_ops;
420
417/* 421/*
418 * find card by tty_index 422 * find card by tty_index
419 */ 423 */
@@ -1473,9 +1477,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
1473 1477
1474 for (i = 0; i < MAX_PORT; i++) { 1478 for (i = 0; i < MAX_PORT; i++) {
1475 struct device *tty_dev; 1479 struct device *tty_dev;
1476 1480 struct port *port = &dc->port[i];
1477 mutex_init(&dc->port[i].tty_sem); 1481 port->dc = dc;
1478 tty_port_init(&dc->port[i].port); 1482 mutex_init(&port->tty_sem);
1483 tty_port_init(&port->port);
1484 port->port.ops = &noz_tty_port_ops;
1479 tty_dev = tty_register_device(ntty_driver, dc->index_start + i, 1485 tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
1480 &pdev->dev); 1486 &pdev->dev);
1481 1487
@@ -1600,67 +1606,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr)
1600 * ---------------------------------------------------------------------------- 1606 * ----------------------------------------------------------------------------
1601 */ 1607 */
1602 1608
1603/* Called when the userspace process opens the tty, /dev/noz*. */ 1609static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
1604static int ntty_open(struct tty_struct *tty, struct file *file)
1605{ 1610{
1606 struct port *port = get_port_by_tty(tty); 1611 struct port *port = get_port_by_tty(tty);
1607 struct nozomi *dc = get_dc_by_tty(tty); 1612 struct nozomi *dc = get_dc_by_tty(tty);
1608 unsigned long flags; 1613 int ret;
1609
1610 if (!port || !dc || dc->state != NOZOMI_STATE_READY) 1614 if (!port || !dc || dc->state != NOZOMI_STATE_READY)
1611 return -ENODEV; 1615 return -ENODEV;
1612 1616 ret = tty_init_termios(tty);
1613 if (mutex_lock_interruptible(&port->tty_sem)) 1617 if (ret == 0) {
1614 return -ERESTARTSYS; 1618 tty_driver_kref_get(driver);
1615 1619 driver->ttys[tty->index] = tty;
1616 port->port.count++;
1617 dc->open_ttys++;
1618
1619 /* Enable interrupt downlink for channel */
1620 if (port->port.count == 1) {
1621 tty->driver_data = port;
1622 tty_port_tty_set(&port->port, tty);
1623 DBG1("open: %d", port->token_dl);
1624 spin_lock_irqsave(&dc->spin_mutex, flags);
1625 dc->last_ier = dc->last_ier | port->token_dl;
1626 writew(dc->last_ier, dc->reg_ier);
1627 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1628 } 1620 }
1629 mutex_unlock(&port->tty_sem); 1621 return ret;
1630 return 0;
1631} 1622}
1632 1623
1633/* Called when the userspace process close the tty, /dev/noz*. Also 1624static void ntty_cleanup(struct tty_struct *tty)
1634 called immediately if ntty_open fails in which case tty->driver_data 1625{
1635 will be NULL an we exit by the first return */ 1626 tty->driver_data = NULL;
1627}
1636 1628
1637static void ntty_close(struct tty_struct *tty, struct file *file) 1629static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
1638{ 1630{
1639 struct nozomi *dc = get_dc_by_tty(tty); 1631 struct port *port = container_of(tport, struct port, port);
1640 struct port *nport = tty->driver_data; 1632 struct nozomi *dc = port->dc;
1641 struct tty_port *port = &nport->port;
1642 unsigned long flags; 1633 unsigned long flags;
1643 1634
1644 if (!dc || !nport) 1635 DBG1("open: %d", port->token_dl);
1645 return; 1636 spin_lock_irqsave(&dc->spin_mutex, flags);
1637 dc->last_ier = dc->last_ier | port->token_dl;
1638 writew(dc->last_ier, dc->reg_ier);
1639 dc->open_ttys++;
1640 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1641 printk("noz: activated %d: %p\n", tty->index, tport);
1642 return 0;
1643}
1646 1644
1647 /* Users cannot interrupt a close */ 1645static int ntty_open(struct tty_struct *tty, struct file *filp)
1648 mutex_lock(&nport->tty_sem); 1646{
1647 struct port *port = get_port_by_tty(tty);
1648 return tty_port_open(&port->port, tty, filp);
1649}
1649 1650
1650 WARN_ON(!port->count); 1651static void ntty_shutdown(struct tty_port *tport)
1652{
1653 struct port *port = container_of(tport, struct port, port);
1654 struct nozomi *dc = port->dc;
1655 unsigned long flags;
1651 1656
1657 DBG1("close: %d", port->token_dl);
1658 spin_lock_irqsave(&dc->spin_mutex, flags);
1659 dc->last_ier &= ~(port->token_dl);
1660 writew(dc->last_ier, dc->reg_ier);
1652 dc->open_ttys--; 1661 dc->open_ttys--;
1653 port->count--; 1662 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1663 printk("noz: shutdown %p\n", tport);
1664}
1654 1665
1655 if (port->count == 0) { 1666static void ntty_close(struct tty_struct *tty, struct file *filp)
1656 DBG1("close: %d", nport->token_dl); 1667{
1657 tty_port_tty_set(port, NULL); 1668 struct port *port = tty->driver_data;
1658 spin_lock_irqsave(&dc->spin_mutex, flags); 1669 if (port)
1659 dc->last_ier &= ~(nport->token_dl); 1670 tty_port_close(&port->port, tty, filp);
1660 writew(dc->last_ier, dc->reg_ier); 1671}
1661 spin_unlock_irqrestore(&dc->spin_mutex, flags); 1672
1662 } 1673static void ntty_hangup(struct tty_struct *tty)
1663 mutex_unlock(&nport->tty_sem); 1674{
1675 struct port *port = tty->driver_data;
1676 tty_port_hangup(&port->port);
1664} 1677}
1665 1678
1666/* 1679/*
@@ -1906,10 +1919,16 @@ exit_in_buffer:
1906 return rval; 1919 return rval;
1907} 1920}
1908 1921
1922static const struct tty_port_operations noz_tty_port_ops = {
1923 .activate = ntty_activate,
1924 .shutdown = ntty_shutdown,
1925};
1926
1909static const struct tty_operations tty_ops = { 1927static const struct tty_operations tty_ops = {
1910 .ioctl = ntty_ioctl, 1928 .ioctl = ntty_ioctl,
1911 .open = ntty_open, 1929 .open = ntty_open,
1912 .close = ntty_close, 1930 .close = ntty_close,
1931 .hangup = ntty_hangup,
1913 .write = ntty_write, 1932 .write = ntty_write,
1914 .write_room = ntty_write_room, 1933 .write_room = ntty_write_room,
1915 .unthrottle = ntty_unthrottle, 1934 .unthrottle = ntty_unthrottle,
@@ -1917,6 +1936,8 @@ static const struct tty_operations tty_ops = {
1917 .chars_in_buffer = ntty_chars_in_buffer, 1936 .chars_in_buffer = ntty_chars_in_buffer,
1918 .tiocmget = ntty_tiocmget, 1937 .tiocmget = ntty_tiocmget,
1919 .tiocmset = ntty_tiocmset, 1938 .tiocmset = ntty_tiocmset,
1939 .install = ntty_install,
1940 .cleanup = ntty_cleanup,
1920}; 1941};
1921 1942
1922/* Module initialization */ 1943/* Module initialization */