hwmon: LM95241 driver
[safe/jmp/linux-2.6] / kernel / module.c
index 34b56cf..f77ac32 100644 (file)
@@ -50,6 +50,8 @@
 #include <asm/sections.h>
 #include <linux/tracepoint.h>
 #include <linux/ftrace.h>
+#include <linux/async.h>
+#include <linux/percpu.h>
 
 #if 0
 #define DEBUGP printk
@@ -365,6 +367,34 @@ static struct module *find_module(const char *name)
 }
 
 #ifdef CONFIG_SMP
+
+#ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA
+
+static void *percpu_modalloc(unsigned long size, unsigned long align,
+                            const char *name)
+{
+       void *ptr;
+
+       if (align > PAGE_SIZE) {
+               printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
+                      name, align, PAGE_SIZE);
+               align = PAGE_SIZE;
+       }
+
+       ptr = __alloc_reserved_percpu(size, align);
+       if (!ptr)
+               printk(KERN_WARNING
+                      "Could not allocate %lu bytes percpu data\n", size);
+       return ptr;
+}
+
+static void percpu_modfree(void *freeme)
+{
+       free_percpu(freeme);
+}
+
+#else /* ... !CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */
+
 /* Number of blocks used and allocated. */
 static unsigned int pcpu_num_used, pcpu_num_allocated;
 /* Size of each block.  -ve means used. */
@@ -479,21 +509,6 @@ static void percpu_modfree(void *freeme)
        }
 }
 
-static unsigned int find_pcpusec(Elf_Ehdr *hdr,
-                                Elf_Shdr *sechdrs,
-                                const char *secstrings)
-{
-       return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
-}
-
-static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size)
-{
-       int cpu;
-
-       for_each_possible_cpu(cpu)
-               memcpy(pcpudest + per_cpu_offset(cpu), from, size);
-}
-
 static int percpu_modinit(void)
 {
        pcpu_num_used = 2;
@@ -512,7 +527,26 @@ static int percpu_modinit(void)
        return 0;
 }
 __initcall(percpu_modinit);
+
+#endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */
+
+static unsigned int find_pcpusec(Elf_Ehdr *hdr,
+                                Elf_Shdr *sechdrs,
+                                const char *secstrings)
+{
+       return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
+}
+
+static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               memcpy(pcpudest + per_cpu_offset(cpu), from, size);
+}
+
 #else /* ... !CONFIG_SMP */
+
 static inline void *percpu_modalloc(unsigned long size, unsigned long align,
                                    const char *name)
 {
@@ -534,6 +568,7 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,
        /* pcpusec should be 0, and size of that section should be 0. */
        BUG_ON(size != 0);
 }
+
 #endif /* CONFIG_SMP */
 
 #define MODINFO_ATTR(field)    \
@@ -572,13 +607,13 @@ static char last_unloaded_module[MODULE_NAME_LEN+1];
 /* Init the unload section of the module. */
 static void module_unload_init(struct module *mod)
 {
-       unsigned int i;
+       int cpu;
 
        INIT_LIST_HEAD(&mod->modules_which_use_me);
-       for (i = 0; i < NR_CPUS; i++)
-               local_set(&mod->ref[i].count, 0);
+       for_each_possible_cpu(cpu)
+               local_set(__module_ref_addr(mod, cpu), 0);
        /* Hold reference count during initialization. */
-       local_set(&mod->ref[raw_smp_processor_id()].count, 1);
+       local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1);
        /* Backwards compatibility macros put refcount during init. */
        mod->waiter = current;
 }
@@ -716,10 +751,11 @@ static int try_stop_module(struct module *mod, int flags, int *forced)
 
 unsigned int module_refcount(struct module *mod)
 {
-       unsigned int i, total = 0;
+       unsigned int total = 0;
+       int cpu;
 
-       for (i = 0; i < NR_CPUS; i++)
-               total += local_read(&mod->ref[i].count);
+       for_each_possible_cpu(cpu)
+               total += local_read(__module_ref_addr(mod, cpu));
        return total;
 }
 EXPORT_SYMBOL(module_refcount);
