nozomi, tty cleanup

- init and deinit tty driver at module load/unload. When the OS (user)
  loads the driver the hardware usually is ready to driver.
- merge (unify) MAX_PORT, NTTY_TTY_MINORS into NOZOMI_MAX_PORTS
- remove struct nozomi_devices, it was used only as list entries

Signed-off-by: Jiri Slaby <[EMAIL PROTECTED]>

---
commit d0b01ce89a7b18ba37ea6192eea6a98cdc01d62e
tree a61f0a99633772b863130ec1e8a2be25891b3578
parent 9f9d7197e901ea00771812b7e903b14b95f54e40
author Jiri Slaby <[EMAIL PROTECTED]> Sat, 10 Nov 2007 00:12:53 +0100
committer Jiri Slaby <[EMAIL PROTECTED]> Sat, 10 Nov 2007 00:12:53 +0100

 drivers/char/nozomi.c |  336 ++++++++++++++++---------------------------------
 1 files changed, 112 insertions(+), 224 deletions(-)

diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 49e16c7..4a3ab38 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -172,9 +172,6 @@ static int debug;
 #define NOZOMI_NAME_TTY                "nozomi_tty"
 #define DRIVER_DESC            "Nozomi driver"
 
-#define NTTY_TTY_MAJOR         241
-#define NTTY_TTY_MINORS                MAX_PORT
-#define NTTY_TTY_MAXMINORS     256
 #define NTTY_FIFO_BUFFER_SIZE  8192
 
 /* Must be power of 2 */
@@ -225,8 +222,9 @@ static int debug;
 #define CTRL_DTR       0x0001
 #define CTRL_RTS       0x0002
 
-#define MAX_PORT               4
-#define NOZOMI_MAX_PORTS       5
+#define NOZOMI_MAX_PORTS       4
+#define NOZOMI_MAX_CARDS       (256 / NOZOMI_MAX_PORTS)
+#define NOZOMI_MAX_MINORS      (NOZOMI_MAX_PORTS * NOZOMI_MAX_CARDS)
 
 /*    Type definitions */
 
@@ -430,10 +428,9 @@ struct nozomi {
        struct port port[NOZOMI_MAX_PORTS];
        u8 *send_buf;
 
-       struct tty_driver *tty_driver;
-
        spinlock_t spin_mutex;  /* secures access to registers and tty */
 
+       unsigned int index_start;
        u32 open_ttys;
 };
 
@@ -443,9 +440,6 @@ struct buffer {
        u8 *data;
 } __attribute__ ((packed));
 
