[MIPS] Change libgcc-style functions from lib-y to obj-y
[linux-drm-fsl-dcu.git] / kernel / module.c
index dcdb32b8b13cd31d51868375a03e1f54b6c34efd..9bd93de01f4a95ab6abb0729401bf424cf5fab21 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/init.h>
+#include <linux/kallsyms.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -45,6 +46,8 @@
 #include <asm/cacheflush.h>
 #include <linux/license.h>
 
+extern int module_sysfs_initialized;
+
 #if 0
 #define DEBUGP printk
 #else
@@ -93,9 +96,9 @@ static inline void add_taint_module(struct module *mod, unsigned flag)
        mod->taints |= flag;
 }
 
-/* A thread that wants to hold a reference to a module only while it
- * is running can call ths to safely exit.
- * nfsd and lockd use this.
+/*
+ * A thread that wants to hold a reference to a module only while it
+ * is running can call this to safely exit.  nfsd and lockd use this.
  */
 void __module_put_and_exit(struct module *mod, long code)
 {
@@ -308,14 +311,14 @@ static int split_block(unsigned int i, unsigned short size)
 {
        /* Reallocation required? */
        if (pcpu_num_used + 1 > pcpu_num_allocated) {
-               int *new = kmalloc(sizeof(new[0]) * pcpu_num_allocated*2,
-                                  GFP_KERNEL);
+               int *new;
+
+               new = krealloc(pcpu_size, sizeof(new[0])*pcpu_num_allocated*2,
+                              GFP_KERNEL);
                if (!new)
                        return 0;
 
-               memcpy(new, pcpu_size, sizeof(new[0])*pcpu_num_allocated);
                pcpu_num_allocated *= 2;
-               kfree(pcpu_size);
                pcpu_size = new;
        }
 
@@ -346,10 +349,10 @@ static void *percpu_modalloc(unsigned long size, unsigned long align,
        unsigned int i;
        void *ptr;
 
-       if (align > SMP_CACHE_BYTES) {
-               printk(KERN_WARNING "%s: per-cpu alignment %li > %i\n",
-                      name, align, SMP_CACHE_BYTES);
-               align = SMP_CACHE_BYTES;
+       if (align > PAGE_SIZE) {
+               printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
+                      name, align, PAGE_SIZE);
+               align = PAGE_SIZE;
        }
 
        ptr = __per_cpu_start;
@@ -430,7 +433,7 @@ static int percpu_modinit(void)
        pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated,
                            GFP_KERNEL);
        /* Static in-kernel percpu data (used). */
-       pcpu_size[0] = -ALIGN(__per_cpu_end-__per_cpu_start, SMP_CACHE_BYTES);
+       pcpu_size[0] = -(__per_cpu_end-__per_cpu_start);
        /* Free room. */
        pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0];
        if (pcpu_size[1] < 0) {
@@ -1117,8 +1120,8 @@ int mod_sysfs_init(struct module *mod)
 {
        int err;
 
-       if (!module_subsys.kset.subsys) {
-               printk(KERN_ERR "%s: module_subsys not initialized\n",
+       if (!module_sysfs_initialized) {
+               printk(KERN_ERR "%s: module sysfs not initialized\n",
                       mod->name);
                err = -EINVAL;
                goto out;
@@ -1148,8 +1151,10 @@ int mod_sysfs_setup(struct module *mod,
                goto out;
 
        mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders");
-       if (!mod->holders_dir)
+       if (!mod->holders_dir) {
+               err = -ENOMEM;
                goto out_unreg;
+       }
 
        err = module_param_sysfs_setup(mod, kparam, num_params);
        if (err)
@@ -1194,7 +1199,7 @@ static int __unlink_module(void *_mod)
        return 0;
 }
 
-/* Free a module, remove from lists, etc (must hold module mutex). */
+/* Free a module, remove from lists, etc (must hold module_mutex). */
 static void free_module(struct module *mod)
 {
        /* Delete from various lists */
@@ -1241,7 +1246,7 @@ EXPORT_SYMBOL_GPL(__symbol_get);
 
 /*
  * Ensure that an exported symbol [global namespace] does not already exist
- * in the Kernel or in some other modules exported symbol table.
+ * in the kernel or in some other module's exported symbol table.
  */
 static int verify_export_symbols(struct module *mod)
 {
@@ -1467,7 +1472,7 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
 }
 
 #ifdef CONFIG_KALLSYMS
-int is_exported(const char *name, const struct module *mod)
+static int is_exported(const char *name, const struct module *mod)
 {
        if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
                return 1;
@@ -2093,8 +2098,10 @@ static const char *get_ksymbol(struct module *mod,
        if (!best)
                return NULL;
 
-       *size = nextval - mod->symtab[best].st_value;
-       *offset = addr - mod->symtab[best].st_value;
+       if (size)
+               *size = nextval - mod->symtab[best].st_value;
+       if (offset)
+               *offset = addr - mod->symtab[best].st_value;
        return mod->strtab + mod->symtab[best].st_name;
 }
 
@@ -2119,8 +2126,58 @@ const char *module_address_lookup(unsigned long addr,
        return NULL;
 }
 
-struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
-                               char *type, char *name, size_t namelen)
+int lookup_module_symbol_name(unsigned long addr, char *symname)
+{
+       struct module *mod;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(mod, &modules, list) {
+               if (within(addr, mod->module_init, mod->init_size) ||
+                   within(addr, mod->module_core, mod->core_size)) {
+                       const char *sym;
+
+                       sym = get_ksymbol(mod, addr, NULL, NULL);
+                       if (!sym)
+                               goto out;
+                       strlcpy(symname, sym, KSYM_NAME_LEN + 1);
+                       mutex_unlock(&module_mutex);
+                       return 0;
+               }
+       }
+out:
+       mutex_unlock(&module_mutex);
+       return -ERANGE;
+}
+
+int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
+                       unsigned long *offset, char *modname, char *name)
+{
+       struct module *mod;
+
+       mutex_lock(&module_mutex);
+       list_for_each_entry(mod, &modules, list) {
+               if (within(addr, mod->module_init, mod->init_size) ||
+                   within(addr, mod->module_core, mod->core_size)) {
+                       const char *sym;
+
+                       sym = get_ksymbol(mod, addr, size, offset);
+                       if (!sym)
+                               goto out;
+                       if (modname)
+                               strlcpy(modname, mod->name, MODULE_NAME_LEN + 1);
+                       if (name)
+                               strlcpy(name, sym, KSYM_NAME_LEN + 1);
+                       mutex_unlock(&module_mutex);
+                       return 0;
+               }
+       }
+out:
+       mutex_unlock(&module_mutex);
+       return -ERANGE;
+}
+
+int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+                       char *name, char *module_name, int *exported)
 {
        struct module *mod;
 
@@ -2130,14 +2187,16 @@ struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
                        *value = mod->symtab[symnum].st_value;
                        *type = mod->symtab[symnum].st_info;
                        strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
-                               namelen);
+                               KSYM_NAME_LEN + 1);
+                       strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
+                       *exported = is_exported(name, mod);
                        mutex_unlock(&module_mutex);
-                       return mod;
+                       return 0;
                }
                symnum -= mod->num_symtab;
        }
        mutex_unlock(&module_mutex);
-       return NULL;
+       return -ERANGE;
 }
 
 static unsigned long mod_find_symname(struct module *mod, const char *name)
@@ -2383,7 +2442,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
                struct kobject *mkobj;
 
                /* Lookup built-in module entry in /sys/modules */
-               mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
+               mkobj = kset_find_obj(&module_subsys, drv->mod_name);
                if (mkobj) {
                        mk = container_of(mkobj, struct module_kobject, kobj);
                        /* remember our module structure */