Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[pandora-kernel.git] / crypto / cryptomgr.c
index 9b5b156..e5fb7cc 100644 (file)
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
 #include <linux/rtnetlink.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/workqueue.h>
 
 #include "internal.h"
 
 struct cryptomgr_param {
-       struct work_struct work;
+       struct rtattr *tb[CRYPTOA_MAX];
+
+       struct {
+               struct rtattr attr;
+               struct crypto_attr_type data;
+       } type;
 
        struct {
                struct rtattr attr;
@@ -32,15 +37,13 @@ struct cryptomgr_param {
        } alg;
 
        struct {
-               u32 type;
-               u32 mask;
                char name[CRYPTO_MAX_ALG_NAME];
        } larval;
 
        char template[CRYPTO_MAX_ALG_NAME];
 };
 
-static void cryptomgr_probe(void *data)
+static int cryptomgr_probe(void *data)
 {
        struct cryptomgr_param *param = data;
        struct crypto_template *tmpl;
@@ -52,7 +55,7 @@ static void cryptomgr_probe(void *data)
                goto err;
 
        do {
-               inst = tmpl->alloc(&param->alg, sizeof(param->alg));
+               inst = tmpl->alloc(param->tb);
                if (IS_ERR(inst))
                        err = PTR_ERR(inst);
                else if ((err = crypto_register_instance(tmpl, inst)))
@@ -66,25 +69,29 @@ static void cryptomgr_probe(void *data)
 
 out:
        kfree(param);
-       return;
+       module_put_and_exit(0);
 
 err:
-       crypto_larval_error(param->larval.name, param->larval.type,
-                           param->larval.mask);
+       crypto_larval_error(param->larval.name, param->type.data.type,
+                           param->type.data.mask);
        goto out;
 }
 
 static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 {
+       struct task_struct *thread;
        struct cryptomgr_param *param;
        const char *name = larval->alg.cra_name;
        const char *p;
        unsigned int len;
 
-       param = kmalloc(sizeof(*param), GFP_KERNEL);
-       if (!param)
+       if (!try_module_get(THIS_MODULE))
                goto err;
 
+       param = kzalloc(sizeof(*param), GFP_KERNEL);
+       if (!param)
+               goto err_put_module;
+
        for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
                ;
 
@@ -93,32 +100,45 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
                goto err_free_param;
 
        memcpy(param->template, name, len);
-       param->template[len] = 0;
 
        name = p + 1;
-       for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
-               ;
+       len = 0;
+       for (p = name; *p; p++) {
+               for (; isalnum(*p) || *p == '-' || *p == '_' || *p == '('; p++)
+                       ;
 
-       len = p - name;
-       if (!len || *p != ')' || p[1])
+               if (*p != ')')
+                       goto err_free_param;
+
+               len = p - name;
+       }
+
+       if (!len || name[len + 1])
                goto err_free_param;
 
+       param->type.attr.rta_len = sizeof(param->type);
+       param->type.attr.rta_type = CRYPTOA_TYPE;
+       param->type.data.type = larval->alg.cra_flags;
+       param->type.data.mask = larval->mask;
+       param->tb[CRYPTOA_TYPE - 1] = &param->type.attr;
+
        param->alg.attr.rta_len = sizeof(param->alg);
        param->alg.attr.rta_type = CRYPTOA_ALG;
        memcpy(param->alg.data.name, name, len);
-       param->alg.data.name[len] = 0;
+       param->tb[CRYPTOA_ALG - 1] = &param->alg.attr;
 
        memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
-       param->larval.type = larval->alg.cra_flags;
-       param->larval.mask = larval->mask;
 
-       INIT_WORK(&param->work, cryptomgr_probe, param);
-       schedule_work(&param->work);
+       thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
+       if (IS_ERR(thread))
+               goto err_free_param;
 
        return NOTIFY_STOP;
 
 err_free_param:
        kfree(param);
+err_put_module:
+       module_put(THIS_MODULE);
 err:
        return NOTIFY_OK;
 }