-/*    Function declarations */
-static int ntty_tty_init(struct nozomi *dc);
-
 /*    Global variables */
 static struct pci_device_id nozomi_pci_tbl[] = {
        {PCI_DEVICE(VENDOR1, DEVICE1)},
@@ -454,80 +448,22 @@ static struct pci_device_id nozomi_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
 
-/* Representing the pci device of interest */
-struct nozomi_devices {
-       struct list_head list;
-       struct nozomi *my_dev;
-       int index_start;
-};
-static atomic_t cards_found = ATOMIC_INIT(0);
-static LIST_HEAD(my_devices);
+static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
+static struct tty_driver *ntty_driver;
 
 /*
  * find card by tty_index
  */
-static struct nozomi *get_dc_by_index(s32 index)
-{
-       struct list_head *p;
-       struct nozomi_devices *curdev;
-       int devidx;
-
-       if (likely(atomic_read(&cards_found) == 1)) {
-               curdev = list_first_entry(&my_devices,
-                                       struct nozomi_devices, list);
-               return curdev->my_dev;
-       } else {
-               devidx = index - (index % NTTY_TTY_MINORS);
 
-               list_for_each(p, &my_devices) {
-                       curdev = list_entry(p, struct nozomi_devices, list);
-                       if (curdev->index_start == devidx)
-                               return curdev->my_dev;
-               }
-       }
-
-       printk(KERN_ALERT "Fatal error: could not find device" \
-               " for tty-index %d\n", index);
-
-       return NULL;
-}
-
-static struct port *get_port_by_tty(const struct tty_struct *tty)
+static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
 {
-       struct nozomi *ndev = get_dc_by_index(tty->index);
-       return ndev ? &ndev->port[tty->index % NTTY_TTY_MINORS] : NULL;
+       return ndevs[tty->index / NOZOMI_MAX_PORTS];
 }
 
-static struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
+static inline struct port *get_port_by_tty(const struct tty_struct *tty)
 {
-       return get_dc_by_index(tty->index);
-}
-
-static int get_free_index(void)
-{
-       struct list_head *p;
-       struct nozomi_devices *curdev;
-       u8 busy;
-       int new_index;
-
-       for (new_index = 0; new_index < NTTY_TTY_MAXMINORS; new_index += 4) {
-               busy = 0;
-               list_for_each(p, &my_devices) {
-                       curdev = list_entry(p, struct nozomi_devices, list);
-                       if (curdev->index_start == new_index) {
-                               ++busy;
-                               break;
-                       }
-               }
-
-               if (!busy)
-                       break;
-       }
-
-       if (new_index >= NTTY_TTY_MAXMINORS)
-               return -ENODEV;
-
-       return new_index;
+       struct nozomi *ndev = get_dc_by_tty(tty);
+       return ndev ? &ndev->port[tty->index % NOZOMI_MAX_PORTS] : NULL;
 }
 
 /*
@@ -822,7 +758,7 @@ static int nozomi_read_config_table(struct nozomi *dc)
 
                dump_table(dc);
 
-               for (i = PORT_MDM; i < MAX_PORT; i++) {
+               for (i = PORT_MDM; i < NOZOMI_MAX_PORTS; i++) {
                        dc->port[i].fifo_ul =
                            kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL);
                        memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
@@ -1234,7 +1170,7 @@ static int send_flow_control(struct nozomi *dc)
        u32 i, more_flow_control_to_be_updated = 0;
        u16 *ctrl;
 
-       for (i = PORT_MDM; i < MAX_PORT; i++) {
+       for (i = PORT_MDM; i < NOZOMI_MAX_PORTS; i++) {
                if (dc->port[i].update_flow_control) {
                        if (more_flow_control_to_be_updated) {
                                /* We have more flow control to be updated */
@@ -1353,15 +1289,9 @@ static int handle_data_ul(struct nozomi *dc, enum 
port_type port, u16 read_iir)
 
 static irqreturn_t interrupt_handler(int irq, void *dev_id)
 {
-       struct nozomi_devices *ndev = dev_id;
-       struct nozomi *dc;
+       struct nozomi *dc = dev_id;
        u16 read_iir;
 
-       if (!ndev)
-               return IRQ_NONE;
-
-       dc = ndev->my_dev;
-
        spin_lock(&dc->spin_mutex);
        read_iir = readw(dc->reg_iir);
 
@@ -1503,27 +1433,25 @@ static void nozomi_setup_private_data(struct nozomi *dc)
        dc->port[PORT_APP1].token_dl = APP1_DL;
        dc->port[PORT_APP2].token_dl = APP2_DL;
 
-       for (i = 0; i < MAX_PORT; i++)
+       for (i = 0; i < NOZOMI_MAX_PORTS; i++)
                init_waitqueue_head(&dc->port[i].tty_wait);
 }
 
 static ssize_t card_type_show(struct device *dev, struct device_attribute 
*attr,
                          char *buf)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct nozomi_devices *deventry = pci_get_drvdata(pdev);
+       struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
 
-       return sprintf(buf, "%d\n", deventry->my_dev->card_type);
+       return sprintf(buf, "%d\n", dc->card_type);
 }
 static DEVICE_ATTR(card_type, 0444, card_type_show, NULL);
 
 static ssize_t open_ttys_show(struct device *dev, struct device_attribute 
*attr,
                          char *buf)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct nozomi_devices *deventry = pci_get_drvdata(pdev);
+       struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
 
-       return sprintf(buf, "%u\n", deventry->my_dev->open_ttys);
+       return sprintf(buf, "%u\n", dc->open_ttys);
 }
 static DEVICE_ATTR(open_ttys, 0444, open_ttys_show, NULL);
 
