Commit 920c3ed741340a88f2042ab0c44a25b8c743a379

Authored by David S. Miller
1 parent cb32da0416

[SPARC64]: Add basic infrastructure for MD add/remove notification.

And add dummy handlers for the VIO device layer.  These will be filled
in with real code after the vdc, vnet, and ds drivers are reworked to
have simpler dependencies on the VIO device tree.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 3 changed files with 118 additions and 3 deletions Inline Diff

arch/sparc64/kernel/mdesc.c
1 /* mdesc.c: Sun4V machine description handling. 1 /* mdesc.c: Sun4V machine description handling.
2 * 2 *
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net> 3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4 */ 4 */
5 #include <linux/kernel.h> 5 #include <linux/kernel.h>
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> 9 #include <linux/list.h>
10 #include <linux/slab.h> 10 #include <linux/slab.h>
11 #include <linux/mm.h> 11 #include <linux/mm.h>
12 12
13 #include <asm/hypervisor.h> 13 #include <asm/hypervisor.h>
14 #include <asm/mdesc.h> 14 #include <asm/mdesc.h>
15 #include <asm/prom.h> 15 #include <asm/prom.h>
16 #include <asm/oplib.h> 16 #include <asm/oplib.h>
17 #include <asm/smp.h> 17 #include <asm/smp.h>
18 18
19 /* Unlike the OBP device tree, the machine description is a full-on 19 /* Unlike the OBP device tree, the machine description is a full-on
20 * DAG. An arbitrary number of ARCs are possible from one 20 * DAG. An arbitrary number of ARCs are possible from one
21 * node to other nodes and thus we can't use the OBP device_node 21 * node to other nodes and thus we can't use the OBP device_node
22 * data structure to represent these nodes inside of the kernel. 22 * data structure to represent these nodes inside of the kernel.
23 * 23 *
24 * Actually, it isn't even a DAG, because there are back pointers 24 * Actually, it isn't even a DAG, because there are back pointers
25 * which create cycles in the graph. 25 * which create cycles in the graph.
26 * 26 *
27 * mdesc_hdr and mdesc_elem describe the layout of the data structure 27 * mdesc_hdr and mdesc_elem describe the layout of the data structure
28 * we get from the Hypervisor. 28 * we get from the Hypervisor.
29 */ 29 */
30 struct mdesc_hdr { 30 struct mdesc_hdr {
31 u32 version; /* Transport version */ 31 u32 version; /* Transport version */
32 u32 node_sz; /* node block size */ 32 u32 node_sz; /* node block size */
33 u32 name_sz; /* name block size */ 33 u32 name_sz; /* name block size */
34 u32 data_sz; /* data block size */ 34 u32 data_sz; /* data block size */
35 } __attribute__((aligned(16))); 35 } __attribute__((aligned(16)));
36 36
37 struct mdesc_elem { 37 struct mdesc_elem {
38 u8 tag; 38 u8 tag;
39 #define MD_LIST_END 0x00 39 #define MD_LIST_END 0x00
40 #define MD_NODE 0x4e 40 #define MD_NODE 0x4e
41 #define MD_NODE_END 0x45 41 #define MD_NODE_END 0x45
42 #define MD_NOOP 0x20 42 #define MD_NOOP 0x20
43 #define MD_PROP_ARC 0x61 43 #define MD_PROP_ARC 0x61
44 #define MD_PROP_VAL 0x76 44 #define MD_PROP_VAL 0x76
45 #define MD_PROP_STR 0x73 45 #define MD_PROP_STR 0x73
46 #define MD_PROP_DATA 0x64 46 #define MD_PROP_DATA 0x64
47 u8 name_len; 47 u8 name_len;
48 u16 resv; 48 u16 resv;
49 u32 name_offset; 49 u32 name_offset;
50 union { 50 union {
51 struct { 51 struct {
52 u32 data_len; 52 u32 data_len;
53 u32 data_offset; 53 u32 data_offset;
54 } data; 54 } data;
55 u64 val; 55 u64 val;
56 } d; 56 } d;
57 }; 57 };
58 58
59 struct mdesc_mem_ops { 59 struct mdesc_mem_ops {
60 struct mdesc_handle *(*alloc)(unsigned int mdesc_size); 60 struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
61 void (*free)(struct mdesc_handle *handle); 61 void (*free)(struct mdesc_handle *handle);
62 }; 62 };
63 63
64 struct mdesc_handle { 64 struct mdesc_handle {
65 struct list_head list; 65 struct list_head list;
66 struct mdesc_mem_ops *mops; 66 struct mdesc_mem_ops *mops;
67 void *self_base; 67 void *self_base;
68 atomic_t refcnt; 68 atomic_t refcnt;
69 unsigned int handle_size; 69 unsigned int handle_size;
70 struct mdesc_hdr mdesc; 70 struct mdesc_hdr mdesc;
71 }; 71 };
72 72
73 static void mdesc_handle_init(struct mdesc_handle *hp, 73 static void mdesc_handle_init(struct mdesc_handle *hp,
74 unsigned int handle_size, 74 unsigned int handle_size,
75 void *base) 75 void *base)
76 { 76 {
77 BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1)); 77 BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
78 78
79 memset(hp, 0, handle_size); 79 memset(hp, 0, handle_size);
80 INIT_LIST_HEAD(&hp->list); 80 INIT_LIST_HEAD(&hp->list);
81 hp->self_base = base; 81 hp->self_base = base;
82 atomic_set(&hp->refcnt, 1); 82 atomic_set(&hp->refcnt, 1);
83 hp->handle_size = handle_size; 83 hp->handle_size = handle_size;
84 } 84 }
85 85
86 static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size) 86 static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
87 { 87 {
88 struct mdesc_handle *hp; 88 struct mdesc_handle *hp;
89 unsigned int handle_size, alloc_size; 89 unsigned int handle_size, alloc_size;
90 90
91 handle_size = (sizeof(struct mdesc_handle) - 91 handle_size = (sizeof(struct mdesc_handle) -
92 sizeof(struct mdesc_hdr) + 92 sizeof(struct mdesc_hdr) +
93 mdesc_size); 93 mdesc_size);
94 alloc_size = PAGE_ALIGN(handle_size); 94 alloc_size = PAGE_ALIGN(handle_size);
95 95
96 hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL); 96 hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
97 if (hp) 97 if (hp)
98 mdesc_handle_init(hp, handle_size, hp); 98 mdesc_handle_init(hp, handle_size, hp);
99 99
100 return hp; 100 return hp;
101 } 101 }
102 102
103 static void mdesc_bootmem_free(struct mdesc_handle *hp) 103 static void mdesc_bootmem_free(struct mdesc_handle *hp)
104 { 104 {
105 unsigned int alloc_size, handle_size = hp->handle_size; 105 unsigned int alloc_size, handle_size = hp->handle_size;
106 unsigned long start, end; 106 unsigned long start, end;
107 107
108 BUG_ON(atomic_read(&hp->refcnt) != 0); 108 BUG_ON(atomic_read(&hp->refcnt) != 0);
109 BUG_ON(!list_empty(&hp->list)); 109 BUG_ON(!list_empty(&hp->list));
110 110
111 alloc_size = PAGE_ALIGN(handle_size); 111 alloc_size = PAGE_ALIGN(handle_size);
112 112
113 start = (unsigned long) hp; 113 start = (unsigned long) hp;
114 end = start + alloc_size; 114 end = start + alloc_size;
115 115
116 while (start < end) { 116 while (start < end) {
117 struct page *p; 117 struct page *p;
118 118
119 p = virt_to_page(start); 119 p = virt_to_page(start);
120 ClearPageReserved(p); 120 ClearPageReserved(p);
121 __free_page(p); 121 __free_page(p);
122 start += PAGE_SIZE; 122 start += PAGE_SIZE;
123 } 123 }
124 } 124 }
125 125
126 static struct mdesc_mem_ops bootmem_mdesc_memops = { 126 static struct mdesc_mem_ops bootmem_mdesc_memops = {
127 .alloc = mdesc_bootmem_alloc, 127 .alloc = mdesc_bootmem_alloc,
128 .free = mdesc_bootmem_free, 128 .free = mdesc_bootmem_free,
129 }; 129 };
130 130
131 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size) 131 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
132 { 132 {
133 unsigned int handle_size; 133 unsigned int handle_size;
134 void *base; 134 void *base;
135 135
136 handle_size = (sizeof(struct mdesc_handle) - 136 handle_size = (sizeof(struct mdesc_handle) -
137 sizeof(struct mdesc_hdr) + 137 sizeof(struct mdesc_hdr) +
138 mdesc_size); 138 mdesc_size);
139 139
140 base = kmalloc(handle_size + 15, GFP_KERNEL); 140 base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
141 if (base) { 141 if (base) {
142 struct mdesc_handle *hp; 142 struct mdesc_handle *hp;
143 unsigned long addr; 143 unsigned long addr;
144 144
145 addr = (unsigned long)base; 145 addr = (unsigned long)base;
146 addr = (addr + 15UL) & ~15UL; 146 addr = (addr + 15UL) & ~15UL;
147 hp = (struct mdesc_handle *) addr; 147 hp = (struct mdesc_handle *) addr;
148 148
149 mdesc_handle_init(hp, handle_size, base); 149 mdesc_handle_init(hp, handle_size, base);
150 return hp; 150 return hp;
151 } 151 }
152 152
153 return NULL; 153 return NULL;
154 } 154 }
155 155
156 static void mdesc_kfree(struct mdesc_handle *hp) 156 static void mdesc_kfree(struct mdesc_handle *hp)
157 { 157 {
158 BUG_ON(atomic_read(&hp->refcnt) != 0); 158 BUG_ON(atomic_read(&hp->refcnt) != 0);
159 BUG_ON(!list_empty(&hp->list)); 159 BUG_ON(!list_empty(&hp->list));
160 160
161 kfree(hp->self_base); 161 kfree(hp->self_base);
162 } 162 }
163 163
164 static struct mdesc_mem_ops kmalloc_mdesc_memops = { 164 static struct mdesc_mem_ops kmalloc_mdesc_memops = {
165 .alloc = mdesc_kmalloc, 165 .alloc = mdesc_kmalloc,
166 .free = mdesc_kfree, 166 .free = mdesc_kfree,
167 }; 167 };
168 168
169 static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size, 169 static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
170 struct mdesc_mem_ops *mops) 170 struct mdesc_mem_ops *mops)
171 { 171 {
172 struct mdesc_handle *hp = mops->alloc(mdesc_size); 172 struct mdesc_handle *hp = mops->alloc(mdesc_size);
173 173
174 if (hp) 174 if (hp)
175 hp->mops = mops; 175 hp->mops = mops;
176 176
177 return hp; 177 return hp;
178 } 178 }
179 179
180 static void mdesc_free(struct mdesc_handle *hp) 180 static void mdesc_free(struct mdesc_handle *hp)
181 { 181 {
182 hp->mops->free(hp); 182 hp->mops->free(hp);
183 } 183 }
184 184
185 static struct mdesc_handle *cur_mdesc; 185 static struct mdesc_handle *cur_mdesc;
186 static LIST_HEAD(mdesc_zombie_list); 186 static LIST_HEAD(mdesc_zombie_list);
187 static DEFINE_SPINLOCK(mdesc_lock); 187 static DEFINE_SPINLOCK(mdesc_lock);
188 188
189 struct mdesc_handle *mdesc_grab(void) 189 struct mdesc_handle *mdesc_grab(void)
190 { 190 {
191 struct mdesc_handle *hp; 191 struct mdesc_handle *hp;
192 unsigned long flags; 192 unsigned long flags;
193 193
194 spin_lock_irqsave(&mdesc_lock, flags); 194 spin_lock_irqsave(&mdesc_lock, flags);
195 hp = cur_mdesc; 195 hp = cur_mdesc;
196 if (hp) 196 if (hp)
197 atomic_inc(&hp->refcnt); 197 atomic_inc(&hp->refcnt);
198 spin_unlock_irqrestore(&mdesc_lock, flags); 198 spin_unlock_irqrestore(&mdesc_lock, flags);
199 199
200 return hp; 200 return hp;
201 } 201 }
202 EXPORT_SYMBOL(mdesc_grab); 202 EXPORT_SYMBOL(mdesc_grab);
203 203
204 void mdesc_release(struct mdesc_handle *hp) 204 void mdesc_release(struct mdesc_handle *hp)
205 { 205 {
206 unsigned long flags; 206 unsigned long flags;
207 207
208 spin_lock_irqsave(&mdesc_lock, flags); 208 spin_lock_irqsave(&mdesc_lock, flags);
209 if (atomic_dec_and_test(&hp->refcnt)) { 209 if (atomic_dec_and_test(&hp->refcnt)) {
210 list_del_init(&hp->list); 210 list_del_init(&hp->list);
211 hp->mops->free(hp); 211 hp->mops->free(hp);
212 } 212 }
213 spin_unlock_irqrestore(&mdesc_lock, flags); 213 spin_unlock_irqrestore(&mdesc_lock, flags);
214 } 214 }
215 EXPORT_SYMBOL(mdesc_release); 215 EXPORT_SYMBOL(mdesc_release);
216 216
217 static DEFINE_MUTEX(mdesc_mutex);
218 static struct mdesc_notifier_client *client_list;
219
220 void mdesc_register_notifier(struct mdesc_notifier_client *client)
221 {
222 u64 node;
223
224 mutex_lock(&mdesc_mutex);
225 client->next = client_list;
226 client_list = client;
227
228 mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
229 client->add(cur_mdesc, node);
230
231 mutex_unlock(&mdesc_mutex);
232 }
233
234 /* Run 'func' on nodes which are in A but not in B. */
235 static void invoke_on_missing(const char *name,
236 struct mdesc_handle *a,
237 struct mdesc_handle *b,
238 void (*func)(struct mdesc_handle *, u64))
239 {
240 u64 node;
241
242 mdesc_for_each_node_by_name(a, node, name) {
243 const u64 *id = mdesc_get_property(a, node, "id", NULL);
244 int found = 0;
245 u64 fnode;
246
247 mdesc_for_each_node_by_name(b, fnode, name) {
248 const u64 *fid = mdesc_get_property(b, fnode,
249 "id", NULL);
250
251 if (*id == *fid) {
252 found = 1;
253 break;
254 }
255 }
256 if (!found)
257 func(a, node);
258 }
259 }
260
261 static void notify_one(struct mdesc_notifier_client *p,
262 struct mdesc_handle *old_hp,
263 struct mdesc_handle *new_hp)
264 {
265 invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
266 invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
267 }
268
269 static void mdesc_notify_clients(struct mdesc_handle *old_hp,
270 struct mdesc_handle *new_hp)
271 {
272 struct mdesc_notifier_client *p = client_list;
273
274 while (p) {
275 notify_one(p, old_hp, new_hp);
276 p = p->next;
277 }
278 }
279
217 void mdesc_update(void) 280 void mdesc_update(void)
218 { 281 {
219 unsigned long len, real_len, status; 282 unsigned long len, real_len, status;
220 struct mdesc_handle *hp, *orig_hp; 283 struct mdesc_handle *hp, *orig_hp;
221 unsigned long flags; 284 unsigned long flags;
222 285
286 mutex_lock(&mdesc_mutex);
287
223 (void) sun4v_mach_desc(0UL, 0UL, &len); 288 (void) sun4v_mach_desc(0UL, 0UL, &len);
224 289
225 hp = mdesc_alloc(len, &kmalloc_mdesc_memops); 290 hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
226 if (!hp) { 291 if (!hp) {
227 printk(KERN_ERR "MD: mdesc alloc fails\n"); 292 printk(KERN_ERR "MD: mdesc alloc fails\n");
228 return; 293 goto out;
229 } 294 }
230 295
231 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); 296 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
232 if (status != HV_EOK || real_len > len) { 297 if (status != HV_EOK || real_len > len) {
233 printk(KERN_ERR "MD: mdesc reread fails with %lu\n", 298 printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
234 status); 299 status);
235 atomic_dec(&hp->refcnt); 300 atomic_dec(&hp->refcnt);
236 mdesc_free(hp); 301 mdesc_free(hp);
237 return; 302 goto out;
238 } 303 }
239 304
240 spin_lock_irqsave(&mdesc_lock, flags); 305 spin_lock_irqsave(&mdesc_lock, flags);
241 orig_hp = cur_mdesc; 306 orig_hp = cur_mdesc;
242 cur_mdesc = hp; 307 cur_mdesc = hp;
308 spin_unlock_irqrestore(&mdesc_lock, flags);
243 309
310 mdesc_notify_clients(orig_hp, hp);
311
312 spin_lock_irqsave(&mdesc_lock, flags);
244 if (atomic_dec_and_test(&orig_hp->refcnt)) 313 if (atomic_dec_and_test(&orig_hp->refcnt))
245 mdesc_free(orig_hp); 314 mdesc_free(orig_hp);
246 else 315 else
247 list_add(&orig_hp->list, &mdesc_zombie_list); 316 list_add(&orig_hp->list, &mdesc_zombie_list);
248 spin_unlock_irqrestore(&mdesc_lock, flags); 317 spin_unlock_irqrestore(&mdesc_lock, flags);
318
319 out:
320 mutex_unlock(&mdesc_mutex);
249 } 321 }
250 322
251 static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) 323 static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
252 { 324 {
253 return (struct mdesc_elem *) (mdesc + 1); 325 return (struct mdesc_elem *) (mdesc + 1);
254 } 326 }
255 327
256 static void *name_block(struct mdesc_hdr *mdesc) 328 static void *name_block(struct mdesc_hdr *mdesc)
257 { 329 {
258 return ((void *) node_block(mdesc)) + mdesc->node_sz; 330 return ((void *) node_block(mdesc)) + mdesc->node_sz;
259 } 331 }
260 332
261 static void *data_block(struct mdesc_hdr *mdesc) 333 static void *data_block(struct mdesc_hdr *mdesc)
262 { 334 {
263 return ((void *) name_block(mdesc)) + mdesc->name_sz; 335 return ((void *) name_block(mdesc)) + mdesc->name_sz;
264 } 336 }
265 337
266 u64 mdesc_node_by_name(struct mdesc_handle *hp, 338 u64 mdesc_node_by_name(struct mdesc_handle *hp,
267 u64 from_node, const char *name) 339 u64 from_node, const char *name)
268 { 340 {
269 struct mdesc_elem *ep = node_block(&hp->mdesc); 341 struct mdesc_elem *ep = node_block(&hp->mdesc);
270 const char *names = name_block(&hp->mdesc); 342 const char *names = name_block(&hp->mdesc);
271 u64 last_node = hp->mdesc.node_sz / 16; 343 u64 last_node = hp->mdesc.node_sz / 16;
272 u64 ret; 344 u64 ret;
273 345
274 if (from_node == MDESC_NODE_NULL) { 346 if (from_node == MDESC_NODE_NULL) {
275 ret = from_node = 0; 347 ret = from_node = 0;
276 } else if (from_node >= last_node) { 348 } else if (from_node >= last_node) {
277 return MDESC_NODE_NULL; 349 return MDESC_NODE_NULL;
278 } else { 350 } else {
279 ret = ep[from_node].d.val; 351 ret = ep[from_node].d.val;
280 } 352 }
281 353
282 while (ret < last_node) { 354 while (ret < last_node) {
283 if (ep[ret].tag != MD_NODE) 355 if (ep[ret].tag != MD_NODE)
284 return MDESC_NODE_NULL; 356 return MDESC_NODE_NULL;
285 if (!strcmp(names + ep[ret].name_offset, name)) 357 if (!strcmp(names + ep[ret].name_offset, name))
286 break; 358 break;
287 ret = ep[ret].d.val; 359 ret = ep[ret].d.val;
288 } 360 }
289 if (ret >= last_node) 361 if (ret >= last_node)
290 ret = MDESC_NODE_NULL; 362 ret = MDESC_NODE_NULL;
291 return ret; 363 return ret;
292 } 364 }
293 EXPORT_SYMBOL(mdesc_node_by_name); 365 EXPORT_SYMBOL(mdesc_node_by_name);
294 366
295 const void *mdesc_get_property(struct mdesc_handle *hp, u64 node, 367 const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
296 const char *name, int *lenp) 368 const char *name, int *lenp)
297 { 369 {
298 const char *names = name_block(&hp->mdesc); 370 const char *names = name_block(&hp->mdesc);
299 u64 last_node = hp->mdesc.node_sz / 16; 371 u64 last_node = hp->mdesc.node_sz / 16;
300 void *data = data_block(&hp->mdesc); 372 void *data = data_block(&hp->mdesc);
301 struct mdesc_elem *ep; 373 struct mdesc_elem *ep;
302 374
303 if (node == MDESC_NODE_NULL || node >= last_node) 375 if (node == MDESC_NODE_NULL || node >= last_node)
304 return NULL; 376 return NULL;
305 377
306 ep = node_block(&hp->mdesc) + node; 378 ep = node_block(&hp->mdesc) + node;
307 ep++; 379 ep++;
308 for (; ep->tag != MD_NODE_END; ep++) { 380 for (; ep->tag != MD_NODE_END; ep++) {
309 void *val = NULL; 381 void *val = NULL;
310 int len = 0; 382 int len = 0;
311 383
312 switch (ep->tag) { 384 switch (ep->tag) {
313 case MD_PROP_VAL: 385 case MD_PROP_VAL:
314 val = &ep->d.val; 386 val = &ep->d.val;
315 len = 8; 387 len = 8;
316 break; 388 break;
317 389
318 case MD_PROP_STR: 390 case MD_PROP_STR:
319 case MD_PROP_DATA: 391 case MD_PROP_DATA:
320 val = data + ep->d.data.data_offset; 392 val = data + ep->d.data.data_offset;
321 len = ep->d.data.data_len; 393 len = ep->d.data.data_len;
322 break; 394 break;
323 395
324 default: 396 default:
325 break; 397 break;
326 } 398 }
327 if (!val) 399 if (!val)
328 continue; 400 continue;
329 401
330 if (!strcmp(names + ep->name_offset, name)) { 402 if (!strcmp(names + ep->name_offset, name)) {
331 if (lenp) 403 if (lenp)
332 *lenp = len; 404 *lenp = len;
333 return val; 405 return val;
334 } 406 }
335 } 407 }
336 408
337 return NULL; 409 return NULL;
338 } 410 }
339 EXPORT_SYMBOL(mdesc_get_property); 411 EXPORT_SYMBOL(mdesc_get_property);
340 412
341 u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type) 413 u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
342 { 414 {
343 struct mdesc_elem *ep, *base = node_block(&hp->mdesc); 415 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
344 const char *names = name_block(&hp->mdesc); 416 const char *names = name_block(&hp->mdesc);
345 u64 last_node = hp->mdesc.node_sz / 16; 417 u64 last_node = hp->mdesc.node_sz / 16;
346 418
347 if (from == MDESC_NODE_NULL || from >= last_node) 419 if (from == MDESC_NODE_NULL || from >= last_node)
348 return MDESC_NODE_NULL; 420 return MDESC_NODE_NULL;
349 421
350 ep = base + from; 422 ep = base + from;
351 423
352 ep++; 424 ep++;
353 for (; ep->tag != MD_NODE_END; ep++) { 425 for (; ep->tag != MD_NODE_END; ep++) {
354 if (ep->tag != MD_PROP_ARC) 426 if (ep->tag != MD_PROP_ARC)
355 continue; 427 continue;
356 428
357 if (strcmp(names + ep->name_offset, arc_type)) 429 if (strcmp(names + ep->name_offset, arc_type))
358 continue; 430 continue;
359 431
360 return ep - base; 432 return ep - base;
361 } 433 }
362 434
363 return MDESC_NODE_NULL; 435 return MDESC_NODE_NULL;
364 } 436 }
365 EXPORT_SYMBOL(mdesc_next_arc); 437 EXPORT_SYMBOL(mdesc_next_arc);
366 438
367 u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc) 439 u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
368 { 440 {
369 struct mdesc_elem *ep, *base = node_block(&hp->mdesc); 441 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
370 442
371 ep = base + arc; 443 ep = base + arc;
372 444
373 return ep->d.val; 445 return ep->d.val;
374 } 446 }
375 EXPORT_SYMBOL(mdesc_arc_target); 447 EXPORT_SYMBOL(mdesc_arc_target);
376 448
377 const char *mdesc_node_name(struct mdesc_handle *hp, u64 node) 449 const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
378 { 450 {
379 struct mdesc_elem *ep, *base = node_block(&hp->mdesc); 451 struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
380 const char *names = name_block(&hp->mdesc); 452 const char *names = name_block(&hp->mdesc);
381 u64 last_node = hp->mdesc.node_sz / 16; 453 u64 last_node = hp->mdesc.node_sz / 16;
382 454
383 if (node == MDESC_NODE_NULL || node >= last_node) 455 if (node == MDESC_NODE_NULL || node >= last_node)
384 return NULL; 456 return NULL;
385 457
386 ep = base + node; 458 ep = base + node;
387 if (ep->tag != MD_NODE) 459 if (ep->tag != MD_NODE)
388 return NULL; 460 return NULL;
389 461
390 return names + ep->name_offset; 462 return names + ep->name_offset;
391 } 463 }
392 EXPORT_SYMBOL(mdesc_node_name); 464 EXPORT_SYMBOL(mdesc_node_name);
393 465
394 static void __init report_platform_properties(void) 466 static void __init report_platform_properties(void)
395 { 467 {
396 struct mdesc_handle *hp = mdesc_grab(); 468 struct mdesc_handle *hp = mdesc_grab();
397 u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform"); 469 u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
398 const char *s; 470 const char *s;
399 const u64 *v; 471 const u64 *v;
400 472
401 if (pn == MDESC_NODE_NULL) { 473 if (pn == MDESC_NODE_NULL) {
402 prom_printf("No platform node in machine-description.\n"); 474 prom_printf("No platform node in machine-description.\n");
403 prom_halt(); 475 prom_halt();
404 } 476 }
405 477
406 s = mdesc_get_property(hp, pn, "banner-name", NULL); 478 s = mdesc_get_property(hp, pn, "banner-name", NULL);
407 printk("PLATFORM: banner-name [%s]\n", s); 479 printk("PLATFORM: banner-name [%s]\n", s);
408 s = mdesc_get_property(hp, pn, "name", NULL); 480 s = mdesc_get_property(hp, pn, "name", NULL);
409 printk("PLATFORM: name [%s]\n", s); 481 printk("PLATFORM: name [%s]\n", s);
410 482
411 v = mdesc_get_property(hp, pn, "hostid", NULL); 483 v = mdesc_get_property(hp, pn, "hostid", NULL);
412 if (v) 484 if (v)
413 printk("PLATFORM: hostid [%08lx]\n", *v); 485 printk("PLATFORM: hostid [%08lx]\n", *v);
414 v = mdesc_get_property(hp, pn, "serial#", NULL); 486 v = mdesc_get_property(hp, pn, "serial#", NULL);
415 if (v) 487 if (v)
416 printk("PLATFORM: serial# [%08lx]\n", *v); 488 printk("PLATFORM: serial# [%08lx]\n", *v);
417 v = mdesc_get_property(hp, pn, "stick-frequency", NULL); 489 v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
418 printk("PLATFORM: stick-frequency [%08lx]\n", *v); 490 printk("PLATFORM: stick-frequency [%08lx]\n", *v);
419 v = mdesc_get_property(hp, pn, "mac-address", NULL); 491 v = mdesc_get_property(hp, pn, "mac-address", NULL);
420 if (v) 492 if (v)
421 printk("PLATFORM: mac-address [%lx]\n", *v); 493 printk("PLATFORM: mac-address [%lx]\n", *v);
422 v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL); 494 v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
423 if (v) 495 if (v)
424 printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v); 496 printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
425 v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL); 497 v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
426 if (v) 498 if (v)
427 printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v); 499 printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
428 v = mdesc_get_property(hp, pn, "max-cpus", NULL); 500 v = mdesc_get_property(hp, pn, "max-cpus", NULL);
429 if (v) 501 if (v)
430 printk("PLATFORM: max-cpus [%lu]\n", *v); 502 printk("PLATFORM: max-cpus [%lu]\n", *v);
431 503
432 #ifdef CONFIG_SMP 504 #ifdef CONFIG_SMP
433 { 505 {
434 int max_cpu, i; 506 int max_cpu, i;
435 507
436 if (v) { 508 if (v) {
437 max_cpu = *v; 509 max_cpu = *v;
438 if (max_cpu > NR_CPUS) 510 if (max_cpu > NR_CPUS)
439 max_cpu = NR_CPUS; 511 max_cpu = NR_CPUS;
440 } else { 512 } else {
441 max_cpu = NR_CPUS; 513 max_cpu = NR_CPUS;
442 } 514 }
443 for (i = 0; i < max_cpu; i++) 515 for (i = 0; i < max_cpu; i++)
444 cpu_set(i, cpu_possible_map); 516 cpu_set(i, cpu_possible_map);
445 } 517 }
446 #endif 518 #endif
447 519
448 mdesc_release(hp); 520 mdesc_release(hp);
449 } 521 }
450 522
451 static int inline find_in_proplist(const char *list, const char *match, int len) 523 static int inline find_in_proplist(const char *list, const char *match, int len)
452 { 524 {
453 while (len > 0) { 525 while (len > 0) {
454 int l; 526 int l;
455 527
456 if (!strcmp(list, match)) 528 if (!strcmp(list, match))
457 return 1; 529 return 1;
458 l = strlen(list) + 1; 530 l = strlen(list) + 1;
459 list += l; 531 list += l;
460 len -= l; 532 len -= l;
461 } 533 }
462 return 0; 534 return 0;
463 } 535 }
464 536
465 static void __devinit fill_in_one_cache(cpuinfo_sparc *c, 537 static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
466 struct mdesc_handle *hp, 538 struct mdesc_handle *hp,
467 u64 mp) 539 u64 mp)
468 { 540 {
469 const u64 *level = mdesc_get_property(hp, mp, "level", NULL); 541 const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
470 const u64 *size = mdesc_get_property(hp, mp, "size", NULL); 542 const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
471 const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL); 543 const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
472 const char *type; 544 const char *type;
473 int type_len; 545 int type_len;
474 546
475 type = mdesc_get_property(hp, mp, "type", &type_len); 547 type = mdesc_get_property(hp, mp, "type", &type_len);
476 548
477 switch (*level) { 549 switch (*level) {
478 case 1: 550 case 1:
479 if (find_in_proplist(type, "instn", type_len)) { 551 if (find_in_proplist(type, "instn", type_len)) {
480 c->icache_size = *size; 552 c->icache_size = *size;
481 c->icache_line_size = *line_size; 553 c->icache_line_size = *line_size;
482 } else if (find_in_proplist(type, "data", type_len)) { 554 } else if (find_in_proplist(type, "data", type_len)) {
483 c->dcache_size = *size; 555 c->dcache_size = *size;
484 c->dcache_line_size = *line_size; 556 c->dcache_line_size = *line_size;
485 } 557 }
486 break; 558 break;
487 559
488 case 2: 560 case 2:
489 c->ecache_size = *size; 561 c->ecache_size = *size;
490 c->ecache_line_size = *line_size; 562 c->ecache_line_size = *line_size;
491 break; 563 break;
492 564
493 default: 565 default:
494 break; 566 break;
495 } 567 }
496 568
497 if (*level == 1) { 569 if (*level == 1) {
498 u64 a; 570 u64 a;
499 571
500 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { 572 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
501 u64 target = mdesc_arc_target(hp, a); 573 u64 target = mdesc_arc_target(hp, a);
502 const char *name = mdesc_node_name(hp, target); 574 const char *name = mdesc_node_name(hp, target);
503 575
504 if (!strcmp(name, "cache")) 576 if (!strcmp(name, "cache"))
505 fill_in_one_cache(c, hp, target); 577 fill_in_one_cache(c, hp, target);
506 } 578 }
507 } 579 }
508 } 580 }
509 581
510 static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp, 582 static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
511 int core_id) 583 int core_id)
512 { 584 {
513 u64 a; 585 u64 a;
514 586
515 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { 587 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
516 u64 t = mdesc_arc_target(hp, a); 588 u64 t = mdesc_arc_target(hp, a);
517 const char *name; 589 const char *name;
518 const u64 *id; 590 const u64 *id;
519 591
520 name = mdesc_node_name(hp, t); 592 name = mdesc_node_name(hp, t);
521 if (!strcmp(name, "cpu")) { 593 if (!strcmp(name, "cpu")) {
522 id = mdesc_get_property(hp, t, "id", NULL); 594 id = mdesc_get_property(hp, t, "id", NULL);
523 if (*id < NR_CPUS) 595 if (*id < NR_CPUS)
524 cpu_data(*id).core_id = core_id; 596 cpu_data(*id).core_id = core_id;
525 } else { 597 } else {
526 u64 j; 598 u64 j;
527 599
528 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) { 600 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
529 u64 n = mdesc_arc_target(hp, j); 601 u64 n = mdesc_arc_target(hp, j);
530 const char *n_name; 602 const char *n_name;
531 603
532 n_name = mdesc_node_name(hp, n); 604 n_name = mdesc_node_name(hp, n);
533 if (strcmp(n_name, "cpu")) 605 if (strcmp(n_name, "cpu"))
534 continue; 606 continue;
535 607
536 id = mdesc_get_property(hp, n, "id", NULL); 608 id = mdesc_get_property(hp, n, "id", NULL);
537 if (*id < NR_CPUS) 609 if (*id < NR_CPUS)
538 cpu_data(*id).core_id = core_id; 610 cpu_data(*id).core_id = core_id;
539 } 611 }
540 } 612 }
541 } 613 }
542 } 614 }
543 615
544 static void __devinit set_core_ids(struct mdesc_handle *hp) 616 static void __devinit set_core_ids(struct mdesc_handle *hp)
545 { 617 {
546 int idx; 618 int idx;
547 u64 mp; 619 u64 mp;
548 620
549 idx = 1; 621 idx = 1;
550 mdesc_for_each_node_by_name(hp, mp, "cache") { 622 mdesc_for_each_node_by_name(hp, mp, "cache") {
551 const u64 *level; 623 const u64 *level;
552 const char *type; 624 const char *type;
553 int len; 625 int len;
554 626
555 level = mdesc_get_property(hp, mp, "level", NULL); 627 level = mdesc_get_property(hp, mp, "level", NULL);
556 if (*level != 1) 628 if (*level != 1)
557 continue; 629 continue;
558 630
559 type = mdesc_get_property(hp, mp, "type", &len); 631 type = mdesc_get_property(hp, mp, "type", &len);
560 if (!find_in_proplist(type, "instn", len)) 632 if (!find_in_proplist(type, "instn", len))
561 continue; 633 continue;
562 634
563 mark_core_ids(hp, mp, idx); 635 mark_core_ids(hp, mp, idx);
564 636
565 idx++; 637 idx++;
566 } 638 }
567 } 639 }
568 640
569 static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, 641 static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
570 int proc_id) 642 int proc_id)
571 { 643 {
572 u64 a; 644 u64 a;
573 645
574 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { 646 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
575 u64 t = mdesc_arc_target(hp, a); 647 u64 t = mdesc_arc_target(hp, a);
576 const char *name; 648 const char *name;
577 const u64 *id; 649 const u64 *id;
578 650
579 name = mdesc_node_name(hp, t); 651 name = mdesc_node_name(hp, t);
580 if (strcmp(name, "cpu")) 652 if (strcmp(name, "cpu"))
581 continue; 653 continue;
582 654
583 id = mdesc_get_property(hp, t, "id", NULL); 655 id = mdesc_get_property(hp, t, "id", NULL);
584 if (*id < NR_CPUS) 656 if (*id < NR_CPUS)
585 cpu_data(*id).proc_id = proc_id; 657 cpu_data(*id).proc_id = proc_id;
586 } 658 }
587 } 659 }
588 660
589 static void __devinit __set_proc_ids(struct mdesc_handle *hp, 661 static void __devinit __set_proc_ids(struct mdesc_handle *hp,
590 const char *exec_unit_name) 662 const char *exec_unit_name)
591 { 663 {
592 int idx; 664 int idx;
593 u64 mp; 665 u64 mp;
594 666
595 idx = 0; 667 idx = 0;
596 mdesc_for_each_node_by_name(hp, mp, exec_unit_name) { 668 mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
597 const char *type; 669 const char *type;
598 int len; 670 int len;
599 671
600 type = mdesc_get_property(hp, mp, "type", &len); 672 type = mdesc_get_property(hp, mp, "type", &len);
601 if (!find_in_proplist(type, "int", len) && 673 if (!find_in_proplist(type, "int", len) &&
602 !find_in_proplist(type, "integer", len)) 674 !find_in_proplist(type, "integer", len))
603 continue; 675 continue;
604 676
605 mark_proc_ids(hp, mp, idx); 677 mark_proc_ids(hp, mp, idx);
606 678
607 idx++; 679 idx++;
608 } 680 }
609 } 681 }
610 682
611 static void __devinit set_proc_ids(struct mdesc_handle *hp) 683 static void __devinit set_proc_ids(struct mdesc_handle *hp)
612 { 684 {
613 __set_proc_ids(hp, "exec_unit"); 685 __set_proc_ids(hp, "exec_unit");
614 __set_proc_ids(hp, "exec-unit"); 686 __set_proc_ids(hp, "exec-unit");
615 } 687 }
616 688
617 static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask, 689 static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
618 unsigned char def) 690 unsigned char def)
619 { 691 {
620 u64 val; 692 u64 val;
621 693
622 if (!p) 694 if (!p)
623 goto use_default; 695 goto use_default;
624 val = *p; 696 val = *p;
625 697
626 if (!val || val >= 64) 698 if (!val || val >= 64)
627 goto use_default; 699 goto use_default;
628 700
629 *mask = ((1U << val) * 64U) - 1U; 701 *mask = ((1U << val) * 64U) - 1U;
630 return; 702 return;
631 703
632 use_default: 704 use_default:
633 *mask = ((1U << def) * 64U) - 1U; 705 *mask = ((1U << def) * 64U) - 1U;
634 } 706 }
635 707
636 static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp, 708 static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
637 struct trap_per_cpu *tb) 709 struct trap_per_cpu *tb)
638 { 710 {
639 const u64 *val; 711 const u64 *val;
640 712
641 val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL); 713 val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
642 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7); 714 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
643 715
644 val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL); 716 val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
645 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7); 717 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
646 718
647 val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL); 719 val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
648 get_one_mondo_bits(val, &tb->resum_qmask, 6); 720 get_one_mondo_bits(val, &tb->resum_qmask, 6);
649 721
650 val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL); 722 val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
651 get_one_mondo_bits(val, &tb->nonresum_qmask, 2); 723 get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
652 } 724 }
653 725
654 void __devinit mdesc_fill_in_cpu_data(cpumask_t mask) 726 void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
655 { 727 {
656 struct mdesc_handle *hp = mdesc_grab(); 728 struct mdesc_handle *hp = mdesc_grab();
657 u64 mp; 729 u64 mp;
658 730
659 ncpus_probed = 0; 731 ncpus_probed = 0;
660 mdesc_for_each_node_by_name(hp, mp, "cpu") { 732 mdesc_for_each_node_by_name(hp, mp, "cpu") {
661 const u64 *id = mdesc_get_property(hp, mp, "id", NULL); 733 const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
662 const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL); 734 const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
663 struct trap_per_cpu *tb; 735 struct trap_per_cpu *tb;
664 cpuinfo_sparc *c; 736 cpuinfo_sparc *c;
665 int cpuid; 737 int cpuid;
666 u64 a; 738 u64 a;
667 739
668 ncpus_probed++; 740 ncpus_probed++;
669 741
670 cpuid = *id; 742 cpuid = *id;
671 743
672 #ifdef CONFIG_SMP 744 #ifdef CONFIG_SMP
673 if (cpuid >= NR_CPUS) 745 if (cpuid >= NR_CPUS)
674 continue; 746 continue;
675 if (!cpu_isset(cpuid, mask)) 747 if (!cpu_isset(cpuid, mask))
676 continue; 748 continue;
677 #else 749 #else
678 /* On uniprocessor we only want the values for the 750 /* On uniprocessor we only want the values for the
679 * real physical cpu the kernel booted onto, however 751 * real physical cpu the kernel booted onto, however
680 * cpu_data() only has one entry at index 0. 752 * cpu_data() only has one entry at index 0.
681 */ 753 */
682 if (cpuid != real_hard_smp_processor_id()) 754 if (cpuid != real_hard_smp_processor_id())
683 continue; 755 continue;
684 cpuid = 0; 756 cpuid = 0;
685 #endif 757 #endif
686 758
687 c = &cpu_data(cpuid); 759 c = &cpu_data(cpuid);
688 c->clock_tick = *cfreq; 760 c->clock_tick = *cfreq;
689 761
690 tb = &trap_block[cpuid]; 762 tb = &trap_block[cpuid];
691 get_mondo_data(hp, mp, tb); 763 get_mondo_data(hp, mp, tb);
692 764
693 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { 765 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
694 u64 j, t = mdesc_arc_target(hp, a); 766 u64 j, t = mdesc_arc_target(hp, a);
695 const char *t_name; 767 const char *t_name;
696 768
697 t_name = mdesc_node_name(hp, t); 769 t_name = mdesc_node_name(hp, t);
698 if (!strcmp(t_name, "cache")) { 770 if (!strcmp(t_name, "cache")) {
699 fill_in_one_cache(c, hp, t); 771 fill_in_one_cache(c, hp, t);
700 continue; 772 continue;
701 } 773 }
702 774
703 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) { 775 mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
704 u64 n = mdesc_arc_target(hp, j); 776 u64 n = mdesc_arc_target(hp, j);
705 const char *n_name; 777 const char *n_name;
706 778
707 n_name = mdesc_node_name(hp, n); 779 n_name = mdesc_node_name(hp, n);
708 if (!strcmp(n_name, "cache")) 780 if (!strcmp(n_name, "cache"))
709 fill_in_one_cache(c, hp, n); 781 fill_in_one_cache(c, hp, n);
710 } 782 }
711 } 783 }
712 784
713 #ifdef CONFIG_SMP 785 #ifdef CONFIG_SMP
714 cpu_set(cpuid, cpu_present_map); 786 cpu_set(cpuid, cpu_present_map);
715 #endif 787 #endif
716 788
717 c->core_id = 0; 789 c->core_id = 0;
718 c->proc_id = -1; 790 c->proc_id = -1;
719 } 791 }
720 792
721 #ifdef CONFIG_SMP 793 #ifdef CONFIG_SMP
722 sparc64_multi_core = 1; 794 sparc64_multi_core = 1;
723 #endif 795 #endif
724 796
725 set_core_ids(hp); 797 set_core_ids(hp);
726 set_proc_ids(hp); 798 set_proc_ids(hp);
727 799
728 smp_fill_in_sib_core_maps(); 800 smp_fill_in_sib_core_maps();
729 801
730 mdesc_release(hp); 802 mdesc_release(hp);
731 } 803 }
732 804
733 void __init sun4v_mdesc_init(void) 805 void __init sun4v_mdesc_init(void)
734 { 806 {
735 struct mdesc_handle *hp; 807 struct mdesc_handle *hp;
736 unsigned long len, real_len, status; 808 unsigned long len, real_len, status;
737 cpumask_t mask; 809 cpumask_t mask;
738 810
739 (void) sun4v_mach_desc(0UL, 0UL, &len); 811 (void) sun4v_mach_desc(0UL, 0UL, &len);
740 812
741 printk("MDESC: Size is %lu bytes.\n", len); 813 printk("MDESC: Size is %lu bytes.\n", len);
742 814
743 hp = mdesc_alloc(len, &bootmem_mdesc_memops); 815 hp = mdesc_alloc(len, &bootmem_mdesc_memops);
744 if (hp == NULL) { 816 if (hp == NULL) {
745 prom_printf("MDESC: alloc of %lu bytes failed.\n", len); 817 prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
746 prom_halt(); 818 prom_halt();
747 } 819 }
748 820
749 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); 821 status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
750 if (status != HV_EOK || real_len > len) { 822 if (status != HV_EOK || real_len > len) {
751 prom_printf("sun4v_mach_desc fails, err(%lu), " 823 prom_printf("sun4v_mach_desc fails, err(%lu), "
752 "len(%lu), real_len(%lu)\n", 824 "len(%lu), real_len(%lu)\n",
753 status, len, real_len); 825 status, len, real_len);
754 mdesc_free(hp); 826 mdesc_free(hp);
755 prom_halt(); 827 prom_halt();
756 } 828 }
757 829
758 cur_mdesc = hp; 830 cur_mdesc = hp;
759 831
760 report_platform_properties(); 832 report_platform_properties();
761 833
762 cpus_setall(mask); 834 cpus_setall(mask);
763 mdesc_fill_in_cpu_data(mask); 835 mdesc_fill_in_cpu_data(mask);
764 } 836 }
765 837
arch/sparc64/kernel/vio.c
1 /* vio.c: Virtual I/O channel devices probing infrastructure. 1 /* vio.c: Virtual I/O channel devices probing infrastructure.
2 * 2 *
3 * Copyright (c) 2003-2005 IBM Corp. 3 * Copyright (c) 2003-2005 IBM Corp.
4 * Dave Engebretsen engebret@us.ibm.com 4 * Dave Engebretsen engebret@us.ibm.com
5 * Santiago Leon santil@us.ibm.com 5 * Santiago Leon santil@us.ibm.com
6 * Hollis Blanchard <hollisb@us.ibm.com> 6 * Hollis Blanchard <hollisb@us.ibm.com>
7 * Stephen Rothwell 7 * Stephen Rothwell
8 * 8 *
9 * Adapted to sparc64 by David S. Miller davem@davemloft.net 9 * Adapted to sparc64 by David S. Miller davem@davemloft.net
10 */ 10 */
11 11
12 #include <linux/kernel.h> 12 #include <linux/kernel.h>
13 #include <linux/irq.h> 13 #include <linux/irq.h>
14 #include <linux/init.h> 14 #include <linux/init.h>
15 15
16 #include <asm/mdesc.h> 16 #include <asm/mdesc.h>
17 #include <asm/vio.h> 17 #include <asm/vio.h>
18 18
19 static inline int find_in_proplist(const char *list, const char *match, 19 static inline int find_in_proplist(const char *list, const char *match,
20 int len) 20 int len)
21 { 21 {
22 while (len > 0) { 22 while (len > 0) {
23 int l; 23 int l;
24 24
25 if (!strcmp(list, match)) 25 if (!strcmp(list, match))
26 return 1; 26 return 1;
27 l = strlen(list) + 1; 27 l = strlen(list) + 1;
28 list += l; 28 list += l;
29 len -= l; 29 len -= l;
30 } 30 }
31 return 0; 31 return 0;
32 } 32 }
33 33
34 static const struct vio_device_id *vio_match_device( 34 static const struct vio_device_id *vio_match_device(
35 const struct vio_device_id *matches, 35 const struct vio_device_id *matches,
36 const struct vio_dev *dev) 36 const struct vio_dev *dev)
37 { 37 {
38 const char *type, *compat; 38 const char *type, *compat;
39 int len; 39 int len;
40 40
41 type = dev->type; 41 type = dev->type;
42 compat = dev->compat; 42 compat = dev->compat;
43 len = dev->compat_len; 43 len = dev->compat_len;
44 44
45 while (matches->type[0] || matches->compat[0]) { 45 while (matches->type[0] || matches->compat[0]) {
46 int match = 1; 46 int match = 1;
47 if (matches->type[0]) 47 if (matches->type[0])
48 match &= !strcmp(matches->type, type); 48 match &= !strcmp(matches->type, type);
49 49
50 if (matches->compat[0]) { 50 if (matches->compat[0]) {
51 match &= len && 51 match &= len &&
52 find_in_proplist(compat, matches->compat, len); 52 find_in_proplist(compat, matches->compat, len);
53 } 53 }
54 if (match) 54 if (match)
55 return matches; 55 return matches;
56 matches++; 56 matches++;
57 } 57 }
58 return NULL; 58 return NULL;
59 } 59 }
60 60
61 static int vio_bus_match(struct device *dev, struct device_driver *drv) 61 static int vio_bus_match(struct device *dev, struct device_driver *drv)
62 { 62 {
63 struct vio_dev *vio_dev = to_vio_dev(dev); 63 struct vio_dev *vio_dev = to_vio_dev(dev);
64 struct vio_driver *vio_drv = to_vio_driver(drv); 64 struct vio_driver *vio_drv = to_vio_driver(drv);
65 const struct vio_device_id *matches = vio_drv->id_table; 65 const struct vio_device_id *matches = vio_drv->id_table;
66 66
67 if (!matches) 67 if (!matches)
68 return 0; 68 return 0;
69 69
70 return vio_match_device(matches, vio_dev) != NULL; 70 return vio_match_device(matches, vio_dev) != NULL;
71 } 71 }
72 72
73 static int vio_device_probe(struct device *dev) 73 static int vio_device_probe(struct device *dev)
74 { 74 {
75 struct vio_dev *vdev = to_vio_dev(dev); 75 struct vio_dev *vdev = to_vio_dev(dev);
76 struct vio_driver *drv = to_vio_driver(dev->driver); 76 struct vio_driver *drv = to_vio_driver(dev->driver);
77 const struct vio_device_id *id; 77 const struct vio_device_id *id;
78 int error = -ENODEV; 78 int error = -ENODEV;
79 79
80 if (drv->probe) { 80 if (drv->probe) {
81 id = vio_match_device(drv->id_table, vdev); 81 id = vio_match_device(drv->id_table, vdev);
82 if (id) 82 if (id)
83 error = drv->probe(vdev, id); 83 error = drv->probe(vdev, id);
84 } 84 }
85 85
86 return error; 86 return error;
87 } 87 }
88 88
89 static int vio_device_remove(struct device *dev) 89 static int vio_device_remove(struct device *dev)
90 { 90 {
91 struct vio_dev *vdev = to_vio_dev(dev); 91 struct vio_dev *vdev = to_vio_dev(dev);
92 struct vio_driver *drv = to_vio_driver(dev->driver); 92 struct vio_driver *drv = to_vio_driver(dev->driver);
93 93
94 if (drv->remove) 94 if (drv->remove)
95 return drv->remove(vdev); 95 return drv->remove(vdev);
96 96
97 return 1; 97 return 1;
98 } 98 }
99 99
100 static ssize_t devspec_show(struct device *dev, 100 static ssize_t devspec_show(struct device *dev,
101 struct device_attribute *attr, char *buf) 101 struct device_attribute *attr, char *buf)
102 { 102 {
103 struct vio_dev *vdev = to_vio_dev(dev); 103 struct vio_dev *vdev = to_vio_dev(dev);
104 const char *str = "none"; 104 const char *str = "none";
105 105
106 if (!strcmp(vdev->type, "network")) 106 if (!strcmp(vdev->type, "network"))
107 str = "vnet"; 107 str = "vnet";
108 else if (!strcmp(vdev->type, "block")) 108 else if (!strcmp(vdev->type, "block"))
109 str = "vdisk"; 109 str = "vdisk";
110 110
111 return sprintf(buf, "%s\n", str); 111 return sprintf(buf, "%s\n", str);
112 } 112 }
113 113
114 static ssize_t type_show(struct device *dev, 114 static ssize_t type_show(struct device *dev,
115 struct device_attribute *attr, char *buf) 115 struct device_attribute *attr, char *buf)
116 { 116 {
117 struct vio_dev *vdev = to_vio_dev(dev); 117 struct vio_dev *vdev = to_vio_dev(dev);
118 return sprintf(buf, "%s\n", vdev->type); 118 return sprintf(buf, "%s\n", vdev->type);
119 } 119 }
120 120
121 static struct device_attribute vio_dev_attrs[] = { 121 static struct device_attribute vio_dev_attrs[] = {
122 __ATTR_RO(devspec), 122 __ATTR_RO(devspec),
123 __ATTR_RO(type), 123 __ATTR_RO(type),
124 __ATTR_NULL 124 __ATTR_NULL
125 }; 125 };
126 126
127 static struct bus_type vio_bus_type = { 127 static struct bus_type vio_bus_type = {
128 .name = "vio", 128 .name = "vio",
129 .dev_attrs = vio_dev_attrs, 129 .dev_attrs = vio_dev_attrs,
130 .match = vio_bus_match, 130 .match = vio_bus_match,
131 .probe = vio_device_probe, 131 .probe = vio_device_probe,
132 .remove = vio_device_remove, 132 .remove = vio_device_remove,
133 }; 133 };
134 134
135 int vio_register_driver(struct vio_driver *viodrv) 135 int vio_register_driver(struct vio_driver *viodrv)
136 { 136 {
137 viodrv->driver.bus = &vio_bus_type; 137 viodrv->driver.bus = &vio_bus_type;
138 138
139 return driver_register(&viodrv->driver); 139 return driver_register(&viodrv->driver);
140 } 140 }
141 EXPORT_SYMBOL(vio_register_driver); 141 EXPORT_SYMBOL(vio_register_driver);
142 142
143 void vio_unregister_driver(struct vio_driver *viodrv) 143 void vio_unregister_driver(struct vio_driver *viodrv)
144 { 144 {
145 driver_unregister(&viodrv->driver); 145 driver_unregister(&viodrv->driver);
146 } 146 }
147 EXPORT_SYMBOL(vio_unregister_driver); 147 EXPORT_SYMBOL(vio_unregister_driver);
148 148
149 static void __devinit vio_dev_release(struct device *dev) 149 static void __devinit vio_dev_release(struct device *dev)
150 { 150 {
151 kfree(to_vio_dev(dev)); 151 kfree(to_vio_dev(dev));
152 } 152 }
153 153
154 static ssize_t 154 static ssize_t
155 show_pciobppath_attr(struct device *dev, struct device_attribute *attr, 155 show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
156 char *buf) 156 char *buf)
157 { 157 {
158 struct vio_dev *vdev; 158 struct vio_dev *vdev;
159 struct device_node *dp; 159 struct device_node *dp;
160 160
161 vdev = to_vio_dev(dev); 161 vdev = to_vio_dev(dev);
162 dp = vdev->dp; 162 dp = vdev->dp;
163 163
164 return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name); 164 return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name);
165 } 165 }
166 166
167 static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, 167 static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
168 show_pciobppath_attr, NULL); 168 show_pciobppath_attr, NULL);
169 169
170 struct device_node *cdev_node; 170 struct device_node *cdev_node;
171 171
172 static struct vio_dev *root_vdev; 172 static struct vio_dev *root_vdev;
173 static u64 cdev_cfg_handle; 173 static u64 cdev_cfg_handle;
174 174
175 static void vio_add(struct mdesc_handle *hp, u64 node)
176 {
177 const char *name = mdesc_get_property(hp, node, "name", NULL);
178 const u64 *id = mdesc_get_property(hp, node, "id", NULL);
179
180 printk(KERN_ERR "VIO: Device add (%s) ID[%lx]\n",
181 name, *id);
182 }
183
184 static void vio_remove(struct mdesc_handle *hp, u64 node)
185 {
186 const char *name = mdesc_get_property(hp, node, "name", NULL);
187 const u64 *id = mdesc_get_property(hp, node, "id", NULL);
188
189 printk(KERN_ERR "VIO: Device remove (%s) ID[%lx]\n",
190 name, *id);
191 }
192
193 static struct mdesc_notifier_client vio_device_notifier = {
194 .add = vio_add,
195 .remove = vio_remove,
196 .node_name = "virtual-device-port",
197 };
198
199 static struct mdesc_notifier_client vio_ds_notifier = {
200 .add = vio_add,
201 .remove = vio_remove,
202 .node_name = "domain-services-port",
203 };
204
175 static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, 205 static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
176 struct vio_dev *vdev) 206 struct vio_dev *vdev)
177 { 207 {
178 u64 a; 208 u64 a;
179 209
180 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { 210 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
181 const u64 *chan_id; 211 const u64 *chan_id;
182 const u64 *irq; 212 const u64 *irq;
183 u64 target; 213 u64 target;
184 214
185 target = mdesc_arc_target(hp, a); 215 target = mdesc_arc_target(hp, a);
186 216
187 irq = mdesc_get_property(hp, target, "tx-ino", NULL); 217 irq = mdesc_get_property(hp, target, "tx-ino", NULL);
188 if (irq) 218 if (irq)
189 vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq); 219 vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
190 220
191 irq = mdesc_get_property(hp, target, "rx-ino", NULL); 221 irq = mdesc_get_property(hp, target, "rx-ino", NULL);
192 if (irq) 222 if (irq)
193 vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq); 223 vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
194 224
195 chan_id = mdesc_get_property(hp, target, "id", NULL); 225 chan_id = mdesc_get_property(hp, target, "id", NULL);
196 if (chan_id) 226 if (chan_id)
197 vdev->channel_id = *chan_id; 227 vdev->channel_id = *chan_id;
198 } 228 }
199 } 229 }
200 230
201 static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, 231 static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
202 struct device *parent) 232 struct device *parent)
203 { 233 {
204 const char *type, *compat; 234 const char *type, *compat;
205 struct device_node *dp; 235 struct device_node *dp;
206 struct vio_dev *vdev; 236 struct vio_dev *vdev;
207 int err, tlen, clen; 237 int err, tlen, clen;
208 238
209 type = mdesc_get_property(hp, mp, "device-type", &tlen); 239 type = mdesc_get_property(hp, mp, "device-type", &tlen);
210 if (!type) { 240 if (!type) {
211 type = mdesc_get_property(hp, mp, "name", &tlen); 241 type = mdesc_get_property(hp, mp, "name", &tlen);
212 if (!type) { 242 if (!type) {
213 type = mdesc_node_name(hp, mp); 243 type = mdesc_node_name(hp, mp);
214 tlen = strlen(type) + 1; 244 tlen = strlen(type) + 1;
215 } 245 }
216 } 246 }
217 if (tlen > VIO_MAX_TYPE_LEN) { 247 if (tlen > VIO_MAX_TYPE_LEN) {
218 printk(KERN_ERR "VIO: Type string [%s] is too long.\n", 248 printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
219 type); 249 type);
220 return NULL; 250 return NULL;
221 } 251 }
222 252
223 compat = mdesc_get_property(hp, mp, "device-type", &clen); 253 compat = mdesc_get_property(hp, mp, "device-type", &clen);
224 if (!compat) { 254 if (!compat) {
225 clen = 0; 255 clen = 0;
226 } else if (clen > VIO_MAX_COMPAT_LEN) { 256 } else if (clen > VIO_MAX_COMPAT_LEN) {
227 printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n", 257 printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
228 clen, type); 258 clen, type);
229 return NULL; 259 return NULL;
230 } 260 }
231 261
232 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); 262 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
233 if (!vdev) { 263 if (!vdev) {
234 printk(KERN_ERR "VIO: Could not allocate vio_dev\n"); 264 printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
235 return NULL; 265 return NULL;
236 } 266 }
237 267
238 vdev->mp = mp; 268 vdev->mp = mp;
239 memcpy(vdev->type, type, tlen); 269 memcpy(vdev->type, type, tlen);
240 if (compat) 270 if (compat)
241 memcpy(vdev->compat, compat, clen); 271 memcpy(vdev->compat, compat, clen);
242 else 272 else
243 memset(vdev->compat, 0, sizeof(vdev->compat)); 273 memset(vdev->compat, 0, sizeof(vdev->compat));
244 vdev->compat_len = clen; 274 vdev->compat_len = clen;
245 275
246 vdev->channel_id = ~0UL; 276 vdev->channel_id = ~0UL;
247 vdev->tx_irq = ~0; 277 vdev->tx_irq = ~0;
248 vdev->rx_irq = ~0; 278 vdev->rx_irq = ~0;
249 279
250 vio_fill_channel_info(hp, mp, vdev); 280 vio_fill_channel_info(hp, mp, vdev);
251 281
252 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp); 282 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp);
253 vdev->dev.parent = parent; 283 vdev->dev.parent = parent;
254 vdev->dev.bus = &vio_bus_type; 284 vdev->dev.bus = &vio_bus_type;
255 vdev->dev.release = vio_dev_release; 285 vdev->dev.release = vio_dev_release;
256 286
257 if (parent == NULL) { 287 if (parent == NULL) {
258 dp = cdev_node; 288 dp = cdev_node;
259 } else if (to_vio_dev(parent) == root_vdev) { 289 } else if (to_vio_dev(parent) == root_vdev) {
260 dp = of_get_next_child(cdev_node, NULL); 290 dp = of_get_next_child(cdev_node, NULL);
261 while (dp) { 291 while (dp) {
262 if (!strcmp(dp->type, type)) 292 if (!strcmp(dp->type, type))
263 break; 293 break;
264 294
265 dp = of_get_next_child(cdev_node, dp); 295 dp = of_get_next_child(cdev_node, dp);
266 } 296 }
267 } else { 297 } else {
268 dp = to_vio_dev(parent)->dp; 298 dp = to_vio_dev(parent)->dp;
269 } 299 }
270 vdev->dp = dp; 300 vdev->dp = dp;
271 301
272 err = device_register(&vdev->dev); 302 err = device_register(&vdev->dev);
273 if (err) { 303 if (err) {
274 printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", 304 printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
275 vdev->dev.bus_id, err); 305 vdev->dev.bus_id, err);
276 kfree(vdev); 306 kfree(vdev);
277 return NULL; 307 return NULL;
278 } 308 }
279 if (vdev->dp) 309 if (vdev->dp)
280 err = sysfs_create_file(&vdev->dev.kobj, 310 err = sysfs_create_file(&vdev->dev.kobj,
281 &dev_attr_obppath.attr); 311 &dev_attr_obppath.attr);
282 312
283 return vdev; 313 return vdev;
284 } 314 }
285 315
286 static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent) 316 static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent)
287 { 317 {
288 u64 a; 318 u64 a;
289 319
290 mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) { 320 mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
291 struct vio_dev *vdev; 321 struct vio_dev *vdev;
292 u64 target; 322 u64 target;
293 323
294 target = mdesc_arc_target(hp, a); 324 target = mdesc_arc_target(hp, a);
295 vdev = vio_create_one(hp, target, &parent->dev); 325 vdev = vio_create_one(hp, target, &parent->dev);
296 if (vdev) 326 if (vdev)
297 walk_tree(hp, target, vdev); 327 walk_tree(hp, target, vdev);
298 } 328 }
299 } 329 }
300 330
301 static void create_devices(struct mdesc_handle *hp, u64 root) 331 static void create_devices(struct mdesc_handle *hp, u64 root)
302 { 332 {
303 u64 mp; 333 u64 mp;
304 334
305 root_vdev = vio_create_one(hp, root, NULL); 335 root_vdev = vio_create_one(hp, root, NULL);
306 if (!root_vdev) { 336 if (!root_vdev) {
307 printk(KERN_ERR "VIO: Coult not create root device.\n"); 337 printk(KERN_ERR "VIO: Coult not create root device.\n");
308 return; 338 return;
309 } 339 }
310 340
311 walk_tree(hp, root, root_vdev); 341 walk_tree(hp, root, root_vdev);
312 342
313 /* Domain services is odd as it doesn't sit underneath the 343 /* Domain services is odd as it doesn't sit underneath the
314 * channel-devices node, so we plug it in manually. 344 * channel-devices node, so we plug it in manually.
315 */ 345 */
316 mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services"); 346 mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services");
317 if (mp != MDESC_NODE_NULL) { 347 if (mp != MDESC_NODE_NULL) {
318 struct vio_dev *parent = vio_create_one(hp, mp, 348 struct vio_dev *parent = vio_create_one(hp, mp,
319 &root_vdev->dev); 349 &root_vdev->dev);
320 350
321 if (parent) 351 if (parent)
322 walk_tree(hp, mp, parent); 352 walk_tree(hp, mp, parent);
323 } 353 }
324 } 354 }
325 355
326 const char *channel_devices_node = "channel-devices"; 356 const char *channel_devices_node = "channel-devices";
327 const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; 357 const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
328 const char *cfg_handle_prop = "cfg-handle"; 358 const char *cfg_handle_prop = "cfg-handle";
329 359
330 static int __init vio_init(void) 360 static int __init vio_init(void)
331 { 361 {
332 struct mdesc_handle *hp; 362 struct mdesc_handle *hp;
333 const char *compat; 363 const char *compat;
334 const u64 *cfg_handle; 364 const u64 *cfg_handle;
335 int err, len; 365 int err, len;
336 u64 root; 366 u64 root;
337 367
338 err = bus_register(&vio_bus_type); 368 err = bus_register(&vio_bus_type);
339 if (err) { 369 if (err) {
340 printk(KERN_ERR "VIO: Could not register bus type err=%d\n", 370 printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
341 err); 371 err);
342 return err; 372 return err;
343 } 373 }
344 374
345 hp = mdesc_grab(); 375 hp = mdesc_grab();
346 if (!hp) 376 if (!hp)
347 return 0; 377 return 0;
348 378
349 root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node); 379 root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
350 if (root == MDESC_NODE_NULL) { 380 if (root == MDESC_NODE_NULL) {
351 printk(KERN_INFO "VIO: No channel-devices MDESC node.\n"); 381 printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
352 mdesc_release(hp); 382 mdesc_release(hp);
353 return 0; 383 return 0;
354 } 384 }
355 385
356 cdev_node = of_find_node_by_name(NULL, "channel-devices"); 386 cdev_node = of_find_node_by_name(NULL, "channel-devices");
357 err = -ENODEV; 387 err = -ENODEV;
358 if (!cdev_node) { 388 if (!cdev_node) {
359 printk(KERN_INFO "VIO: No channel-devices OBP node.\n"); 389 printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
360 goto out_release; 390 goto out_release;
361 } 391 }
362 392
363 compat = mdesc_get_property(hp, root, "compatible", &len); 393 compat = mdesc_get_property(hp, root, "compatible", &len);
364 if (!compat) { 394 if (!compat) {
365 printk(KERN_ERR "VIO: Channel devices lacks compatible " 395 printk(KERN_ERR "VIO: Channel devices lacks compatible "
366 "property\n"); 396 "property\n");
367 goto out_release; 397 goto out_release;
368 } 398 }
369 if (!find_in_proplist(compat, channel_devices_compat, len)) { 399 if (!find_in_proplist(compat, channel_devices_compat, len)) {
370 printk(KERN_ERR "VIO: Channel devices node lacks (%s) " 400 printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
371 "compat entry.\n", channel_devices_compat); 401 "compat entry.\n", channel_devices_compat);
372 goto out_release; 402 goto out_release;
373 } 403 }
374 404
375 cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL); 405 cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
376 if (!cfg_handle) { 406 if (!cfg_handle) {
377 printk(KERN_ERR "VIO: Channel devices lacks %s property\n", 407 printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
378 cfg_handle_prop); 408 cfg_handle_prop);
379 goto out_release; 409 goto out_release;
380 } 410 }
381 411
382 cdev_cfg_handle = *cfg_handle; 412 cdev_cfg_handle = *cfg_handle;
413
414 mdesc_register_notifier(&vio_device_notifier);
415 mdesc_register_notifier(&vio_ds_notifier);
383 416
384 create_devices(hp, root); 417 create_devices(hp, root);
385 418
386 mdesc_release(hp); 419 mdesc_release(hp);
387 420
388 return 0; 421 return 0;
389 422
390 out_release: 423 out_release:
391 mdesc_release(hp); 424 mdesc_release(hp);
392 return err; 425 return err;
393 } 426 }
394 427
395 postcore_initcall(vio_init); 428 postcore_initcall(vio_init);
396 429
include/asm-sparc64/mdesc.h
1 #ifndef _SPARC64_MDESC_H 1 #ifndef _SPARC64_MDESC_H
2 #define _SPARC64_MDESC_H 2 #define _SPARC64_MDESC_H
3 3
4 #include <linux/types.h> 4 #include <linux/types.h>
5 #include <linux/cpumask.h> 5 #include <linux/cpumask.h>
6 #include <asm/prom.h> 6 #include <asm/prom.h>
7 7
8 struct mdesc_handle; 8 struct mdesc_handle;
9 9
10 /* Machine description operations are to be surrounded by grab and 10 /* Machine description operations are to be surrounded by grab and
11 * release calls. The mdesc_handle returned from the grab is 11 * release calls. The mdesc_handle returned from the grab is
12 * the first argument to all of the operational calls that work 12 * the first argument to all of the operational calls that work
13 * on mdescs. 13 * on mdescs.
14 */ 14 */
15 extern struct mdesc_handle *mdesc_grab(void); 15 extern struct mdesc_handle *mdesc_grab(void);
16 extern void mdesc_release(struct mdesc_handle *); 16 extern void mdesc_release(struct mdesc_handle *);
17 17
18 #define MDESC_NODE_NULL (~(u64)0) 18 #define MDESC_NODE_NULL (~(u64)0)
19 19
20 extern u64 mdesc_node_by_name(struct mdesc_handle *handle, 20 extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
21 u64 from_node, const char *name); 21 u64 from_node, const char *name);
22 #define mdesc_for_each_node_by_name(__hdl, __node, __name) \ 22 #define mdesc_for_each_node_by_name(__hdl, __node, __name) \
23 for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \ 23 for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
24 (__node) != MDESC_NODE_NULL; \ 24 (__node) != MDESC_NODE_NULL; \
25 __node = mdesc_node_by_name(__hdl, __node, __name)) 25 __node = mdesc_node_by_name(__hdl, __node, __name))
26 26
27 /* Access to property values returned from mdesc_get_property() are 27 /* Access to property values returned from mdesc_get_property() are
28 * only valid inside of a mdesc_grab()/mdesc_release() sequence. 28 * only valid inside of a mdesc_grab()/mdesc_release() sequence.
29 * Once mdesc_release() is called, the memory backed up by these 29 * Once mdesc_release() is called, the memory backed up by these
30 * pointers may reference freed up memory. 30 * pointers may reference freed up memory.
31 * 31 *
32 * Therefore callers must make copies of any property values 32 * Therefore callers must make copies of any property values
33 * they need. 33 * they need.
34 * 34 *
35 * These same rules apply to mdesc_node_name(). 35 * These same rules apply to mdesc_node_name().
36 */ 36 */
37 extern const void *mdesc_get_property(struct mdesc_handle *handle, 37 extern const void *mdesc_get_property(struct mdesc_handle *handle,
38 u64 node, const char *name, int *lenp); 38 u64 node, const char *name, int *lenp);
39 extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node); 39 extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
40 40
41 /* MD arc iteration, the standard sequence is: 41 /* MD arc iteration, the standard sequence is:
42 * 42 *
43 * unsigned long arc; 43 * unsigned long arc;
44 * mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) { 44 * mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
45 * unsigned long target = mdesc_arc_target(handle, arc); 45 * unsigned long target = mdesc_arc_target(handle, arc);
46 * ... 46 * ...
47 * } 47 * }
48 */ 48 */
49 49
50 #define MDESC_ARC_TYPE_FWD "fwd" 50 #define MDESC_ARC_TYPE_FWD "fwd"
51 #define MDESC_ARC_TYPE_BACK "back" 51 #define MDESC_ARC_TYPE_BACK "back"
52 52
53 extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from, 53 extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
54 const char *arc_type); 54 const char *arc_type);
55 #define mdesc_for_each_arc(__arc, __hdl, __node, __type) \ 55 #define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
56 for (__arc = mdesc_next_arc(__hdl, __node, __type); \ 56 for (__arc = mdesc_next_arc(__hdl, __node, __type); \
57 (__arc) != MDESC_NODE_NULL; \ 57 (__arc) != MDESC_NODE_NULL; \
58 __arc = mdesc_next_arc(__hdl, __arc, __type)) 58 __arc = mdesc_next_arc(__hdl, __arc, __type))
59 59
60 extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc); 60 extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
61 61
62 extern void mdesc_update(void); 62 extern void mdesc_update(void);
63 63
64 struct mdesc_notifier_client {
65 void (*add)(struct mdesc_handle *handle, u64 node);
66 void (*remove)(struct mdesc_handle *handle, u64 node);
67
68 const char *node_name;
69 struct mdesc_notifier_client *next;
70 };
71
72 extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
73
64 extern void mdesc_fill_in_cpu_data(cpumask_t mask); 74 extern void mdesc_fill_in_cpu_data(cpumask_t mask);
65 75
66 extern void sun4v_mdesc_init(void); 76 extern void sun4v_mdesc_init(void);
67 77
68 #endif 78 #endif
69 79