summaryrefslogtreecommitdiffstats
path: root/drivers/char/ppdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ppdev.c')
-rw-r--r--drivers/char/ppdev.c86
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);