@@ -1548,35 +1476,36 @@ static int __devinit nozomi_card_init(struct pci_dev 
*pdev,
                                      const struct pci_device_id *ent)
 {
        resource_size_t start;
-       int ret = -ENOMEM;
        struct nozomi *dc = NULL;
-       struct nozomi_devices *newdev = NULL;
-       struct nozomi_devices *first = NULL;
-       int new_index;
-       int i;
+       unsigned int i, ndev_idx;
+       int ret;
 
-       atomic_inc(&cards_found);
-       dev_dbg(&pdev->dev, "Init, cards_found: %d\n",
-               atomic_read(&cards_found));
+       dev_dbg(&pdev->dev, "Init\n");
+
+       for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
+               if (!ndevs[ndev_idx])
+                       break;
+
+       if (ndev_idx >= ARRAY_SIZE(ndevs)) {
+               dev_err(&pdev->dev, "no free tty range for this card\n");
+               ret = -EIO;
+               goto err;
+       }
 
        dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
        if (unlikely(!dc)) {
                dev_err(&pdev->dev, "Could not allocate memory\n");
-               goto err_free;
-       }
-       newdev = kzalloc(sizeof(struct nozomi_devices), GFP_KERNEL);
-       if (unlikely(!newdev)) {
-               dev_err(&pdev->dev, "Could not allocate memory\n");
+               ret = -ENOMEM;
                goto err_free;
        }
 
        dc->pdev = pdev;
-       newdev->my_dev = dc;
 
        /* Find out what card type it is */
        nozomi_get_card_type(dc);
 
-       if (pci_enable_device(dc->pdev)) {
+       ret = pci_enable_device(dc->pdev);
+       if (ret) {
                dev_err(&pdev->dev, "Failed to enable PCI Device\n");
                goto err_free;
        }
@@ -1618,7 +1547,7 @@ static int __devinit nozomi_card_init(struct pci_dev 
*pdev,
        writew(dc->last_ier, dc->reg_ier);
 
        ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
-                       NOZOMI_NAME, newdev);
+                       NOZOMI_NAME, dc);
        if (unlikely(ret)) {
                dev_err(&pdev->dev, "can't request irq\n");
                goto err_free_sbuf;
@@ -1626,53 +1555,26 @@ static int __devinit nozomi_card_init(struct pci_dev 
*pdev,
 
        DBG1("base_addr: %p", dc->base_addr);
 
-       new_index = get_free_index();
-       if (new_index < 0) {
-               dev_err(&pdev->dev, "already reached maximum card count.\n");
-               ret = -EIO;
-               goto err_free_irq;
-       }
-
        make_sysfs_files(dc);
 
-       if (atomic_read(&cards_found) == 1) {
-               ret = ntty_tty_init(dc);
-               if (ret) {
-                       dev_err(&pdev->dev, "can't alloc ntty\n");
-                       goto err_sysfs;
-               }
-       } else {
-               first = list_first_entry(&my_devices, struct nozomi_devices,
-                                                                       list);
-               dc->tty_driver = first->my_dev->tty_driver;
-       }
-
-       for (i = 0; i < NTTY_TTY_MINORS; i++) {
+       dc->index_start = ndev_idx * NOZOMI_MAX_PORTS;
+       ndevs[ndev_idx] = dc;
+       for (i = 0; i < NOZOMI_MAX_PORTS; i++) {
                init_MUTEX(&dc->port[i].tty_sem);
                dc->port[i].tty_open_count = 0;
                dc->port[i].tty = NULL;
-               tty_register_device(dc->tty_driver, new_index + i,
-                                                       &dc->pdev->dev);
+               tty_register_device(ntty_driver, dc->index_start + i,
+                                                       &pdev->dev);
        }
-       newdev->index_start = new_index;
 
        /* Enable  RESET interrupt. */
        dc->last_ier = RESET;
        writew(dc->last_ier, dc->reg_ier);
 
-       list_add_tail(&newdev->list, &my_devices);
-
-       pci_set_drvdata(pdev, newdev);
+       pci_set_drvdata(pdev, dc);
 
        return 0;
 
-err_sysfs:
-       remove_sysfs_files(dc);
-err_free_irq:
-       free_irq(pdev->irq, newdev);
-       for (i = PORT_MDM; i < MAX_PORT; i++)   /* allocated in isr, might be */
-               if (dc->port[i].fifo_ul)        /* filled yet */
-                       kfifo_free(dc->port[i].fifo_ul);
 err_free_sbuf:
        kfree(dc->send_buf);
        iounmap(dc->base_addr);
@@ -1682,40 +1584,25 @@ err_disable_device:
        pci_disable_device(pdev);
 err_free:
        kfree(dc);
-       kfree(newdev);
-       atomic_dec(&cards_found);
+err:
        return ret;
 }
 
-static void __devexit tty_exit(struct nozomi_devices *ndev)
+static void __devexit tty_exit(struct nozomi *dc)
 {
-       struct nozomi *dc = ndev->my_dev;
-       int i, ret;
+       unsigned int i;
 
        DBG1(" ");
 
-       flush_scheduled_work();
-
-       for (i = 0; i < NTTY_TTY_MINORS; ++i)
-               if (dc->port[i].tty && \
-                               list_empty(&dc->port[i].tty->hangup_work.entry))
+       for (i = 0; i < NOZOMI_MAX_PORTS; i++)
+               if (dc->port[i].tty)
                        tty_hangup(dc->port[i].tty);
 
        while (dc->open_ttys)
                msleep(1);
 
-       for (i = ndev->index_start; i < ndev->index_start + NTTY_TTY_MINORS; \
-                                                                       ++i)
-               tty_unregister_device(dc->tty_driver, i);
-
-       /* only unregister ttydriver if its the last card available */
-       if (atomic_read(&cards_found) == 1) {
-               ret = tty_unregister_driver(dc->tty_driver);
-               if (ret)
-                       printk(KERN_ERR "Unable to unregister the tty driver !"
-                                                       " (%d)\n", ret);
-               put_tty_driver(dc->tty_driver);
-       }
+       for (i = dc->index_start; i < dc->index_start + NOZOMI_MAX_PORTS; ++i)
+               tty_unregister_device(ntty_driver, i);
 }
 
 /* Deallocate memory for one device */
@@ -1723,14 +1610,13 @@ static void __devexit nozomi_card_exit(struct pci_dev 
*pdev)
 {
        int i;
        struct ctrl_ul ctrl;
-       struct nozomi_devices *deventry = pci_get_drvdata(pdev);
-       struct nozomi *dc = deventry->my_dev;
+       struct nozomi *dc = pci_get_drvdata(pdev);
 
        /* Disable all interrupts */
        dc->last_ier = 0;
        writew(dc->last_ier, dc->reg_ier);
 
-       tty_exit(deventry);
+       tty_exit(dc);
 
        /* Send 0x0001, command card to resend the reset token.  */
        /* This is to get the reset when the module is reloaded. */
@@ -1744,13 +1630,11 @@ static void __devexit nozomi_card_exit(struct pci_dev 
*pdev)
        write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
        writew(CTRL_UL, dc->reg_fcr);   /* push the token to the card. */
 
-       list_del(&deventry->list);
-
        remove_sysfs_files(dc);
 
-       free_irq(pdev->irq, deventry);
+       free_irq(pdev->irq, dc);
 
-       for (i = PORT_MDM; i < MAX_PORT; i++)
+       for (i = 0; i < NOZOMI_MAX_PORTS; i++)
                if (dc->port[i].fifo_ul)
                        kfifo_free(dc->port[i].fifo_ul);
 
@@ -1762,32 +1646,29 @@ static void __devexit nozomi_card_exit(struct pci_dev 
*pdev)
 
        pci_disable_device(pdev);
 
-       kfree(dc);
-       kfree(deventry);
+       ndevs[dc->index_start / NOZOMI_MAX_PORTS] = NULL;
 
-       atomic_dec(&cards_found);
+       kfree(dc);
 }
 
-static void set_rts(int index, int rts)
+static void set_rts(struct tty_struct *tty, int rts)
 {
-       struct nozomi *dc = get_dc_by_index(index);
-       struct port *port = &dc->port[index % MAX_PORT];
+       struct port *port = get_port_by_tty(tty);
 
        port->ctrl_ul.RTS = rts;
        port->update_flow_control = 1;
-       enable_transmit_ul(PORT_CTRL, dc);
+       enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
 }
 
-static void set_dtr(int index, int dtr)
+static void set_dtr(struct tty_struct *tty, int dtr)
 {
-       struct nozomi *dc = get_dc_by_index(index);
-       struct port *port = &dc->port[index % MAX_PORT];
+       struct port *port = get_port_by_tty(tty);
 
-       DBG1("SETTING DTR index: %d, dtr: %d", index, dtr);
+       DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
 
        port->ctrl_ul.DTR = dtr;
        port->update_flow_control = 1;
-       enable_transmit_ul(PORT_CTRL, dc);
+       enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
 }
 
 /*
@@ -1906,13 +1787,13 @@ static int ntty_write(struct tty_struct *tty, const 
unsigned char *buffer,
        if (port == &(dc->port[PORT_MDM])) {
                if (port->ctrl_dl.CTS) {
                        DBG4("Enable interrupt");
-                       enable_transmit_ul(tty->index % MAX_PORT, dc);
+                       enable_transmit_ul(tty->index % NOZOMI_MAX_PORTS, dc);
                } else {
                        dev_err(&dc->pdev->dev,
                                "CTS not active on modem port?\n");
                }
        } else {
-               enable_transmit_ul(tty->index % MAX_PORT, dc);
+               enable_transmit_ul(tty->index % NOZOMI_MAX_PORTS, dc);
        }
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 
@@ -1968,14 +1849,14 @@ static int ntty_tiocmset(struct tty_struct *tty, struct 
file *file,
        unsigned int set, unsigned int clear)
 {
        if (set & TIOCM_RTS)
-               set_rts(tty->index, 1);
+               set_rts(tty, 1);
        else if (clear & TIOCM_RTS)
-               set_rts(tty->index, 0);
+               set_rts(tty, 0);
 
        if (set & TIOCM_DTR)
-               set_dtr(tty->index, 1);
+               set_dtr(tty, 1);
        else if (clear & TIOCM_DTR)
-               set_dtr(tty->index, 0);
+               set_dtr(tty, 0);
 
        return 0;
 }
@@ -2054,8 +1935,8 @@ static void ntty_unthrottle(struct tty_struct *tty)
 
        DBG1("UNTHROTTLE");
        spin_lock_irqsave(&dc->spin_mutex, flags);
-       enable_transmit_dl(tty->index % MAX_PORT, dc);
-       set_rts(tty->index, 1);
+       enable_transmit_dl(tty->index % NOZOMI_MAX_PORTS, dc);
+       set_rts(tty, 1);
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 }
 
@@ -2070,7 +1951,7 @@ static void ntty_throttle(struct tty_struct *tty)
 
        DBG1("THROTTLE");
        spin_lock_irqsave(&dc->spin_mutex, flags);
-       set_rts(tty->index, 0);
+       set_rts(tty, 0);
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 }
 
@@ -2119,39 +2000,6 @@ static struct tty_operations tty_ops = {
        .tiocmset = ntty_tiocmset,
 };
 
-/* Initializes the tty */
-static int ntty_tty_init(struct nozomi *dc)
-{
-       struct tty_driver *td;
-       int rval;
-
-       dc->tty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
-       if (!dc->tty_driver)
-               return -ENOMEM;
-       td = dc->tty_driver;
-       td->owner = THIS_MODULE;
-       td->driver_name = NOZOMI_NAME_TTY;
-       td->name = "noz";
-       td->major = NTTY_TTY_MAJOR;
-       td->type = TTY_DRIVER_TYPE_SERIAL;
-       td->subtype = SERIAL_TYPE_NORMAL;
-       td->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-       td->init_termios = tty_std_termios;
-       td->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
-       td->init_termios.c_ispeed = 115200;
-       td->init_termios.c_ospeed = 115200;
-       tty_set_operations(dc->tty_driver, &tty_ops);
-
-       rval = tty_register_driver(td);
-       if (rval) {
-               dev_err(&dc->pdev->dev, "failed to register ntty tty driver\n");
-               return rval;
-       }
-
-       dev_info(&dc->pdev->dev, DRIVER_DESC " " NOZOMI_NAME_TTY "\n");
-       return rval;
-}
-
 /* Module initialization */
 static struct pci_driver nozomi_driver = {
        .name = NOZOMI_NAME,
@@ -2162,14 +2010,54 @@ static struct pci_driver nozomi_driver = {
 
 static __init int nozomi_init(void)
 {
+       int ret;
+
        printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
-       return pci_register_driver(&nozomi_driver);
+
+       ntty_driver = alloc_tty_driver(NOZOMI_MAX_MINORS);
+       if (!ntty_driver)
+               return -ENOMEM;
+
+       ntty_driver->owner = THIS_MODULE;
+       ntty_driver->driver_name = NOZOMI_NAME_TTY;
+       ntty_driver->name = "noz";
+       ntty_driver->major = 0;
+       ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+       ntty_driver->subtype = SERIAL_TYPE_NORMAL;
+       ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+       ntty_driver->init_termios = tty_std_termios;
+       ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL |
+               CLOCAL;
+       ntty_driver->init_termios.c_ispeed = 115200;
+       ntty_driver->init_termios.c_ospeed = 115200;
+       tty_set_operations(ntty_driver, &tty_ops);
+
+       ret = tty_register_driver(ntty_driver);
+       if (ret) {
+               printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
+               goto free_tty;
+       }
+
+       ret = pci_register_driver(&nozomi_driver);
+       if (ret) {
+               printk(KERN_ERR "Nozomi: can't register pci driver\n");
+               goto unr_tty;
+       }
+
+       return 0;
+unr_tty:
+       tty_unregister_driver(ntty_driver);
+free_tty:
+       put_tty_driver(ntty_driver);
+       return ret;
 }
 
 static __exit void nozomi_exit(void)
 {
        printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
        pci_unregister_driver(&nozomi_driver);
+       tty_unregister_driver(ntty_driver);
+       put_tty_driver(ntty_driver);
 }
 
 module_init(nozomi_init);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to