diff options
Diffstat (limited to 'drivers/char/ppdev.c')
-rw-r--r-- | drivers/char/ppdev.c | 86 |
1 files changed, 10 insertions, 76 deletions
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 4e2be3c8b..07877c1a7 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -52,6 +52,7 @@ #include <linux/poll.h> #include <asm/uaccess.h> #include <linux/ppdev.h> +#include <linux/smp_lock.h> #define PP_VERSION "ppdev: user-space parallel port driver" #define CHRDEV "ppdev" @@ -83,64 +84,6 @@ struct pp_struct { /* ROUND_UP macro from fs/select.c */ #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) -struct pp_port_list_struct { - struct parport *port; - struct pp_port_list_struct *next; -}; -static struct pp_port_list_struct *pp_port_list; -static DECLARE_MUTEX(pp_port_list_lock); - -/* pp_attach and pp_detach are for keeping a list of currently - * available ports, held under a mutex. We do this rather than - * using parport_enumerate because it stops a load of races. - */ - -static void pp_attach (struct parport *port) -{ - struct pp_port_list_struct *add; - - add = kmalloc (sizeof (struct pp_port_list_struct), GFP_KERNEL); - if (!add) { - printk (KERN_WARNING CHRDEV ": memory squeeze\n"); - return; - } - - add->port = port; - down (&pp_port_list_lock); - add->next = pp_port_list; - pp_port_list = add; - up (&pp_port_list_lock); -} - -static void pp_detach (struct parport *port) -{ - struct pp_port_list_struct *del; - - down (&pp_port_list_lock); - del = pp_port_list; - if (del->port == port) - pp_port_list = del->next; - else { - struct pp_port_list_struct *prev; - do { - prev = del; - del = del->next; - } while (del && del->port != port); - if (del) - prev->next = del->next; - } - up (&pp_port_list_lock); - - if (del) - kfree (del); -} - -static struct parport_driver ppdev_driver = { - name: CHRDEV, - attach: pp_attach, - detach: pp_detach -}; - static inline void pp_enable_irq (struct pp_struct *pp) { struct parport *port = pp->pdev->port; @@ -274,7 +217,7 @@ static void pp_irq (int irq, void * private, struct pt_regs * unused) static int register_device (int minor, struct pp_struct *pp) { - struct pp_port_list_struct *ports; + struct parport *port; struct pardevice * pdev = NULL; char *name; int fl; @@ -285,23 +228,17 @@ static int register_device (int minor, struct pp_struct *pp) sprintf (name, CHRDEV "%x", minor); - down (&pp_port_list_lock); - ports = pp_port_list; - while (ports && ports->port->number != minor) - ports = ports->next; - if (ports->port) { - fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device (ports->port, name, NULL, - NULL, pp_irq, fl, pp); - } - up (&pp_port_list_lock); - - if (!ports->port) { + port = parport_find_number (minor); + if (!port) { printk (KERN_WARNING "%s: no associated port!\n", name); kfree (name); return -ENXIO; } + fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + pdev = parport_register_device (port, name, NULL, + NULL, pp_irq, fl, pp); + parport_put_port (port); if (!pdev) { printk (KERN_WARNING "%s: failed to register device!\n", name); @@ -595,6 +532,7 @@ static int pp_release (struct inode * inode, struct file * file) unsigned int minor = MINOR (inode->i_rdev); struct pp_struct *pp = file->private_data; + lock_kernel(); if (pp->pdev && pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT) { if (!(pp->flags & PP_CLAIMED)) { parport_claim_or_block (pp->pdev); @@ -620,6 +558,7 @@ static int pp_release (struct inode * inode, struct file * file) printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n", minor); } + unlock_kernel(); kfree (pp); @@ -654,10 +593,6 @@ static devfs_handle_t devfs_handle = NULL; static int __init ppdev_init (void) { - if (parport_register_driver (&ppdev_driver)) { - printk (KERN_WARNING CHRDEV ": unable to register driver\n"); - return -EIO; - } if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { printk (KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); @@ -678,7 +613,6 @@ static void __exit ppdev_cleanup (void) /* Clean up all parport stuff */ devfs_unregister (devfs_handle); devfs_unregister_chrdev (PP_MAJOR, CHRDEV); - parport_unregister_driver (&ppdev_driver); } module_init(ppdev_init); |