diff options
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/ds.c | 249 | ||||
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 72 | ||||
-rw-r--r-- | arch/sparc64/kernel/isa.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/mdesc.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/of_device.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/power.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 56 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 70 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 79 | ||||
-rw-r--r-- | arch/sparc64/kernel/vio.c | 35 |
14 files changed, 370 insertions, 225 deletions
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index 1a2062ecb0bc..9f472a79d37e 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c | |||
@@ -124,10 +124,11 @@ struct ds_data_nack { | |||
124 | __u64 result; | 124 | __u64 result; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | struct ds_info; | ||
127 | struct ds_cap_state { | 128 | struct ds_cap_state { |
128 | __u64 handle; | 129 | __u64 handle; |
129 | 130 | ||
130 | void (*data)(struct ldc_channel *lp, | 131 | void (*data)(struct ds_info *dp, |
131 | struct ds_cap_state *cp, | 132 | struct ds_cap_state *cp, |
132 | void *buf, int len); | 133 | void *buf, int len); |
133 | 134 | ||
@@ -139,27 +140,27 @@ struct ds_cap_state { | |||
139 | #define CAP_STATE_REGISTERED 0x02 | 140 | #define CAP_STATE_REGISTERED 0x02 |
140 | }; | 141 | }; |
141 | 142 | ||
142 | static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp, | 143 | static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp, |
143 | void *buf, int len); | 144 | void *buf, int len); |
144 | static void domain_shutdown_data(struct ldc_channel *lp, | 145 | static void domain_shutdown_data(struct ds_info *dp, |
145 | struct ds_cap_state *cp, | 146 | struct ds_cap_state *cp, |
146 | void *buf, int len); | 147 | void *buf, int len); |
147 | static void domain_panic_data(struct ldc_channel *lp, | 148 | static void domain_panic_data(struct ds_info *dp, |
148 | struct ds_cap_state *cp, | 149 | struct ds_cap_state *cp, |
149 | void *buf, int len); | 150 | void *buf, int len); |
150 | #ifdef CONFIG_HOTPLUG_CPU | 151 | #ifdef CONFIG_HOTPLUG_CPU |
151 | static void dr_cpu_data(struct ldc_channel *lp, | 152 | static void dr_cpu_data(struct ds_info *dp, |
152 | struct ds_cap_state *cp, | 153 | struct ds_cap_state *cp, |
153 | void *buf, int len); | 154 | void *buf, int len); |
154 | #endif | 155 | #endif |
155 | static void ds_pri_data(struct ldc_channel *lp, | 156 | static void ds_pri_data(struct ds_info *dp, |
156 | struct ds_cap_state *cp, | 157 | struct ds_cap_state *cp, |
157 | void *buf, int len); | 158 | void *buf, int len); |
158 | static void ds_var_data(struct ldc_channel *lp, | 159 | static void ds_var_data(struct ds_info *dp, |
159 | struct ds_cap_state *cp, | 160 | struct ds_cap_state *cp, |
160 | void *buf, int len); | 161 | void *buf, int len); |
161 | 162 | ||
162 | struct ds_cap_state ds_states[] = { | 163 | struct ds_cap_state ds_states_template[] = { |
163 | { | 164 | { |
164 | .service_id = "md-update", | 165 | .service_id = "md-update", |
165 | .data = md_update_data, | 166 | .data = md_update_data, |
@@ -200,30 +201,38 @@ struct ds_info { | |||
200 | #define DS_HS_START 0x01 | 201 | #define DS_HS_START 0x01 |
201 | #define DS_HS_DONE 0x02 | 202 | #define DS_HS_DONE 0x02 |
202 | 203 | ||
204 | u64 id; | ||
205 | |||
203 | void *rcv_buf; | 206 | void *rcv_buf; |
204 | int rcv_buf_len; | 207 | int rcv_buf_len; |
208 | |||
209 | struct ds_cap_state *ds_states; | ||
210 | int num_ds_states; | ||
211 | |||
212 | struct ds_info *next; | ||
205 | }; | 213 | }; |
206 | 214 | ||
207 | static struct ds_info *ds_info; | 215 | static struct ds_info *ds_info_list; |
208 | 216 | ||
209 | static struct ds_cap_state *find_cap(u64 handle) | 217 | static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle) |
210 | { | 218 | { |
211 | unsigned int index = handle >> 32; | 219 | unsigned int index = handle >> 32; |
212 | 220 | ||
213 | if (index >= ARRAY_SIZE(ds_states)) | 221 | if (index >= dp->num_ds_states) |
214 | return NULL; | 222 | return NULL; |
215 | return &ds_states[index]; | 223 | return &dp->ds_states[index]; |
216 | } | 224 | } |
217 | 225 | ||
218 | static struct ds_cap_state *find_cap_by_string(const char *name) | 226 | static struct ds_cap_state *find_cap_by_string(struct ds_info *dp, |
227 | const char *name) | ||
219 | { | 228 | { |
220 | int i; | 229 | int i; |
221 | 230 | ||
222 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 231 | for (i = 0; i < dp->num_ds_states; i++) { |
223 | if (strcmp(ds_states[i].service_id, name)) | 232 | if (strcmp(dp->ds_states[i].service_id, name)) |
224 | continue; | 233 | continue; |
225 | 234 | ||
226 | return &ds_states[i]; | 235 | return &dp->ds_states[i]; |
227 | } | 236 | } |
228 | return NULL; | 237 | return NULL; |
229 | } | 238 | } |
@@ -264,10 +273,11 @@ struct ds_md_update_res { | |||
264 | __u32 result; | 273 | __u32 result; |
265 | }; | 274 | }; |
266 | 275 | ||
267 | static void md_update_data(struct ldc_channel *lp, | 276 | static void md_update_data(struct ds_info *dp, |
268 | struct ds_cap_state *dp, | 277 | struct ds_cap_state *cp, |
269 | void *buf, int len) | 278 | void *buf, int len) |
270 | { | 279 | { |
280 | struct ldc_channel *lp = dp->lp; | ||
271 | struct ds_data *dpkt = buf; | 281 | struct ds_data *dpkt = buf; |
272 | struct ds_md_update_req *rp; | 282 | struct ds_md_update_req *rp; |
273 | struct { | 283 | struct { |
@@ -277,14 +287,14 @@ static void md_update_data(struct ldc_channel *lp, | |||
277 | 287 | ||
278 | rp = (struct ds_md_update_req *) (dpkt + 1); | 288 | rp = (struct ds_md_update_req *) (dpkt + 1); |
279 | 289 | ||
280 | printk(KERN_INFO PFX "Machine description update.\n"); | 290 | printk(KERN_INFO "ds-%lu: Machine description update.\n", dp->id); |
281 | 291 | ||
282 | mdesc_update(); | 292 | mdesc_update(); |
283 | 293 | ||
284 | memset(&pkt, 0, sizeof(pkt)); | 294 | memset(&pkt, 0, sizeof(pkt)); |
285 | pkt.data.tag.type = DS_DATA; | 295 | pkt.data.tag.type = DS_DATA; |
286 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 296 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
287 | pkt.data.handle = dp->handle; | 297 | pkt.data.handle = cp->handle; |
288 | pkt.res.req_num = rp->req_num; | 298 | pkt.res.req_num = rp->req_num; |
289 | pkt.res.result = DS_OK; | 299 | pkt.res.result = DS_OK; |
290 | 300 | ||
@@ -302,10 +312,11 @@ struct ds_shutdown_res { | |||
302 | char reason[1]; | 312 | char reason[1]; |
303 | }; | 313 | }; |
304 | 314 | ||
305 | static void domain_shutdown_data(struct ldc_channel *lp, | 315 | static void domain_shutdown_data(struct ds_info *dp, |
306 | struct ds_cap_state *dp, | 316 | struct ds_cap_state *cp, |
307 | void *buf, int len) | 317 | void *buf, int len) |
308 | { | 318 | { |
319 | struct ldc_channel *lp = dp->lp; | ||
309 | struct ds_data *dpkt = buf; | 320 | struct ds_data *dpkt = buf; |
310 | struct ds_shutdown_req *rp; | 321 | struct ds_shutdown_req *rp; |
311 | struct { | 322 | struct { |
@@ -315,13 +326,13 @@ static void domain_shutdown_data(struct ldc_channel *lp, | |||
315 | 326 | ||
316 | rp = (struct ds_shutdown_req *) (dpkt + 1); | 327 | rp = (struct ds_shutdown_req *) (dpkt + 1); |
317 | 328 | ||
318 | printk(KERN_ALERT PFX "Shutdown request from " | 329 | printk(KERN_ALERT "ds-%lu: Shutdown request from " |
319 | "LDOM manager received.\n"); | 330 | "LDOM manager received.\n", dp->id); |
320 | 331 | ||
321 | memset(&pkt, 0, sizeof(pkt)); | 332 | memset(&pkt, 0, sizeof(pkt)); |
322 | pkt.data.tag.type = DS_DATA; | 333 | pkt.data.tag.type = DS_DATA; |
323 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 334 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
324 | pkt.data.handle = dp->handle; | 335 | pkt.data.handle = cp->handle; |
325 | pkt.res.req_num = rp->req_num; | 336 | pkt.res.req_num = rp->req_num; |
326 | pkt.res.result = DS_OK; | 337 | pkt.res.result = DS_OK; |
327 | pkt.res.reason[0] = 0; | 338 | pkt.res.reason[0] = 0; |
@@ -341,10 +352,11 @@ struct ds_panic_res { | |||
341 | char reason[1]; | 352 | char reason[1]; |
342 | }; | 353 | }; |
343 | 354 | ||
344 | static void domain_panic_data(struct ldc_channel *lp, | 355 | static void domain_panic_data(struct ds_info *dp, |
345 | struct ds_cap_state *dp, | 356 | struct ds_cap_state *cp, |
346 | void *buf, int len) | 357 | void *buf, int len) |
347 | { | 358 | { |
359 | struct ldc_channel *lp = dp->lp; | ||
348 | struct ds_data *dpkt = buf; | 360 | struct ds_data *dpkt = buf; |
349 | struct ds_panic_req *rp; | 361 | struct ds_panic_req *rp; |
350 | struct { | 362 | struct { |
@@ -354,13 +366,13 @@ static void domain_panic_data(struct ldc_channel *lp, | |||
354 | 366 | ||
355 | rp = (struct ds_panic_req *) (dpkt + 1); | 367 | rp = (struct ds_panic_req *) (dpkt + 1); |
356 | 368 | ||
357 | printk(KERN_ALERT PFX "Panic request from " | 369 | printk(KERN_ALERT "ds-%lu: Panic request from " |
358 | "LDOM manager received.\n"); | 370 | "LDOM manager received.\n", dp->id); |
359 | 371 | ||
360 | memset(&pkt, 0, sizeof(pkt)); | 372 | memset(&pkt, 0, sizeof(pkt)); |
361 | pkt.data.tag.type = DS_DATA; | 373 | pkt.data.tag.type = DS_DATA; |
362 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 374 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
363 | pkt.data.handle = dp->handle; | 375 | pkt.data.handle = cp->handle; |
364 | pkt.res.req_num = rp->req_num; | 376 | pkt.res.req_num = rp->req_num; |
365 | pkt.res.result = DS_OK; | 377 | pkt.res.result = DS_OK; |
366 | pkt.res.reason[0] = 0; | 378 | pkt.res.reason[0] = 0; |
@@ -403,10 +415,11 @@ struct dr_cpu_resp_entry { | |||
403 | __u32 str_off; | 415 | __u32 str_off; |
404 | }; | 416 | }; |
405 | 417 | ||
406 | static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 418 | static void __dr_cpu_send_error(struct ds_info *dp, |
419 | struct ds_cap_state *cp, | ||
420 | struct ds_data *data) | ||
407 | { | 421 | { |
408 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); | 422 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); |
409 | struct ds_info *dp = ds_info; | ||
410 | struct { | 423 | struct { |
411 | struct ds_data data; | 424 | struct ds_data data; |
412 | struct dr_cpu_tag tag; | 425 | struct dr_cpu_tag tag; |
@@ -428,12 +441,14 @@ static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | |||
428 | __ds_send(dp->lp, &pkt, msg_len); | 441 | __ds_send(dp->lp, &pkt, msg_len); |
429 | } | 442 | } |
430 | 443 | ||
431 | static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 444 | static void dr_cpu_send_error(struct ds_info *dp, |
445 | struct ds_cap_state *cp, | ||
446 | struct ds_data *data) | ||
432 | { | 447 | { |
433 | unsigned long flags; | 448 | unsigned long flags; |
434 | 449 | ||
435 | spin_lock_irqsave(&ds_lock, flags); | 450 | spin_lock_irqsave(&ds_lock, flags); |
436 | __dr_cpu_send_error(cp, data); | 451 | __dr_cpu_send_error(dp, cp, data); |
437 | spin_unlock_irqrestore(&ds_lock, flags); | 452 | spin_unlock_irqrestore(&ds_lock, flags); |
438 | } | 453 | } |
439 | 454 | ||
@@ -511,7 +526,9 @@ static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus, | |||
511 | } | 526 | } |
512 | } | 527 | } |
513 | 528 | ||
514 | static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | 529 | static int dr_cpu_configure(struct ds_info *dp, |
530 | struct ds_cap_state *cp, | ||
531 | u64 req_num, | ||
515 | cpumask_t *mask) | 532 | cpumask_t *mask) |
516 | { | 533 | { |
517 | struct ds_data *resp; | 534 | struct ds_data *resp; |
@@ -533,7 +550,8 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
533 | for_each_cpu_mask(cpu, *mask) { | 550 | for_each_cpu_mask(cpu, *mask) { |
534 | int err; | 551 | int err; |
535 | 552 | ||
536 | printk(KERN_INFO PFX "Starting cpu %d...\n", cpu); | 553 | printk(KERN_INFO "ds-%lu: Starting cpu %d...\n", |
554 | dp->id, cpu); | ||
537 | err = cpu_up(cpu); | 555 | err = cpu_up(cpu); |
538 | if (err) { | 556 | if (err) { |
539 | __u32 res = DR_CPU_RES_FAILURE; | 557 | __u32 res = DR_CPU_RES_FAILURE; |
@@ -548,14 +566,14 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
548 | res = DR_CPU_RES_CPU_NOT_RESPONDING; | 566 | res = DR_CPU_RES_CPU_NOT_RESPONDING; |
549 | } | 567 | } |
550 | 568 | ||
551 | printk(KERN_INFO PFX "CPU startup failed err=%d\n", | 569 | printk(KERN_INFO "ds-%lu: CPU startup failed err=%d\n", |
552 | err); | 570 | dp->id, err); |
553 | dr_cpu_mark(resp, cpu, ncpus, res, stat); | 571 | dr_cpu_mark(resp, cpu, ncpus, res, stat); |
554 | } | 572 | } |
555 | } | 573 | } |
556 | 574 | ||
557 | spin_lock_irqsave(&ds_lock, flags); | 575 | spin_lock_irqsave(&ds_lock, flags); |
558 | __ds_send(ds_info->lp, resp, resp_len); | 576 | __ds_send(dp->lp, resp, resp_len); |
559 | spin_unlock_irqrestore(&ds_lock, flags); | 577 | spin_unlock_irqrestore(&ds_lock, flags); |
560 | 578 | ||
561 | kfree(resp); | 579 | kfree(resp); |
@@ -566,7 +584,9 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
566 | return 0; | 584 | return 0; |
567 | } | 585 | } |
568 | 586 | ||
569 | static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | 587 | static int dr_cpu_unconfigure(struct ds_info *dp, |
588 | struct ds_cap_state *cp, | ||
589 | u64 req_num, | ||
570 | cpumask_t *mask) | 590 | cpumask_t *mask) |
571 | { | 591 | { |
572 | struct ds_data *resp; | 592 | struct ds_data *resp; |
@@ -586,8 +606,8 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
586 | for_each_cpu_mask(cpu, *mask) { | 606 | for_each_cpu_mask(cpu, *mask) { |
587 | int err; | 607 | int err; |
588 | 608 | ||
589 | printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n", | 609 | printk(KERN_INFO "ds-%lu: Shutting down cpu %d...\n", |
590 | smp_processor_id(), cpu); | 610 | dp->id, cpu); |
591 | err = cpu_down(cpu); | 611 | err = cpu_down(cpu); |
592 | if (err) | 612 | if (err) |
593 | dr_cpu_mark(resp, cpu, ncpus, | 613 | dr_cpu_mark(resp, cpu, ncpus, |
@@ -596,7 +616,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
596 | } | 616 | } |
597 | 617 | ||
598 | spin_lock_irqsave(&ds_lock, flags); | 618 | spin_lock_irqsave(&ds_lock, flags); |
599 | __ds_send(ds_info->lp, resp, resp_len); | 619 | __ds_send(dp->lp, resp, resp_len); |
600 | spin_unlock_irqrestore(&ds_lock, flags); | 620 | spin_unlock_irqrestore(&ds_lock, flags); |
601 | 621 | ||
602 | kfree(resp); | 622 | kfree(resp); |
@@ -604,7 +624,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
604 | return 0; | 624 | return 0; |
605 | } | 625 | } |
606 | 626 | ||
607 | static void dr_cpu_data(struct ldc_channel *lp, | 627 | static void dr_cpu_data(struct ds_info *dp, |
608 | struct ds_cap_state *cp, | 628 | struct ds_cap_state *cp, |
609 | void *buf, int len) | 629 | void *buf, int len) |
610 | { | 630 | { |
@@ -623,7 +643,7 @@ static void dr_cpu_data(struct ldc_channel *lp, | |||
623 | break; | 643 | break; |
624 | 644 | ||
625 | default: | 645 | default: |
626 | dr_cpu_send_error(cp, data); | 646 | dr_cpu_send_error(dp, cp, data); |
627 | return; | 647 | return; |
628 | } | 648 | } |
629 | 649 | ||
@@ -639,12 +659,12 @@ static void dr_cpu_data(struct ldc_channel *lp, | |||
639 | } | 659 | } |
640 | 660 | ||
641 | if (tag->type == DR_CPU_CONFIGURE) | 661 | if (tag->type == DR_CPU_CONFIGURE) |
642 | err = dr_cpu_configure(cp, req_num, &mask); | 662 | err = dr_cpu_configure(dp, cp, req_num, &mask); |
643 | else | 663 | else |
644 | err = dr_cpu_unconfigure(cp, req_num, &mask); | 664 | err = dr_cpu_unconfigure(dp, cp, req_num, &mask); |
645 | 665 | ||
646 | if (err) | 666 | if (err) |
647 | dr_cpu_send_error(cp, data); | 667 | dr_cpu_send_error(dp, cp, data); |
648 | } | 668 | } |
649 | #endif /* CONFIG_HOTPLUG_CPU */ | 669 | #endif /* CONFIG_HOTPLUG_CPU */ |
650 | 670 | ||
@@ -656,8 +676,8 @@ struct ds_pri_msg { | |||
656 | #define DS_PRI_UPDATE 0x02 | 676 | #define DS_PRI_UPDATE 0x02 |
657 | }; | 677 | }; |
658 | 678 | ||
659 | static void ds_pri_data(struct ldc_channel *lp, | 679 | static void ds_pri_data(struct ds_info *dp, |
660 | struct ds_cap_state *dp, | 680 | struct ds_cap_state *cp, |
661 | void *buf, int len) | 681 | void *buf, int len) |
662 | { | 682 | { |
663 | struct ds_data *dpkt = buf; | 683 | struct ds_data *dpkt = buf; |
@@ -665,8 +685,8 @@ static void ds_pri_data(struct ldc_channel *lp, | |||
665 | 685 | ||
666 | rp = (struct ds_pri_msg *) (dpkt + 1); | 686 | rp = (struct ds_pri_msg *) (dpkt + 1); |
667 | 687 | ||
668 | printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n", | 688 | printk(KERN_INFO "ds-%lu: PRI REQ [%lx:%lx], len=%d\n", |
669 | rp->req_num, rp->type, len); | 689 | dp->id, rp->req_num, rp->type, len); |
670 | } | 690 | } |
671 | 691 | ||
672 | struct ds_var_hdr { | 692 | struct ds_var_hdr { |
@@ -701,8 +721,8 @@ static DEFINE_MUTEX(ds_var_mutex); | |||
701 | static int ds_var_doorbell; | 721 | static int ds_var_doorbell; |
702 | static int ds_var_response; | 722 | static int ds_var_response; |
703 | 723 | ||
704 | static void ds_var_data(struct ldc_channel *lp, | 724 | static void ds_var_data(struct ds_info *dp, |
705 | struct ds_cap_state *dp, | 725 | struct ds_cap_state *cp, |
706 | void *buf, int len) | 726 | void *buf, int len) |
707 | { | 727 | { |
708 | struct ds_data *dpkt = buf; | 728 | struct ds_data *dpkt = buf; |
@@ -721,14 +741,35 @@ static void ds_var_data(struct ldc_channel *lp, | |||
721 | 741 | ||
722 | void ldom_set_var(const char *var, const char *value) | 742 | void ldom_set_var(const char *var, const char *value) |
723 | { | 743 | { |
724 | struct ds_info *dp = ds_info; | ||
725 | struct ds_cap_state *cp; | 744 | struct ds_cap_state *cp; |
745 | struct ds_info *dp; | ||
746 | unsigned long flags; | ||
747 | |||
748 | spin_lock_irqsave(&ds_lock, flags); | ||
749 | cp = NULL; | ||
750 | for (dp = ds_info_list; dp; dp = dp->next) { | ||
751 | struct ds_cap_state *tmp; | ||
752 | |||
753 | tmp = find_cap_by_string(dp, "var-config"); | ||
754 | if (tmp && tmp->state == CAP_STATE_REGISTERED) { | ||
755 | cp = tmp; | ||
756 | break; | ||
757 | } | ||
758 | } | ||
759 | if (!cp) { | ||
760 | for (dp = ds_info_list; dp; dp = dp->next) { | ||
761 | struct ds_cap_state *tmp; | ||
726 | 762 | ||
727 | cp = find_cap_by_string("var-config"); | 763 | tmp = find_cap_by_string(dp, "var-config-backup"); |
728 | if (cp->state != CAP_STATE_REGISTERED) | 764 | if (tmp && tmp->state == CAP_STATE_REGISTERED) { |
729 | cp = find_cap_by_string("var-config-backup"); | 765 | cp = tmp; |
766 | break; | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | spin_unlock_irqrestore(&ds_lock, flags); | ||
730 | 771 | ||
731 | if (cp->state == CAP_STATE_REGISTERED) { | 772 | if (cp) { |
732 | union { | 773 | union { |
733 | struct { | 774 | struct { |
734 | struct ds_data data; | 775 | struct ds_data data; |
@@ -736,7 +777,6 @@ void ldom_set_var(const char *var, const char *value) | |||
736 | } header; | 777 | } header; |
737 | char all[512]; | 778 | char all[512]; |
738 | } pkt; | 779 | } pkt; |
739 | unsigned long flags; | ||
740 | char *base, *p; | 780 | char *base, *p; |
741 | int msg_len, loops; | 781 | int msg_len, loops; |
742 | 782 | ||
@@ -777,9 +817,9 @@ void ldom_set_var(const char *var, const char *value) | |||
777 | 817 | ||
778 | if (ds_var_doorbell == 0 || | 818 | if (ds_var_doorbell == 0 || |
779 | ds_var_response != DS_VAR_SUCCESS) | 819 | ds_var_response != DS_VAR_SUCCESS) |
780 | printk(KERN_ERR PFX "var-config [%s:%s] " | 820 | printk(KERN_ERR "ds-%lu: var-config [%s:%s] " |
781 | "failed, response(%d).\n", | 821 | "failed, response(%d).\n", |
782 | var, value, | 822 | dp->id, var, value, |
783 | ds_var_response); | 823 | ds_var_response); |
784 | } else { | 824 | } else { |
785 | printk(KERN_ERR PFX "var-config not registered so " | 825 | printk(KERN_ERR PFX "var-config not registered so " |
@@ -811,8 +851,8 @@ void ldom_power_off(void) | |||
811 | 851 | ||
812 | static void ds_conn_reset(struct ds_info *dp) | 852 | static void ds_conn_reset(struct ds_info *dp) |
813 | { | 853 | { |
814 | printk(KERN_ERR PFX "ds_conn_reset() from %p\n", | 854 | printk(KERN_ERR "ds-%lu: ds_conn_reset() from %p\n", |
815 | __builtin_return_address(0)); | 855 | dp->id, __builtin_return_address(0)); |
816 | } | 856 | } |
817 | 857 | ||
818 | static int register_services(struct ds_info *dp) | 858 | static int register_services(struct ds_info *dp) |
@@ -820,12 +860,12 @@ static int register_services(struct ds_info *dp) | |||
820 | struct ldc_channel *lp = dp->lp; | 860 | struct ldc_channel *lp = dp->lp; |
821 | int i; | 861 | int i; |
822 | 862 | ||
823 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 863 | for (i = 0; i < dp->num_ds_states; i++) { |
824 | struct { | 864 | struct { |
825 | struct ds_reg_req req; | 865 | struct ds_reg_req req; |
826 | u8 id_buf[256]; | 866 | u8 id_buf[256]; |
827 | } pbuf; | 867 | } pbuf; |
828 | struct ds_cap_state *cp = &ds_states[i]; | 868 | struct ds_cap_state *cp = &dp->ds_states[i]; |
829 | int err, msg_len; | 869 | int err, msg_len; |
830 | u64 new_count; | 870 | u64 new_count; |
831 | 871 | ||
@@ -870,28 +910,26 @@ static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt) | |||
870 | 910 | ||
871 | if (pkt->type == DS_REG_ACK) { | 911 | if (pkt->type == DS_REG_ACK) { |
872 | struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt; | 912 | struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt; |
873 | struct ds_cap_state *cp = find_cap(ap->handle); | 913 | struct ds_cap_state *cp = find_cap(dp, ap->handle); |
874 | 914 | ||
875 | if (!cp) { | 915 | if (!cp) { |
876 | printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n", | 916 | printk(KERN_ERR "ds-%lu: REG ACK for unknown " |
877 | ap->handle); | 917 | "handle %lx\n", dp->id, ap->handle); |
878 | return 0; | 918 | return 0; |
879 | } | 919 | } |
880 | printk(KERN_INFO PFX "Registered %s service.\n", | 920 | printk(KERN_INFO "ds-%lu: Registered %s service.\n", |
881 | cp->service_id); | 921 | dp->id, cp->service_id); |
882 | cp->state = CAP_STATE_REGISTERED; | 922 | cp->state = CAP_STATE_REGISTERED; |
883 | } else if (pkt->type == DS_REG_NACK) { | 923 | } else if (pkt->type == DS_REG_NACK) { |
884 | struct ds_reg_nack *np = (struct ds_reg_nack *) pkt; | 924 | struct ds_reg_nack *np = (struct ds_reg_nack *) pkt; |
885 | struct ds_cap_state *cp = find_cap(np->handle); | 925 | struct ds_cap_state *cp = find_cap(dp, np->handle); |
886 | 926 | ||
887 | if (!cp) { | 927 | if (!cp) { |
888 | printk(KERN_ERR PFX "REG NACK for " | 928 | printk(KERN_ERR "ds-%lu: REG NACK for " |
889 | "unknown handle %lx\n", | 929 | "unknown handle %lx\n", |
890 | np->handle); | 930 | dp->id, np->handle); |
891 | return 0; | 931 | return 0; |
892 | } | 932 | } |
893 | printk(KERN_INFO PFX "Could not register %s service\n", | ||
894 | cp->service_id); | ||
895 | cp->state = CAP_STATE_UNKNOWN; | 933 | cp->state = CAP_STATE_UNKNOWN; |
896 | } | 934 | } |
897 | 935 | ||
@@ -922,6 +960,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ds_wait); | |||
922 | 960 | ||
923 | struct ds_queue_entry { | 961 | struct ds_queue_entry { |
924 | struct list_head list; | 962 | struct list_head list; |
963 | struct ds_info *dp; | ||
925 | int req_len; | 964 | int req_len; |
926 | int __pad; | 965 | int __pad; |
927 | u64 req[0]; | 966 | u64 req[0]; |
@@ -930,7 +969,6 @@ struct ds_queue_entry { | |||
930 | static void process_ds_work(void) | 969 | static void process_ds_work(void) |
931 | { | 970 | { |
932 | struct ds_queue_entry *qp, *tmp; | 971 | struct ds_queue_entry *qp, *tmp; |
933 | static struct ds_info *dp; | ||
934 | unsigned long flags; | 972 | unsigned long flags; |
935 | LIST_HEAD(todo); | 973 | LIST_HEAD(todo); |
936 | 974 | ||
@@ -939,22 +977,22 @@ static void process_ds_work(void) | |||
939 | INIT_LIST_HEAD(&ds_work_list); | 977 | INIT_LIST_HEAD(&ds_work_list); |
940 | spin_unlock_irqrestore(&ds_lock, flags); | 978 | spin_unlock_irqrestore(&ds_lock, flags); |
941 | 979 | ||
942 | dp = ds_info; | ||
943 | |||
944 | list_for_each_entry_safe(qp, tmp, &todo, list) { | 980 | list_for_each_entry_safe(qp, tmp, &todo, list) { |
945 | struct ds_data *dpkt = (struct ds_data *) qp->req; | 981 | struct ds_data *dpkt = (struct ds_data *) qp->req; |
946 | struct ds_cap_state *cp = find_cap(dpkt->handle); | 982 | struct ds_info *dp = qp->dp; |
983 | struct ds_cap_state *cp = find_cap(dp, dpkt->handle); | ||
947 | int req_len = qp->req_len; | 984 | int req_len = qp->req_len; |
948 | 985 | ||
949 | if (!cp) { | 986 | if (!cp) { |
950 | printk(KERN_ERR PFX "Data for unknown handle %lu\n", | 987 | printk(KERN_ERR "ds-%lu: Data for unknown " |
951 | dpkt->handle); | 988 | "handle %lu\n", |
989 | dp->id, dpkt->handle); | ||
952 | 990 | ||
953 | spin_lock_irqsave(&ds_lock, flags); | 991 | spin_lock_irqsave(&ds_lock, flags); |
954 | __send_ds_nack(dp, dpkt->handle); | 992 | __send_ds_nack(dp, dpkt->handle); |
955 | spin_unlock_irqrestore(&ds_lock, flags); | 993 | spin_unlock_irqrestore(&ds_lock, flags); |
956 | } else { | 994 | } else { |
957 | cp->data(dp->lp, cp, dpkt, req_len); | 995 | cp->data(dp, cp, dpkt, req_len); |
958 | } | 996 | } |
959 | 997 | ||
960 | list_del(&qp->list); | 998 | list_del(&qp->list); |
@@ -990,6 +1028,7 @@ static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len) | |||
990 | if (!qp) { | 1028 | if (!qp) { |
991 | __send_ds_nack(dp, dpkt->handle); | 1029 | __send_ds_nack(dp, dpkt->handle); |
992 | } else { | 1030 | } else { |
1031 | qp->dp = dp; | ||
993 | memcpy(&qp->req, pkt, len); | 1032 | memcpy(&qp->req, pkt, len); |
994 | list_add_tail(&qp->list, &ds_work_list); | 1033 | list_add_tail(&qp->list, &ds_work_list); |
995 | wake_up(&ds_wait); | 1034 | wake_up(&ds_wait); |
@@ -1019,8 +1058,8 @@ static void ds_reset(struct ds_info *dp) | |||
1019 | 1058 | ||
1020 | dp->hs_state = 0; | 1059 | dp->hs_state = 0; |
1021 | 1060 | ||
1022 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | 1061 | for (i = 0; i < dp->num_ds_states; i++) { |
1023 | struct ds_cap_state *cp = &ds_states[i]; | 1062 | struct ds_cap_state *cp = &dp->ds_states[i]; |
1024 | 1063 | ||
1025 | cp->state = CAP_STATE_UNKNOWN; | 1064 | cp->state = CAP_STATE_UNKNOWN; |
1026 | } | 1065 | } |
@@ -1048,7 +1087,8 @@ static void ds_event(void *arg, int event) | |||
1048 | } | 1087 | } |
1049 | 1088 | ||
1050 | if (event != LDC_EVENT_DATA_READY) { | 1089 | if (event != LDC_EVENT_DATA_READY) { |
1051 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); | 1090 | printk(KERN_WARNING "ds-%lu: Unexpected LDC event %d\n", |
1091 | dp->id, event); | ||
1052 | spin_unlock_irqrestore(&ds_lock, flags); | 1092 | spin_unlock_irqrestore(&ds_lock, flags); |
1053 | return; | 1093 | return; |
1054 | } | 1094 | } |
@@ -1099,9 +1139,11 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
1099 | .mtu = 4096, | 1139 | .mtu = 4096, |
1100 | .mode = LDC_MODE_STREAM, | 1140 | .mode = LDC_MODE_STREAM, |
1101 | }; | 1141 | }; |
1142 | struct mdesc_handle *hp; | ||
1102 | struct ldc_channel *lp; | 1143 | struct ldc_channel *lp; |
1103 | struct ds_info *dp; | 1144 | struct ds_info *dp; |
1104 | int err; | 1145 | const u64 *val; |
1146 | int err, i; | ||
1105 | 1147 | ||
1106 | if (ds_version_printed++ == 0) | 1148 | if (ds_version_printed++ == 0) |
1107 | printk(KERN_INFO "%s", version); | 1149 | printk(KERN_INFO "%s", version); |
@@ -1111,19 +1153,37 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
1111 | if (!dp) | 1153 | if (!dp) |
1112 | goto out_err; | 1154 | goto out_err; |
1113 | 1155 | ||
1156 | hp = mdesc_grab(); | ||
1157 | val = mdesc_get_property(hp, vdev->mp, "id", NULL); | ||
1158 | if (val) | ||
1159 | dp->id = *val; | ||
1160 | mdesc_release(hp); | ||
1161 | |||
1114 | dp->rcv_buf = kzalloc(4096, GFP_KERNEL); | 1162 | dp->rcv_buf = kzalloc(4096, GFP_KERNEL); |
1115 | if (!dp->rcv_buf) | 1163 | if (!dp->rcv_buf) |
1116 | goto out_free_dp; | 1164 | goto out_free_dp; |
1117 | 1165 | ||
1118 | dp->rcv_buf_len = 4096; | 1166 | dp->rcv_buf_len = 4096; |
1119 | 1167 | ||
1168 | dp->ds_states = kzalloc(sizeof(ds_states_template), | ||
1169 | GFP_KERNEL); | ||
1170 | if (!dp->ds_states) | ||
1171 | goto out_free_rcv_buf; | ||
1172 | |||
1173 | memcpy(dp->ds_states, ds_states_template, | ||
1174 | sizeof(ds_states_template)); | ||
1175 | dp->num_ds_states = ARRAY_SIZE(ds_states_template); | ||
1176 | |||
1177 | for (i = 0; i < dp->num_ds_states; i++) | ||
1178 | dp->ds_states[i].handle = ((u64)i << 32); | ||
1179 | |||
1120 | ds_cfg.tx_irq = vdev->tx_irq; | 1180 | ds_cfg.tx_irq = vdev->tx_irq; |
1121 | ds_cfg.rx_irq = vdev->rx_irq; | 1181 | ds_cfg.rx_irq = vdev->rx_irq; |
1122 | 1182 | ||
1123 | lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); | 1183 | lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); |
1124 | if (IS_ERR(lp)) { | 1184 | if (IS_ERR(lp)) { |
1125 | err = PTR_ERR(lp); | 1185 | err = PTR_ERR(lp); |
1126 | goto out_free_rcv_buf; | 1186 | goto out_free_ds_states; |
1127 | } | 1187 | } |
1128 | dp->lp = lp; | 1188 | dp->lp = lp; |
1129 | 1189 | ||
@@ -1131,13 +1191,19 @@ static int __devinit ds_probe(struct vio_dev *vdev, | |||
1131 | if (err) | 1191 | if (err) |
1132 | goto out_free_ldc; | 1192 | goto out_free_ldc; |
1133 | 1193 | ||
1134 | ds_info = dp; | 1194 | spin_lock_irq(&ds_lock); |
1195 | dp->next = ds_info_list; | ||
1196 | ds_info_list = dp; | ||
1197 | spin_unlock_irq(&ds_lock); | ||
1135 | 1198 | ||
1136 | return err; | 1199 | return err; |
1137 | 1200 | ||
1138 | out_free_ldc: | 1201 | out_free_ldc: |
1139 | ldc_free(dp->lp); | 1202 | ldc_free(dp->lp); |
1140 | 1203 | ||
1204 | out_free_ds_states: | ||
1205 | kfree(dp->ds_states); | ||
1206 | |||
1141 | out_free_rcv_buf: | 1207 | out_free_rcv_buf: |
1142 | kfree(dp->rcv_buf); | 1208 | kfree(dp->rcv_buf); |
1143 | 1209 | ||
@@ -1172,11 +1238,6 @@ static struct vio_driver ds_driver = { | |||
1172 | 1238 | ||
1173 | static int __init ds_init(void) | 1239 | static int __init ds_init(void) |
1174 | { | 1240 | { |
1175 | int i; | ||
1176 | |||
1177 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) | ||
1178 | ds_states[i].handle = ((u64)i << 32); | ||
1179 | |||
1180 | kthread_run(ds_thread, NULL, "kldomd"); | 1241 | kthread_run(ds_thread, NULL, "kldomd"); |
1181 | 1242 | ||
1182 | return vio_register_driver(&ds_driver); | 1243 | return vio_register_driver(&ds_driver); |
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index ad55a9bb50dd..6d2956179cde 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
@@ -362,6 +362,7 @@ static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | |||
362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) | 362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) |
363 | { | 363 | { |
364 | struct linux_ebus_child *child; | 364 | struct linux_ebus_child *child; |
365 | struct dev_archdata *sd; | ||
365 | struct of_device *op; | 366 | struct of_device *op; |
366 | int i, len; | 367 | int i, len; |
367 | 368 | ||
@@ -387,6 +388,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de | |||
387 | dev->irqs[i] = op->irqs[i]; | 388 | dev->irqs[i] = op->irqs[i]; |
388 | } | 389 | } |
389 | 390 | ||
391 | sd = &dev->ofdev.dev.archdata; | ||
392 | sd->prom_node = dp; | ||
393 | sd->op = &dev->ofdev; | ||
394 | |||
390 | dev->ofdev.node = dp; | 395 | dev->ofdev.node = dp; |
391 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | 396 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; |
392 | dev->ofdev.dev.bus = &ebus_bus_type; | 397 | dev->ofdev.dev.bus = &ebus_bus_type; |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index c72795666a62..db31bf6b42db 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -87,7 +87,11 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY | |||
87 | */ | 87 | */ |
88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) | 88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) |
89 | 89 | ||
90 | static unsigned int virt_to_real_irq_table[NR_IRQS]; | 90 | static struct { |
91 | unsigned int irq; | ||
92 | unsigned int dev_handle; | ||
93 | unsigned int dev_ino; | ||
94 | } virt_to_real_irq_table[NR_IRQS]; | ||
91 | 95 | ||
92 | static unsigned char virt_irq_alloc(unsigned int real_irq) | 96 | static unsigned char virt_irq_alloc(unsigned int real_irq) |
93 | { | 97 | { |
@@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
96 | BUILD_BUG_ON(NR_IRQS >= 256); | 100 | BUILD_BUG_ON(NR_IRQS >= 256); |
97 | 101 | ||
98 | for (ent = 1; ent < NR_IRQS; ent++) { | 102 | for (ent = 1; ent < NR_IRQS; ent++) { |
99 | if (!virt_to_real_irq_table[ent]) | 103 | if (!virt_to_real_irq_table[ent].irq) |
100 | break; | 104 | break; |
101 | } | 105 | } |
102 | if (ent >= NR_IRQS) { | 106 | if (ent >= NR_IRQS) { |
@@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
104 | return 0; | 108 | return 0; |
105 | } | 109 | } |
106 | 110 | ||
107 | virt_to_real_irq_table[ent] = real_irq; | 111 | virt_to_real_irq_table[ent].irq = real_irq; |
108 | 112 | ||
109 | return ent; | 113 | return ent; |
110 | } | 114 | } |
@@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq) | |||
117 | if (virt_irq >= NR_IRQS) | 121 | if (virt_irq >= NR_IRQS) |
118 | return; | 122 | return; |
119 | 123 | ||
120 | real_irq = virt_to_real_irq_table[virt_irq]; | 124 | real_irq = virt_to_real_irq_table[virt_irq].irq; |
121 | virt_to_real_irq_table[virt_irq] = 0; | 125 | virt_to_real_irq_table[virt_irq].irq = 0; |
122 | 126 | ||
123 | __bucket(real_irq)->virt_irq = 0; | 127 | __bucket(real_irq)->virt_irq = 0; |
124 | } | 128 | } |
@@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq) | |||
126 | 130 | ||
127 | static unsigned int virt_to_real_irq(unsigned char virt_irq) | 131 | static unsigned int virt_to_real_irq(unsigned char virt_irq) |
128 | { | 132 | { |
129 | return virt_to_real_irq_table[virt_irq]; | 133 | return virt_to_real_irq_table[virt_irq].irq; |
130 | } | 134 | } |
131 | 135 | ||
132 | /* | 136 | /* |
@@ -336,15 +340,15 @@ static void sun4v_irq_enable(unsigned int virt_irq) | |||
336 | 340 | ||
337 | err = sun4v_intr_settarget(ino, cpuid); | 341 | err = sun4v_intr_settarget(ino, cpuid); |
338 | if (err != HV_EOK) | 342 | if (err != HV_EOK) |
339 | printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", | 343 | printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " |
340 | ino, cpuid, err); | 344 | "err(%d)\n", ino, cpuid, err); |
341 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); | 345 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); |
342 | if (err != HV_EOK) | 346 | if (err != HV_EOK) |
343 | printk("sun4v_intr_setstate(%x): " | 347 | printk(KERN_ERR "sun4v_intr_setstate(%x): " |
344 | "err(%d)\n", ino, err); | 348 | "err(%d)\n", ino, err); |
345 | err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); | 349 | err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); |
346 | if (err != HV_EOK) | 350 | if (err != HV_EOK) |
347 | printk("sun4v_intr_setenabled(%x): err(%d)\n", | 351 | printk(KERN_ERR "sun4v_intr_setenabled(%x): err(%d)\n", |
348 | ino, err); | 352 | ino, err); |
349 | } | 353 | } |
350 | } | 354 | } |
@@ -362,8 +366,8 @@ static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
362 | 366 | ||
363 | err = sun4v_intr_settarget(ino, cpuid); | 367 | err = sun4v_intr_settarget(ino, cpuid); |
364 | if (err != HV_EOK) | 368 | if (err != HV_EOK) |
365 | printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", | 369 | printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " |
366 | ino, cpuid, err); | 370 | "err(%d)\n", ino, cpuid, err); |
367 | } | 371 | } |
368 | } | 372 | } |
369 | 373 | ||
@@ -377,7 +381,7 @@ static void sun4v_irq_disable(unsigned int virt_irq) | |||
377 | 381 | ||
378 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); | 382 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); |
379 | if (err != HV_EOK) | 383 | if (err != HV_EOK) |
380 | printk("sun4v_intr_setenabled(%x): " | 384 | printk(KERN_ERR "sun4v_intr_setenabled(%x): " |
381 | "err(%d)\n", ino, err); | 385 | "err(%d)\n", ino, err); |
382 | } | 386 | } |
383 | } | 387 | } |
@@ -410,7 +414,7 @@ static void sun4v_irq_end(unsigned int virt_irq) | |||
410 | 414 | ||
411 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); | 415 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); |
412 | if (err != HV_EOK) | 416 | if (err != HV_EOK) |
413 | printk("sun4v_intr_setstate(%x): " | 417 | printk(KERN_ERR "sun4v_intr_setstate(%x): " |
414 | "err(%d)\n", ino, err); | 418 | "err(%d)\n", ino, err); |
415 | } | 419 | } |
416 | } | 420 | } |
@@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq) | |||
418 | static void sun4v_virq_enable(unsigned int virt_irq) | 422 | static void sun4v_virq_enable(unsigned int virt_irq) |
419 | { | 423 | { |
420 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 424 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
421 | unsigned int ino = bucket - &ivector_table[0]; | ||
422 | 425 | ||
423 | if (likely(bucket)) { | 426 | if (likely(bucket)) { |
424 | unsigned long cpuid, dev_handle, dev_ino; | 427 | unsigned long cpuid, dev_handle, dev_ino; |
@@ -426,24 +429,24 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
426 | 429 | ||
427 | cpuid = irq_choose_cpu(virt_irq); | 430 | cpuid = irq_choose_cpu(virt_irq); |
428 | 431 | ||
429 | dev_handle = ino & IMAP_IGN; | 432 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
430 | dev_ino = ino & IMAP_INO; | 433 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
431 | 434 | ||
432 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 435 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
433 | if (err != HV_EOK) | 436 | if (err != HV_EOK) |
434 | printk("sun4v_vintr_set_target(%lx,%lx,%lu): " | 437 | printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " |
435 | "err(%d)\n", | 438 | "err(%d)\n", |
436 | dev_handle, dev_ino, cpuid, err); | 439 | dev_handle, dev_ino, cpuid, err); |
437 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 440 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
438 | HV_INTR_STATE_IDLE); | 441 | HV_INTR_STATE_IDLE); |
439 | if (err != HV_EOK) | 442 | if (err != HV_EOK) |
440 | printk("sun4v_vintr_set_state(%lx,%lx," | 443 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
441 | "HV_INTR_STATE_IDLE): err(%d)\n", | 444 | "HV_INTR_STATE_IDLE): err(%d)\n", |
442 | dev_handle, dev_ino, err); | 445 | dev_handle, dev_ino, err); |
443 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 446 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
444 | HV_INTR_ENABLED); | 447 | HV_INTR_ENABLED); |
445 | if (err != HV_EOK) | 448 | if (err != HV_EOK) |
446 | printk("sun4v_vintr_set_state(%lx,%lx," | 449 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
447 | "HV_INTR_ENABLED): err(%d)\n", | 450 | "HV_INTR_ENABLED): err(%d)\n", |
448 | dev_handle, dev_ino, err); | 451 | dev_handle, dev_ino, err); |
449 | } | 452 | } |
@@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
452 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | 455 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) |
453 | { | 456 | { |
454 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 457 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
455 | unsigned int ino = bucket - &ivector_table[0]; | ||
456 | 458 | ||
457 | if (likely(bucket)) { | 459 | if (likely(bucket)) { |
458 | unsigned long cpuid, dev_handle, dev_ino; | 460 | unsigned long cpuid, dev_handle, dev_ino; |
@@ -460,12 +462,12 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
460 | 462 | ||
461 | cpuid = irq_choose_cpu(virt_irq); | 463 | cpuid = irq_choose_cpu(virt_irq); |
462 | 464 | ||
463 | dev_handle = ino & IMAP_IGN; | 465 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
464 | dev_ino = ino & IMAP_INO; | 466 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
465 | 467 | ||
466 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 468 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
467 | if (err != HV_EOK) | 469 | if (err != HV_EOK) |
468 | printk("sun4v_vintr_set_target(%lx,%lx,%lu): " | 470 | printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " |
469 | "err(%d)\n", | 471 | "err(%d)\n", |
470 | dev_handle, dev_ino, cpuid, err); | 472 | dev_handle, dev_ino, cpuid, err); |
471 | } | 473 | } |
@@ -474,19 +476,18 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
474 | static void sun4v_virq_disable(unsigned int virt_irq) | 476 | static void sun4v_virq_disable(unsigned int virt_irq) |
475 | { | 477 | { |
476 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 478 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
477 | unsigned int ino = bucket - &ivector_table[0]; | ||
478 | 479 | ||
479 | if (likely(bucket)) { | 480 | if (likely(bucket)) { |
480 | unsigned long dev_handle, dev_ino; | 481 | unsigned long dev_handle, dev_ino; |
481 | int err; | 482 | int err; |
482 | 483 | ||
483 | dev_handle = ino & IMAP_IGN; | 484 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
484 | dev_ino = ino & IMAP_INO; | 485 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
485 | 486 | ||
486 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 487 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
487 | HV_INTR_DISABLED); | 488 | HV_INTR_DISABLED); |
488 | if (err != HV_EOK) | 489 | if (err != HV_EOK) |
489 | printk("sun4v_vintr_set_state(%lx,%lx," | 490 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
490 | "HV_INTR_DISABLED): err(%d)\n", | 491 | "HV_INTR_DISABLED): err(%d)\n", |
491 | dev_handle, dev_ino, err); | 492 | dev_handle, dev_ino, err); |
492 | } | 493 | } |
@@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
495 | static void sun4v_virq_end(unsigned int virt_irq) | 496 | static void sun4v_virq_end(unsigned int virt_irq) |
496 | { | 497 | { |
497 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 498 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
498 | unsigned int ino = bucket - &ivector_table[0]; | ||
499 | struct irq_desc *desc = irq_desc + virt_irq; | 499 | struct irq_desc *desc = irq_desc + virt_irq; |
500 | 500 | ||
501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
@@ -505,13 +505,13 @@ static void sun4v_virq_end(unsigned int virt_irq) | |||
505 | unsigned long dev_handle, dev_ino; | 505 | unsigned long dev_handle, dev_ino; |
506 | int err; | 506 | int err; |
507 | 507 | ||
508 | dev_handle = ino & IMAP_IGN; | 508 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
509 | dev_ino = ino & IMAP_INO; | 509 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
510 | 510 | ||
511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
512 | HV_INTR_STATE_IDLE); | 512 | HV_INTR_STATE_IDLE); |
513 | if (err != HV_EOK) | 513 | if (err != HV_EOK) |
514 | printk("sun4v_vintr_set_state(%lx,%lx," | 514 | printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," |
515 | "HV_INTR_STATE_IDLE): err(%d)\n", | 515 | "HV_INTR_STATE_IDLE): err(%d)\n", |
516 | dev_handle, dev_ino, err); | 516 | dev_handle, dev_ino, err); |
517 | } | 517 | } |
@@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | |||
700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) |
701 | { | 701 | { |
702 | unsigned long sysino, hv_err; | 702 | unsigned long sysino, hv_err; |
703 | unsigned int virq; | ||
703 | 704 | ||
704 | BUG_ON(devhandle & devino); | 705 | BUG_ON(devhandle & devino); |
705 | 706 | ||
@@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
713 | prom_halt(); | 714 | prom_halt(); |
714 | } | 715 | } |
715 | 716 | ||
716 | return sun4v_build_common(sysino, &sun4v_virq); | 717 | virq = sun4v_build_common(sysino, &sun4v_virq); |
718 | |||
719 | virt_to_real_irq_table[virq].dev_handle = devhandle; | ||
720 | virt_to_real_irq_table[virq].dev_ino = devino; | ||
721 | |||
722 | return virq; | ||
717 | } | 723 | } |
718 | 724 | ||
719 | #ifdef CONFIG_PCI_MSI | 725 | #ifdef CONFIG_PCI_MSI |
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 6a6882e57ff2..1a1043fcf97d 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c | |||
@@ -79,6 +79,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
79 | 79 | ||
80 | while (dp) { | 80 | while (dp) { |
81 | struct sparc_isa_device *isa_dev; | 81 | struct sparc_isa_device *isa_dev; |
82 | struct dev_archdata *sd; | ||
82 | 83 | ||
83 | isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); | 84 | isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); |
84 | if (!isa_dev) { | 85 | if (!isa_dev) { |
@@ -86,6 +87,10 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
86 | return; | 87 | return; |
87 | } | 88 | } |
88 | 89 | ||
90 | sd = &isa_dev->ofdev.dev.archdata; | ||
91 | sd->prom_node = dp; | ||
92 | sd->op = &isa_dev->ofdev; | ||
93 | |||
89 | isa_dev->ofdev.node = dp; | 94 | isa_dev->ofdev.node = dp; |
90 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; | 95 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; |
91 | isa_dev->ofdev.dev.bus = &isa_bus_type; | 96 | isa_dev->ofdev.dev.bus = &isa_bus_type; |
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 13a79fe5115b..cce4d0ddf5d5 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c | |||
@@ -83,7 +83,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp, | |||
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 * __init 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; |
@@ -123,7 +123,7 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp) | |||
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
126 | static struct mdesc_mem_ops bootmem_mdesc_memops = { | 126 | static struct mdesc_mem_ops bootmem_mdesc_ops = { |
127 | .alloc = mdesc_bootmem_alloc, | 127 | .alloc = mdesc_bootmem_alloc, |
128 | .free = mdesc_bootmem_free, | 128 | .free = mdesc_bootmem_free, |
129 | }; | 129 | }; |
@@ -860,7 +860,7 @@ void __init sun4v_mdesc_init(void) | |||
860 | 860 | ||
861 | printk("MDESC: Size is %lu bytes.\n", len); | 861 | printk("MDESC: Size is %lu bytes.\n", len); |
862 | 862 | ||
863 | hp = mdesc_alloc(len, &bootmem_mdesc_memops); | 863 | hp = mdesc_alloc(len, &bootmem_mdesc_ops); |
864 | if (hp == NULL) { | 864 | if (hp == NULL) { |
865 | prom_printf("MDESC: alloc of %lu bytes failed.\n", len); | 865 | prom_printf("MDESC: alloc of %lu bytes failed.\n", len); |
866 | prom_halt(); | 866 | prom_halt(); |
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 7b0dce9604ee..4cc77485f536 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
@@ -752,11 +752,16 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
752 | { | 752 | { |
753 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); | 753 | struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); |
754 | const unsigned int *irq; | 754 | const unsigned int *irq; |
755 | struct dev_archdata *sd; | ||
755 | int len, i; | 756 | int len, i; |
756 | 757 | ||
757 | if (!op) | 758 | if (!op) |
758 | return NULL; | 759 | return NULL; |
759 | 760 | ||
761 | sd = &op->dev.archdata; | ||
762 | sd->prom_node = dp; | ||
763 | sd->op = op; | ||
764 | |||
760 | op->node = dp; | 765 | op->node = dp; |
761 | 766 | ||
762 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", | 767 | op->clock_freq = of_getintprop_default(dp, "clock-frequency", |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 6b3fe2c1d65e..639cf06ca372 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -1129,7 +1129,7 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |||
1129 | } | 1129 | } |
1130 | #endif /* !(CONFIG_PCI_MSI) */ | 1130 | #endif /* !(CONFIG_PCI_MSI) */ |
1131 | 1131 | ||
1132 | static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) | 1132 | static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) |
1133 | { | 1133 | { |
1134 | struct pci_pbm_info *pbm; | 1134 | struct pci_pbm_info *pbm; |
1135 | 1135 | ||
@@ -1163,7 +1163,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1163 | pci_sun4v_msi_init(pbm); | 1163 | pci_sun4v_msi_init(pbm); |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | void sun4v_pci_init(struct device_node *dp, char *model_name) | 1166 | void __init sun4v_pci_init(struct device_node *dp, char *model_name) |
1167 | { | 1167 | { |
1168 | static int hvapi_negotiated = 0; | 1168 | static int hvapi_negotiated = 0; |
1169 | struct pci_controller_info *p; | 1169 | struct pci_controller_info *p; |
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index b00feb01c16f..881a09ee4c4c 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c | |||
@@ -46,7 +46,7 @@ static void (*poweroff_method)(void) = machine_alt_power_off; | |||
46 | void machine_power_off(void) | 46 | void machine_power_off(void) |
47 | { | 47 | { |
48 | sstate_poweroff(); | 48 | sstate_poweroff(); |
49 | if (!serial_console || scons_pwroff) { | 49 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) { |
50 | if (power_reg) { | 50 | if (power_reg) { |
51 | /* Both register bits seem to have the | 51 | /* Both register bits seem to have the |
52 | * same effect, so until I figure out | 52 | * same effect, so until I figure out |
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 93557507ec9f..fd7899ba1d70 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -119,7 +119,7 @@ extern void (*prom_keyboard)(void); | |||
119 | void machine_halt(void) | 119 | void machine_halt(void) |
120 | { | 120 | { |
121 | sstate_halt(); | 121 | sstate_halt(); |
122 | if (!serial_console && prom_palette) | 122 | if (prom_palette) |
123 | prom_palette (1); | 123 | prom_palette (1); |
124 | if (prom_keyboard) | 124 | if (prom_keyboard) |
125 | prom_keyboard(); | 125 | prom_keyboard(); |
@@ -130,7 +130,7 @@ void machine_halt(void) | |||
130 | void machine_alt_power_off(void) | 130 | void machine_alt_power_off(void) |
131 | { | 131 | { |
132 | sstate_poweroff(); | 132 | sstate_poweroff(); |
133 | if (!serial_console && prom_palette) | 133 | if (prom_palette) |
134 | prom_palette(1); | 134 | prom_palette(1); |
135 | if (prom_keyboard) | 135 | if (prom_keyboard) |
136 | prom_keyboard(); | 136 | prom_keyboard(); |
@@ -145,7 +145,7 @@ void machine_restart(char * cmd) | |||
145 | sstate_reboot(); | 145 | sstate_reboot(); |
146 | p = strchr (reboot_command, '\n'); | 146 | p = strchr (reboot_command, '\n'); |
147 | if (p) *p = 0; | 147 | if (p) *p = 0; |
148 | if (!serial_console && prom_palette) | 148 | if (prom_palette) |
149 | prom_palette (1); | 149 | prom_palette (1); |
150 | if (prom_keyboard) | 150 | if (prom_keyboard) |
151 | prom_keyboard(); | 151 | prom_keyboard(); |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 2b2017ce2267..f4e0a9ad9be3 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -1646,6 +1646,60 @@ static void __init of_fill_in_cpu_data(void) | |||
1646 | smp_fill_in_sib_core_maps(); | 1646 | smp_fill_in_sib_core_maps(); |
1647 | } | 1647 | } |
1648 | 1648 | ||
1649 | struct device_node *of_console_device; | ||
1650 | EXPORT_SYMBOL(of_console_device); | ||
1651 | |||
1652 | char *of_console_path; | ||
1653 | EXPORT_SYMBOL(of_console_path); | ||
1654 | |||
1655 | char *of_console_options; | ||
1656 | EXPORT_SYMBOL(of_console_options); | ||
1657 | |||
1658 | static void __init of_console_init(void) | ||
1659 | { | ||
1660 | char *msg = "OF stdout device is: %s\n"; | ||
1661 | struct device_node *dp; | ||
1662 | const char *type; | ||
1663 | phandle node; | ||
1664 | |||
1665 | of_console_path = prom_early_alloc(256); | ||
1666 | if (prom_ihandle2path(prom_stdout, of_console_path, 256) < 0) { | ||
1667 | prom_printf("Cannot obtain path of stdout.\n"); | ||
1668 | prom_halt(); | ||
1669 | } | ||
1670 | of_console_options = strrchr(of_console_path, ':'); | ||
1671 | if (of_console_options) { | ||
1672 | of_console_options++; | ||
1673 | if (*of_console_options == '\0') | ||
1674 | of_console_options = NULL; | ||
1675 | } | ||
1676 | |||
1677 | node = prom_inst2pkg(prom_stdout); | ||
1678 | if (!node) { | ||
1679 | prom_printf("Cannot resolve stdout node from " | ||
1680 | "instance %08x.\n", prom_stdout); | ||
1681 | prom_halt(); | ||
1682 | } | ||
1683 | |||
1684 | dp = of_find_node_by_phandle(node); | ||
1685 | type = of_get_property(dp, "device_type", NULL); | ||
1686 | if (!type) { | ||
1687 | prom_printf("Console stdout lacks device_type property.\n"); | ||
1688 | prom_halt(); | ||
1689 | } | ||
1690 | |||
1691 | if (strcmp(type, "display") && strcmp(type, "serial")) { | ||
1692 | prom_printf("Console device_type is neither display " | ||
1693 | "nor serial.\n"); | ||
1694 | prom_halt(); | ||
1695 | } | ||
1696 | |||
1697 | of_console_device = dp; | ||
1698 | |||
1699 | prom_printf(msg, of_console_path); | ||
1700 | printk(msg, of_console_path); | ||
1701 | } | ||
1702 | |||
1649 | void __init prom_build_devicetree(void) | 1703 | void __init prom_build_devicetree(void) |
1650 | { | 1704 | { |
1651 | struct device_node **nextp; | 1705 | struct device_node **nextp; |
@@ -1658,6 +1712,8 @@ void __init prom_build_devicetree(void) | |||
1658 | allnodes->child = build_tree(allnodes, | 1712 | allnodes->child = build_tree(allnodes, |
1659 | prom_getchild(allnodes->node), | 1713 | prom_getchild(allnodes->node), |
1660 | &nextp); | 1714 | &nextp); |
1715 | of_console_init(); | ||
1716 | |||
1661 | printk("PROM: Built device tree with %u bytes of memory.\n", | 1717 | printk("PROM: Built device tree with %u bytes of memory.\n", |
1662 | prom_early_allocated); | 1718 | prom_early_allocated); |
1663 | 1719 | ||
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index aafde3dd9fd4..0f5be828ee92 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c | |||
@@ -133,33 +133,6 @@ static void __init process_switch(char c) | |||
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | static void __init process_console(char *commands) | ||
137 | { | ||
138 | serial_console = 0; | ||
139 | commands += 8; | ||
140 | /* Linux-style serial */ | ||
141 | if (!strncmp(commands, "ttyS", 4)) | ||
142 | serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; | ||
143 | else if (!strncmp(commands, "tty", 3)) { | ||
144 | char c = *(commands + 3); | ||
145 | /* Solaris-style serial */ | ||
146 | if (c == 'a' || c == 'b') { | ||
147 | serial_console = c - 'a' + 1; | ||
148 | prom_printf ("Using /dev/tty%c as console.\n", c); | ||
149 | } | ||
150 | /* else Linux-style fbcon, not serial */ | ||
151 | } | ||
152 | #if defined(CONFIG_PROM_CONSOLE) | ||
153 | if (!strncmp(commands, "prom", 4)) { | ||
154 | char *p; | ||
155 | |||
156 | for (p = commands - 8; *p && *p != ' '; p++) | ||
157 | *p = ' '; | ||
158 | conswitchp = &prom_con; | ||
159 | } | ||
160 | #endif | ||
161 | } | ||
162 | |||
163 | static void __init boot_flags_init(char *commands) | 136 | static void __init boot_flags_init(char *commands) |
164 | { | 137 | { |
165 | while (*commands) { | 138 | while (*commands) { |
@@ -176,9 +149,7 @@ static void __init boot_flags_init(char *commands) | |||
176 | process_switch(*commands++); | 149 | process_switch(*commands++); |
177 | continue; | 150 | continue; |
178 | } | 151 | } |
179 | if (!strncmp(commands, "console=", 8)) { | 152 | if (!strncmp(commands, "mem=", 4)) { |
180 | process_console(commands); | ||
181 | } else if (!strncmp(commands, "mem=", 4)) { | ||
182 | /* | 153 | /* |
183 | * "mem=XXX[kKmM]" overrides the PROM-reported | 154 | * "mem=XXX[kKmM]" overrides the PROM-reported |
184 | * memory size. | 155 | * memory size. |
@@ -378,44 +349,6 @@ void __init setup_arch(char **cmdline_p) | |||
378 | paging_init(); | 349 | paging_init(); |
379 | } | 350 | } |
380 | 351 | ||
381 | static int __init set_preferred_console(void) | ||
382 | { | ||
383 | int idev, odev; | ||
384 | |||
385 | /* The user has requested a console so this is already set up. */ | ||
386 | if (serial_console >= 0) | ||
387 | return -EBUSY; | ||
388 | |||
389 | idev = prom_query_input_device(); | ||
390 | odev = prom_query_output_device(); | ||
391 | if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { | ||
392 | serial_console = 0; | ||
393 | } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { | ||
394 | serial_console = 1; | ||
395 | } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { | ||
396 | serial_console = 2; | ||
397 | } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { | ||
398 | serial_console = 3; | ||
399 | } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) { | ||
400 | /* sunhv_console_init() doesn't check the serial_console | ||
401 | * value anyways... | ||
402 | */ | ||
403 | serial_console = 4; | ||
404 | return add_preferred_console("ttyHV", 0, NULL); | ||
405 | } else { | ||
406 | prom_printf("Inconsistent console: " | ||
407 | "input %d, output %d\n", | ||
408 | idev, odev); | ||
409 | prom_halt(); | ||
410 | } | ||
411 | |||
412 | if (serial_console) | ||
413 | return add_preferred_console("ttyS", serial_console - 1, NULL); | ||
414 | |||
415 | return -ENODEV; | ||
416 | } | ||
417 | console_initcall(set_preferred_console); | ||
418 | |||
419 | /* BUFFER is PAGE_SIZE bytes long. */ | 352 | /* BUFFER is PAGE_SIZE bytes long. */ |
420 | 353 | ||
421 | extern char *sparc_cpu_type; | 354 | extern char *sparc_cpu_type; |
@@ -508,5 +441,4 @@ void sun_do_break(void) | |||
508 | prom_cmdline(); | 441 | prom_cmdline(); |
509 | } | 442 | } |
510 | 443 | ||
511 | int serial_console = -1; | ||
512 | int stop_a_enabled = 1; | 444 | int stop_a_enabled = 1; |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 719d676c2ddc..7d36531aa5b9 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -330,7 +330,6 @@ EXPORT_SYMBOL(VISenter); | |||
330 | 330 | ||
331 | /* for input/keybdev */ | 331 | /* for input/keybdev */ |
332 | EXPORT_SYMBOL(sun_do_break); | 332 | EXPORT_SYMBOL(sun_do_break); |
333 | EXPORT_SYMBOL(serial_console); | ||
334 | EXPORT_SYMBOL(stop_a_enabled); | 333 | EXPORT_SYMBOL(stop_a_enabled); |
335 | 334 | ||
336 | #ifdef CONFIG_DEBUG_BUGVERBOSE | 335 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 592ffcd57605..e340eb401fb9 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -1434,6 +1434,78 @@ static int bq4802_set_rtc_time(struct rtc_time *time) | |||
1434 | 1434 | ||
1435 | return 0; | 1435 | return 0; |
1436 | } | 1436 | } |
1437 | |||
1438 | static void cmos_get_rtc_time(struct rtc_time *rtc_tm) | ||
1439 | { | ||
1440 | unsigned char ctrl; | ||
1441 | |||
1442 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | ||
1443 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | ||
1444 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | ||
1445 | rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); | ||
1446 | rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); | ||
1447 | rtc_tm->tm_year = CMOS_READ(RTC_YEAR); | ||
1448 | rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); | ||
1449 | |||
1450 | ctrl = CMOS_READ(RTC_CONTROL); | ||
1451 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
1452 | BCD_TO_BIN(rtc_tm->tm_sec); | ||
1453 | BCD_TO_BIN(rtc_tm->tm_min); | ||
1454 | BCD_TO_BIN(rtc_tm->tm_hour); | ||
1455 | BCD_TO_BIN(rtc_tm->tm_mday); | ||
1456 | BCD_TO_BIN(rtc_tm->tm_mon); | ||
1457 | BCD_TO_BIN(rtc_tm->tm_year); | ||
1458 | BCD_TO_BIN(rtc_tm->tm_wday); | ||
1459 | } | ||
1460 | |||
1461 | if (rtc_tm->tm_year <= 69) | ||
1462 | rtc_tm->tm_year += 100; | ||
1463 | |||
1464 | rtc_tm->tm_mon--; | ||
1465 | } | ||
1466 | |||
1467 | static int cmos_set_rtc_time(struct rtc_time *rtc_tm) | ||
1468 | { | ||
1469 | unsigned char mon, day, hrs, min, sec; | ||
1470 | unsigned char save_control, save_freq_select; | ||
1471 | unsigned int yrs; | ||
1472 | |||
1473 | yrs = rtc_tm->tm_year; | ||
1474 | mon = rtc_tm->tm_mon + 1; | ||
1475 | day = rtc_tm->tm_mday; | ||
1476 | hrs = rtc_tm->tm_hour; | ||
1477 | min = rtc_tm->tm_min; | ||
1478 | sec = rtc_tm->tm_sec; | ||
1479 | |||
1480 | if (yrs >= 100) | ||
1481 | yrs -= 100; | ||
1482 | |||
1483 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
1484 | BIN_TO_BCD(sec); | ||
1485 | BIN_TO_BCD(min); | ||
1486 | BIN_TO_BCD(hrs); | ||
1487 | BIN_TO_BCD(day); | ||
1488 | BIN_TO_BCD(mon); | ||
1489 | BIN_TO_BCD(yrs); | ||
1490 | } | ||
1491 | |||
1492 | save_control = CMOS_READ(RTC_CONTROL); | ||
1493 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
1494 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
1495 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
1496 | |||
1497 | CMOS_WRITE(yrs, RTC_YEAR); | ||
1498 | CMOS_WRITE(mon, RTC_MONTH); | ||
1499 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | ||
1500 | CMOS_WRITE(hrs, RTC_HOURS); | ||
1501 | CMOS_WRITE(min, RTC_MINUTES); | ||
1502 | CMOS_WRITE(sec, RTC_SECONDS); | ||
1503 | |||
1504 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
1505 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1437 | #endif /* CONFIG_PCI */ | 1509 | #endif /* CONFIG_PCI */ |
1438 | 1510 | ||
1439 | struct mini_rtc_ops { | 1511 | struct mini_rtc_ops { |
@@ -1456,6 +1528,11 @@ static struct mini_rtc_ops bq4802_rtc_ops = { | |||
1456 | .get_rtc_time = bq4802_get_rtc_time, | 1528 | .get_rtc_time = bq4802_get_rtc_time, |
1457 | .set_rtc_time = bq4802_set_rtc_time, | 1529 | .set_rtc_time = bq4802_set_rtc_time, |
1458 | }; | 1530 | }; |
1531 | |||
1532 | static struct mini_rtc_ops cmos_rtc_ops = { | ||
1533 | .get_rtc_time = cmos_get_rtc_time, | ||
1534 | .set_rtc_time = cmos_set_rtc_time, | ||
1535 | }; | ||
1459 | #endif /* CONFIG_PCI */ | 1536 | #endif /* CONFIG_PCI */ |
1460 | 1537 | ||
1461 | static struct mini_rtc_ops *mini_rtc_ops; | 1538 | static struct mini_rtc_ops *mini_rtc_ops; |
@@ -1583,6 +1660,8 @@ static int __init rtc_mini_init(void) | |||
1583 | #ifdef CONFIG_PCI | 1660 | #ifdef CONFIG_PCI |
1584 | else if (bq4802_regs) | 1661 | else if (bq4802_regs) |
1585 | mini_rtc_ops = &bq4802_rtc_ops; | 1662 | mini_rtc_ops = &bq4802_rtc_ops; |
1663 | else if (ds1287_regs) | ||
1664 | mini_rtc_ops = &cmos_rtc_ops; | ||
1586 | #endif /* CONFIG_PCI */ | 1665 | #endif /* CONFIG_PCI */ |
1587 | else | 1666 | else |
1588 | return -ENODEV; | 1667 | return -ENODEV; |
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 491223a6628f..3685daf5157f 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
@@ -205,7 +205,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
205 | struct device_node *dp; | 205 | struct device_node *dp; |
206 | struct vio_dev *vdev; | 206 | struct vio_dev *vdev; |
207 | int err, tlen, clen; | 207 | int err, tlen, clen; |
208 | const u64 *id; | 208 | const u64 *id, *cfg_handle; |
209 | u64 a; | ||
209 | 210 | ||
210 | type = mdesc_get_property(hp, mp, "device-type", &tlen); | 211 | type = mdesc_get_property(hp, mp, "device-type", &tlen); |
211 | if (!type) { | 212 | if (!type) { |
@@ -221,26 +222,18 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
221 | return NULL; | 222 | return NULL; |
222 | } | 223 | } |
223 | 224 | ||
224 | if (!strcmp(type, "vdc-port")) { | 225 | id = mdesc_get_property(hp, mp, "id", NULL); |
225 | u64 a; | ||
226 | 226 | ||
227 | id = NULL; | 227 | cfg_handle = NULL; |
228 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { | 228 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { |
229 | u64 target; | 229 | u64 target; |
230 | 230 | ||
231 | target = mdesc_arc_target(hp, a); | 231 | target = mdesc_arc_target(hp, a); |
232 | id = mdesc_get_property(hp, target, | 232 | cfg_handle = mdesc_get_property(hp, target, |
233 | "cfg-handle", NULL); | 233 | "cfg-handle", NULL); |
234 | if (id) | 234 | if (cfg_handle) |
235 | break; | 235 | break; |
236 | } | 236 | } |
237 | if (!id) { | ||
238 | printk(KERN_ERR "VIO: vdc-port lacks parent " | ||
239 | "cfg-handle.\n"); | ||
240 | return NULL; | ||
241 | } | ||
242 | } else | ||
243 | id = mdesc_get_property(hp, mp, "id", NULL); | ||
244 | 237 | ||
245 | bus_id_name = type; | 238 | bus_id_name = type; |
246 | if (!strcmp(type, "domain-services-port")) | 239 | if (!strcmp(type, "domain-services-port")) |
@@ -285,10 +278,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
285 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", | 278 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", |
286 | bus_id_name); | 279 | bus_id_name); |
287 | vdev->dev_no = ~(u64)0; | 280 | vdev->dev_no = ~(u64)0; |
288 | } else { | 281 | } else if (!cfg_handle) { |
289 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", | 282 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", |
290 | bus_id_name, *id); | 283 | bus_id_name, *id); |
291 | vdev->dev_no = *id; | 284 | vdev->dev_no = *id; |
285 | } else { | ||
286 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu", | ||
287 | bus_id_name, *cfg_handle, *id); | ||
288 | vdev->dev_no = *cfg_handle; | ||
292 | } | 289 | } |
293 | 290 | ||
294 | vdev->dev.parent = parent; | 291 | vdev->dev.parent = parent; |