Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / arch / sparc64 / kernel / mdesc.c
1 /* mdesc.c: Sun4V machine description handling.
2  *
3  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4  */
5 #include <linux/kernel.h>
6 #include <linux/types.h>
7 #include <linux/bootmem.h>
8 #include <linux/log2.h>
9 #include <linux/list.h>
10 #include <linux/slab.h>
11 #include <linux/mm.h>
12 #include <linux/miscdevice.h>
13
14 #include <asm/hypervisor.h>
15 #include <asm/mdesc.h>
16 #include <asm/prom.h>
17 #include <asm/oplib.h>
18 #include <asm/smp.h>
19
20 /* Unlike the OBP device tree, the machine description is a full-on
21  * DAG.  An arbitrary number of ARCs are possible from one
22  * node to other nodes and thus we can't use the OBP device_node
23  * data structure to represent these nodes inside of the kernel.
24  *
25  * Actually, it isn't even a DAG, because there are back pointers
26  * which create cycles in the graph.
27  *
28  * mdesc_hdr and mdesc_elem describe the layout of the data structure
29  * we get from the Hypervisor.
30  */
31 struct mdesc_hdr {
32         u32     version; /* Transport version */
33         u32     node_sz; /* node block size */
34         u32     name_sz; /* name block size */
35         u32     data_sz; /* data block size */
36 } __attribute__((aligned(16)));
37
38 struct mdesc_elem {
39         u8      tag;
40 #define MD_LIST_END     0x00
41 #define MD_NODE         0x4e
42 #define MD_NODE_END     0x45
43 #define MD_NOOP         0x20
44 #define MD_PROP_ARC     0x61
45 #define MD_PROP_VAL     0x76
46 #define MD_PROP_STR     0x73
47 #define MD_PROP_DATA    0x64
48         u8      name_len;
49         u16     resv;
50         u32     name_offset;
51         union {
52                 struct {
53                         u32     data_len;
54                         u32     data_offset;
55                 } data;
56                 u64     val;
57         } d;
58 };
59
60 struct mdesc_mem_ops {
61         struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
62         void (*free)(struct mdesc_handle *handle);
63 };
64
65 struct mdesc_handle {
66         struct list_head        list;
67         struct mdesc_mem_ops    *mops;
68         void                    *self_base;
69         atomic_t                refcnt;
70         unsigned int            handle_size;
71         struct mdesc_hdr        mdesc;
72 };
73
74 static void mdesc_handle_init(struct mdesc_handle *hp,
75                               unsigned int handle_size,
76                               void *base)
77 {
78         BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
79
80         memset(hp, 0, handle_size);
81         INIT_LIST_HEAD(&hp->list);
82         hp->self_base = base;
83         atomic_set(&hp->refcnt, 1);
84         hp->handle_size = handle_size;
85 }
86
87 static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size)
88 {
89         struct mdesc_handle *hp;
90         unsigned int handle_size, alloc_size;
91
92         handle_size = (sizeof(struct mdesc_handle) -
93                        sizeof(struct mdesc_hdr) +
94                        mdesc_size);
95         alloc_size = PAGE_ALIGN(handle_size);
96
97         hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
98         if (hp)
99                 mdesc_handle_init(hp, handle_size, hp);
100
101         return hp;
102 }
103
104 static void mdesc_bootmem_free(struct mdesc_handle *hp)
105 {
106         unsigned int alloc_size, handle_size = hp->handle_size;
107         unsigned long start, end;
108
109         BUG_ON(atomic_read(&hp->refcnt) != 0);
110         BUG_ON(!list_empty(&hp->list));
111
112         alloc_size = PAGE_ALIGN(handle_size);
113
114         start = (unsigned long) hp;
115         end = start + alloc_size;
116
117         while (start < end) {
118                 struct page *p;
119
120                 p = virt_to_page(start);
121                 ClearPageReserved(p);
122                 __free_page(p);
123                 start += PAGE_SIZE;
124         }
125 }
126
127 static struct mdesc_mem_ops bootmem_mdesc_ops = {
128         .alloc = mdesc_bootmem_alloc,
129         .free  = mdesc_bootmem_free,
130 };
131
132 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
133 {
134         unsigned int handle_size;
135         void *base;
136
137         handle_size = (sizeof(struct mdesc_handle) -
138                        sizeof(struct mdesc_hdr) +
139                        mdesc_size);
140
141         base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
142         if (base) {
143                 struct mdesc_handle *hp;
144                 unsigned long addr;
145
146                 addr = (unsigned long)base;
147                 addr = (addr + 15UL) & ~15UL;
148                 hp = (struct mdesc_handle *) addr;
149
150                 mdesc_handle_init(hp, handle_size, base);
151                 return hp;
152         }
153
154         return NULL;
155 }
156
157 static void mdesc_kfree(struct mdesc_handle *hp)
158 {
159         BUG_ON(atomic_read(&hp->refcnt) != 0);
160         BUG_ON(!list_empty(&hp->list));
161
162         kfree(hp->self_base);
163 }
164
165 static struct mdesc_mem_ops kmalloc_mdesc_memops = {
166         .alloc = mdesc_kmalloc,
167         .free  = mdesc_kfree,
168 };
169
170 static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
171                                         struct mdesc_mem_ops *mops)
172 {
173         struct mdesc_handle *hp = mops->alloc(mdesc_size);
174
175         if (hp)
176                 hp->mops = mops;
177
178         return hp;
179 }
180
181 static void mdesc_free(struct mdesc_handle *hp)
182 {
183         hp->mops->free(hp);
184 }
185
186 static struct mdesc_handle *cur_mdesc;
187 static LIST_HEAD(mdesc_zombie_list);
188 static DEFINE_SPINLOCK(mdesc_lock);
189
190 struct mdesc_handle *mdesc_grab(void)
191 {
192         struct mdesc_handle *hp;
193         unsigned long flags;
194
195         spin_lock_irqsave(&mdesc_lock, flags);
196         hp = cur_mdesc;
197         if (hp)
198                 atomic_inc(&hp->refcnt);
199         spin_unlock_irqrestore(&mdesc_lock, flags);
200
201         return hp;
202 }
203 EXPORT_SYMBOL(mdesc_grab);
204
205 void mdesc_release(struct mdesc_handle *hp)
206 {
207         unsigned long flags;
208
209         spin_lock_irqsave(&mdesc_lock, flags);
210         if (atomic_dec_and_test(&hp->refcnt)) {
211                 list_del_init(&hp->list);
212                 hp->mops->free(hp);
213         }
214         spin_unlock_irqrestore(&mdesc_lock, flags);
215 }
216 EXPORT_SYMBOL(mdesc_release);
217
218 static DEFINE_MUTEX(mdesc_mutex);
219 static struct mdesc_notifier_client *client_list;
220
221 void mdesc_register_notifier(struct mdesc_notifier_client *client)
222 {
223         u64 node;
224
225         mutex_lock(&mdesc_mutex);
226         client->next = client_list;
227         client_list = client;
228
229         mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
230                 client->add(cur_mdesc, node);
231
232         mutex_unlock(&mdesc_mutex);
233 }
234
235 static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
236 {
237         const u64 *id;
238         u64 a;
239
240         id = NULL;
241         mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
242                 u64 target;
243
244                 target = mdesc_arc_target(hp, a);
245                 id = mdesc_get_property(hp, target,
246                                         "cfg-handle", NULL);
247                 if (id)
248                         break;
249         }
250
251         return id;
252 }
253
254 /* Run 'func' on nodes which are in A but not in B.  */
255 static void invoke_on_missing(const char *name,
256                               struct mdesc_handle *a,
257                               struct mdesc_handle *b,
258                               void (*func)(struct mdesc_handle *, u64))
259 {
260         u64 node;
261
262         mdesc_for_each_node_by_name(a, node, name) {
263                 int found = 0, is_vdc_port = 0;
264                 const char *name_prop;
265                 const u64 *id;
266                 u64 fnode;
267
268                 name_prop = mdesc_get_property(a, node, "name", NULL);
269                 if (name_prop && !strcmp(name_prop, "vdc-port")) {
270                         is_vdc_port = 1;
271                         id = parent_cfg_handle(a, node);
272                 } else
273                         id = mdesc_get_property(a, node, "id", NULL);
274
275                 if (!id) {
276                         printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
277                                (name_prop ? name_prop : name));
278                         continue;
279                 }
280
281                 mdesc_for_each_node_by_name(b, fnode, name) {
282                         const u64 *fid;
283
284                         if (is_vdc_port) {
285                                 name_prop = mdesc_get_property(b, fnode,
286                                                                "name", NULL);
287                                 if (!name_prop ||
288                                     strcmp(name_prop, "vdc-port"))
289                                         continue;
290                                 fid = parent_cfg_handle(b, fnode);
291                                 if (!fid) {
292                                         printk(KERN_ERR "MD: Cannot find ID "
293                                                "for vdc-port node.\n");
294                                         continue;
295                                 }
296                         } else
297                                 fid = mdesc_get_property(b, fnode,
298                                                          "id", NULL);
299
300                         if (*id == *fid) {
301                                 found = 1;
302                                 break;
303                         }
304                 }
305                 if (!found)
306                         func(a, node);
307         }
308 }
309
310 static void notify_one(struct mdesc_notifier_client *p,
311                        struct mdesc_handle *old_hp,
312                        struct mdesc_handle *new_hp)
313 {
314         invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
315         invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
316 }
317
318 static void mdesc_notify_clients(struct mdesc_handle *old_hp,
319                                  struct mdesc_handle *new_hp)
320 {
321         struct mdesc_notifier_client *p = client_list;
322
323         while (p) {
324                 notify_one(p, old_hp, new_hp);
325                 p = p->next;
326         }
327 }
328
329 void mdesc_update(void)
330 {
331         unsigned long len, real_len, status;
332         struct mdesc_handle *hp, *orig_hp;
333         unsigned long flags;
334
335         mutex_lock(&mdesc_mutex);
336
337         (void) sun4v_mach_desc(0UL, 0UL, &len);
338
339         hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
340         if (!hp) {
341                 printk(KERN_ERR "MD: mdesc alloc fails\n");
342                 goto out;
343         }
344
345         status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
346         if (status != HV_EOK || real_len > len) {
347                 printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
348                        status);
349                 atomic_dec(&hp->refcnt);
350                 mdesc_free(hp);
351                 goto out;
352         }
353
354         spin_lock_irqsave(&mdesc_lock, flags);
355         orig_hp = cur_mdesc;
356         cur_mdesc = hp;
357         spin_unlock_irqrestore(&mdesc_lock, flags);
358
359         mdesc_notify_clients(orig_hp, hp);
360
361         spin_lock_irqsave(&mdesc_lock, flags);
362         if (atomic_dec_and_test(&orig_hp->refcnt))
363                 mdesc_free(orig_hp);
364         else
365                 list_add(&orig_hp->list, &mdesc_zombie_list);
366         spin_unlock_irqrestore(&mdesc_lock, flags);
367
368 out:
369         mutex_unlock(&mdesc_mutex);
370 }
371
372 static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
373 {
374         return (struct mdesc_elem *) (mdesc + 1);
375 }
376
377 static void *name_block(struct mdesc_hdr *mdesc)
378 {
379         return ((void *) node_block(mdesc)) + mdesc->node_sz;
380 }
381
382 static void *data_block(struct mdesc_hdr *mdesc)
383 {
384         return ((void *) name_block(mdesc)) + mdesc->name_sz;
385 }
386
387 u64 mdesc_node_by_name(struct mdesc_handle *hp,
388                        u64 from_node, const char *name)
389 {
390         struct mdesc_elem *ep = node_block(&hp->mdesc);
391         const char *names = name_block(&hp->mdesc);
392         u64 last_node = hp->mdesc.node_sz / 16;
393         u64 ret;
394
395         if (from_node == MDESC_NODE_NULL) {
396                 ret = from_node = 0;
397         } else if (from_node >= last_node) {
398                 return MDESC_NODE_NULL;
399         } else {
400                 ret = ep[from_node].d.val;
401         }
402
403         while (ret < last_node) {
404                 if (ep[ret].tag != MD_NODE)
405                         return MDESC_NODE_NULL;
406                 if (!strcmp(names + ep[ret].name_offset, name))
407                         break;
408                 ret = ep[ret].d.val;
409         }
410         if (ret >= last_node)
411                 ret = MDESC_NODE_NULL;
412         return ret;
413 }
414 EXPORT_SYMBOL(mdesc_node_by_name);
415
416 const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
417                                const char *name, int *lenp)
418 {
419         const char *names = name_block(&hp->mdesc);
420         u64 last_node = hp->mdesc.node_sz / 16;
421         void *data = data_block(&hp->mdesc);
422         struct mdesc_elem *ep;
423
424         if (node == MDESC_NODE_NULL || node >= last_node)
425                 return NULL;
426
427         ep = node_block(&hp->mdesc) + node;
428         ep++;
429         for (; ep->tag != MD_NODE_END; ep++) {
430                 void *val = NULL;
431                 int len = 0;
432
433                 switch (ep->tag) {
434                 case MD_PROP_VAL:
435                         val = &ep->d.val;
436                         len = 8;
437                         break;
438
439                 case MD_PROP_STR:
440                 case MD_PROP_DATA:
441                         val = data + ep->d.data.data_offset;
442                         len = ep->d.data.data_len;
443                         break;
444
445                 default:
446                         break;
447                 }
448                 if (!val)
449                         continue;
450
451                 if (!strcmp(names + ep->name_offset, name)) {
452                         if (lenp)
453                                 *lenp = len;
454                         return val;
455                 }
456         }
457
458         return NULL;
459 }
460 EXPORT_SYMBOL(mdesc_get_property);
461
462 u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
463 {
464         struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
465         const char *names = name_block(&hp->mdesc);
466         u64 last_node = hp->mdesc.node_sz / 16;
467
468         if (from == MDESC_NODE_NULL || from >= last_node)
469                 return MDESC_NODE_NULL;
470
471         ep = base + from;
472
473         ep++;
474         for (; ep->tag != MD_NODE_END; ep++) {
475                 if (ep->tag != MD_PROP_ARC)
476                         continue;
477
478                 if (strcmp(names + ep->name_offset, arc_type))
479                         continue;
480
481                 return ep - base;
482         }
483
484         return MDESC_NODE_NULL;
485 }
486 EXPORT_SYMBOL(mdesc_next_arc);
487
488 u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
489 {
490         struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
491
492         ep = base + arc;
493
494         return ep->d.val;
495 }
496 EXPORT_SYMBOL(mdesc_arc_target);
497
498 const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
499 {
500         struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
501         const char *names = name_block(&hp->mdesc);
502         u64 last_node = hp->mdesc.node_sz / 16;
503
504         if (node == MDESC_NODE_NULL || node >= last_node)
505                 return NULL;
506
507         ep = base + node;
508         if (ep->tag != MD_NODE)
509                 return NULL;
510
511         return names + ep->name_offset;
512 }
513 EXPORT_SYMBOL(mdesc_node_name);
514
515 static void __init report_platform_properties(void)
516 {
517         struct mdesc_handle *hp = mdesc_grab();
518         u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
519         const char *s;
520         const u64 *v;
521
522         if (pn == MDESC_NODE_NULL) {
523                 prom_printf("No platform node in machine-description.\n");
524                 prom_halt();
525         }
526
527         s = mdesc_get_property(hp, pn, "banner-name", NULL);
528         printk("PLATFORM: banner-name [%s]\n", s);
529         s = mdesc_get_property(hp, pn, "name", NULL);
530         printk("PLATFORM: name [%s]\n", s);
531
532         v = mdesc_get_property(hp, pn, "hostid", NULL);
533         if (v)
534                 printk("PLATFORM: hostid [%08lx]\n", *v);
535         v = mdesc_get_property(hp, pn, "serial#", NULL);
536         if (v)
537                 printk("PLATFORM: serial# [%08lx]\n", *v);
538         v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
539         printk("PLATFORM: stick-frequency [%08lx]\n", *v);
540         v = mdesc_get_property(hp, pn, "mac-address", NULL);
541         if (v)
542                 printk("PLATFORM: mac-address [%lx]\n", *v);
543         v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
544         if (v)
545                 printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
546         v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
547         if (v)
548                 printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
549         v = mdesc_get_property(hp, pn, "max-cpus", NULL);
550         if (v)
551                 printk("PLATFORM: max-cpus [%lu]\n", *v);
552
553 #ifdef CONFIG_SMP
554         {
555                 int max_cpu, i;
556
557                 if (v) {
558                         max_cpu = *v;
559                         if (max_cpu > NR_CPUS)
560                                 max_cpu = NR_CPUS;
561                 } else {
562                         max_cpu = NR_CPUS;
563                 }
564                 for (i = 0; i < max_cpu; i++)
565                         cpu_set(i, cpu_possible_map);
566         }
567 #endif
568
569         mdesc_release(hp);
570 }
571
572 static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
573                                         struct mdesc_handle *hp,
574                                         u64 mp)
575 {
576         const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
577         const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
578         const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
579         const char *type;
580         int type_len;
581
582         type = mdesc_get_property(hp, mp, "type", &type_len);
583
584         switch (*level) {
585         case 1:
586                 if (of_find_in_proplist(type, "instn", type_len)) {
587                         c->icache_size = *size;
588                         c->icache_line_size = *line_size;
589                 } else if (of_find_in_proplist(type, "data", type_len)) {
590                         c->dcache_size = *size;
591                         c->dcache_line_size = *line_size;
592                 }
593                 break;
594
595         case 2:
596                 c->ecache_size = *size;
597                 c->ecache_line_size = *line_size;
598                 break;
599
600         default:
601                 break;
602         }
603
604         if (*level == 1) {
605                 u64 a;
606
607                 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
608                         u64 target = mdesc_arc_target(hp, a);
609                         const char *name = mdesc_node_name(hp, target);
610
611                         if (!strcmp(name, "cache"))
612                                 fill_in_one_cache(c, hp, target);
613                 }
614         }
615 }
616
617 static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
618                                     int core_id)
619 {
620         u64 a;
621
622         mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
623                 u64 t = mdesc_arc_target(hp, a);
624                 const char *name;
625                 const u64 *id;
626
627                 name = mdesc_node_name(hp, t);
628                 if (!strcmp(name, "cpu")) {
629                         id = mdesc_get_property(hp, t, "id", NULL);
630                         if (*id < NR_CPUS)
631                                 cpu_data(*id).core_id = core_id;
632                 } else {
633                         u64 j;
634
635                         mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
636                                 u64 n = mdesc_arc_target(hp, j);
637                                 const char *n_name;
638
639                                 n_name = mdesc_node_name(hp, n);
640                                 if (strcmp(n_name, "cpu"))
641                                         continue;
642
643                                 id = mdesc_get_property(hp, n, "id", NULL);
644                                 if (*id < NR_CPUS)
645                                         cpu_data(*id).core_id = core_id;
646                         }
647                 }
648         }
649 }
650
651 static void __devinit set_core_ids(struct mdesc_handle *hp)
652 {
653         int idx;
654         u64 mp;
655
656         idx = 1;
657         mdesc_for_each_node_by_name(hp, mp, "cache") {
658                 const u64 *level;
659                 const char *type;
660                 int len;
661
662                 level = mdesc_get_property(hp, mp, "level", NULL);
663                 if (*level != 1)
664                         continue;
665
666                 type = mdesc_get_property(hp, mp, "type", &len);
667                 if (!of_find_in_proplist(type, "instn", len))
668                         continue;
669
670                 mark_core_ids(hp, mp, idx);
671
672                 idx++;
673         }
674 }
675
676 static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
677                                     int proc_id)
678 {
679         u64 a;
680
681         mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
682                 u64 t = mdesc_arc_target(hp, a);
683                 const char *name;
684                 const u64 *id;
685
686                 name = mdesc_node_name(hp, t);
687                 if (strcmp(name, "cpu"))
688                         continue;
689
690                 id = mdesc_get_property(hp, t, "id", NULL);
691                 if (*id < NR_CPUS)
692                         cpu_data(*id).proc_id = proc_id;
693         }
694 }
695
696 static void __devinit __set_proc_ids(struct mdesc_handle *hp,
697                                      const char *exec_unit_name)
698 {
699         int idx;
700         u64 mp;
701
702         idx = 0;
703         mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
704                 const char *type;
705                 int len;
706
707                 type = mdesc_get_property(hp, mp, "type", &len);
708                 if (!of_find_in_proplist(type, "int", len) &&
709                     !of_find_in_proplist(type, "integer", len))
710                         continue;
711
712                 mark_proc_ids(hp, mp, idx);
713
714                 idx++;
715         }
716 }
717
718 static void __devinit set_proc_ids(struct mdesc_handle *hp)
719 {
720         __set_proc_ids(hp, "exec_unit");
721         __set_proc_ids(hp, "exec-unit");
722 }
723
724 static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
725                                          unsigned char def)
726 {
727         u64 val;
728
729         if (!p)
730                 goto use_default;
731         val = *p;
732
733         if (!val || val >= 64)
734                 goto use_default;
735
736         *mask = ((1U << val) * 64U) - 1U;
737         return;
738
739 use_default:
740         *mask = ((1U << def) * 64U) - 1U;
741 }
742
743 static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
744                                      struct trap_per_cpu *tb)
745 {
746         const u64 *val;
747
748         val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
749         get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
750
751         val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
752         get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
753
754         val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
755         get_one_mondo_bits(val, &tb->resum_qmask, 6);
756
757         val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
758         get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
759 }
760
761 void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
762 {
763         struct mdesc_handle *hp = mdesc_grab();
764         u64 mp;
765
766         ncpus_probed = 0;
767         mdesc_for_each_node_by_name(hp, mp, "cpu") {
768                 const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
769                 const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
770                 struct trap_per_cpu *tb;
771                 cpuinfo_sparc *c;
772                 int cpuid;
773                 u64 a;
774
775                 ncpus_probed++;
776
777                 cpuid = *id;
778
779 #ifdef CONFIG_SMP
780                 if (cpuid >= NR_CPUS) {
781                         printk(KERN_WARNING "Ignoring CPU %d which is "
782                                ">= NR_CPUS (%d)\n",
783                                cpuid, NR_CPUS);
784                         continue;
785                 }
786                 if (!cpu_isset(cpuid, mask))
787                         continue;
788 #else
789                 /* On uniprocessor we only want the values for the
790                  * real physical cpu the kernel booted onto, however
791                  * cpu_data() only has one entry at index 0.
792                  */
793                 if (cpuid != real_hard_smp_processor_id())
794                         continue;
795                 cpuid = 0;
796 #endif
797
798                 c = &cpu_data(cpuid);
799                 c->clock_tick = *cfreq;
800
801                 tb = &trap_block[cpuid];
802                 get_mondo_data(hp, mp, tb);
803
804                 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
805                         u64 j, t = mdesc_arc_target(hp, a);
806                         const char *t_name;
807
808                         t_name = mdesc_node_name(hp, t);
809                         if (!strcmp(t_name, "cache")) {
810                                 fill_in_one_cache(c, hp, t);
811                                 continue;
812                         }
813
814                         mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
815                                 u64 n = mdesc_arc_target(hp, j);
816                                 const char *n_name;
817
818                                 n_name = mdesc_node_name(hp, n);
819                                 if (!strcmp(n_name, "cache"))
820                                         fill_in_one_cache(c, hp, n);
821                         }
822                 }
823
824 #ifdef CONFIG_SMP
825                 cpu_set(cpuid, cpu_present_map);
826 #endif
827
828                 c->core_id = 0;
829                 c->proc_id = -1;
830         }
831
832 #ifdef CONFIG_SMP
833         sparc64_multi_core = 1;
834 #endif
835
836         set_core_ids(hp);
837         set_proc_ids(hp);
838
839         smp_fill_in_sib_core_maps();
840
841         mdesc_release(hp);
842 }
843
844 static ssize_t mdesc_read(struct file *file, char __user *buf,
845                           size_t len, loff_t *offp)
846 {
847         struct mdesc_handle *hp = mdesc_grab();
848         int err;
849
850         if (!hp)
851                 return -ENODEV;
852
853         err = hp->handle_size;
854         if (len < hp->handle_size)
855                 err = -EMSGSIZE;
856         else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
857                 err = -EFAULT;
858         mdesc_release(hp);
859
860         return err;
861 }
862
863 static const struct file_operations mdesc_fops = {
864         .read   = mdesc_read,
865         .owner  = THIS_MODULE,
866 };
867
868 static struct miscdevice mdesc_misc = {
869         .minor  = MISC_DYNAMIC_MINOR,
870         .name   = "mdesc",
871         .fops   = &mdesc_fops,
872 };
873
874 static int __init mdesc_misc_init(void)
875 {
876         return misc_register(&mdesc_misc);
877 }
878
879 __initcall(mdesc_misc_init);
880
881 void __init sun4v_mdesc_init(void)
882 {
883         struct mdesc_handle *hp;
884         unsigned long len, real_len, status;
885         cpumask_t mask;
886
887         (void) sun4v_mach_desc(0UL, 0UL, &len);
888
889         printk("MDESC: Size is %lu bytes.\n", len);
890
891         hp = mdesc_alloc(len, &bootmem_mdesc_ops);
892         if (hp == NULL) {
893                 prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
894                 prom_halt();
895         }
896
897         status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
898         if (status != HV_EOK || real_len > len) {
899                 prom_printf("sun4v_mach_desc fails, err(%lu), "
900                             "len(%lu), real_len(%lu)\n",
901                             status, len, real_len);
902                 mdesc_free(hp);
903                 prom_halt();
904         }
905
906         cur_mdesc = hp;
907
908         report_platform_properties();
909
910         cpus_setall(mask);
911         mdesc_fill_in_cpu_data(mask);
912 }