aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/nozomi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/nozomi.c')
-rw-r--r--drivers/char/nozomi.c157
1 files changed, 81 insertions, 76 deletions
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 2ad7d37afbd0..a3f32a15fde4 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -136,10 +136,6 @@ static int debug;
136#define RECEIVE_BUF_MAX 4 136#define RECEIVE_BUF_MAX 4
137 137
138 138
139/* Define all types of vendors and devices to support */
140#define VENDOR1 0x1931 /* Vendor Option */
141#define DEVICE1 0x000c /* HSDPA card */
142
143#define R_IIR 0x0000 /* Interrupt Identity Register */ 139#define R_IIR 0x0000 /* Interrupt Identity Register */
144#define R_FCR 0x0000 /* Flow Control Register */ 140#define R_FCR 0x0000 /* Flow Control Register */
145#define R_IER 0x0004 /* Interrupt Enable Register */ 141#define R_IER 0x0004 /* Interrupt Enable Register */
@@ -371,6 +367,8 @@ struct port {
371 struct mutex tty_sem; 367 struct mutex tty_sem;
372 wait_queue_head_t tty_wait; 368 wait_queue_head_t tty_wait;
373 struct async_icount tty_icount; 369 struct async_icount tty_icount;
370
371 struct nozomi *dc;
374}; 372};
375 373
376/* Private data one for each card in the system */ 374/* Private data one for each card in the system */
@@ -405,7 +403,7 @@ struct buffer {
405 403
406/* Global variables */ 404/* Global variables */
407static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { 405static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
408 {PCI_DEVICE(VENDOR1, DEVICE1)}, 406 {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
409 {}, 407 {},
410}; 408};
411 409
@@ -414,6 +412,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
414static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; 412static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
415static struct tty_driver *ntty_driver; 413static struct tty_driver *ntty_driver;
416 414
415static const struct tty_port_operations noz_tty_port_ops;
416
417/* 417/*
418 * find card by tty_index 418 * find card by tty_index
419 */ 419 */
@@ -853,8 +853,6 @@ static int receive_data(enum port_type index, struct nozomi *dc)
853 goto put; 853 goto put;
854 } 854 }
855 855
856 tty_buffer_request_room(tty, size);
857
858 while (size > 0) { 856 while (size > 0) {
859 read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); 857 read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
860 858
@@ -1473,9 +1471,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
1473 1471
1474 for (i = 0; i < MAX_PORT; i++) { 1472 for (i = 0; i < MAX_PORT; i++) {
1475 struct device *tty_dev; 1473 struct device *tty_dev;
1476 1474 struct port *port = &dc->port[i];
1477 mutex_init(&dc->port[i].tty_sem); 1475 port->dc = dc;
1478 tty_port_init(&dc->port[i].port); 1476 mutex_init(&port->tty_sem);
1477 tty_port_init(&port->port);
1478 port->port.ops = &noz_tty_port_ops;
1479 tty_dev = tty_register_device(ntty_driver, dc->index_start + i, 1479 tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
1480 &pdev->dev); 1480 &pdev->dev);
1481 1481
@@ -1600,67 +1600,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr)
1600 * ---------------------------------------------------------------------------- 1600 * ----------------------------------------------------------------------------
1601 */ 1601 */
1602 1602
1603/* Called when the userspace process opens the tty, /dev/noz*. */ 1603static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
1604static int ntty_open(struct tty_struct *tty, struct file *file)
1605{ 1604{
1606 struct port *port = get_port_by_tty(tty); 1605 struct port *port = get_port_by_tty(tty);
1607 struct nozomi *dc = get_dc_by_tty(tty); 1606 struct nozomi *dc = get_dc_by_tty(tty);
1608 unsigned long flags; 1607 int ret;
1609
1610 if (!port || !dc || dc->state != NOZOMI_STATE_READY) 1608 if (!port || !dc || dc->state != NOZOMI_STATE_READY)
1611 return -ENODEV; 1609 return -ENODEV;
1612 1610 ret = tty_init_termios(tty);
1613 if (mutex_lock_interruptible(&port->tty_sem)) 1611 if (ret == 0) {
1614 return -ERESTARTSYS; 1612 tty_driver_kref_get(driver);
1615 1613 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 } 1614 }
1629 mutex_unlock(&port->tty_sem); 1615 return ret;
1630 return 0;
1631} 1616}
1632 1617
1633/* Called when the userspace process close the tty, /dev/noz*. Also 1618static void ntty_cleanup(struct tty_struct *tty)
1634 called immediately if ntty_open fails in which case tty->driver_data 1619{
1635 will be NULL an we exit by the first return */ 1620 tty->driver_data = NULL;
1621}
1636 1622
1637static void ntty_close(struct tty_struct *tty, struct file *file) 1623static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
1638{ 1624{
1639 struct nozomi *dc = get_dc_by_tty(tty); 1625 struct port *port = container_of(tport, struct port, port);
1640 struct port *nport = tty->driver_data; 1626 struct nozomi *dc = port->dc;
1641 struct tty_port *port = &nport->port;
1642 unsigned long flags; 1627 unsigned long flags;
1643 1628
1644 if (!dc || !nport) 1629 DBG1("open: %d", port->token_dl);
1645 return; 1630 spin_lock_irqsave(&dc->spin_mutex, flags);
1631 dc->last_ier = dc->last_ier | port->token_dl;
1632 writew(dc->last_ier, dc->reg_ier);
1633 dc->open_ttys++;
1634 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1635 printk("noz: activated %d: %p\n", tty->index, tport);
1636 return 0;
1637}
1646 1638
1647 /* Users cannot interrupt a close */ 1639static int ntty_open(struct tty_struct *tty, struct file *filp)
1648 mutex_lock(&nport->tty_sem); 1640{
1641 struct port *port = get_port_by_tty(tty);
1642 return tty_port_open(&port->port, tty, filp);
1643}
1649 1644
1650 WARN_ON(!port->count); 1645static void ntty_shutdown(struct tty_port *tport)
1646{
1647 struct port *port = container_of(tport, struct port, port);
1648 struct nozomi *dc = port->dc;
1649 unsigned long flags;
1651 1650
1651 DBG1("close: %d", port->token_dl);
1652 spin_lock_irqsave(&dc->spin_mutex, flags);
1653 dc->last_ier &= ~(port->token_dl);
1654 writew(dc->last_ier, dc->reg_ier);
1652 dc->open_ttys--; 1655 dc->open_ttys--;
1653 port->count--; 1656 spin_unlock_irqrestore(&dc->spin_mutex, flags);
1657 printk("noz: shutdown %p\n", tport);
1658}
1654 1659
1655 if (port->count == 0) { 1660static void ntty_close(struct tty_struct *tty, struct file *filp)
1656 DBG1("close: %d", nport->token_dl); 1661{
1657 tty_port_tty_set(port, NULL); 1662 struct port *port = tty->driver_data;
1658 spin_lock_irqsave(&dc->spin_mutex, flags); 1663 if (port)
1659 dc->last_ier &= ~(nport->token_dl); 1664 tty_port_close(&port->port, tty, filp);
1660 writew(dc->last_ier, dc->reg_ier); 1665}
1661 spin_unlock_irqrestore(&dc->spin_mutex, flags); 1666
1662 } 1667static void ntty_hangup(struct tty_struct *tty)
1663 mutex_unlock(&nport->tty_sem); 1668{
1669 struct port *port = tty->driver_data;
1670 tty_port_hangup(&port->port);
1664} 1671}
1665 1672
1666/* 1673/*
@@ -1680,15 +1687,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
1680 if (!dc || !port) 1687 if (!dc || !port)
1681 return -ENODEV; 1688 return -ENODEV;
1682 1689
1683 if (unlikely(!mutex_trylock(&port->tty_sem))) { 1690 mutex_lock(&port->tty_sem);
1684 /*
1685 * must test lock as tty layer wraps calls
1686 * to this function with BKL
1687 */
1688 dev_err(&dc->pdev->dev, "Would have deadlocked - "
1689 "return EAGAIN\n");
1690 return -EAGAIN;
1691 }
1692 1691
1693 if (unlikely(!port->port.count)) { 1692 if (unlikely(!port->port.count)) {
1694 DBG1(" "); 1693 DBG1(" ");
@@ -1728,25 +1727,23 @@ exit:
1728 * This method is called by the upper tty layer. 1727 * This method is called by the upper tty layer.
1729 * #according to sources N_TTY.c it expects a value >= 0 and 1728 * #according to sources N_TTY.c it expects a value >= 0 and
1730 * does not check for negative values. 1729 * does not check for negative values.
1730 *
1731 * If the port is unplugged report lots of room and let the bits
1732 * dribble away so we don't block anything.
1731 */ 1733 */
1732static int ntty_write_room(struct tty_struct *tty) 1734static int ntty_write_room(struct tty_struct *tty)
1733{ 1735{
1734 struct port *port = tty->driver_data; 1736 struct port *port = tty->driver_data;
1735 int room = 0; 1737 int room = 4096;
1736 const struct nozomi *dc = get_dc_by_tty(tty); 1738 const struct nozomi *dc = get_dc_by_tty(tty);
1737 1739
1738 if (!dc || !port) 1740 if (dc) {
1739 return 0; 1741 mutex_lock(&port->tty_sem);
1740 if (!mutex_trylock(&port->tty_sem)) 1742 if (port->port.count)
1741 return 0; 1743 room = port->fifo_ul.size -
1742 1744 kfifo_len(&port->fifo_ul);
1743 if (!port->port.count) 1745 mutex_unlock(&port->tty_sem);
1744 goto exit; 1746 }
1745
1746 room = port->fifo_ul.size - kfifo_len(&port->fifo_ul);
1747
1748exit:
1749 mutex_unlock(&port->tty_sem);
1750 return room; 1747 return room;
1751} 1748}
1752 1749
@@ -1906,10 +1903,16 @@ exit_in_buffer:
1906 return rval; 1903 return rval;
1907} 1904}
1908 1905
1906static const struct tty_port_operations noz_tty_port_ops = {
1907 .activate = ntty_activate,
1908 .shutdown = ntty_shutdown,
1909};
1910
1909static const struct tty_operations tty_ops = { 1911static const struct tty_operations tty_ops = {
1910 .ioctl = ntty_ioctl, 1912 .ioctl = ntty_ioctl,
1911 .open = ntty_open, 1913 .open = ntty_open,
1912 .close = ntty_close, 1914 .close = ntty_close,
1915 .hangup = ntty_hangup,
1913 .write = ntty_write, 1916 .write = ntty_write,
1914 .write_room = ntty_write_room, 1917 .write_room = ntty_write_room,
1915 .unthrottle = ntty_unthrottle, 1918 .unthrottle = ntty_unthrottle,
@@ -1917,6 +1920,8 @@ static const struct tty_operations tty_ops = {
1917 .chars_in_buffer = ntty_chars_in_buffer, 1920 .chars_in_buffer = ntty_chars_in_buffer,
1918 .tiocmget = ntty_tiocmget, 1921 .tiocmget = ntty_tiocmget,
1919 .tiocmset = ntty_tiocmset, 1922 .tiocmset = ntty_tiocmset,
1923 .install = ntty_install,
1924 .cleanup = ntty_cleanup,
1920}; 1925};
1921 1926
1922/* Module initialization */ 1927/* Module initialization */