Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[pandora-kernel.git] / drivers / usb / core / file.c
index 01c857a..6b1b229 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/rwsem.h>
+#include <linux/smp_lock.h>
 #include <linux/usb.h>
 
 #include "usb.h"
 
 #define MAX_USB_MINORS 256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
-static DEFINE_SPINLOCK(minor_lock);
+static DECLARE_RWSEM(minor_rwsem);
 
 static int usb_open(struct inode * inode, struct file * file)
 {
@@ -33,14 +34,12 @@ static int usb_open(struct inode * inode, struct file * file)
        int err = -ENODEV;
        const struct file_operations *old_fops, *new_fops = NULL;
 
-       spin_lock (&minor_lock);
+       lock_kernel();
+       down_read(&minor_rwsem);
        c = usb_minors[minor];
 
-       if (!c || !(new_fops = fops_get(c))) {
-               spin_unlock(&minor_lock);
-               return err;
-       }
-       spin_unlock(&minor_lock);
+       if (!c || !(new_fops = fops_get(c)))
+               goto done;
 
        old_fops = file->f_op;
        file->f_op = new_fops;
@@ -52,6 +51,9 @@ static int usb_open(struct inode * inode, struct file * file)
                file->f_op = fops_get(old_fops);
        }
        fops_put(old_fops);
+ done:
+       up_read(&minor_rwsem);
+       unlock_kernel();
        return err;
 }
 
@@ -148,7 +150,7 @@ int usb_register_dev(struct usb_interface *intf,
        int retval = -EINVAL;
        int minor_base = class_driver->minor_base;
        int minor = 0;
-       char name[BUS_ID_SIZE];
+       char name[20];
        char *temp;
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -166,7 +168,7 @@ int usb_register_dev(struct usb_interface *intf,
        if (class_driver->fops == NULL)
                goto exit;
 
-       spin_lock (&minor_lock);
+       down_write(&minor_rwsem);
        for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
                if (usb_minors[minor])
                        continue;
@@ -176,7 +178,7 @@ int usb_register_dev(struct usb_interface *intf,
                retval = 0;
                break;
        }
-       spin_unlock (&minor_lock);
+       up_write(&minor_rwsem);
 
        if (retval)
                goto exit;
@@ -188,24 +190,25 @@ int usb_register_dev(struct usb_interface *intf,
        intf->minor = minor;
 
        /* create a usb class device for this usb interface */
-       snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
+       snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
        temp = strrchr(name, '/');
-       if (temp && (temp[1] != 0x00))
+       if (temp && (temp[1] != '\0'))
                ++temp;
        else
                temp = name;
-       intf->usb_dev = device_create(usb_class->class, &intf->dev,
-                                     MKDEV(USB_MAJOR, minor), "%s", temp);
+       intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
+                                             MKDEV(USB_MAJOR, minor), NULL,
+                                             "%s", temp);
        if (IS_ERR(intf->usb_dev)) {
-               spin_lock (&minor_lock);
+               down_write(&minor_rwsem);
                usb_minors[intf->minor] = NULL;
-               spin_unlock (&minor_lock);
+               up_write(&minor_rwsem);
                retval = PTR_ERR(intf->usb_dev);
        }
 exit:
        return retval;
 }
-EXPORT_SYMBOL(usb_register_dev);
+EXPORT_SYMBOL_GPL(usb_register_dev);
 
 /**
  * usb_deregister_dev - deregister a USB device's dynamic minor.
@@ -225,7 +228,7 @@ void usb_deregister_dev(struct usb_interface *intf,
                        struct usb_class_driver *class_driver)
 {
        int minor_base = class_driver->minor_base;
-       char name[BUS_ID_SIZE];
+       char name[20];
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
        minor_base = 0;
@@ -236,16 +239,14 @@ void usb_deregister_dev(struct usb_interface *intf,
 
        dbg ("removing %d minor", intf->minor);
 
-       spin_lock (&minor_lock);
+       down_write(&minor_rwsem);
        usb_minors[intf->minor] = NULL;
-       spin_unlock (&minor_lock);
+       up_write(&minor_rwsem);
 
-       snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
+       snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base);
        device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
        intf->usb_dev = NULL;
        intf->minor = -1;
        destroy_usb_class();
 }
-EXPORT_SYMBOL(usb_deregister_dev);
-
-
+EXPORT_SYMBOL_GPL(usb_deregister_dev);