@@ -742,8 +778,8 @@ static void wait_for_zero_refcount(struct module *mod)
        mutex_lock(&module_mutex);
 }
 
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
+SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
+               unsigned int, flags)
 {
        struct module *mod;
        char name[MODULE_NAME_LEN];
@@ -816,10 +852,11 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
                mod->exit();
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
+       async_synchronize_full();
        mutex_lock(&module_mutex);
        /* Store the name of the last unloaded module for diagnostic purposes */
        strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
-       unregister_dynamic_debug_module(mod->name);
+       ddebug_remove_module(mod->name);
        free_module(mod);
 
  out:
@@ -892,7 +929,7 @@ void module_put(struct module *module)
 {
        if (module) {
                unsigned int cpu = get_cpu();
-               local_dec(&module->ref[cpu].count);
+               local_dec(__module_ref_addr(module, cpu));
                /* Maybe they're waiting for us to drop reference? */
                if (unlikely(!module_is_live(module)))
                        wake_up_process(module->waiter);
@@ -1462,7 +1499,10 @@ static void free_module(struct module *mod)
        kfree(mod->args);
        if (mod->percpu)
                percpu_modfree(mod->percpu);
-
+#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+       if (mod->refptr)
+               percpu_modfree(mod->refptr);
+#endif
        /* Free lock-classes: */
        lockdep_free_key_range(mod->module_core, mod->core_size);
 
@@ -1821,19 +1861,13 @@ static inline void add_kallsyms(struct module *mod,
 }
 #endif /* CONFIG_KALLSYMS */
 
-static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
+static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
 {
-#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
-       unsigned int i;
-
-       for (i = 0; i < num; i++) {
-               register_dynamic_debug_module(debug[i].modname,
-                                             debug[i].type,
-                                             debug[i].logical_modname,
-                                             debug[i].flag_names,
-                                             debug[i].hash, debug[i].hash2);
-       }
-#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
+#ifdef CONFIG_DYNAMIC_DEBUG
+       if (ddebug_add_module(debug, num, debug->modname))
+               printk(KERN_ERR "dynamic debug error adding module: %s\n",
+                                       debug->modname);
+#endif
 }
 
 static void *module_alloc_update_bounds(unsigned long size)
@@ -2068,6 +2102,14 @@ static noinline struct module *load_module(void __user *umod,
        /* Module has been moved. */
        mod = (void *)sechdrs[modindex].sh_addr;
 
+#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+       mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t),
+                                     mod->name);
+       if (!mod->refptr) {
+               err = -ENOMEM;
+               goto free_init;
+       }
+#endif
        /* Now we've moved module, initialize linked lists, etc. */
        module_unload_init(mod);
 
@@ -2199,12 +2241,13 @@ static noinline struct module *load_module(void __user *umod,
        add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
 
        if (!mod->taints) {
-               struct mod_debug *debug;
+               struct _ddebug *debug;
                unsigned int num_debug;
 
                debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
                                     sizeof(*debug), &num_debug);
-               dynamic_printk_setup(debug, num_debug);
+               if (debug)
+                       dynamic_debug_setup(debug, num_debug);
        }
 
        /* sechdrs[0].sh_size is always zero */
@@ -2274,9 +2317,14 @@ static noinline struct module *load_module(void __user *umod,
        ftrace_release(mod->module_core, mod->core_size);
  free_unload:
        module_unload_free(mod);
+ free_init:
+#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+       percpu_modfree(mod->refptr);
+#endif
        module_free(mod, mod->module_init);
  free_core:
        module_free(mod, mod->module_core);
+       /* mod will be freed with core. Don't access it beyond this line! */
  free_percpu:
        if (percpu)
                percpu_modfree(percpu);
@@ -2294,10 +2342,8 @@ static noinline struct module *load_module(void __user *umod,
 }
 
 /* This is where the real work happens */
-asmlinkage long
-sys_init_module(void __user *umod,
-               unsigned long len,
-               const char __user *uargs)
+SYSCALL_DEFINE3(init_module, void __user *, umod,
+               unsigned long, len, const char __user *, uargs)
 {
        struct module *mod;
        int ret = 0;
@@ -2352,6 +2398,8 @@ sys_init_module(void __user *umod,
        /* Now it's a first class citizen!  Wake up anyone waiting for it. */
        mod->state = MODULE_STATE_LIVE;
        wake_up(&module_wq);
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_LIVE, mod);
 
        mutex_lock(&module_mutex);
        /* Drop initial reference. */
@@ -2390,7 +2438,7 @@ static const char *get_ksymbol(struct module *mod,
        unsigned long nextval;
 
        /* At worse, next value is at end of module */
-       if (within(addr, mod->module_init, mod->init_size))
+       if (within_module_init(addr, mod))
                nextval = (unsigned long)mod->module_init+mod->init_text_size;
        else
                nextval = (unsigned long)mod->module_core+mod->core_text_size;
@@ -2438,8 +2486,8 @@ const char *module_address_lookup(unsigned long addr,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
-               if (within(addr, mod->module_init, mod->init_size)
-                   || within(addr, mod->module_core, mod->core_size)) {
+               if (within_module_init(addr, mod) ||
+                   within_module_core(addr, mod)) {
                        if (modname)
                                *modname = mod->name;
                        ret = get_ksymbol(mod, addr, size, offset);
@@ -2461,8 +2509,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
-               if (within(addr, mod->module_init, mod->init_size) ||
-                   within(addr, mod->module_core, mod->core_size)) {
+               if (within_module_init(addr, mod) ||
+                   within_module_core(addr, mod)) {
                        const char *sym;
 
                        sym = get_ksymbol(mod, addr, NULL, NULL);
@@ -2485,8 +2533,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
-               if (within(addr, mod->module_init, mod->init_size) ||
-                   within(addr, mod->module_core, mod->core_size)) {
+               if (within_module_init(addr, mod) ||
+                   within_module_core(addr, mod)) {
                        const char *sym;
 
                        sym = get_ksymbol(mod, addr, size, offset);
@@ -2705,7 +2753,7 @@ int is_module_address(unsigned long addr)
        preempt_disable();
 
        list_for_each_entry_rcu(mod, &modules, list) {
-               if (within(addr, mod->module_core, mod->core_size)) {
+               if (within_module_core(addr, mod)) {
                        preempt_enable();
                        return 1;
                }