aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/ds.c22
-rw-r--r--arch/sparc64/kernel/ldc.c13
-rw-r--r--arch/sparc64/kernel/mdesc.c666
-rw-r--r--arch/sparc64/kernel/vio.c143
-rw-r--r--arch/sparc64/kernel/viohs.c35
5 files changed, 471 insertions, 408 deletions
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
index c7ece8c52039..9c8839d1cffd 100644
--- a/arch/sparc64/kernel/ds.c
+++ b/arch/sparc64/kernel/ds.c
@@ -15,6 +15,7 @@
15#include <asm/ldc.h> 15#include <asm/ldc.h>
16#include <asm/vio.h> 16#include <asm/vio.h>
17#include <asm/power.h> 17#include <asm/power.h>
18#include <asm/mdesc.h>
18 19
19#define DRV_MODULE_NAME "ds" 20#define DRV_MODULE_NAME "ds"
20#define PFX DRV_MODULE_NAME ": " 21#define PFX DRV_MODULE_NAME ": "
@@ -170,8 +171,7 @@ static void md_update_data(struct ldc_channel *lp,
170 171
171 rp = (struct ds_md_update_req *) (dpkt + 1); 172 rp = (struct ds_md_update_req *) (dpkt + 1);
172 173
173 printk(KERN_ERR PFX "MD update REQ [%lx] len=%d\n", 174 printk(KERN_ERR PFX "Machine description update.\n");
174 rp->req_num, len);
175 175
176 memset(&pkt, 0, sizeof(pkt)); 176 memset(&pkt, 0, sizeof(pkt));
177 pkt.data.tag.type = DS_DATA; 177 pkt.data.tag.type = DS_DATA;
@@ -181,6 +181,8 @@ static void md_update_data(struct ldc_channel *lp,
181 pkt.res.result = DS_OK; 181 pkt.res.result = DS_OK;
182 182
183 ds_send(lp, &pkt, sizeof(pkt)); 183 ds_send(lp, &pkt, sizeof(pkt));
184
185 mdesc_update();
184} 186}
185 187
186struct ds_shutdown_req { 188struct ds_shutdown_req {
@@ -555,7 +557,6 @@ static int __devinit ds_probe(struct vio_dev *vdev,
555 const struct vio_device_id *id) 557 const struct vio_device_id *id)
556{ 558{
557 static int ds_version_printed; 559 static int ds_version_printed;
558 struct mdesc_node *endp;
559 struct ldc_channel_config ds_cfg = { 560 struct ldc_channel_config ds_cfg = {
560 .event = ds_event, 561 .event = ds_event,
561 .mtu = 4096, 562 .mtu = 4096,
@@ -563,20 +564,11 @@ static int __devinit ds_probe(struct vio_dev *vdev,
563 }; 564 };
564 struct ldc_channel *lp; 565 struct ldc_channel *lp;
565 struct ds_info *dp; 566 struct ds_info *dp;
566 const u64 *chan_id;
567 int err; 567 int err;
568 568
569 if (ds_version_printed++ == 0) 569 if (ds_version_printed++ == 0)
570 printk(KERN_INFO "%s", version); 570 printk(KERN_INFO "%s", version);
571 571
572 endp = vio_find_endpoint(vdev);
573 if (!endp)
574 return -ENODEV;
575
576 chan_id = md_get_property(endp, "id", NULL);
577 if (!chan_id)
578 return -ENODEV;
579
580 dp = kzalloc(sizeof(*dp), GFP_KERNEL); 572 dp = kzalloc(sizeof(*dp), GFP_KERNEL);
581 err = -ENOMEM; 573 err = -ENOMEM;
582 if (!dp) 574 if (!dp)
@@ -588,10 +580,10 @@ static int __devinit ds_probe(struct vio_dev *vdev,
588 580
589 dp->rcv_buf_len = 4096; 581 dp->rcv_buf_len = 4096;
590 582
591 ds_cfg.tx_irq = endp->irqs[0]; 583 ds_cfg.tx_irq = vdev->tx_irq;
592 ds_cfg.rx_irq = endp->irqs[1]; 584 ds_cfg.rx_irq = vdev->rx_irq;
593 585
594 lp = ldc_alloc(*chan_id, &ds_cfg, dp); 586 lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
595 if (IS_ERR(lp)) { 587 if (IS_ERR(lp)) {
596 err = PTR_ERR(lp); 588 err = PTR_ERR(lp);
597 goto out_free_rcv_buf; 589 goto out_free_rcv_buf;
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
index dbb65b674a67..85a2be0b0962 100644
--- a/arch/sparc64/kernel/ldc.c
+++ b/arch/sparc64/kernel/ldc.c
@@ -2335,15 +2335,20 @@ EXPORT_SYMBOL(ldc_free_exp_dring);
2335 2335
2336static int __init ldc_init(void) 2336static int __init ldc_init(void)
2337{ 2337{
2338 struct mdesc_node *mp;
2339 unsigned long major, minor; 2338 unsigned long major, minor;
2339 struct mdesc_handle *hp;
2340 const u64 *v; 2340 const u64 *v;
2341 u64 mp;
2341 2342
2342 mp = md_find_node_by_name(NULL, "platform"); 2343 hp = mdesc_grab();
2343 if (!mp) 2344 if (!hp)
2344 return -ENODEV; 2345 return -ENODEV;
2345 2346
2346 v = md_get_property(mp, "domaining-enabled", NULL); 2347 mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
2348 if (mp == MDESC_NODE_NULL)
2349 return -ENODEV;
2350
2351 v = mdesc_get_property(hp, mp, "domaining-enabled", NULL);
2347 if (!v) 2352 if (!v)
2348 return -ENODEV; 2353 return -ENODEV;
2349 2354
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();
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 7eccc91cd59d..64f082555bcd 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -147,30 +147,6 @@ void vio_unregister_driver(struct vio_driver *viodrv)
147} 147}
148EXPORT_SYMBOL(vio_unregister_driver); 148EXPORT_SYMBOL(vio_unregister_driver);
149 149
150struct mdesc_node *vio_find_endpoint(struct vio_dev *vdev)
151{
152 struct mdesc_node *endp, *mp = vdev->mp;
153 int i;
154
155 endp = NULL;
156 for (i = 0; i < mp->num_arcs; i++) {
157 struct mdesc_node *t;
158
159 if (strcmp(mp->arcs[i].name, "fwd"))
160 continue;
161
162 t = mp->arcs[i].arc;
163 if (strcmp(t->name, "channel-endpoint"))
164 continue;
165
166 endp = t;
167 break;
168 }
169
170 return endp;
171}
172EXPORT_SYMBOL(vio_find_endpoint);
173
174static void __devinit vio_dev_release(struct device *dev) 150static void __devinit vio_dev_release(struct device *dev)
175{ 151{
176 kfree(to_vio_dev(dev)); 152 kfree(to_vio_dev(dev));
@@ -197,22 +173,47 @@ struct device_node *cdev_node;
197static struct vio_dev *root_vdev; 173static struct vio_dev *root_vdev;
198static u64 cdev_cfg_handle; 174static u64 cdev_cfg_handle;
199 175
200static struct vio_dev *vio_create_one(struct mdesc_node *mp, 176static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
177 struct vio_dev *vdev)
178{
179 u64 a;
180
181 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
182 const u64 *chan_id;
183 const u64 *irq;
184 u64 target;
185
186 target = mdesc_arc_target(hp, a);
187
188 irq = mdesc_get_property(hp, target, "tx-ino", NULL);
189 if (irq)
190 vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
191
192 irq = mdesc_get_property(hp, target, "rx-ino", NULL);
193 if (irq)
194 vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
195
196 chan_id = mdesc_get_property(hp, target, "id", NULL);
197 if (chan_id)
198 vdev->channel_id = *chan_id;
199 }
200}
201
202static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
201 struct device *parent) 203 struct device *parent)
202{ 204{
203 const char *type, *compat; 205 const char *type, *compat;
204 struct device_node *dp; 206 struct device_node *dp;
205 struct vio_dev *vdev; 207 struct vio_dev *vdev;
206 const u64 *irq;
207 int err, clen; 208 int err, clen;
208 209
209 type = md_get_property(mp, "device-type", NULL); 210 type = mdesc_get_property(hp, mp, "device-type", NULL);
210 if (!type) { 211 if (!type) {
211 type = md_get_property(mp, "name", NULL); 212 type = mdesc_get_property(hp, mp, "name", NULL);
212 if (!type) 213 if (!type)
213 type = mp->name; 214 type = mdesc_node_name(hp, mp);
214 } 215 }
215 compat = md_get_property(mp, "device-type", &clen); 216 compat = mdesc_get_property(hp, mp, "device-type", &clen);
216 217
217 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); 218 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
218 if (!vdev) { 219 if (!vdev) {
@@ -225,15 +226,13 @@ static struct vio_dev *vio_create_one(struct mdesc_node *mp,
225 vdev->compat = compat; 226 vdev->compat = compat;
226 vdev->compat_len = clen; 227 vdev->compat_len = clen;
227 228
228 irq = md_get_property(mp, "tx-ino", NULL); 229 vdev->channel_id = ~0UL;
229 if (irq) 230 vdev->tx_irq = ~0;
230 mp->irqs[0] = sun4v_build_virq(cdev_cfg_handle, *irq); 231 vdev->rx_irq = ~0;
231 232
232 irq = md_get_property(mp, "rx-ino", NULL); 233 vio_fill_channel_info(hp, mp, vdev);
233 if (irq)
234 mp->irqs[1] = sun4v_build_virq(cdev_cfg_handle, *irq);
235 234
236 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp->node); 235 snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp);
237 vdev->dev.parent = parent; 236 vdev->dev.parent = parent;
238 vdev->dev.bus = &vio_bus_type; 237 vdev->dev.bus = &vio_bus_type;
239 vdev->dev.release = vio_dev_release; 238 vdev->dev.release = vio_dev_release;
@@ -267,46 +266,43 @@ static struct vio_dev *vio_create_one(struct mdesc_node *mp,
267 return vdev; 266 return vdev;
268} 267}
269 268
270static void walk_tree(struct mdesc_node *n, struct vio_dev *parent) 269static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent)
271{ 270{
272 int i; 271 u64 a;
273 272
274 for (i = 0; i < n->num_arcs; i++) { 273 mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
275 struct mdesc_node *mp;
276 struct vio_dev *vdev; 274 struct vio_dev *vdev;
275 u64 target;
277 276
278 if (strcmp(n->arcs[i].name, "fwd")) 277 target = mdesc_arc_target(hp, a);
279 continue; 278 vdev = vio_create_one(hp, target, &parent->dev);
280 279 if (vdev)
281 mp = n->arcs[i].arc; 280 walk_tree(hp, target, vdev);
282
283 vdev = vio_create_one(mp, &parent->dev);
284 if (vdev && mp->num_arcs)
285 walk_tree(mp, vdev);
286 } 281 }
287} 282}
288 283
289static void create_devices(struct mdesc_node *root) 284static void create_devices(struct mdesc_handle *hp, u64 root)
290{ 285{
291 struct mdesc_node *mp; 286 u64 mp;
292 287
293 root_vdev = vio_create_one(root, NULL); 288 root_vdev = vio_create_one(hp, root, NULL);
294 if (!root_vdev) { 289 if (!root_vdev) {
295 printk(KERN_ERR "VIO: Coult not create root device.\n"); 290 printk(KERN_ERR "VIO: Coult not create root device.\n");
296 return; 291 return;
297 } 292 }
298 293
299 walk_tree(root, root_vdev); 294 walk_tree(hp, root, root_vdev);
300 295
301 /* Domain services is odd as it doesn't sit underneath the 296 /* Domain services is odd as it doesn't sit underneath the
302 * channel-devices node, so we plug it in manually. 297 * channel-devices node, so we plug it in manually.
303 */ 298 */
304 mp = md_find_node_by_name(NULL, "domain-services"); 299 mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services");
305 if (mp) { 300 if (mp != MDESC_NODE_NULL) {
306 struct vio_dev *parent = vio_create_one(mp, &root_vdev->dev); 301 struct vio_dev *parent = vio_create_one(hp, mp,
302 &root_vdev->dev);
307 303
308 if (parent) 304 if (parent)
309 walk_tree(mp, parent); 305 walk_tree(hp, mp, parent);
310 } 306 }
311} 307}
312 308
@@ -316,40 +312,47 @@ const char *cfg_handle_prop = "cfg-handle";
316 312
317static int __init vio_init(void) 313static int __init vio_init(void)
318{ 314{
319 struct mdesc_node *root; 315 struct mdesc_handle *hp;
320 const char *compat; 316 const char *compat;
321 const u64 *cfg_handle; 317 const u64 *cfg_handle;
322 int err, len; 318 int err, len;
319 u64 root;
320
321 hp = mdesc_grab();
322 if (!hp)
323 return 0;
323 324
324 root = md_find_node_by_name(NULL, channel_devices_node); 325 root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
325 if (!root) { 326 if (root == MDESC_NODE_NULL) {
326 printk(KERN_INFO "VIO: No channel-devices MDESC node.\n"); 327 printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
328 mdesc_release(hp);
327 return 0; 329 return 0;
328 } 330 }
329 331
330 cdev_node = of_find_node_by_name(NULL, "channel-devices"); 332 cdev_node = of_find_node_by_name(NULL, "channel-devices");
333 err = -ENODEV;
331 if (!cdev_node) { 334 if (!cdev_node) {
332 printk(KERN_INFO "VIO: No channel-devices OBP node.\n"); 335 printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
333 return -ENODEV; 336 goto out_release;
334 } 337 }
335 338
336 compat = md_get_property(root, "compatible", &len); 339 compat = mdesc_get_property(hp, root, "compatible", &len);
337 if (!compat) { 340 if (!compat) {
338 printk(KERN_ERR "VIO: Channel devices lacks compatible " 341 printk(KERN_ERR "VIO: Channel devices lacks compatible "
339 "property\n"); 342 "property\n");
340 return -ENODEV; 343 goto out_release;
341 } 344 }
342 if (!find_in_proplist(compat, channel_devices_compat, len)) { 345 if (!find_in_proplist(compat, channel_devices_compat, len)) {
343 printk(KERN_ERR "VIO: Channel devices node lacks (%s) " 346 printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
344 "compat entry.\n", channel_devices_compat); 347 "compat entry.\n", channel_devices_compat);
345 return -ENODEV; 348 goto out_release;
346 } 349 }
347 350
348 cfg_handle = md_get_property(root, cfg_handle_prop, NULL); 351 cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
349 if (!cfg_handle) { 352 if (!cfg_handle) {
350 printk(KERN_ERR "VIO: Channel devices lacks %s property\n", 353 printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
351 cfg_handle_prop); 354 cfg_handle_prop);
352 return -ENODEV; 355 goto out_release;
353 } 356 }
354 357
355 cdev_cfg_handle = *cfg_handle; 358 cdev_cfg_handle = *cfg_handle;
@@ -361,9 +364,15 @@ static int __init vio_init(void)
361 return err; 364 return err;
362 } 365 }
363 366
364 create_devices(root); 367 create_devices(hp, root);
368
369 mdesc_release(hp);
365 370
366 return 0; 371 return 0;
372
373out_release:
374 mdesc_release(hp);
375 return err;
367} 376}
368 377
369postcore_initcall(vio_init); 378postcore_initcall(vio_init);
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
index b0b1b8779342..15613add45d1 100644
--- a/arch/sparc64/kernel/viohs.c
+++ b/arch/sparc64/kernel/viohs.c
@@ -136,7 +136,7 @@ static int process_unknown(struct vio_driver_state *vio, void *arg)
136 pkt->type, pkt->stype, pkt->stype_env, pkt->sid); 136 pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
137 137
138 printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n", 138 printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
139 vio->channel_id); 139 vio->vdev->channel_id);
140 140
141 ldc_disconnect(vio->lp); 141 ldc_disconnect(vio->lp);
142 142
@@ -678,21 +678,11 @@ extern int vio_ldc_alloc(struct vio_driver_state *vio,
678{ 678{
679 struct ldc_channel_config cfg = *base_cfg; 679 struct ldc_channel_config cfg = *base_cfg;
680 struct ldc_channel *lp; 680 struct ldc_channel *lp;
681 const u64 *id;
682 681
683 id = md_get_property(vio->endpoint, "id", NULL); 682 cfg.tx_irq = vio->vdev->tx_irq;
684 if (!id) { 683 cfg.rx_irq = vio->vdev->rx_irq;
685 printk(KERN_ERR "%s: Channel lacks id property.\n",
686 vio->name);
687 return -ENODEV;
688 }
689
690 vio->channel_id = *id;
691
692 cfg.rx_irq = vio->rx_irq;
693 cfg.tx_irq = vio->tx_irq;
694 684
695 lp = ldc_alloc(vio->channel_id, &cfg, event_arg); 685 lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
696 if (IS_ERR(lp)) 686 if (IS_ERR(lp))
697 return PTR_ERR(lp); 687 return PTR_ERR(lp);
698 688
@@ -728,7 +718,7 @@ void vio_port_up(struct vio_driver_state *vio)
728 if (err) 718 if (err)
729 printk(KERN_WARNING "%s: Port %lu bind failed, " 719 printk(KERN_WARNING "%s: Port %lu bind failed, "
730 "err=%d\n", 720 "err=%d\n",
731 vio->name, vio->channel_id, err); 721 vio->name, vio->vdev->channel_id, err);
732 } 722 }
733 723
734 if (!err) { 724 if (!err) {
@@ -736,7 +726,7 @@ void vio_port_up(struct vio_driver_state *vio)
736 if (err) 726 if (err)
737 printk(KERN_WARNING "%s: Port %lu connect failed, " 727 printk(KERN_WARNING "%s: Port %lu connect failed, "
738 "err=%d\n", 728 "err=%d\n",
739 vio->name, vio->channel_id, err); 729 vio->name, vio->vdev->channel_id, err);
740 } 730 }
741 if (err) { 731 if (err) {
742 unsigned long expires = jiffies + HZ; 732 unsigned long expires = jiffies + HZ;
@@ -757,9 +747,9 @@ static void vio_port_timer(unsigned long _arg)
757} 747}
758 748
759int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev, 749int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
760 u8 dev_class, struct mdesc_node *channel_endpoint, 750 u8 dev_class, struct vio_version *ver_table,
761 struct vio_version *ver_table, int ver_table_size, 751 int ver_table_size, struct vio_driver_ops *ops,
762 struct vio_driver_ops *ops, char *name) 752 char *name)
763{ 753{
764 switch (dev_class) { 754 switch (dev_class) {
765 case VDEV_NETWORK: 755 case VDEV_NETWORK:
@@ -777,9 +767,6 @@ int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
777 !ops->handshake_complete) 767 !ops->handshake_complete)
778 return -EINVAL; 768 return -EINVAL;
779 769
780 if (!channel_endpoint)
781 return -EINVAL;
782
783 if (!ver_table || ver_table_size < 0) 770 if (!ver_table || ver_table_size < 0)
784 return -EINVAL; 771 return -EINVAL;
785 772
@@ -793,10 +780,6 @@ int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
793 vio->dev_class = dev_class; 780 vio->dev_class = dev_class;
794 vio->vdev = vdev; 781 vio->vdev = vdev;
795 782
796 vio->endpoint = channel_endpoint;
797 vio->tx_irq = channel_endpoint->irqs[0];
798 vio->rx_irq = channel_endpoint->irqs[1];
799
800 vio->ver_table = ver_table; 783 vio->ver_table = ver_table;
801 vio->ver_table_entries = ver_table_size; 784 vio->ver_table_entries = ver_table_size;
802 785