]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sparc64/kernel/mdesc.c
[SPARC64]: Warn user if cpu is ignored.
[linux-2.6-omap-h63xx.git] / arch / sparc64 / kernel / mdesc.c
index 302ba5e5a0bb85d1b8c5f66b938c0177c9e504d2..856659bb13116ed7444c263ec1a9f8087c660ec7 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/miscdevice.h>
 
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
@@ -83,7 +84,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
        hp->handle_size = handle_size;
 }
 
-static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
+static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size)
 {
        struct mdesc_handle *hp;
        unsigned int handle_size, alloc_size;
@@ -123,7 +124,7 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp)
        }
 }
 
-static struct mdesc_mem_ops bootmem_mdesc_memops = {
+static struct mdesc_mem_ops bootmem_mdesc_ops = {
        .alloc = mdesc_bootmem_alloc,
        .free  = mdesc_bootmem_free,
 };
@@ -231,6 +232,25 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client)
        mutex_unlock(&mdesc_mutex);
 }
 
+static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
+{
+       const u64 *id;
+       u64 a;
+
+       id = NULL;
+       mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
+               u64 target;
+
+               target = mdesc_arc_target(hp, a);
+               id = mdesc_get_property(hp, target,
+                                       "cfg-handle", NULL);
+               if (id)
+                       break;
+       }
+
+       return id;
+}
+
 /* Run 'func' on nodes which are in A but not in B.  */
 static void invoke_on_missing(const char *name,
                              struct mdesc_handle *a,
@@ -240,13 +260,42 @@ static void invoke_on_missing(const char *name,
        u64 node;
 
        mdesc_for_each_node_by_name(a, node, name) {
-               const u64 *id = mdesc_get_property(a, node, "id", NULL);
-               int found = 0;
+               int found = 0, is_vdc_port = 0;
+               const char *name_prop;
+               const u64 *id;
                u64 fnode;
 
+               name_prop = mdesc_get_property(a, node, "name", NULL);
+               if (name_prop && !strcmp(name_prop, "vdc-port")) {
+                       is_vdc_port = 1;
+                       id = parent_cfg_handle(a, node);
+               } else
+                       id = mdesc_get_property(a, node, "id", NULL);
+
+               if (!id) {
+                       printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
+                              (name_prop ? name_prop : name));
+                       continue;
+               }
+
                mdesc_for_each_node_by_name(b, fnode, name) {
-                       const u64 *fid = mdesc_get_property(b, fnode,
-                                                           "id", NULL);
+                       const u64 *fid;
+
+                       if (is_vdc_port) {
+                               name_prop = mdesc_get_property(b, fnode,
+                                                              "name", NULL);
+                               if (!name_prop ||
+                                   strcmp(name_prop, "vdc-port"))
+                                       continue;
+                               fid = parent_cfg_handle(b, fnode);
+                               if (!fid) {
+                                       printk(KERN_ERR "MD: Cannot find ID "
+                                              "for vdc-port node.\n");
+                                       continue;
+                               }
+                       } else
+                               fid = mdesc_get_property(b, fnode,
+                                                        "id", NULL);
 
                        if (*id == *fid) {
                                found = 1;
@@ -520,20 +569,6 @@ static void __init report_platform_properties(void)
        mdesc_release(hp);
 }
 
-static int inline find_in_proplist(const char *list, const char *match, int len)
-{
-       while (len > 0) {
-               int l;
-
-               if (!strcmp(list, match))
-                       return 1;
-               l = strlen(list) + 1;
-               list += l;
-               len -= l;
-       }
-       return 0;
-}
-
 static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
                                        struct mdesc_handle *hp,
                                        u64 mp)
@@ -548,10 +583,10 @@ static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
 
        switch (*level) {
        case 1:
-               if (find_in_proplist(type, "instn", type_len)) {
+               if (of_find_in_proplist(type, "instn", type_len)) {
                        c->icache_size = *size;
                        c->icache_line_size = *line_size;
-               } else if (find_in_proplist(type, "data", type_len)) {
+               } else if (of_find_in_proplist(type, "data", type_len)) {
                        c->dcache_size = *size;
                        c->dcache_line_size = *line_size;
                }
@@ -629,7 +664,7 @@ static void __devinit set_core_ids(struct mdesc_handle *hp)
                        continue;
 
                type = mdesc_get_property(hp, mp, "type", &len);
-               if (!find_in_proplist(type, "instn", len))
+               if (!of_find_in_proplist(type, "instn", len))
                        continue;
 
                mark_core_ids(hp, mp, idx);
@@ -670,8 +705,8 @@ static void __devinit __set_proc_ids(struct mdesc_handle *hp,
                int len;
 
                type = mdesc_get_property(hp, mp, "type", &len);
-               if (!find_in_proplist(type, "int", len) &&
-                   !find_in_proplist(type, "integer", len))
+               if (!of_find_in_proplist(type, "int", len) &&
+                   !of_find_in_proplist(type, "integer", len))
                        continue;
 
                mark_proc_ids(hp, mp, idx);
@@ -742,8 +777,12 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
                cpuid = *id;
 
 #ifdef CONFIG_SMP
-               if (cpuid >= NR_CPUS)
+               if (cpuid >= NR_CPUS) {
+                       printk(KERN_WARNING "Ignoring CPU %d which is "
+                              ">= NR_CPUS (%d)\n",
+                              cpuid, NR_CPUS);
                        continue;
+               }
                if (!cpu_isset(cpuid, mask))
                        continue;
 #else
@@ -802,6 +841,43 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
        mdesc_release(hp);
 }
 
+static ssize_t mdesc_read(struct file *file, char __user *buf,
+                         size_t len, loff_t *offp)
+{
+       struct mdesc_handle *hp = mdesc_grab();
+       int err;
+
+       if (!hp)
+               return -ENODEV;
+
+       err = hp->handle_size;
+       if (len < hp->handle_size)
+               err = -EMSGSIZE;
+       else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
+               err = -EFAULT;
+       mdesc_release(hp);
+
+       return err;
+}
+
+static const struct file_operations mdesc_fops = {
+       .read   = mdesc_read,
+       .owner  = THIS_MODULE,
+};
+
+static struct miscdevice mdesc_misc = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       .name   = "mdesc",
+       .fops   = &mdesc_fops,
+};
+
+static int __init mdesc_misc_init(void)
+{
+       return misc_register(&mdesc_misc);
+}
+
+__initcall(mdesc_misc_init);
+
 void __init sun4v_mdesc_init(void)
 {
        struct mdesc_handle *hp;
@@ -812,7 +888,7 @@ void __init sun4v_mdesc_init(void)
 
        printk("MDESC: Size is %lu bytes.\n", len);
 
-       hp = mdesc_alloc(len, &bootmem_mdesc_memops);
+       hp = mdesc_alloc(len, &bootmem_mdesc_ops);
        if (hp == NULL) {
                prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
                prom_halt();