Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
[pandora-kernel.git] / kernel / params.c
index ef60db1..08107d1 100644 (file)
 #define DEBUGP(fmt, a...)
 #endif
 
+/* Protects all parameters, and incidentally kmalloced_param list. */
+static DEFINE_MUTEX(param_lock);
+
 /* This just allows us to keep track of which parameters are kmalloced. */
 struct kmalloced_param {
        struct list_head list;
        char val[];
 };
-static DEFINE_MUTEX(param_lock);
 static LIST_HEAD(kmalloced_params);
 
 static void *kmalloc_parameter(unsigned int size)
@@ -47,10 +49,7 @@ static void *kmalloc_parameter(unsigned int size)
        if (!p)
                return NULL;
 
-       mutex_lock(&param_lock);
        list_add(&p->list, &kmalloced_params);
-       mutex_unlock(&param_lock);
-
        return p->val;
 }
 
@@ -59,7 +58,6 @@ static void maybe_kfree_parameter(void *param)
 {
        struct kmalloced_param *p;
 
-       mutex_lock(&param_lock);
        list_for_each_entry(p, &kmalloced_params, list) {
                if (p->val == param) {
                        list_del(&p->list);
@@ -67,7 +65,6 @@ static void maybe_kfree_parameter(void *param)
                        break;
                }
        }
-       mutex_unlock(&param_lock);
 }
 
 static inline char dash2underscore(char c)
@@ -88,11 +85,12 @@ static inline int parameq(const char *input, const char *paramname)
 
 static int parse_one(char *param,
                     char *val,
-                    struct kernel_param *params, 
+                    const struct kernel_param *params,
                     unsigned num_params,
                     int (*handle_unknown)(char *param, char *val))
 {
        unsigned int i;
+       int err;
 
        /* Find parameter */
        for (i = 0; i < num_params; i++) {
@@ -102,7 +100,10 @@ static int parse_one(char *param,
                                return -EINVAL;
                        DEBUGP("They are equal!  Calling %p\n",
                               params[i].ops->set);
-                       return params[i].ops->set(val, &params[i]);
+                       mutex_lock(&param_lock);
+                       err = params[i].ops->set(val, &params[i]);
+                       mutex_unlock(&param_lock);
+                       return err;
                }
        }
 
@@ -170,7 +171,7 @@ static char *next_arg(char *args, char **param, char **val)
 /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
 int parse_args(const char *name,
               char *args,
-              struct kernel_param *params,
+              const struct kernel_param *params,
               unsigned num,
               int (*unknown)(char *param, char *val))
 {
@@ -400,6 +401,7 @@ static int param_array(const char *name,
                /* nul-terminate and parse */
                save = val[len];
                ((char *)val)[len] = '\0';
+               BUG_ON(!mutex_is_locked(&param_lock));
                ret = set(val, &kp);
 
                if (ret != 0)
@@ -438,6 +440,7 @@ static int param_array_get(char *buffer, const struct kernel_param *kp)
                if (i)
                        buffer[off++] = ',';
                p.arg = arr->elem + arr->elemsize * i;
+               BUG_ON(!mutex_is_locked(&param_lock));
                ret = arr->ops->get(buffer + off, &p);
                if (ret < 0)
                        return ret;
@@ -522,7 +525,9 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
        if (!attribute->param->ops->get)
                return -EPERM;
 
+       mutex_lock(&param_lock);
        count = attribute->param->ops->get(buf, attribute->param);
+       mutex_unlock(&param_lock);
        if (count > 0) {
                strcat(buf, "\n");
                ++count;
@@ -541,7 +546,9 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
        if (!attribute->param->ops->set)
                return -EPERM;
 
+       mutex_lock(&param_lock);
        err = attribute->param->ops->set(buf, attribute->param);
+       mutex_unlock(&param_lock);
        if (!err)
                return len;
        return err;
@@ -555,6 +562,18 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
 #endif
 
 #ifdef CONFIG_SYSFS
+void __kernel_param_lock(void)
+{
+       mutex_lock(&param_lock);
+}
+EXPORT_SYMBOL(__kernel_param_lock);
+
+void __kernel_param_unlock(void)
+{
+       mutex_unlock(&param_lock);
+}
+EXPORT_SYMBOL(__kernel_param_unlock);
+
 /*
  * add_sysfs_param - add a parameter to sysfs
  * @mk: struct module_kobject