aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/mdesc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/mdesc.c')
-rw-r--r--arch/sparc64/kernel/mdesc.c666
1 files changed, 370 insertions, 296 deletions
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index f0e16045fb16..9e5088d563cc 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -6,6 +6,8 @@
6#include <linux/types.h> 6#include <linux/types.h>
7#include <linux/bootmem.h> 7#include <linux/bootmem.h>
8#include <linux/log2.h> 8#include <linux/log2.h>
9#include <linux/list.h>
10#include <linux/slab.h>
9 11
10#include <asm/hypervisor.h> 12#include <asm/hypervisor.h>
11#include <asm/mdesc.h> 13#include <asm/mdesc.h>
@@ -29,7 +31,7 @@ struct mdesc_hdr {
29 u32 node_sz; /* node block size */ 31 u32 node_sz; /* node block size */
30 u32 name_sz; /* name block size */ 32 u32 name_sz; /* name block size */
31 u32 data_sz; /* data block size */ 33 u32 data_sz; /* data block size */
32}; 34} __attribute__((aligned(16)));
33 35
34struct mdesc_elem { 36struct mdesc_elem {
35 u8 tag; 37 u8 tag;
@@ -53,306 +55,386 @@ struct mdesc_elem {
53 } d; 55 } d;
54}; 56};
55 57
56static struct mdesc_hdr *main_mdesc; 58struct mdesc_mem_ops {
57static struct mdesc_node *allnodes; 59 struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
58 60 void (*free)(struct mdesc_handle *handle);
59static struct mdesc_node *allnodes_tail; 61};
60static unsigned int unique_id;
61 62
62static struct mdesc_node **mdesc_hash; 63struct mdesc_handle {
63static unsigned int mdesc_hash_size; 64 struct list_head list;
65 struct mdesc_mem_ops *mops;
66 void *self_base;
67 atomic_t refcnt;
68 unsigned int handle_size;
69 struct mdesc_hdr mdesc;
70};
64 71
65static inline unsigned int node_hashfn(u64 node) 72static void mdesc_handle_init(struct mdesc_handle *hp,
73 unsigned int handle_size,
74 void *base)
66{ 75{
67 return ((unsigned int) (node ^ (node >> 8) ^ (node >> 16))) 76 BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
68 & (mdesc_hash_size - 1); 77
78 memset(hp, 0, handle_size);
79 INIT_LIST_HEAD(&hp->list);
80 hp->self_base = base;
81 atomic_set(&hp->refcnt, 1);
82 hp->handle_size = handle_size;
69} 83}
70 84
71static inline void hash_node(struct mdesc_node *mp) 85static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
72{ 86{
73 struct mdesc_node **head = &mdesc_hash[node_hashfn(mp->node)]; 87 struct mdesc_handle *hp;
88 unsigned int handle_size, alloc_size;
74 89
75 mp->hash_next = *head; 90 handle_size = (sizeof(struct mdesc_handle) -
76 *head = mp; 91 sizeof(struct mdesc_hdr) +
92 mdesc_size);
93 alloc_size = PAGE_ALIGN(handle_size);
77 94
78 if (allnodes_tail) { 95 hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
79 allnodes_tail->allnodes_next = mp; 96 if (hp)
80 allnodes_tail = mp; 97 mdesc_handle_init(hp, handle_size, hp);
81 } else { 98
82 allnodes = allnodes_tail = mp; 99 return hp;
83 }
84} 100}
85 101
86static struct mdesc_node *find_node(u64 node) 102static void mdesc_bootmem_free(struct mdesc_handle *hp)
87{ 103{
88 struct mdesc_node *mp = mdesc_hash[node_hashfn(node)]; 104 unsigned int alloc_size, handle_size = hp->handle_size;
105 unsigned long start, end;
89 106
90 while (mp) { 107 BUG_ON(atomic_read(&hp->refcnt) != 0);
91 if (mp->node == node) 108 BUG_ON(!list_empty(&hp->list));
92 return mp;
93 109
94 mp = mp->hash_next; 110 alloc_size = PAGE_ALIGN(handle_size);
111
112 start = (unsigned long) hp;
113 end = start + alloc_size;
114
115 while (start < end) {
116 struct page *p;
117
118 p = virt_to_page(start);
119 ClearPageReserved(p);
120 __free_page(p);
121 start += PAGE_SIZE;
95 } 122 }
96 return NULL;
97} 123}
98 124
99struct property *md_find_property(const struct mdesc_node *mp, 125static struct mdesc_mem_ops bootmem_mdesc_memops = {
100 const char *name, 126 .alloc = mdesc_bootmem_alloc,
101 int *lenp) 127 .free = mdesc_bootmem_free,
128};
129
130static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
102{ 131{
103 struct property *pp; 132 unsigned int handle_size;
133 void *base;
104 134
105 for (pp = mp->properties; pp != 0; pp = pp->next) { 135 handle_size = (sizeof(struct mdesc_handle) -
106 if (strcasecmp(pp->name, name) == 0) { 136 sizeof(struct mdesc_hdr) +
107 if (lenp) 137 mdesc_size);
108 *lenp = pp->length; 138
109 break; 139 base = kmalloc(handle_size + 15, GFP_KERNEL);
110 } 140 if (base) {
141 struct mdesc_handle *hp;
142 unsigned long addr;
143
144 addr = (unsigned long)base;
145 addr = (addr + 15UL) & ~15UL;
146 hp = (struct mdesc_handle *) addr;
147
148 mdesc_handle_init(hp, handle_size, base);
149 return hp;
111 } 150 }
112 return pp; 151
152 return NULL;
113} 153}
114EXPORT_SYMBOL(md_find_property);
115 154
116/* 155static void mdesc_kfree(struct mdesc_handle *hp)
117 * Find a property with a given name for a given node
118 * and return the value.
119 */
120const void *md_get_property(const struct mdesc_node *mp, const char *name,
121 int *lenp)
122{ 156{
123 struct property *pp = md_find_property(mp, name, lenp); 157 BUG_ON(atomic_read(&hp->refcnt) != 0);
124 return pp ? pp->value : NULL; 158 BUG_ON(!list_empty(&hp->list));
159
160 kfree(hp->self_base);
125} 161}
126EXPORT_SYMBOL(md_get_property);
127 162
128struct mdesc_node *md_find_node_by_name(struct mdesc_node *from, 163static struct mdesc_mem_ops kmalloc_mdesc_memops = {
129 const char *name) 164 .alloc = mdesc_kmalloc,
165 .free = mdesc_kfree,
166};
167
168static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
169 struct mdesc_mem_ops *mops)
130{ 170{
131 struct mdesc_node *mp; 171 struct mdesc_handle *hp = mops->alloc(mdesc_size);
132 172
133 mp = from ? from->allnodes_next : allnodes; 173 if (hp)
134 for (; mp != NULL; mp = mp->allnodes_next) { 174 hp->mops = mops;
135 if (strcmp(mp->name, name) == 0)
136 break;
137 }
138 return mp;
139}
140EXPORT_SYMBOL(md_find_node_by_name);
141 175
142static unsigned int mdesc_early_allocated; 176 return hp;
177}
143 178
144static void * __init mdesc_early_alloc(unsigned long size) 179static void mdesc_free(struct mdesc_handle *hp)
145{ 180{
146 void *ret; 181 hp->mops->free(hp);
182}
147 183
148 ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); 184static struct mdesc_handle *cur_mdesc;
149 if (ret == NULL) { 185static LIST_HEAD(mdesc_zombie_list);
150 prom_printf("MDESC: alloc of %lu bytes failed.\n", size); 186static DEFINE_SPINLOCK(mdesc_lock);
151 prom_halt();
152 }
153 187
154 memset(ret, 0, size); 188struct mdesc_handle *mdesc_grab(void)
189{
190 struct mdesc_handle *hp;
191 unsigned long flags;
155 192
156 mdesc_early_allocated += size; 193 spin_lock_irqsave(&mdesc_lock, flags);
194 hp = cur_mdesc;
195 if (hp)
196 atomic_inc(&hp->refcnt);
197 spin_unlock_irqrestore(&mdesc_lock, flags);
157 198
158 return ret; 199 return hp;
159} 200}
201EXPORT_SYMBOL(mdesc_grab);
160 202
161static unsigned int __init count_arcs(struct mdesc_elem *ep) 203void mdesc_release(struct mdesc_handle *hp)
162{ 204{
163 unsigned int ret = 0; 205 unsigned long flags;
164 206
165 ep++; 207 spin_lock_irqsave(&mdesc_lock, flags);
166 while (ep->tag != MD_NODE_END) { 208 if (atomic_dec_and_test(&hp->refcnt)) {
167 if (ep->tag == MD_PROP_ARC) 209 list_del_init(&hp->list);
168 ret++; 210 hp->mops->free(hp);
169 ep++;
170 } 211 }
171 return ret; 212 spin_unlock_irqrestore(&mdesc_lock, flags);
172} 213}
214EXPORT_SYMBOL(mdesc_release);
173 215
174static void __init mdesc_node_alloc(u64 node, struct mdesc_elem *ep, const char *names) 216static void do_mdesc_update(struct work_struct *work)
175{ 217{
176 unsigned int num_arcs = count_arcs(ep); 218 unsigned long len, real_len, status;
177 struct mdesc_node *mp; 219 struct mdesc_handle *hp, *orig_hp;
220 unsigned long flags;
221
222 (void) sun4v_mach_desc(0UL, 0UL, &len);
223
224 hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
225 if (!hp) {
226 printk(KERN_ERR "MD: mdesc alloc fails\n");
227 return;
228 }
229
230 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
231 if (status != HV_EOK || real_len > len) {
232 printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
233 status);
234 atomic_dec(&hp->refcnt);
235 mdesc_free(hp);
236 return;
237 }
178 238
179 mp = mdesc_early_alloc(sizeof(*mp) + 239 spin_lock_irqsave(&mdesc_lock, flags);
180 (num_arcs * sizeof(struct mdesc_arc))); 240 orig_hp = cur_mdesc;
181 mp->name = names + ep->name_offset; 241 cur_mdesc = hp;
182 mp->node = node;
183 mp->unique_id = unique_id++;
184 mp->num_arcs = num_arcs;
185 242
186 hash_node(mp); 243 if (atomic_dec_and_test(&orig_hp->refcnt))
244 mdesc_free(orig_hp);
245 else
246 list_add(&orig_hp->list, &mdesc_zombie_list);
247 spin_unlock_irqrestore(&mdesc_lock, flags);
187} 248}
188 249
189static inline struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) 250static DECLARE_WORK(mdesc_update_work, do_mdesc_update);
251
252void mdesc_update(void)
253{
254 schedule_work(&mdesc_update_work);
255}
256
257static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
190{ 258{
191 return (struct mdesc_elem *) (mdesc + 1); 259 return (struct mdesc_elem *) (mdesc + 1);
192} 260}
193 261
194static inline void *name_block(struct mdesc_hdr *mdesc) 262static void *name_block(struct mdesc_hdr *mdesc)
195{ 263{
196 return ((void *) node_block(mdesc)) + mdesc->node_sz; 264 return ((void *) node_block(mdesc)) + mdesc->node_sz;
197} 265}
198 266
199static inline void *data_block(struct mdesc_hdr *mdesc) 267static void *data_block(struct mdesc_hdr *mdesc)
200{ 268{
201 return ((void *) name_block(mdesc)) + mdesc->name_sz; 269 return ((void *) name_block(mdesc)) + mdesc->name_sz;
202} 270}
203 271
204/* In order to avoid recursion (the graph can be very deep) we use a 272u64 mdesc_node_by_name(struct mdesc_handle *hp,
205 * two pass algorithm. First we allocate all the nodes and hash them. 273 u64 from_node, const char *name)
206 * Then we iterate over each node, filling in the arcs and properties.
207 */
208static void __init build_all_nodes(struct mdesc_hdr *mdesc)
209{ 274{
210 struct mdesc_elem *start, *ep; 275 struct mdesc_elem *ep = node_block(&hp->mdesc);
211 struct mdesc_node *mp; 276 const char *names = name_block(&hp->mdesc);
212 const char *names; 277 u64 last_node = hp->mdesc.node_sz / 16;
213 void *data; 278 u64 ret;
214 u64 last_node; 279
215 280 if (from_node == MDESC_NODE_NULL)
216 start = ep = node_block(mdesc); 281 from_node = 0;
217 last_node = mdesc->node_sz / 16; 282
283 if (from_node >= last_node)
284 return MDESC_NODE_NULL;
285
286 ret = ep[from_node].d.val;
287 while (ret < last_node) {
288 if (ep[ret].tag != MD_NODE)
289 return MDESC_NODE_NULL;
290 if (!strcmp(names + ep[ret].name_offset, name))
291 break;
292 ret = ep[ret].d.val;
293 }
294 if (ret >= last_node)
295 ret = MDESC_NODE_NULL;
296 return ret;
297}
298EXPORT_SYMBOL(mdesc_node_by_name);
218 299
219 names = name_block(mdesc); 300const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
301 const char *name, int *lenp)
302{
303 const char *names = name_block(&hp->mdesc);
304 u64 last_node = hp->mdesc.node_sz / 16;
305 void *data = data_block(&hp->mdesc);
306 struct mdesc_elem *ep;
220 307
221 while (1) { 308 if (node == MDESC_NODE_NULL || node >= last_node)
222 u64 node = ep - start; 309 return NULL;
223 310
224 if (ep->tag == MD_LIST_END) 311 ep = node_block(&hp->mdesc) + node;
312 ep++;
313 for (; ep->tag != MD_NODE_END; ep++) {
314 void *val = NULL;
315 int len = 0;
316
317 switch (ep->tag) {
318 case MD_PROP_VAL:
319 val = &ep->d.val;
320 len = 8;
225 break; 321 break;
226 322
227 if (ep->tag != MD_NODE) { 323 case MD_PROP_STR:
228 prom_printf("MDESC: Inconsistent element list.\n"); 324 case MD_PROP_DATA:
229 prom_halt(); 325 val = data + ep->d.data.data_offset;
230 } 326 len = ep->d.data.data_len;
231 327 break;
232 mdesc_node_alloc(node, ep, names);
233 328
234 if (ep->d.val >= last_node) { 329 default:
235 printk("MDESC: Warning, early break out of node scan.\n");
236 printk("MDESC: Next node [%lu] last_node [%lu].\n",
237 node, last_node);
238 break; 330 break;
239 } 331 }
332 if (!val)
333 continue;
240 334
241 ep = start + ep->d.val; 335 if (!strcmp(names + ep->name_offset, name)) {
336 if (lenp)
337 *lenp = len;
338 return val;
339 }
242 } 340 }
243 341
244 data = data_block(mdesc); 342 return NULL;
245 for (mp = allnodes; mp; mp = mp->allnodes_next) { 343}
246 struct mdesc_elem *ep = start + mp->node; 344EXPORT_SYMBOL(mdesc_get_property);
247 struct property **link = &mp->properties;
248 unsigned int this_arc = 0;
249
250 ep++;
251 while (ep->tag != MD_NODE_END) {
252 switch (ep->tag) {
253 case MD_PROP_ARC: {
254 struct mdesc_node *target;
255
256 if (this_arc >= mp->num_arcs) {
257 prom_printf("MDESC: ARC overrun [%u:%u]\n",
258 this_arc, mp->num_arcs);
259 prom_halt();
260 }
261 target = find_node(ep->d.val);
262 if (!target) {
263 printk("MDESC: Warning, arc points to "
264 "missing node, ignoring.\n");
265 break;
266 }
267 mp->arcs[this_arc].name =
268 (names + ep->name_offset);
269 mp->arcs[this_arc].arc = target;
270 this_arc++;
271 break;
272 }
273 345
274 case MD_PROP_VAL: 346u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
275 case MD_PROP_STR: 347{
276 case MD_PROP_DATA: { 348 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
277 struct property *p = mdesc_early_alloc(sizeof(*p)); 349 const char *names = name_block(&hp->mdesc);
278 350 u64 last_node = hp->mdesc.node_sz / 16;
279 p->unique_id = unique_id++;
280 p->name = (char *) names + ep->name_offset;
281 if (ep->tag == MD_PROP_VAL) {
282 p->value = &ep->d.val;
283 p->length = 8;
284 } else {
285 p->value = data + ep->d.data.data_offset;
286 p->length = ep->d.data.data_len;
287 }
288 *link = p;
289 link = &p->next;
290 break;
291 }
292 351
293 case MD_NOOP: 352 if (from == MDESC_NODE_NULL || from >= last_node)
294 break; 353 return MDESC_NODE_NULL;
295 354
296 default: 355 ep = base + from;
297 printk("MDESC: Warning, ignoring unknown tag type %02x\n", 356
298 ep->tag); 357 ep++;
299 } 358 for (; ep->tag != MD_NODE_END; ep++) {
300 ep++; 359 if (ep->tag != MD_PROP_ARC)
301 } 360 continue;
361
362 if (strcmp(names + ep->name_offset, arc_type))
363 continue;
364
365 return ep - base;
302 } 366 }
367
368 return MDESC_NODE_NULL;
303} 369}
370EXPORT_SYMBOL(mdesc_next_arc);
304 371
305static unsigned int __init count_nodes(struct mdesc_hdr *mdesc) 372u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
306{ 373{
307 struct mdesc_elem *ep = node_block(mdesc); 374 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
308 struct mdesc_elem *end; 375
309 unsigned int cnt = 0; 376 ep = base + arc;
310 377
311 end = ((void *)ep) + mdesc->node_sz; 378 return ep->d.val;
312 while (ep < end) {
313 if (ep->tag == MD_NODE)
314 cnt++;
315 ep++;
316 }
317 return cnt;
318} 379}
380EXPORT_SYMBOL(mdesc_arc_target);
381
382const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
383{
384 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
385 const char *names = name_block(&hp->mdesc);
386 u64 last_node = hp->mdesc.node_sz / 16;
387
388 if (node == MDESC_NODE_NULL || node >= last_node)
389 return NULL;
390
391 ep = base + node;
392 if (ep->tag != MD_NODE)
393 return NULL;
394
395 return names + ep->name_offset;
396}
397EXPORT_SYMBOL(mdesc_node_name);
319 398
320static void __init report_platform_properties(void) 399static void __init report_platform_properties(void)
321{ 400{
322 struct mdesc_node *pn = md_find_node_by_name(NULL, "platform"); 401 struct mdesc_handle *hp = mdesc_grab();
402 u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
323 const char *s; 403 const char *s;
324 const u64 *v; 404 const u64 *v;
325 405
326 if (!pn) { 406 if (pn == MDESC_NODE_NULL) {
327 prom_printf("No platform node in machine-description.\n"); 407 prom_printf("No platform node in machine-description.\n");
328 prom_halt(); 408 prom_halt();
329 } 409 }
330 410
331 s = md_get_property(pn, "banner-name", NULL); 411 s = mdesc_get_property(hp, pn, "banner-name", NULL);
332 printk("PLATFORM: banner-name [%s]\n", s); 412 printk("PLATFORM: banner-name [%s]\n", s);
333 s = md_get_property(pn, "name", NULL); 413 s = mdesc_get_property(hp, pn, "name", NULL);
334 printk("PLATFORM: name [%s]\n", s); 414 printk("PLATFORM: name [%s]\n", s);
335 415
336 v = md_get_property(pn, "hostid", NULL); 416 v = mdesc_get_property(hp, pn, "hostid", NULL);
337 if (v) 417 if (v)
338 printk("PLATFORM: hostid [%08lx]\n", *v); 418 printk("PLATFORM: hostid [%08lx]\n", *v);
339 v = md_get_property(pn, "serial#", NULL); 419 v = mdesc_get_property(hp, pn, "serial#", NULL);
340 if (v) 420 if (v)
341 printk("PLATFORM: serial# [%08lx]\n", *v); 421 printk("PLATFORM: serial# [%08lx]\n", *v);
342 v = md_get_property(pn, "stick-frequency", NULL); 422 v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
343 printk("PLATFORM: stick-frequency [%08lx]\n", *v); 423 printk("PLATFORM: stick-frequency [%08lx]\n", *v);
344 v = md_get_property(pn, "mac-address", NULL); 424 v = mdesc_get_property(hp, pn, "mac-address", NULL);
345 if (v) 425 if (v)
346 printk("PLATFORM: mac-address [%lx]\n", *v); 426 printk("PLATFORM: mac-address [%lx]\n", *v);
347 v = md_get_property(pn, "watchdog-resolution", NULL); 427 v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
348 if (v) 428 if (v)
349 printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v); 429 printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
350 v = md_get_property(pn, "watchdog-max-timeout", NULL); 430 v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
351 if (v) 431 if (v)
352 printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v); 432 printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
353 v = md_get_property(pn, "max-cpus", NULL); 433 v = mdesc_get_property(hp, pn, "max-cpus", NULL);
354 if (v) 434 if (v)
355 printk("PLATFORM: max-cpus [%lu]\n", *v); 435 printk("PLATFORM: max-cpus [%lu]\n", *v);
436
437 mdesc_release(hp);
356} 438}
357 439
358static int inline find_in_proplist(const char *list, const char *match, int len) 440static int inline find_in_proplist(const char *list, const char *match, int len)
@@ -369,15 +451,17 @@ static int inline find_in_proplist(const char *list, const char *match, int len)
369 return 0; 451 return 0;
370} 452}
371 453
372static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp) 454static void __init fill_in_one_cache(cpuinfo_sparc *c,
455 struct mdesc_handle *hp,
456 u64 mp)
373{ 457{
374 const u64 *level = md_get_property(mp, "level", NULL); 458 const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
375 const u64 *size = md_get_property(mp, "size", NULL); 459 const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
376 const u64 *line_size = md_get_property(mp, "line-size", NULL); 460 const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
377 const char *type; 461 const char *type;
378 int type_len; 462 int type_len;
379 463
380 type = md_get_property(mp, "type", &type_len); 464 type = mdesc_get_property(hp, mp, "type", &type_len);
381 465
382 switch (*level) { 466 switch (*level) {
383 case 1: 467 case 1:
@@ -400,48 +484,44 @@ static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp)
400 } 484 }
401 485
402 if (*level == 1) { 486 if (*level == 1) {
403 unsigned int i; 487 u64 a;
404 488
405 for (i = 0; i < mp->num_arcs; i++) { 489 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
406 struct mdesc_node *t = mp->arcs[i].arc; 490 u64 target = mdesc_arc_target(hp, a);
491 const char *name = mdesc_node_name(hp, target);
407 492
408 if (strcmp(mp->arcs[i].name, "fwd")) 493 if (!strcmp(name, "cache"))
409 continue; 494 fill_in_one_cache(c, hp, target);
410
411 if (!strcmp(t->name, "cache"))
412 fill_in_one_cache(c, t);
413 } 495 }
414 } 496 }
415} 497}
416 498
417static void __init mark_core_ids(struct mdesc_node *mp, int core_id) 499static void __init mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
418{ 500{
419 unsigned int i; 501 u64 a;
420 502
421 for (i = 0; i < mp->num_arcs; i++) { 503 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
422 struct mdesc_node *t = mp->arcs[i].arc; 504 u64 t = mdesc_arc_target(hp, a);
505 const char *name;
423 const u64 *id; 506 const u64 *id;
424 507
425 if (strcmp(mp->arcs[i].name, "back")) 508 name = mdesc_node_name(hp, t);
426 continue; 509 if (!strcmp(name, "cpu")) {
427 510 id = mdesc_get_property(hp, t, "id", NULL);
428 if (!strcmp(t->name, "cpu")) {
429 id = md_get_property(t, "id", NULL);
430 if (*id < NR_CPUS) 511 if (*id < NR_CPUS)
431 cpu_data(*id).core_id = core_id; 512 cpu_data(*id).core_id = core_id;
432 } else { 513 } else {
433 unsigned int j; 514 u64 j;
434 515
435 for (j = 0; j < t->num_arcs; j++) { 516 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
436 struct mdesc_node *n = t->arcs[j].arc; 517 u64 n = mdesc_arc_target(hp, j);
518 const char *n_name;
437 519
438 if (strcmp(t->arcs[j].name, "back")) 520 n_name = mdesc_node_name(hp, n);
521 if (strcmp(n_name, "cpu"))
439 continue; 522 continue;
440 523
441 if (strcmp(n->name, "cpu")) 524 id = mdesc_get_property(hp, n, "id", NULL);
442 continue;
443
444 id = md_get_property(n, "id", NULL);
445 if (*id < NR_CPUS) 525 if (*id < NR_CPUS)
446 cpu_data(*id).core_id = core_id; 526 cpu_data(*id).core_id = core_id;
447 } 527 }
@@ -449,75 +529,76 @@ static void __init mark_core_ids(struct mdesc_node *mp, int core_id)
449 } 529 }
450} 530}
451 531
452static void __init set_core_ids(void) 532static void __init set_core_ids(struct mdesc_handle *hp)
453{ 533{
454 struct mdesc_node *mp;
455 int idx; 534 int idx;
535 u64 mp;
456 536
457 idx = 1; 537 idx = 1;
458 md_for_each_node_by_name(mp, "cache") { 538 mdesc_for_each_node_by_name(hp, mp, "cache") {
459 const u64 *level = md_get_property(mp, "level", NULL); 539 const u64 *level;
460 const char *type; 540 const char *type;
461 int len; 541 int len;
462 542
543 level = mdesc_get_property(hp, mp, "level", NULL);
463 if (*level != 1) 544 if (*level != 1)
464 continue; 545 continue;
465 546
466 type = md_get_property(mp, "type", &len); 547 type = mdesc_get_property(hp, mp, "type", &len);
467 if (!find_in_proplist(type, "instn", len)) 548 if (!find_in_proplist(type, "instn", len))
468 continue; 549 continue;
469 550
470 mark_core_ids(mp, idx); 551 mark_core_ids(hp, mp, idx);
471 552
472 idx++; 553 idx++;
473 } 554 }
474} 555}
475 556
476static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id) 557static void __init mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
477{ 558{
478 int i; 559 u64 a;
479 560
480 for (i = 0; i < mp->num_arcs; i++) { 561 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
481 struct mdesc_node *t = mp->arcs[i].arc; 562 u64 t = mdesc_arc_target(hp, a);
563 const char *name;
482 const u64 *id; 564 const u64 *id;
483 565
484 if (strcmp(mp->arcs[i].name, "back")) 566 name = mdesc_node_name(hp, t);
485 continue; 567 if (strcmp(name, "cpu"))
486
487 if (strcmp(t->name, "cpu"))
488 continue; 568 continue;
489 569
490 id = md_get_property(t, "id", NULL); 570 id = mdesc_get_property(hp, t, "id", NULL);
491 if (*id < NR_CPUS) 571 if (*id < NR_CPUS)
492 cpu_data(*id).proc_id = proc_id; 572 cpu_data(*id).proc_id = proc_id;
493 } 573 }
494} 574}
495 575
496static void __init __set_proc_ids(const char *exec_unit_name) 576static void __init __set_proc_ids(struct mdesc_handle *hp,
577 const char *exec_unit_name)
497{ 578{
498 struct mdesc_node *mp;
499 int idx; 579 int idx;
580 u64 mp;
500 581
501 idx = 0; 582 idx = 0;
502 md_for_each_node_by_name(mp, exec_unit_name) { 583 mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
503 const char *type; 584 const char *type;
504 int len; 585 int len;
505 586
506 type = md_get_property(mp, "type", &len); 587 type = mdesc_get_property(hp, mp, "type", &len);
507 if (!find_in_proplist(type, "int", len) && 588 if (!find_in_proplist(type, "int", len) &&
508 !find_in_proplist(type, "integer", len)) 589 !find_in_proplist(type, "integer", len))
509 continue; 590 continue;
510 591
511 mark_proc_ids(mp, idx); 592 mark_proc_ids(hp, mp, idx);
512 593
513 idx++; 594 idx++;
514 } 595 }
515} 596}
516 597
517static void __init set_proc_ids(void) 598static void __init set_proc_ids(struct mdesc_handle *hp)
518{ 599{
519 __set_proc_ids("exec_unit"); 600 __set_proc_ids(hp, "exec_unit");
520 __set_proc_ids("exec-unit"); 601 __set_proc_ids(hp, "exec-unit");
521} 602}
522 603
523static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def) 604static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
@@ -538,35 +619,37 @@ use_default:
538 *mask = ((1U << def) * 64U) - 1U; 619 *mask = ((1U << def) * 64U) - 1U;
539} 620}
540 621
541static void __init get_mondo_data(struct mdesc_node *mp, struct trap_per_cpu *tb) 622static void __init get_mondo_data(struct mdesc_handle *hp, u64 mp,
623 struct trap_per_cpu *tb)
542{ 624{
543 const u64 *val; 625 const u64 *val;
544 626
545 val = md_get_property(mp, "q-cpu-mondo-#bits", NULL); 627 val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
546 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7); 628 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
547 629
548 val = md_get_property(mp, "q-dev-mondo-#bits", NULL); 630 val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
549 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7); 631 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
550 632
551 val = md_get_property(mp, "q-resumable-#bits", NULL); 633 val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
552 get_one_mondo_bits(val, &tb->resum_qmask, 6); 634 get_one_mondo_bits(val, &tb->resum_qmask, 6);
553 635
554 val = md_get_property(mp, "q-nonresumable-#bits", NULL); 636 val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
555 get_one_mondo_bits(val, &tb->nonresum_qmask, 2); 637 get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
556} 638}
557 639
558static void __init mdesc_fill_in_cpu_data(void) 640static void __init mdesc_fill_in_cpu_data(void)
559{ 641{
560 struct mdesc_node *mp; 642 struct mdesc_handle *hp = mdesc_grab();
643 u64 mp;
561 644
562 ncpus_probed = 0; 645 ncpus_probed = 0;
563 md_for_each_node_by_name(mp, "cpu") { 646 mdesc_for_each_node_by_name(hp, mp, "cpu") {
564 const u64 *id = md_get_property(mp, "id", NULL); 647 const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
565 const u64 *cfreq = md_get_property(mp, "clock-frequency", NULL); 648 const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
566 struct trap_per_cpu *tb; 649 struct trap_per_cpu *tb;
567 cpuinfo_sparc *c; 650 cpuinfo_sparc *c;
568 unsigned int i;
569 int cpuid; 651 int cpuid;
652 u64 a;
570 653
571 ncpus_probed++; 654 ncpus_probed++;
572 655
@@ -589,29 +672,25 @@ static void __init mdesc_fill_in_cpu_data(void)
589 c->clock_tick = *cfreq; 672 c->clock_tick = *cfreq;
590 673
591 tb = &trap_block[cpuid]; 674 tb = &trap_block[cpuid];
592 get_mondo_data(mp, tb); 675 get_mondo_data(hp, mp, tb);
593
594 for (i = 0; i < mp->num_arcs; i++) {
595 struct mdesc_node *t = mp->arcs[i].arc;
596 unsigned int j;
597 676
598 if (strcmp(mp->arcs[i].name, "fwd")) 677 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
599 continue; 678 u64 j, t = mdesc_arc_target(hp, a);
679 const char *t_name;
600 680
601 if (!strcmp(t->name, "cache")) { 681 t_name = mdesc_node_name(hp, t);
602 fill_in_one_cache(c, t); 682 if (!strcmp(t_name, "cache")) {
683 fill_in_one_cache(c, hp, t);
603 continue; 684 continue;
604 } 685 }
605 686
606 for (j = 0; j < t->num_arcs; j++) { 687 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
607 struct mdesc_node *n; 688 u64 n = mdesc_arc_target(hp, j);
689 const char *n_name;
608 690
609 n = t->arcs[j].arc; 691 n_name = mdesc_node_name(hp, n);
610 if (strcmp(t->arcs[j].name, "fwd")) 692 if (!strcmp(n_name, "cache"))
611 continue; 693 fill_in_one_cache(c, hp, n);
612
613 if (!strcmp(n->name, "cache"))
614 fill_in_one_cache(c, n);
615 } 694 }
616 } 695 }
617 696
@@ -628,44 +707,39 @@ static void __init mdesc_fill_in_cpu_data(void)
628 sparc64_multi_core = 1; 707 sparc64_multi_core = 1;
629#endif 708#endif
630 709
631 set_core_ids(); 710 set_core_ids(hp);
632 set_proc_ids(); 711 set_proc_ids(hp);
633 712
634 smp_fill_in_sib_core_maps(); 713 smp_fill_in_sib_core_maps();
714
715 mdesc_release(hp);
635} 716}
636 717
637void __init sun4v_mdesc_init(void) 718void __init sun4v_mdesc_init(void)
638{ 719{
720 struct mdesc_handle *hp;
639 unsigned long len, real_len, status; 721 unsigned long len, real_len, status;
640 722
641 (void) sun4v_mach_desc(0UL, 0UL, &len); 723 (void) sun4v_mach_desc(0UL, 0UL, &len);
642 724
643 printk("MDESC: Size is %lu bytes.\n", len); 725 printk("MDESC: Size is %lu bytes.\n", len);
644 726
645 main_mdesc = mdesc_early_alloc(len); 727 hp = mdesc_alloc(len, &bootmem_mdesc_memops);
728 if (hp == NULL) {
729 prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
730 prom_halt();
731 }
646 732
647 status = sun4v_mach_desc(__pa(main_mdesc), len, &real_len); 733 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
648 if (status != HV_EOK || real_len > len) { 734 if (status != HV_EOK || real_len > len) {
649 prom_printf("sun4v_mach_desc fails, err(%lu), " 735 prom_printf("sun4v_mach_desc fails, err(%lu), "
650 "len(%lu), real_len(%lu)\n", 736 "len(%lu), real_len(%lu)\n",
651 status, len, real_len); 737 status, len, real_len);
738 mdesc_free(hp);
652 prom_halt(); 739 prom_halt();
653 } 740 }
654 741
655 len = count_nodes(main_mdesc); 742 cur_mdesc = hp;
656 printk("MDESC: %lu nodes.\n", len);
657
658 len = roundup_pow_of_two(len);
659
660 mdesc_hash = mdesc_early_alloc(len * sizeof(struct mdesc_node *));
661 mdesc_hash_size = len;
662
663 printk("MDESC: Hash size %lu entries.\n", len);
664
665 build_all_nodes(main_mdesc);
666
667 printk("MDESC: Built graph with %u bytes of memory.\n",
668 mdesc_early_allocated);
669 743
670 report_platform_properties(); 744 report_platform_properties();
671 mdesc_fill_in_cpu_data(); 745 mdesc_fill_in_cpu_data();