diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 11 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/smp.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/time.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/irq.c | 25 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/pci.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/setup.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/pci.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/time.c | 11 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/feature.c | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/pci.c | 62 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/time.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvconsole.c | 74 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvcserver.c | 251 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 30 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 1 |
17 files changed, 430 insertions, 89 deletions
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 4099ddab9205..dda5f2c72c25 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -257,6 +257,13 @@ void __init chrp_setup_arch(void) | |||
257 | if (rtas_token("display-character") >= 0) | 257 | if (rtas_token("display-character") >= 0) |
258 | ppc_md.progress = rtas_progress; | 258 | ppc_md.progress = rtas_progress; |
259 | 259 | ||
260 | /* use RTAS time-of-day routines if available */ | ||
261 | if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) { | ||
262 | ppc_md.get_boot_time = rtas_get_boot_time; | ||
263 | ppc_md.get_rtc_time = rtas_get_rtc_time; | ||
264 | ppc_md.set_rtc_time = rtas_set_rtc_time; | ||
265 | } | ||
266 | |||
260 | #ifdef CONFIG_BOOTX_TEXT | 267 | #ifdef CONFIG_BOOTX_TEXT |
261 | if (ppc_md.progress == NULL && boot_text_mapped) | 268 | if (ppc_md.progress == NULL && boot_text_mapped) |
262 | ppc_md.progress = btext_progress; | 269 | ppc_md.progress = btext_progress; |
@@ -505,9 +512,11 @@ void __init chrp_init(void) | |||
505 | ppc_md.halt = rtas_halt; | 512 | ppc_md.halt = rtas_halt; |
506 | 513 | ||
507 | ppc_md.time_init = chrp_time_init; | 514 | ppc_md.time_init = chrp_time_init; |
515 | ppc_md.calibrate_decr = chrp_calibrate_decr; | ||
516 | |||
517 | /* this may get overridden with rtas routines later... */ | ||
508 | ppc_md.set_rtc_time = chrp_set_rtc_time; | 518 | ppc_md.set_rtc_time = chrp_set_rtc_time; |
509 | ppc_md.get_rtc_time = chrp_get_rtc_time; | 519 | ppc_md.get_rtc_time = chrp_get_rtc_time; |
510 | ppc_md.calibrate_decr = chrp_calibrate_decr; | ||
511 | 520 | ||
512 | #ifdef CONFIG_SMP | 521 | #ifdef CONFIG_SMP |
513 | smp_ops = &chrp_smp_ops; | 522 | smp_ops = &chrp_smp_ops; |
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index bb2315997d45..b616053bc331 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/machdep.h> | 34 | #include <asm/machdep.h> |
35 | #include <asm/smp.h> | 35 | #include <asm/smp.h> |
36 | #include <asm/mpic.h> | 36 | #include <asm/mpic.h> |
37 | #include <asm/rtas.h> | ||
37 | 38 | ||
38 | static void __devinit smp_chrp_kick_cpu(int nr) | 39 | static void __devinit smp_chrp_kick_cpu(int nr) |
39 | { | 40 | { |
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 9e53535ddb82..737ee5d9f0aa 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
@@ -87,7 +87,6 @@ int chrp_set_rtc_time(struct rtc_time *tmarg) | |||
87 | 87 | ||
88 | chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | 88 | chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); |
89 | 89 | ||
90 | tm.tm_year -= 1900; | ||
91 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 90 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
92 | BIN_TO_BCD(tm.tm_sec); | 91 | BIN_TO_BCD(tm.tm_sec); |
93 | BIN_TO_BCD(tm.tm_min); | 92 | BIN_TO_BCD(tm.tm_min); |
@@ -156,7 +155,7 @@ void chrp_get_rtc_time(struct rtc_time *tm) | |||
156 | BCD_TO_BIN(mon); | 155 | BCD_TO_BIN(mon); |
157 | BCD_TO_BIN(year); | 156 | BCD_TO_BIN(year); |
158 | } | 157 | } |
159 | if ((year += 1900) < 1970) | 158 | if (year < 70) |
160 | year += 100; | 159 | year += 100; |
161 | tm->tm_sec = sec; | 160 | tm->tm_sec = sec; |
162 | tm->tm_min = min; | 161 | tm->tm_min = min; |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 01090e9ce0cf..a58daa153686 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -42,13 +42,6 @@ | |||
42 | #include "irq.h" | 42 | #include "irq.h" |
43 | #include "call_pci.h" | 43 | #include "call_pci.h" |
44 | 44 | ||
45 | /* This maps virtual irq numbers to real irqs */ | ||
46 | unsigned int virt_irq_to_real_map[NR_IRQS]; | ||
47 | |||
48 | /* The next available virtual irq number */ | ||
49 | /* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ | ||
50 | static int next_virtual_irq = 2; | ||
51 | |||
52 | static long Pci_Interrupt_Count; | 45 | static long Pci_Interrupt_Count; |
53 | static long Pci_Event_Count; | 46 | static long Pci_Event_Count; |
54 | 47 | ||
@@ -350,26 +343,14 @@ static hw_irq_controller iSeries_IRQ_handler = { | |||
350 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, | 343 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, |
351 | HvSubBusNumber subBusNumber, HvAgentId deviceId) | 344 | HvSubBusNumber subBusNumber, HvAgentId deviceId) |
352 | { | 345 | { |
353 | unsigned int realirq, virtirq; | 346 | int virtirq; |
347 | unsigned int realirq; | ||
354 | u8 idsel = (deviceId >> 4); | 348 | u8 idsel = (deviceId >> 4); |
355 | u8 function = deviceId & 7; | 349 | u8 function = deviceId & 7; |
356 | 350 | ||
357 | virtirq = next_virtual_irq++; | ||
358 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; | 351 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; |
359 | virt_irq_to_real_map[virtirq] = realirq; | 352 | virtirq = virt_irq_create_mapping(realirq); |
360 | 353 | ||
361 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; | 354 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; |
362 | return virtirq; | 355 | return virtirq; |
363 | } | 356 | } |
364 | |||
365 | int virt_irq_create_mapping(unsigned int real_irq) | ||
366 | { | ||
367 | BUG(); /* Don't call this on iSeries, yet */ | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | void virt_irq_init(void) | ||
373 | { | ||
374 | return; | ||
375 | } | ||
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4b75131773a6..dafc518fbb83 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -244,10 +244,9 @@ unsigned long __init find_and_init_phbs(void) | |||
244 | if (ret == 0) { | 244 | if (ret == 0) { |
245 | printk("bus %d appears to exist\n", bus); | 245 | printk("bus %d appears to exist\n", bus); |
246 | 246 | ||
247 | phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | 247 | phb = pcibios_alloc_controller(NULL); |
248 | if (phb == NULL) | 248 | if (phb == NULL) |
249 | return -ENOMEM; | 249 | return -ENOMEM; |
250 | pci_setup_pci_controller(phb); | ||
251 | 250 | ||
252 | phb->pci_mem_offset = phb->local_number = bus; | 251 | phb->pci_mem_offset = phb->local_number = bus; |
253 | phb->first_busno = bus; | 252 | phb->first_busno = bus; |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 6a29f301436b..da26639190db 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | #include <asm/systemcfg.h> | ||
43 | #include <asm/system.h> | 42 | #include <asm/system.h> |
44 | #include <asm/time.h> | 43 | #include <asm/time.h> |
45 | #include <asm/paca.h> | 44 | #include <asm/paca.h> |
@@ -548,8 +547,6 @@ static unsigned long __init build_iSeries_Memory_Map(void) | |||
548 | */ | 547 | */ |
549 | static void __init iSeries_setup_arch(void) | 548 | static void __init iSeries_setup_arch(void) |
550 | { | 549 | { |
551 | unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index; | ||
552 | |||
553 | if (get_paca()->lppaca.shared_proc) { | 550 | if (get_paca()->lppaca.shared_proc) { |
554 | ppc_md.idle_loop = iseries_shared_idle; | 551 | ppc_md.idle_loop = iseries_shared_idle; |
555 | printk(KERN_INFO "Using shared processor idle loop\n"); | 552 | printk(KERN_INFO "Using shared processor idle loop\n"); |
@@ -565,9 +562,6 @@ static void __init iSeries_setup_arch(void) | |||
565 | itVpdAreas.xSlicMaxLogicalProcs); | 562 | itVpdAreas.xSlicMaxLogicalProcs); |
566 | printk("Max physical processors = %d\n", | 563 | printk("Max physical processors = %d\n", |
567 | itVpdAreas.xSlicMaxPhysicalProcs); | 564 | itVpdAreas.xSlicMaxPhysicalProcs); |
568 | |||
569 | _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; | ||
570 | printk("Processor version = %x\n", _systemcfg->processor); | ||
571 | } | 565 | } |
572 | 566 | ||
573 | static void iSeries_show_cpuinfo(struct seq_file *m) | 567 | static void iSeries_show_cpuinfo(struct seq_file *m) |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 895aeb3f75d0..f40451da037c 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -326,26 +326,12 @@ static int __init add_bridge(struct device_node *dev) | |||
326 | dev->full_name); | 326 | dev->full_name); |
327 | } | 327 | } |
328 | 328 | ||
329 | hose = alloc_bootmem(sizeof(struct pci_controller)); | 329 | hose = pcibios_alloc_controller(dev); |
330 | if (hose == NULL) | 330 | if (hose == NULL) |
331 | return -ENOMEM; | 331 | return -ENOMEM; |
332 | pci_setup_pci_controller(hose); | ||
333 | |||
334 | hose->arch_data = dev; | ||
335 | hose->first_busno = bus_range ? bus_range[0] : 0; | 332 | hose->first_busno = bus_range ? bus_range[0] : 0; |
336 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 333 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
337 | 334 | ||
338 | of_prop = alloc_bootmem(sizeof(struct property) + | ||
339 | sizeof(hose->global_number)); | ||
340 | if (of_prop) { | ||
341 | memset(of_prop, 0, sizeof(struct property)); | ||
342 | of_prop->name = "linux,pci-domain"; | ||
343 | of_prop->length = sizeof(hose->global_number); | ||
344 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
345 | memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number)); | ||
346 | prom_add_property(dev, of_prop); | ||
347 | } | ||
348 | |||
349 | disp_name = NULL; | 335 | disp_name = NULL; |
350 | if (device_is_compatible(dev, "u3-agp")) { | 336 | if (device_is_compatible(dev, "u3-agp")) { |
351 | setup_u3_agp(hose); | 337 | setup_u3_agp(hose); |
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 40fc07a8e606..15846cc938ac 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c | |||
@@ -158,6 +158,11 @@ int maple_set_rtc_time(struct rtc_time *tm) | |||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | static struct resource rtc_iores = { | ||
162 | .name = "rtc", | ||
163 | .flags = IORESOURCE_BUSY, | ||
164 | }; | ||
165 | |||
161 | unsigned long __init maple_get_boot_time(void) | 166 | unsigned long __init maple_get_boot_time(void) |
162 | { | 167 | { |
163 | struct rtc_time tm; | 168 | struct rtc_time tm; |
@@ -172,7 +177,11 @@ unsigned long __init maple_get_boot_time(void) | |||
172 | printk(KERN_INFO "Maple: No device node for RTC, assuming " | 177 | printk(KERN_INFO "Maple: No device node for RTC, assuming " |
173 | "legacy address (0x%x)\n", maple_rtc_addr); | 178 | "legacy address (0x%x)\n", maple_rtc_addr); |
174 | } | 179 | } |
175 | 180 | ||
181 | rtc_iores.start = maple_rtc_addr; | ||
182 | rtc_iores.end = maple_rtc_addr + 7; | ||
183 | request_resource(&ioport_resource, &rtc_iores); | ||
184 | |||
176 | maple_get_rtc_time(&tm); | 185 | maple_get_rtc_time(&tm); |
177 | return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, | 186 | return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, |
178 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 187 | tm.tm_hour, tm.tm_min, tm.tm_sec); |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 10f1d942c661..0d7fa00fcb00 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -2362,6 +2362,14 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2362 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2362 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2363 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2363 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
2364 | }, | 2364 | }, |
2365 | { "PowerBook5,8", "PowerBook G4 15\"", | ||
2366 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2367 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2368 | }, | ||
2369 | { "PowerBook5,9", "PowerBook G4 17\"", | ||
2370 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2371 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2372 | }, | ||
2365 | { "PowerBook6,1", "PowerBook G4 12\"", | 2373 | { "PowerBook6,1", "PowerBook G4 12\"", |
2366 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2374 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2367 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2375 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index dfd41b9781a9..443be526cde7 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -640,15 +640,16 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
640 | * the reg address cell, we shall fix that by killing struct | 640 | * the reg address cell, we shall fix that by killing struct |
641 | * reg_property and using some accessor functions instead | 641 | * reg_property and using some accessor functions instead |
642 | */ | 642 | */ |
643 | hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000); | 643 | hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, |
644 | 0x02000000); | ||
644 | 645 | ||
645 | /* | 646 | /* |
646 | * /ht node doesn't expose a "ranges" property, so we "remove" regions that | 647 | * /ht node doesn't expose a "ranges" property, so we "remove" |
647 | * have been allocated to AGP. So far, this version of the code doesn't assign | 648 | * regions that have been allocated to AGP. So far, this version of |
648 | * any of the 0xfxxxxxxx "fine" memory regions to /ht. | 649 | * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions |
649 | * We need to fix that sooner or later by either parsing all child "ranges" | 650 | * to /ht. We need to fix that sooner or later by either parsing all |
650 | * properties or figuring out the U3 address space decoding logic and | 651 | * child "ranges" properties or figuring out the U3 address space |
651 | * then read its configuration register (if any). | 652 | * decoding logic and then read its configuration register (if any). |
652 | */ | 653 | */ |
653 | hose->io_base_phys = 0xf4000000; | 654 | hose->io_base_phys = 0xf4000000; |
654 | hose->pci_io_size = 0x00400000; | 655 | hose->pci_io_size = 0x00400000; |
@@ -671,10 +672,10 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
671 | return; | 672 | return; |
672 | } | 673 | } |
673 | 674 | ||
674 | /* We "remove" the AGP resources from the resources allocated to HT, that | 675 | /* We "remove" the AGP resources from the resources allocated to HT, |
675 | * is we create "holes". However, that code does assumptions that so far | 676 | * that is we create "holes". However, that code does assumptions |
676 | * happen to be true (cross fingers...), typically that resources in the | 677 | * that so far happen to be true (cross fingers...), typically that |
677 | * AGP node are properly ordered | 678 | * resources in the AGP node are properly ordered |
678 | */ | 679 | */ |
679 | cur = 0; | 680 | cur = 0; |
680 | for (i=0; i<3; i++) { | 681 | for (i=0; i<3; i++) { |
@@ -684,23 +685,30 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
684 | /* We don't care about "fine" resources */ | 685 | /* We don't care about "fine" resources */ |
685 | if (res->start >= 0xf0000000) | 686 | if (res->start >= 0xf0000000) |
686 | continue; | 687 | continue; |
687 | /* Check if it's just a matter of "shrinking" us in one direction */ | 688 | /* Check if it's just a matter of "shrinking" us in one |
689 | * direction | ||
690 | */ | ||
688 | if (hose->mem_resources[cur].start == res->start) { | 691 | if (hose->mem_resources[cur].start == res->start) { |
689 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", | 692 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", |
690 | cur, hose->mem_resources[cur].start, res->end + 1); | 693 | cur, hose->mem_resources[cur].start, |
694 | res->end + 1); | ||
691 | hose->mem_resources[cur].start = res->end + 1; | 695 | hose->mem_resources[cur].start = res->end + 1; |
692 | continue; | 696 | continue; |
693 | } | 697 | } |
694 | if (hose->mem_resources[cur].end == res->end) { | 698 | if (hose->mem_resources[cur].end == res->end) { |
695 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", | 699 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", |
696 | cur, hose->mem_resources[cur].end, res->start - 1); | 700 | cur, hose->mem_resources[cur].end, |
701 | res->start - 1); | ||
697 | hose->mem_resources[cur].end = res->start - 1; | 702 | hose->mem_resources[cur].end = res->start - 1; |
698 | continue; | 703 | continue; |
699 | } | 704 | } |
700 | /* No, it's not the case, we need a hole */ | 705 | /* No, it's not the case, we need a hole */ |
701 | if (cur == 2) { | 706 | if (cur == 2) { |
702 | /* not enough resources for a hole, we drop part of the range */ | 707 | /* not enough resources for a hole, we drop part |
703 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); | 708 | * of the range |
709 | */ | ||
710 | printk(KERN_WARNING "Running out of resources" | ||
711 | " for /ht host !\n"); | ||
704 | hose->mem_resources[cur].end = res->start - 1; | 712 | hose->mem_resources[cur].end = res->start - 1; |
705 | continue; | 713 | continue; |
706 | } | 714 | } |
@@ -714,17 +722,6 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
714 | hose->mem_resources[cur-1].end = res->start - 1; | 722 | hose->mem_resources[cur-1].end = res->start - 1; |
715 | } | 723 | } |
716 | } | 724 | } |
717 | |||
718 | /* XXX this needs to be converged between ppc32 and ppc64... */ | ||
719 | static struct pci_controller * __init pcibios_alloc_controller(void) | ||
720 | { | ||
721 | struct pci_controller *hose; | ||
722 | |||
723 | hose = alloc_bootmem(sizeof(struct pci_controller)); | ||
724 | if (hose) | ||
725 | pci_setup_pci_controller(hose); | ||
726 | return hose; | ||
727 | } | ||
728 | #endif | 725 | #endif |
729 | 726 | ||
730 | /* | 727 | /* |
@@ -756,11 +753,16 @@ static int __init add_bridge(struct device_node *dev) | |||
756 | #endif | 753 | #endif |
757 | bus_range = (int *) get_property(dev, "bus-range", &len); | 754 | bus_range = (int *) get_property(dev, "bus-range", &len); |
758 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 755 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
759 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | 756 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
760 | dev->full_name); | 757 | " bus 0\n", dev->full_name); |
761 | } | 758 | } |
762 | 759 | ||
760 | /* XXX Different prototypes, to be merged */ | ||
761 | #ifdef CONFIG_PPC64 | ||
762 | hose = pcibios_alloc_controller(dev); | ||
763 | #else | ||
763 | hose = pcibios_alloc_controller(); | 764 | hose = pcibios_alloc_controller(); |
765 | #endif | ||
764 | if (!hose) | 766 | if (!hose) |
765 | return -ENOMEM; | 767 | return -ENOMEM; |
766 | hose->arch_data = dev; | 768 | hose->arch_data = dev; |
@@ -768,7 +770,7 @@ static int __init add_bridge(struct device_node *dev) | |||
768 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 770 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
769 | 771 | ||
770 | disp_name = NULL; | 772 | disp_name = NULL; |
771 | #ifdef CONFIG_POWER4 | 773 | #ifdef CONFIG_PPC64 |
772 | if (device_is_compatible(dev, "u3-agp")) { | 774 | if (device_is_compatible(dev, "u3-agp")) { |
773 | setup_u3_agp(hose); | 775 | setup_u3_agp(hose); |
774 | disp_name = "U3-AGP"; | 776 | disp_name = "U3-AGP"; |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5947b21a8588..feb0a94e7819 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -102,7 +102,7 @@ static unsigned long from_rtc_time(struct rtc_time *tm) | |||
102 | static unsigned long cuda_get_time(void) | 102 | static unsigned long cuda_get_time(void) |
103 | { | 103 | { |
104 | struct adb_request req; | 104 | struct adb_request req; |
105 | unsigned long now; | 105 | unsigned int now; |
106 | 106 | ||
107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | 107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) |
108 | return 0; | 108 | return 0; |
@@ -113,7 +113,7 @@ static unsigned long cuda_get_time(void) | |||
113 | req.reply_len); | 113 | req.reply_len); |
114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | 114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) |
115 | + (req.reply[5] << 8) + req.reply[6]; | 115 | + (req.reply[5] << 8) + req.reply[6]; |
116 | return now - RTC_OFFSET; | 116 | return ((unsigned long)now) - RTC_OFFSET; |
117 | } | 117 | } |
118 | 118 | ||
119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) | 119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) |
@@ -146,7 +146,7 @@ static int cuda_set_rtc_time(struct rtc_time *tm) | |||
146 | static unsigned long pmu_get_time(void) | 146 | static unsigned long pmu_get_time(void) |
147 | { | 147 | { |
148 | struct adb_request req; | 148 | struct adb_request req; |
149 | unsigned long now; | 149 | unsigned int now; |
150 | 150 | ||
151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | 151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) |
152 | return 0; | 152 | return 0; |
@@ -156,7 +156,7 @@ static unsigned long pmu_get_time(void) | |||
156 | req.reply_len); | 156 | req.reply_len); |
157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | 157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) |
158 | + (req.reply[2] << 8) + req.reply[3]; | 158 | + (req.reply[2] << 8) + req.reply[3]; |
159 | return now - RTC_OFFSET; | 159 | return ((unsigned long)now) - RTC_OFFSET; |
160 | } | 160 | } |
161 | 161 | ||
162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) | 162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) |
@@ -199,6 +199,7 @@ static unsigned long smu_get_time(void) | |||
199 | #define smu_set_rtc_time(tm, spin) 0 | 199 | #define smu_set_rtc_time(tm, spin) 0 |
200 | #endif | 200 | #endif |
201 | 201 | ||
202 | /* Can't be __init, it's called when suspending and resuming */ | ||
202 | unsigned long pmac_get_boot_time(void) | 203 | unsigned long pmac_get_boot_time(void) |
203 | { | 204 | { |
204 | /* Get the time from the RTC, used only at boot time */ | 205 | /* Get the time from the RTC, used only at boot time */ |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index e7ca5b1f591e..06d5ef501218 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -4,4 +4,7 @@ obj-$(CONFIG_SMP) += smp.o | |||
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | 6 | obj-$(CONFIG_SCANLOG) += scanlog.o |
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | 7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o |
8 | |||
9 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
10 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 79de2310e70b..c8d2a40dc5b4 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -86,7 +86,8 @@ static int ibm_read_slot_reset_state; | |||
86 | static int ibm_read_slot_reset_state2; | 86 | static int ibm_read_slot_reset_state2; |
87 | static int ibm_slot_error_detail; | 87 | static int ibm_slot_error_detail; |
88 | 88 | ||
89 | static int eeh_subsystem_enabled; | 89 | int eeh_subsystem_enabled; |
90 | EXPORT_SYMBOL(eeh_subsystem_enabled); | ||
90 | 91 | ||
91 | /* Lock to avoid races due to multiple reports of an error */ | 92 | /* Lock to avoid races due to multiple reports of an error */ |
92 | static DEFINE_SPINLOCK(confirm_error_lock); | 93 | static DEFINE_SPINLOCK(confirm_error_lock); |
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c new file mode 100644 index 000000000000..138e128a3886 --- /dev/null +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * hvconsole.c | ||
3 | * Copyright (C) 2004 Hollis Blanchard, IBM Corporation | ||
4 | * Copyright (C) 2004 IBM Corporation | ||
5 | * | ||
6 | * Additional Author(s): | ||
7 | * Ryan S. Arnold <rsa@us.ibm.com> | ||
8 | * | ||
9 | * LPAR console support. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <asm/hvcall.h> | ||
29 | #include <asm/hvconsole.h> | ||
30 | |||
31 | /** | ||
32 | * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper | ||
33 | * @vtermno: The vtermno or unit_address of the adapter from which to fetch the | ||
34 | * data. | ||
35 | * @buf: The character buffer into which to put the character data fetched from | ||
36 | * firmware. | ||
37 | * @count: not used? | ||
38 | */ | ||
39 | int hvc_get_chars(uint32_t vtermno, char *buf, int count) | ||
40 | { | ||
41 | unsigned long got; | ||
42 | |||
43 | if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got, | ||
44 | (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) | ||
45 | return got; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | EXPORT_SYMBOL(hvc_get_chars); | ||
50 | |||
51 | |||
52 | /** | ||
53 | * hvc_put_chars: send characters to firmware for denoted vterm adapter | ||
54 | * @vtermno: The vtermno or unit_address of the adapter from which the data | ||
55 | * originated. | ||
56 | * @buf: The character buffer that contains the character data to send to | ||
57 | * firmware. | ||
58 | * @count: Send this number of characters. | ||
59 | */ | ||
60 | int hvc_put_chars(uint32_t vtermno, const char *buf, int count) | ||
61 | { | ||
62 | unsigned long *lbuf = (unsigned long *) buf; | ||
63 | long ret; | ||
64 | |||
65 | ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], | ||
66 | lbuf[1]); | ||
67 | if (ret == H_Success) | ||
68 | return count; | ||
69 | if (ret == H_Busy) | ||
70 | return 0; | ||
71 | return -EIO; | ||
72 | } | ||
73 | |||
74 | EXPORT_SYMBOL(hvc_put_chars); | ||
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c new file mode 100644 index 000000000000..4d584172055a --- /dev/null +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * hvcserver.c | ||
3 | * Copyright (C) 2004 Ryan S Arnold, IBM Corporation | ||
4 | * | ||
5 | * PPC64 virtual I/O console server support. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <asm/hvcall.h> | ||
28 | #include <asm/hvcserver.h> | ||
29 | #include <asm/io.h> | ||
30 | |||
31 | #define HVCS_ARCH_VERSION "1.0.0" | ||
32 | |||
33 | MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>"); | ||
34 | MODULE_DESCRIPTION("IBM hvcs ppc64 API"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | MODULE_VERSION(HVCS_ARCH_VERSION); | ||
37 | |||
38 | /* | ||
39 | * Convert arch specific return codes into relevant errnos. The hvcs | ||
40 | * functions aren't performance sensitive, so this conversion isn't an | ||
41 | * issue. | ||
42 | */ | ||
43 | int hvcs_convert(long to_convert) | ||
44 | { | ||
45 | switch (to_convert) { | ||
46 | case H_Success: | ||
47 | return 0; | ||
48 | case H_Parameter: | ||
49 | return -EINVAL; | ||
50 | case H_Hardware: | ||
51 | return -EIO; | ||
52 | case H_Busy: | ||
53 | case H_LongBusyOrder1msec: | ||
54 | case H_LongBusyOrder10msec: | ||
55 | case H_LongBusyOrder100msec: | ||
56 | case H_LongBusyOrder1sec: | ||
57 | case H_LongBusyOrder10sec: | ||
58 | case H_LongBusyOrder100sec: | ||
59 | return -EBUSY; | ||
60 | case H_Function: /* fall through */ | ||
61 | default: | ||
62 | return -EPERM; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * hvcs_free_partner_info - free pi allocated by hvcs_get_partner_info | ||
68 | * @head: list_head pointer for an allocated list of partner info structs to | ||
69 | * free. | ||
70 | * | ||
71 | * This function is used to free the partner info list that was returned by | ||
72 | * calling hvcs_get_partner_info(). | ||
73 | */ | ||
74 | int hvcs_free_partner_info(struct list_head *head) | ||
75 | { | ||
76 | struct hvcs_partner_info *pi; | ||
77 | struct list_head *element; | ||
78 | |||
79 | if (!head) | ||
80 | return -EINVAL; | ||
81 | |||
82 | while (!list_empty(head)) { | ||
83 | element = head->next; | ||
84 | pi = list_entry(element, struct hvcs_partner_info, node); | ||
85 | list_del(element); | ||
86 | kfree(pi); | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | EXPORT_SYMBOL(hvcs_free_partner_info); | ||
92 | |||
93 | /* Helper function for hvcs_get_partner_info */ | ||
94 | int hvcs_next_partner(uint32_t unit_address, | ||
95 | unsigned long last_p_partition_ID, | ||
96 | unsigned long last_p_unit_address, unsigned long *pi_buff) | ||
97 | |||
98 | { | ||
99 | long retval; | ||
100 | retval = plpar_hcall_norets(H_VTERM_PARTNER_INFO, unit_address, | ||
101 | last_p_partition_ID, | ||
102 | last_p_unit_address, virt_to_phys(pi_buff)); | ||
103 | return hvcs_convert(retval); | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * hvcs_get_partner_info - Get all of the partner info for a vty-server adapter | ||
108 | * @unit_address: The unit_address of the vty-server adapter for which this | ||
109 | * function is fetching partner info. | ||
110 | * @head: An initialized list_head pointer to an empty list to use to return the | ||
111 | * list of partner info fetched from the hypervisor to the caller. | ||
112 | * @pi_buff: A page sized buffer pre-allocated prior to calling this function | ||
113 | * that is to be used to be used by firmware as an iterator to keep track | ||
114 | * of the partner info retrieval. | ||
115 | * | ||
116 | * This function returns non-zero on success, or if there is no partner info. | ||
117 | * | ||
118 | * The pi_buff is pre-allocated prior to calling this function because this | ||
119 | * function may be called with a spin_lock held and kmalloc of a page is not | ||
120 | * recommended as GFP_ATOMIC. | ||
121 | * | ||
122 | * The first long of this buffer is used to store a partner unit address. The | ||
123 | * second long is used to store a partner partition ID and starting at | ||
124 | * pi_buff[2] is the 79 character Converged Location Code (diff size than the | ||
125 | * unsigned longs, hence the casting mumbo jumbo you see later). | ||
126 | * | ||
127 | * Invocation of this function should always be followed by an invocation of | ||
128 | * hvcs_free_partner_info() using a pointer to the SAME list head instance | ||
129 | * that was passed as a parameter to this function. | ||
130 | */ | ||
131 | int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head, | ||
132 | unsigned long *pi_buff) | ||
133 | { | ||
134 | /* | ||
135 | * Dealt with as longs because of the hcall interface even though the | ||
136 | * values are uint32_t. | ||
137 | */ | ||
138 | unsigned long last_p_partition_ID; | ||
139 | unsigned long last_p_unit_address; | ||
140 | struct hvcs_partner_info *next_partner_info = NULL; | ||
141 | int more = 1; | ||
142 | int retval; | ||
143 | |||
144 | memset(pi_buff, 0x00, PAGE_SIZE); | ||
145 | /* invalid parameters */ | ||
146 | if (!head || !pi_buff) | ||
147 | return -EINVAL; | ||
148 | |||
149 | last_p_partition_ID = last_p_unit_address = ~0UL; | ||
150 | INIT_LIST_HEAD(head); | ||
151 | |||
152 | do { | ||
153 | retval = hvcs_next_partner(unit_address, last_p_partition_ID, | ||
154 | last_p_unit_address, pi_buff); | ||
155 | if (retval) { | ||
156 | /* | ||
157 | * Don't indicate that we've failed if we have | ||
158 | * any list elements. | ||
159 | */ | ||
160 | if (!list_empty(head)) | ||
161 | return 0; | ||
162 | return retval; | ||
163 | } | ||
164 | |||
165 | last_p_partition_ID = pi_buff[0]; | ||
166 | last_p_unit_address = pi_buff[1]; | ||
167 | |||
168 | /* This indicates that there are no further partners */ | ||
169 | if (last_p_partition_ID == ~0UL | ||
170 | && last_p_unit_address == ~0UL) | ||
171 | break; | ||
172 | |||
173 | /* This is a very small struct and will be freed soon in | ||
174 | * hvcs_free_partner_info(). */ | ||
175 | next_partner_info = kmalloc(sizeof(struct hvcs_partner_info), | ||
176 | GFP_ATOMIC); | ||
177 | |||
178 | if (!next_partner_info) { | ||
179 | printk(KERN_WARNING "HVCONSOLE: kmalloc() failed to" | ||
180 | " allocate partner info struct.\n"); | ||
181 | hvcs_free_partner_info(head); | ||
182 | return -ENOMEM; | ||
183 | } | ||
184 | |||
185 | next_partner_info->unit_address | ||
186 | = (unsigned int)last_p_unit_address; | ||
187 | next_partner_info->partition_ID | ||
188 | = (unsigned int)last_p_partition_ID; | ||
189 | |||
190 | /* copy the Null-term char too */ | ||
191 | strncpy(&next_partner_info->location_code[0], | ||
192 | (char *)&pi_buff[2], | ||
193 | strlen((char *)&pi_buff[2]) + 1); | ||
194 | |||
195 | list_add_tail(&(next_partner_info->node), head); | ||
196 | next_partner_info = NULL; | ||
197 | |||
198 | } while (more); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | EXPORT_SYMBOL(hvcs_get_partner_info); | ||
203 | |||
204 | /** | ||
205 | * hvcs_register_connection - establish a connection between this vty-server and | ||
206 | * a vty. | ||
207 | * @unit_address: The unit address of the vty-server adapter that is to be | ||
208 | * establish a connection. | ||
209 | * @p_partition_ID: The partition ID of the vty adapter that is to be connected. | ||
210 | * @p_unit_address: The unit address of the vty adapter to which the vty-server | ||
211 | * is to be connected. | ||
212 | * | ||
213 | * If this function is called once and -EINVAL is returned it may | ||
214 | * indicate that the partner info needs to be refreshed for the | ||
215 | * target unit address at which point the caller must invoke | ||
216 | * hvcs_get_partner_info() and then call this function again. If, | ||
217 | * for a second time, -EINVAL is returned then it indicates that | ||
218 | * there is probably already a partner connection registered to a | ||
219 | * different vty-server adapter. It is also possible that a second | ||
220 | * -EINVAL may indicate that one of the parms is not valid, for | ||
221 | * instance if the link was removed between the vty-server adapter | ||
222 | * and the vty adapter that you are trying to open. Don't shoot the | ||
223 | * messenger. Firmware implemented it this way. | ||
224 | */ | ||
225 | int hvcs_register_connection( uint32_t unit_address, | ||
226 | uint32_t p_partition_ID, uint32_t p_unit_address) | ||
227 | { | ||
228 | long retval; | ||
229 | retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address, | ||
230 | p_partition_ID, p_unit_address); | ||
231 | return hvcs_convert(retval); | ||
232 | } | ||
233 | EXPORT_SYMBOL(hvcs_register_connection); | ||
234 | |||
235 | /** | ||
236 | * hvcs_free_connection - free the connection between a vty-server and vty | ||
237 | * @unit_address: The unit address of the vty-server that is to have its | ||
238 | * connection severed. | ||
239 | * | ||
240 | * This function is used to free the partner connection between a vty-server | ||
241 | * adapter and a vty adapter. | ||
242 | * | ||
243 | * If -EBUSY is returned continue to call this function until 0 is returned. | ||
244 | */ | ||
245 | int hvcs_free_connection(uint32_t unit_address) | ||
246 | { | ||
247 | long retval; | ||
248 | retval = plpar_hcall_norets(H_FREE_VTERM, unit_address); | ||
249 | return hvcs_convert(retval); | ||
250 | } | ||
251 | EXPORT_SYMBOL(hvcs_free_connection); | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 31990829310c..4a465f067ede 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -200,14 +200,12 @@ static void __init pSeries_setup_arch(void) | |||
200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { | 200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { |
201 | ppc_md.init_IRQ = pSeries_init_mpic; | 201 | ppc_md.init_IRQ = pSeries_init_mpic; |
202 | ppc_md.get_irq = mpic_get_irq; | 202 | ppc_md.get_irq = mpic_get_irq; |
203 | ppc_md.cpu_irq_down = mpic_teardown_this_cpu; | ||
204 | /* Allocate the mpic now, so that find_and_init_phbs() can | 203 | /* Allocate the mpic now, so that find_and_init_phbs() can |
205 | * fill the ISUs */ | 204 | * fill the ISUs */ |
206 | pSeries_setup_mpic(); | 205 | pSeries_setup_mpic(); |
207 | } else { | 206 | } else { |
208 | ppc_md.init_IRQ = xics_init_IRQ; | 207 | ppc_md.init_IRQ = xics_init_IRQ; |
209 | ppc_md.get_irq = xics_get_irq; | 208 | ppc_md.get_irq = xics_get_irq; |
210 | ppc_md.cpu_irq_down = xics_teardown_cpu; | ||
211 | } | 209 | } |
212 | 210 | ||
213 | #ifdef CONFIG_SMP | 211 | #ifdef CONFIG_SMP |
@@ -506,7 +504,7 @@ static void pseries_dedicated_idle(void) | |||
506 | lpaca->lppaca.idle = 1; | 504 | lpaca->lppaca.idle = 1; |
507 | 505 | ||
508 | if (!need_resched()) { | 506 | if (!need_resched()) { |
509 | start_snooze = __get_tb() + | 507 | start_snooze = get_tb() + |
510 | *smt_snooze_delay * tb_ticks_per_usec; | 508 | *smt_snooze_delay * tb_ticks_per_usec; |
511 | 509 | ||
512 | while (!need_resched() && !cpu_is_offline(cpu)) { | 510 | while (!need_resched() && !cpu_is_offline(cpu)) { |
@@ -520,7 +518,7 @@ static void pseries_dedicated_idle(void) | |||
520 | HMT_very_low(); | 518 | HMT_very_low(); |
521 | 519 | ||
522 | if (*smt_snooze_delay != 0 && | 520 | if (*smt_snooze_delay != 0 && |
523 | __get_tb() > start_snooze) { | 521 | get_tb() > start_snooze) { |
524 | HMT_medium(); | 522 | HMT_medium(); |
525 | dedicated_idle_sleep(cpu); | 523 | dedicated_idle_sleep(cpu); |
526 | } | 524 | } |
@@ -595,6 +593,27 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
595 | return PCI_PROBE_NORMAL; | 593 | return PCI_PROBE_NORMAL; |
596 | } | 594 | } |
597 | 595 | ||
596 | #ifdef CONFIG_KEXEC | ||
597 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | ||
598 | { | ||
599 | /* Don't risk a hypervisor call if we're crashing */ | ||
600 | if (!crash_shutdown) { | ||
601 | unsigned long vpa = __pa(&get_paca()->lppaca); | ||
602 | |||
603 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { | ||
604 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | ||
605 | "failed\n", smp_processor_id(), | ||
606 | hard_smp_processor_id()); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | if (ppc64_interrupt_controller == IC_OPEN_PIC) | ||
611 | mpic_teardown_this_cpu(secondary); | ||
612 | else | ||
613 | xics_teardown_cpu(secondary); | ||
614 | } | ||
615 | #endif | ||
616 | |||
598 | struct machdep_calls __initdata pSeries_md = { | 617 | struct machdep_calls __initdata pSeries_md = { |
599 | .probe = pSeries_probe, | 618 | .probe = pSeries_probe, |
600 | .setup_arch = pSeries_setup_arch, | 619 | .setup_arch = pSeries_setup_arch, |
@@ -617,4 +636,7 @@ struct machdep_calls __initdata pSeries_md = { | |||
617 | .check_legacy_ioport = pSeries_check_legacy_ioport, | 636 | .check_legacy_ioport = pSeries_check_legacy_ioport, |
618 | .system_reset_exception = pSeries_system_reset_exception, | 637 | .system_reset_exception = pSeries_system_reset_exception, |
619 | .machine_check_exception = pSeries_machine_check_exception, | 638 | .machine_check_exception = pSeries_machine_check_exception, |
639 | #ifdef CONFIG_KEXEC | ||
640 | .kexec_cpu_down = pseries_kexec_cpu_down, | ||
641 | #endif | ||
620 | }; | 642 | }; |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 5800cde7d5ad..25181c594d73 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "plpar_wrappers.h" | 51 | #include "plpar_wrappers.h" |
52 | 52 | ||
53 | #ifdef DEBUG | 53 | #ifdef DEBUG |
54 | #include <asm/udbg.h> | ||
54 | #define DBG(fmt...) udbg_printf(fmt) | 55 | #define DBG(fmt...) udbg_printf(fmt) |
55 | #else | 56 | #else |
56 | #define DBG(fmt...) | 57 | #define DBG(fmt...) |