include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[sfrench/cifs-2.6.git] / drivers / char / nozomi.c
index 2ad7d37afbd080306d849d8a4558daca888f2e9b..a6638003f530ff55688231f2acf09b3e12262b05 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/init.h>
 #include <linux/kfifo.h>
 #include <linux/uaccess.h>
+#include <linux/slab.h>
 #include <asm/byteorder.h>
 
 #include <linux/delay.h>
@@ -136,10 +137,6 @@ static int debug;
 #define RECEIVE_BUF_MAX                4
 
 
-/* Define all types of vendors and devices to support */
-#define VENDOR1                0x1931  /* Vendor Option */
-#define DEVICE1                0x000c  /* HSDPA card */
-
 #define R_IIR          0x0000  /* Interrupt Identity Register */
 #define R_FCR          0x0000  /* Flow Control Register */
 #define R_IER          0x0004  /* Interrupt Enable Register */
@@ -371,6 +368,8 @@ struct port {
        struct mutex tty_sem;
        wait_queue_head_t tty_wait;
        struct async_icount tty_icount;
+
+       struct nozomi *dc;
 };
 
 /* Private data one for each card in the system */
@@ -405,7 +404,7 @@ struct buffer {
 
 /*    Global variables */
 static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
-       {PCI_DEVICE(VENDOR1, DEVICE1)},
+       {PCI_DEVICE(0x1931, 0x000c)},   /* Nozomi HSDPA */
        {},
 };
 
@@ -414,6 +413,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
 static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
 static struct tty_driver *ntty_driver;
 
+static const struct tty_port_operations noz_tty_port_ops;
+
 /*
  * find card by tty_index
  */
@@ -853,8 +854,6 @@ static int receive_data(enum port_type index, struct nozomi *dc)
                goto put;
        }
 
-       tty_buffer_request_room(tty, size);
-
        while (size > 0) {
                read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
 
@@ -1473,9 +1472,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 
        for (i = 0; i < MAX_PORT; i++) {
                struct device *tty_dev;
-
-               mutex_init(&dc->port[i].tty_sem);
-               tty_port_init(&dc->port[i].port);
+               struct port *port = &dc->port[i];
+               port->dc = dc;
+               mutex_init(&port->tty_sem);
+               tty_port_init(&port->port);
+               port->port.ops = &noz_tty_port_ops;
                tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
                                                        &pdev->dev);
 
@@ -1600,67 +1601,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr)
  * ----------------------------------------------------------------------------
  */
 
-/* Called when the userspace process opens the tty, /dev/noz*.  */
-static int ntty_open(struct tty_struct *tty, struct file *file)
+static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
        struct port *port = get_port_by_tty(tty);
        struct nozomi *dc = get_dc_by_tty(tty);
-       unsigned long flags;
-
+       int ret;
        if (!port || !dc || dc->state != NOZOMI_STATE_READY)
                return -ENODEV;
-
-       if (mutex_lock_interruptible(&port->tty_sem))
-               return -ERESTARTSYS;
-
-       port->port.count++;
-       dc->open_ttys++;
-
-       /* Enable interrupt downlink for channel */
-       if (port->port.count == 1) {
-               tty->driver_data = port;
-               tty_port_tty_set(&port->port, tty);
-               DBG1("open: %d", port->token_dl);
-               spin_lock_irqsave(&dc->spin_mutex, flags);
-               dc->last_ier = dc->last_ier | port->token_dl;
-               writew(dc->last_ier, dc->reg_ier);
-               spin_unlock_irqrestore(&dc->spin_mutex, flags);
+       ret = tty_init_termios(tty);
+       if (ret == 0) {
+               tty_driver_kref_get(driver);
+               driver->ttys[tty->index] = tty;
        }
-       mutex_unlock(&port->tty_sem);
-       return 0;
+       return ret;
 }
 
-/* Called when the userspace process close the tty, /dev/noz*. Also
-   called immediately if ntty_open fails in which case tty->driver_data
-   will be NULL an we exit by the first return */
+static void ntty_cleanup(struct tty_struct *tty)
+{
+       tty->driver_data = NULL;
+}
 
-static void ntty_close(struct tty_struct *tty, struct file *file)
+static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
 {
-       struct nozomi *dc = get_dc_by_tty(tty);
-       struct port *nport = tty->driver_data;
-       struct tty_port *port = &nport->port;
+       struct port *port = container_of(tport, struct port, port);
+       struct nozomi *dc = port->dc;
        unsigned long flags;
 
-       if (!dc || !nport)
-               return;
+       DBG1("open: %d", port->token_dl);
+       spin_lock_irqsave(&dc->spin_mutex, flags);
+       dc->last_ier = dc->last_ier | port->token_dl;
+       writew(dc->last_ier, dc->reg_ier);
+       dc->open_ttys++;
+       spin_unlock_irqrestore(&dc->spin_mutex, flags);
+       printk("noz: activated %d: %p\n", tty->index, tport);
+       return 0;
+}
 
