Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee13...
[powerpc.git] / drivers / usb / storage / libusual.c
index 61f73d8..599ad10 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/usb.h>
 #include <linux/usb_usual.h>
 #include <linux/vmalloc.h>
+#include <linux/kthread.h>
 
 /*
  */
@@ -24,10 +25,9 @@ static DEFINE_SPINLOCK(usu_lock);
 /*
  */
 #define USB_US_DEFAULT_BIAS    USB_US_TYPE_STOR
+static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
 
 #define BIAS_NAME_SIZE  (sizeof("usb-storage"))
-static char bias[BIAS_NAME_SIZE];
-static int usb_usual_bias;
 static const char *bias_names[3] = { "none", "usb-storage", "ub" };
 
 static DECLARE_MUTEX_LOCKED(usu_init_notify);
@@ -35,7 +35,6 @@ static DECLARE_COMPLETION(usu_end_notify);
 static atomic_t total_threads = ATOMIC_INIT(0);
 
 static int usu_probe_thread(void *arg);
-static int parse_bias(const char *bias_s);
 
 /*
  * The table.
@@ -107,7 +106,7 @@ int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
        if (id_type == caller_type)
                return 0;
        /* Drivers grab devices biased to them */
-       if (id_type == USB_US_TYPE_NONE && caller_type == usb_usual_bias)
+       if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias))
                return 0;
        return -ENODEV;
 }
@@ -118,13 +117,13 @@ EXPORT_SYMBOL_GPL(usb_usual_check_type);
 static int usu_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
-       int type;
-       int rc;
+       unsigned long type;
+       struct task_struct* task;
        unsigned long flags;
 
        type = USB_US_TYPE(id->driver_info);
        if (type == 0)
-               type = usb_usual_bias;
+               type = atomic_read(&usu_bias);
 
        spin_lock_irqsave(&usu_lock, flags);
        if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
@@ -134,8 +133,9 @@ static int usu_probe(struct usb_interface *intf,
        stat[type].fls |= USU_MOD_FL_THREAD;
        spin_unlock_irqrestore(&usu_lock, flags);
 
-       rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
-       if (rc < 0) {
+       task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
+       if (IS_ERR(task)) {
+               int rc = PTR_ERR(task);
                printk(KERN_WARNING "libusual: "
                    "Unable to start the thread for %s: %d\n",
                    bias_names[type], rc);
@@ -155,7 +155,6 @@ static void usu_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver usu_driver = {
-       .owner =        THIS_MODULE,
        .name =         "libusual",
        .probe =        usu_probe,
        .disconnect =   usu_disconnect,
@@ -178,8 +177,6 @@ static int usu_probe_thread(void *arg)
        int rc;
        unsigned long flags;
 
-       daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
-
        /* A completion does not work here because it's counted. */
        down(&usu_init_notify);
        up(&usu_init_notify);
@@ -206,9 +203,6 @@ static int __init usb_usual_init(void)
 {
        int rc;
 
-       bias[BIAS_NAME_SIZE-1] = 0;
-       usb_usual_bias = parse_bias(bias);
-
        rc = usb_register(&usu_driver);
        up(&usu_init_notify);
        return rc;
@@ -231,36 +225,42 @@ static void __exit usb_usual_exit(void)
 
 /*
  * Validate and accept the bias parameter.
- * Maybe make an sysfs method later. XXX
  */
-static int parse_bias(const char *bias_s)
+static int usu_set_bias(const char *bias_s, struct kernel_param *kp)
 {
        int i;
+       int len;
        int bias_n = 0;
 
-       if (bias_s[0] == 0 || bias_s[0] == ' ') {
-               bias_n = USB_US_DEFAULT_BIAS;
-       } else {
-               for (i = 1; i < 3; i++) {
-                       if (strcmp(bias_s, bias_names[i]) == 0) {
-                               bias_n = i;
-                               break;
-                       }
-               }
-               if (bias_n == 0) {
-                       bias_n = USB_US_DEFAULT_BIAS;
-                       printk(KERN_INFO
-                           "libusual: unknown bias \"%s\", using \"%s\"\n",
-                           bias_s, bias_names[bias_n]);
+       len = strlen(bias_s);
+       if (len == 0)
+               return -EDOM;
+       if (bias_s[len-1] == '\n')
+               --len;
+
+       for (i = 1; i < 3; i++) {
+               if (strncmp(bias_s, bias_names[i], len) == 0) {
+                       bias_n = i;
+                       break;
                }
        }
-       return bias_n;
+       if (bias_n == 0)
+               return -EINVAL;
+
+       atomic_set(&usu_bias, bias_n);
+       return 0;
+}
+
+static int usu_get_bias(char *buffer, struct kernel_param *kp)
+{
+       return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)]));
 }
 
 module_init(usb_usual_init);
 module_exit(usb_usual_exit);
 
-module_param_string(bias, bias, BIAS_NAME_SIZE,  S_IRUGO|S_IWUSR);
+module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR);
+__MODULE_PARM_TYPE(bias, "string");
 MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
 
 MODULE_LICENSE("GPL");