]> git.hungrycats.org Git - linux/commitdiff
[PATCH] tty_driver refcounting
authorAlexander Viro <viro@www.linux.org.uk>
Wed, 11 Jun 2003 14:48:06 +0000 (07:48 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 11 Jun 2003 14:48:06 +0000 (07:48 -0700)
drivers/char/epca.c converted to dynamic allocation

drivers/char/epca.c

index b6a8ef7f4ed5621f4ee7069f904570b12d38d1cb..d26e9ed868a12dfc0bce6fa6cd09dcdc9ef1501e 100644 (file)
@@ -97,8 +97,8 @@ static struct board_info boards[MAXBOARDS];
 
 /* ------------- Begin structures used for driver registeration ---------- */
 
-struct tty_driver pc_driver;
-struct tty_driver pc_info;
+static struct tty_driver *pc_driver;
+static struct tty_driver *pc_info;
 
 /* ------------------ Begin Digi specific structures -------------------- */
 
@@ -204,6 +204,8 @@ static void epcaparam(struct tty_struct *, struct channel *);
 static void receive_data(struct channel *);
 static int pc_ioctl(struct tty_struct *, struct file *,
                     unsigned int, unsigned long);
+static int info_ioctl(struct tty_struct *, struct file *,
+                    unsigned int, unsigned long);
 static void pc_set_termios(struct tty_struct *, struct termios *);
 static void do_softint(void *);
 static void pc_stop(struct tty_struct *);
@@ -491,12 +493,6 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
        struct channel *ch;
        unsigned long flags;
 
-       if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-       {
-               return;
-       }
-
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
@@ -704,13 +700,6 @@ static int pc_write(struct tty_struct * tty, int from_user,
                brought into the driver.  
        ------------------------------------------------------------------- */
 
-       /* Stop users from hurting themselves on control minor */
-
-       if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-       {
-               return (0) ;
-       }
-
        /* ---------------------------------------------------------
                verifyChannel returns the channel from the tty struct
                if it is valid.  This serves as a sanity check.
@@ -1306,13 +1295,6 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
        volatile struct board_chan *bc;
        volatile unsigned int head;
 
-       /* Nothing "real" happens in open of control device */
-
-       if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-       {
-               return (0) ;
-       }
-
        line = tty->index;
        if (line < 0 || line >= nbdevs) 
        {
@@ -1485,13 +1467,15 @@ static void __exit epca_module_exit(void)
        save_flags(flags);
        cli();
 
-       if ((tty_unregister_driver(&pc_driver)) ||  
-           (tty_unregister_driver(&pc_info)))
+       if ((tty_unregister_driver(pc_driver)) ||  
+           (tty_unregister_driver(pc_info)))
        {
                printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
                restore_flags(flags);
                return;
        }
+       put_tty_driver(pc_driver);
+       put_tty_driver(pc_info);
 
        for (crd = 0; crd < num_cards; crd++) 
        { /* Begin for each card */
@@ -1529,6 +1513,34 @@ static void __exit epca_module_exit(void)
 module_exit(epca_module_exit);
 #endif /* MODULE */
 
+static struct tty_operations pc_ops = {
+       .open = pc_open,
+       .close = pc_close,
+       .write = pc_write,
+       .write_room = pc_write_room,
+       .flush_buffer = pc_flush_buffer,
+       .chars_in_buffer = pc_chars_in_buffer,
+       .flush_chars = pc_flush_chars,
+       .put_char = pc_put_char,
+       .ioctl = pc_ioctl,
+       .set_termios = pc_set_termios,
+       .stop = pc_stop,
+       .start = pc_start,
+       .throttle = pc_throttle,
+       .unthrottle = pc_unthrottle,
+       .hangup = pc_hangup,
+};
+
+static int info_open(struct tty_struct *tty, struct file * filp)
+{
+       return 0;
+}
+
+static struct tty_operations info_ops = {
+       .open = info_open,
+       .ioctl = info_ioctl,
+};
+
 /* ------------------ Begin pc_init  ---------------------- */
 
 int __init pc_init(void)
@@ -1553,7 +1565,6 @@ int __init pc_init(void)
        int crd;
        struct board_info *bd;
        unsigned char board_id = 0;
-       
 
 #ifdef ENABLE_PCI
        int pci_boards_found, pci_count;
@@ -1561,6 +1572,16 @@ int __init pc_init(void)
        pci_count = 0;
 #endif /* ENABLE_PCI */
 
+       pc_driver = alloc_tty_driver(MAX_ALLOC);
+       if (!pc_driver)
+               return -ENOMEM;
+
+       pc_info = alloc_tty_driver(MAX_ALLOC);
+       if (!pc_info) {
+               put_tty_driver(pc_driver);
+               return -ENOMEM;
+       }
+
        /* -----------------------------------------------------------------------
                If epca_setup has not been ran by LILO set num_cards to defaults; copy
                board structure defined by digiConfig into drivers board structure.
@@ -1620,53 +1641,33 @@ int __init pc_init(void)
 
 #endif /* ENABLE_PCI */
 
-       memset(&pc_driver, 0, sizeof(struct tty_driver));
-       memset(&pc_info, 0, sizeof(struct tty_driver));
-
-       pc_driver.magic = TTY_DRIVER_MAGIC;
-       pc_driver.owner = THIS_MODULE;
-       pc_driver.name = "ttyD"; 
-       pc_driver.major = DIGI_MAJOR; 
-       pc_driver.minor_start = 0;
-       pc_driver.num = MAX_ALLOC;
-       pc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-       pc_driver.subtype = SERIAL_TYPE_NORMAL;
-       pc_driver.init_termios = tty_std_termios;
-       pc_driver.init_termios.c_iflag = 0;
-       pc_driver.init_termios.c_oflag = 0;
-
-       pc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-       pc_driver.init_termios.c_lflag = 0;
-       pc_driver.flags = TTY_DRIVER_REAL_RAW;
-
-       /* ------------------------------------------------------------------
-               Setup entry points for the driver.  These are primarily called by 
-               the kernel in tty_io.c and n_tty.c
-       --------------------------------------------------------------------- */
-
-       pc_driver.open = pc_open;
-       pc_driver.close = pc_close;
-       pc_driver.write = pc_write;
-       pc_driver.write_room = pc_write_room;
-       pc_driver.flush_buffer = pc_flush_buffer;
-       pc_driver.chars_in_buffer = pc_chars_in_buffer;
-       pc_driver.flush_chars = pc_flush_chars;
-       pc_driver.put_char = pc_put_char;
-       pc_driver.ioctl = pc_ioctl;
-       pc_driver.set_termios = pc_set_termios;
-       pc_driver.stop = pc_stop;
-       pc_driver.start = pc_start;
-       pc_driver.throttle = pc_throttle;
-       pc_driver.unthrottle = pc_unthrottle;
-       pc_driver.hangup = pc_hangup;
-
-       pc_info = pc_driver;
-       pc_info.name = "digi_ctl";
-       pc_info.major = DIGIINFOMAJOR;
-       pc_info.minor_start = 0;
-       pc_info.num = 1;
-       pc_info.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-       pc_info.subtype = SERIAL_TYPE_INFO;
+       pc_driver->owner = THIS_MODULE;
+       pc_driver->name = "ttyD"; 
+       pc_driver->major = DIGI_MAJOR; 
+       pc_driver->minor_start = 0;
+       pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
+       pc_driver->subtype = SERIAL_TYPE_NORMAL;
+       pc_driver->init_termios = tty_std_termios;
+       pc_driver->init_termios.c_iflag = 0;
+       pc_driver->init_termios.c_oflag = 0;
+       pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+       pc_driver->init_termios.c_lflag = 0;
+       pc_driver->flags = TTY_DRIVER_REAL_RAW;
+       tty_set_operations(pc_driver, &pc_ops);
+
+       pc_info->owner = THIS_MODULE;
+       pc_info->name = "digi_ctl";
+       pc_info->major = DIGIINFOMAJOR;
+       pc_info->minor_start = 0;
+       pc_info->type = TTY_DRIVER_TYPE_SERIAL;
+       pc_info->subtype = SERIAL_TYPE_INFO;
+       pc_info->init_termios = tty_std_termios;
+       pc_info->init_termios.c_iflag = 0;
+       pc_info->init_termios.c_oflag = 0;
+       pc_info->init_termios.c_lflag = 0;
+       pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+       pc_info->flags = TTY_DRIVER_REAL_RAW;
+       tty_set_operations(pc_info, &info_ops);
 
 
        save_flags(flags);
@@ -1791,10 +1792,10 @@ int __init pc_init(void)
 
        } /* End for each card */
 
-       if (tty_register_driver(&pc_driver))
+       if (tty_register_driver(pc_driver))
                panic("Couldn't register Digi PC/ driver");
 
-       if (tty_register_driver(&pc_info))
+       if (tty_register_driver(pc_info))
                panic("Couldn't register Digi PC/ info ");
 
        /* -------------------------------------------------------------------
@@ -2845,103 +2846,102 @@ static void receive_data(struct channel *ch)
 
 } /* End receive_data */
 
-/* --------------------- Begin pc_ioctl  ----------------------- */
-
-static int pc_ioctl(struct tty_struct *tty, struct file * file,
+static int info_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg)
-{ /* Begin pc_ioctl */
-
-       digiflow_t dflow;
-       int retval, error;
-       unsigned long flags;
-       unsigned int mflag, mstat;
-       unsigned char startc, stopc;
-       volatile struct board_chan *bc;
-       struct channel *ch = (struct channel *) tty->driver_data;
+{
+       int error;
        
-       /* The control device has it's own set of commands */
-       if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-       { /* Begin if subtype is the control device */
-
-               switch (cmd) 
-               { /* Begin switch cmd */
+       switch (cmd) 
+       { /* Begin switch cmd */
 
-                       case DIGI_GETINFO:
-                       { /* Begin case DIGI_GETINFO */
+               case DIGI_GETINFO:
+               { /* Begin case DIGI_GETINFO */
 
-                               struct digi_info di ;
-                               int brd;
+                       struct digi_info di ;
+                       int brd;
 
-                               getUser(brd, (unsigned int *)arg);
+                       getUser(brd, (unsigned int *)arg);
 
-                               if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
-                               {
-                                       printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
-                                       return(error);
-                               }
+                       if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
+                       {
+                               printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
+                               return(error);
+                       }
 
-                               if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
-                                       return (-ENODEV);
+                       if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
+                               return (-ENODEV);
 
-                               memset(&di, 0, sizeof(di));
+                       memset(&di, 0, sizeof(di));
 
-                               di.board = brd ; 
-                               di.status = boards[brd].status;
-                               di.type = boards[brd].type ;
-                               di.numports = boards[brd].numports ;
-                               di.port = boards[brd].port ;
-                               di.membase = boards[brd].membase ;
+                       di.board = brd ; 
+                       di.status = boards[brd].status;
+                       di.type = boards[brd].type ;
+                       di.numports = boards[brd].numports ;
+                       di.port = boards[brd].port ;
+                       di.membase = boards[brd].membase ;
 
-                               if (copy_to_user((char *)arg, &di, sizeof (di)))
-                                       return -EFAULT;
-                               break;
+                       if (copy_to_user((char *)arg, &di, sizeof (di)))
+                               return -EFAULT;
+                       break;
 
-                       } /* End case DIGI_GETINFO */
+               } /* End case DIGI_GETINFO */
 
-                       case DIGI_POLLER:
-                       { /* Begin case DIGI_POLLER */
+               case DIGI_POLLER:
+               { /* Begin case DIGI_POLLER */
 
-                               int brd = arg & 0xff000000 >> 16 ; 
-                               unsigned char state = arg & 0xff ; 
+                       int brd = arg & 0xff000000 >> 16 ; 
+                       unsigned char state = arg & 0xff ; 
 
-                               if ((brd < 0) || (brd >= num_cards))
-                               {
-                                       printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
-                                       return (-ENODEV);
-                               }
+                       if ((brd < 0) || (brd >= num_cards))
+                       {
+                               printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
+                               return (-ENODEV);
+                       }
 
-                               digi_poller_inhibited = state ;
-                               break ; 
+                       digi_poller_inhibited = state ;
+                       break ; 
 
-                       } /* End case DIGI_POLLER */
+               } /* End case DIGI_POLLER */
 
-                       case DIGI_INIT:
-                       { /* Begin case DIGI_INIT */
+               case DIGI_INIT:
+               { /* Begin case DIGI_INIT */
 
-                               /* ------------------------------------------------------------
-                                       This call is made by the apps to complete the initilization
-                                       of the board(s).  This routine is responsible for setting
-                                       the card to its initial state and setting the drivers control
-                                       fields to the sutianle settings for the card in question.
-                               ---------------------------------------------------------------- */
-                       
-                               int crd ; 
-                               for (crd = 0; crd < num_cards; crd++) 
-                                       post_fep_init (crd);
+                       /* ------------------------------------------------------------
+                               This call is made by the apps to complete the initilization
+                               of the board(s).  This routine is responsible for setting
+                               the card to its initial state and setting the drivers control
+                               fields to the sutianle settings for the card in question.
+                       ---------------------------------------------------------------- */
+               
+                       int crd ; 
+                       for (crd = 0; crd < num_cards; crd++) 
+                               post_fep_init (crd);
 
-                               break ; 
+                       break ; 
 
-                       } /* End case DIGI_INIT */
+               } /* End case DIGI_INIT */
 
 
-                       default:
-                               return -ENOIOCTLCMD;
+               default:
+                       return -ENOIOCTLCMD;
 
-               } /* End switch cmd */
-               return (0) ;
+       } /* End switch cmd */
+       return (0) ;
+}
+/* --------------------- Begin pc_ioctl  ----------------------- */
 
-       } /* End if subtype is the control device */
+static int pc_ioctl(struct tty_struct *tty, struct file * file,
+                   unsigned int cmd, unsigned long arg)
+{ /* Begin pc_ioctl */
 
+       digiflow_t dflow;
+       int retval, error;
+       unsigned long flags;
+       unsigned int mflag, mstat;
+       unsigned char startc, stopc;
+       volatile struct board_chan *bc;
+       struct channel *ch = (struct channel *) tty->driver_data;
+       
        if (ch)
                bc = ch->brdchan;
        else