-       /* Users cannot interrupt a close */
-       mutex_lock(&nport->tty_sem);
+static int ntty_open(struct tty_struct *tty, struct file *filp)
+{
+       struct port *port = get_port_by_tty(tty);
+       return tty_port_open(&port->port, tty, filp);
+}
 
-       WARN_ON(!port->count);
+static void ntty_shutdown(struct tty_port *tport)
+{
+       struct port *port = container_of(tport, struct port, port);
+       struct nozomi *dc = port->dc;
+       unsigned long flags;
 
+       DBG1("close: %d", port->token_dl);
+       spin_lock_irqsave(&dc->spin_mutex, flags);
+       dc->last_ier &= ~(port->token_dl);
+       writew(dc->last_ier, dc->reg_ier);
        dc->open_ttys--;
-       port->count--;
+       spin_unlock_irqrestore(&dc->spin_mutex, flags);
+       printk("noz: shutdown %p\n", tport);
+}
 
-       if (port->count == 0) {
-               DBG1("close: %d", nport->token_dl);
-               tty_port_tty_set(port, NULL);
-               spin_lock_irqsave(&dc->spin_mutex, flags);
-               dc->last_ier &= ~(nport->token_dl);
-               writew(dc->last_ier, dc->reg_ier);
-               spin_unlock_irqrestore(&dc->spin_mutex, flags);
-       }
-       mutex_unlock(&nport->tty_sem);
+static void ntty_close(struct tty_struct *tty, struct file *filp)
+{
+       struct port *port = tty->driver_data;
+       if (port)
+               tty_port_close(&port->port, tty, filp);
+}
+
+static void ntty_hangup(struct tty_struct *tty)
+{
+       struct port *port = tty->driver_data;
+       tty_port_hangup(&port->port);
 }
 
 /*
@@ -1680,15 +1688,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
        if (!dc || !port)
                return -ENODEV;
 
-       if (unlikely(!mutex_trylock(&port->tty_sem))) {
-               /*
-                * must test lock as tty layer wraps calls
-                * to this function with BKL
-                */
-               dev_err(&dc->pdev->dev, "Would have deadlocked - "
-                       "return EAGAIN\n");
-               return -EAGAIN;
-       }
+       mutex_lock(&port->tty_sem);
 
        if (unlikely(!port->port.count)) {
                DBG1(" ");
@@ -1728,25 +1728,23 @@ exit:
  * This method is called by the upper tty layer.
  *   #according to sources N_TTY.c it expects a value >= 0 and
  *    does not check for negative values.
+ *
+ * If the port is unplugged report lots of room and let the bits
+ * dribble away so we don't block anything.
  */
 static int ntty_write_room(struct tty_struct *tty)
 {
        struct port *port = tty->driver_data;
-       int room = 0;
+       int room = 4096;
        const struct nozomi *dc = get_dc_by_tty(tty);
 
-       if (!dc || !port)
-               return 0;
-       if (!mutex_trylock(&port->tty_sem))
-               return 0;
-
-       if (!port->port.count)
-               goto exit;
-
-       room = port->fifo_ul.size - kfifo_len(&port->fifo_ul);
-
-exit:
-       mutex_unlock(&port->tty_sem);
+       if (dc) {
+               mutex_lock(&port->tty_sem);
+               if (port->port.count)
+                       room = port->fifo_ul.size -
+                                       kfifo_len(&port->fifo_ul);
+               mutex_unlock(&port->tty_sem);
+       }
        return room;
 }
 
@@ -1906,10 +1904,16 @@ exit_in_buffer:
        return rval;
 }
 
+static const struct tty_port_operations noz_tty_port_ops = {
+       .activate = ntty_activate,
+       .shutdown = ntty_shutdown,
+};
+
 static const struct tty_operations tty_ops = {
        .ioctl = ntty_ioctl,
        .open = ntty_open,
        .close = ntty_close,
+       .hangup = ntty_hangup,
        .write = ntty_write,
        .write_room = ntty_write_room,
        .unthrottle = ntty_unthrottle,
@@ -1917,6 +1921,8 @@ static const struct tty_operations tty_ops = {
        .chars_in_buffer = ntty_chars_in_buffer,
        .tiocmget = ntty_tiocmget,
        .tiocmset = ntty_tiocmset,
+       .install = ntty_install,
+       .cleanup = ntty_cleanup,
 };
 
 /* Module initialization */