diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 21 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/firmware.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/firmware.h | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall_inst.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/kexec.c | 72 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 55 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/power.c | 87 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pseries.h | 39 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/ras.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/ras.h | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/rtasd.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/scanlog.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 90 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 1 |
18 files changed, 315 insertions, 100 deletions
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 69590fbf83da..2dfd05095a25 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -4,11 +4,12 @@ endif | |||
4 | 4 | ||
5 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ | 5 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ |
6 | setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ | 6 | setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ |
7 | firmware.o | 7 | firmware.o power.o |
8 | obj-$(CONFIG_SMP) += smp.o | 8 | obj-$(CONFIG_SMP) += smp.o |
9 | obj-$(CONFIG_XICS) += xics.o | 9 | obj-$(CONFIG_XICS) += xics.o |
10 | obj-$(CONFIG_SCANLOG) += scanlog.o | 10 | obj-$(CONFIG_SCANLOG) += scanlog.o |
11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o | 11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o |
12 | obj-$(CONFIG_KEXEC) += kexec.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o | 14 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o |
14 | 15 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index da6e5362e7cd..6cedbc002e0f 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -747,6 +747,7 @@ struct eeh_early_enable_info { | |||
747 | /* Enable eeh for the given device node. */ | 747 | /* Enable eeh for the given device node. */ |
748 | static void *early_enable_eeh(struct device_node *dn, void *data) | 748 | static void *early_enable_eeh(struct device_node *dn, void *data) |
749 | { | 749 | { |
750 | unsigned int rets[3]; | ||
750 | struct eeh_early_enable_info *info = data; | 751 | struct eeh_early_enable_info *info = data; |
751 | int ret; | 752 | int ret; |
752 | const char *status = get_property(dn, "status", NULL); | 753 | const char *status = get_property(dn, "status", NULL); |
@@ -803,16 +804,14 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
803 | regs[0], info->buid_hi, info->buid_lo, | 804 | regs[0], info->buid_hi, info->buid_lo, |
804 | EEH_ENABLE); | 805 | EEH_ENABLE); |
805 | 806 | ||
807 | enable = 0; | ||
806 | if (ret == 0) { | 808 | if (ret == 0) { |
807 | eeh_subsystem_enabled = 1; | ||
808 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | ||
809 | pdn->eeh_config_addr = regs[0]; | 809 | pdn->eeh_config_addr = regs[0]; |
810 | 810 | ||
811 | /* If the newer, better, ibm,get-config-addr-info is supported, | 811 | /* If the newer, better, ibm,get-config-addr-info is supported, |
812 | * then use that instead. */ | 812 | * then use that instead. */ |
813 | pdn->eeh_pe_config_addr = 0; | 813 | pdn->eeh_pe_config_addr = 0; |
814 | if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { | 814 | if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { |
815 | unsigned int rets[2]; | ||
816 | ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, | 815 | ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, |
817 | pdn->eeh_config_addr, | 816 | pdn->eeh_config_addr, |
818 | info->buid_hi, info->buid_lo, | 817 | info->buid_hi, info->buid_lo, |
@@ -820,6 +819,20 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
820 | if (ret == 0) | 819 | if (ret == 0) |
821 | pdn->eeh_pe_config_addr = rets[0]; | 820 | pdn->eeh_pe_config_addr = rets[0]; |
822 | } | 821 | } |
822 | |||
823 | /* Some older systems (Power4) allow the | ||
824 | * ibm,set-eeh-option call to succeed even on nodes | ||
825 | * where EEH is not supported. Verify support | ||
826 | * explicitly. */ | ||
827 | ret = read_slot_reset_state(pdn, rets); | ||
828 | if ((ret == 0) && (rets[1] == 1)) | ||
829 | enable = 1; | ||
830 | } | ||
831 | |||
832 | if (enable) { | ||
833 | eeh_subsystem_enabled = 1; | ||
834 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | ||
835 | |||
823 | #ifdef DEBUG | 836 | #ifdef DEBUG |
824 | printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n", | 837 | printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n", |
825 | dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr); | 838 | dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr); |
@@ -1065,7 +1078,7 @@ static int proc_eeh_open(struct inode *inode, struct file *file) | |||
1065 | return single_open(file, proc_eeh_show, NULL); | 1078 | return single_open(file, proc_eeh_show, NULL); |
1066 | } | 1079 | } |
1067 | 1080 | ||
1068 | static struct file_operations proc_eeh_operations = { | 1081 | static const struct file_operations proc_eeh_operations = { |
1069 | .open = proc_eeh_open, | 1082 | .open = proc_eeh_open, |
1070 | .read = seq_read, | 1083 | .read = seq_read, |
1071 | .llseek = seq_lseek, | 1084 | .llseek = seq_lseek, |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index cbd6b0711ab4..a4c0bf84ef2e 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -446,7 +446,8 @@ excess_failures: | |||
446 | */ | 446 | */ |
447 | printk(KERN_ERR | 447 | printk(KERN_ERR |
448 | "EEH: PCI device at location=%s driver=%s pci addr=%s \n" | 448 | "EEH: PCI device at location=%s driver=%s pci addr=%s \n" |
449 | "has failed %d times and has been permanently disabled. \n" | 449 | "has failed %d times in the last hour " |
450 | "and has been permanently disabled. \n" | ||
450 | "Please try reseating this device or replacing it.\n", | 451 | "Please try reseating this device or replacing it.\n", |
451 | location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); | 452 | location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); |
452 | goto perm_error; | 453 | goto perm_error; |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 1c7b2baa5f73..90522e3c9d46 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -59,6 +59,7 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = { | |||
59 | {FW_FEATURE_XDABR, "hcall-xdabr"}, | 59 | {FW_FEATURE_XDABR, "hcall-xdabr"}, |
60 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, | 60 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, |
61 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, | 61 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, |
62 | {FW_FEATURE_BULK_REMOVE, "hcall-bulk"}, | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | /* Build up the firmware features bitmask using the contents of | 65 | /* Build up the firmware features bitmask using the contents of |
diff --git a/arch/powerpc/platforms/pseries/firmware.h b/arch/powerpc/platforms/pseries/firmware.h deleted file mode 100644 index 714f56f55362..000000000000 --- a/arch/powerpc/platforms/pseries/firmware.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2006 IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PSERIES_FIRMWARE_H | ||
11 | #define _PSERIES_FIRMWARE_H | ||
12 | |||
13 | #include <asm/firmware.h> | ||
14 | |||
15 | extern void __init fw_feature_init(void); | ||
16 | |||
17 | #endif /* _PSERIES_FIRMWARE_H */ | ||
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index 3ddc04925d50..eae51ef9af24 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -90,7 +90,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file) | |||
90 | return rc; | 90 | return rc; |
91 | } | 91 | } |
92 | 92 | ||
93 | static struct file_operations hcall_inst_seq_fops = { | 93 | static const struct file_operations hcall_inst_seq_fops = { |
94 | .open = hcall_inst_seq_open, | 94 | .open = hcall_inst_seq_open, |
95 | .read = seq_read, | 95 | .read = seq_read, |
96 | .llseek = seq_lseek, | 96 | .llseek = seq_lseek, |
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c new file mode 100644 index 000000000000..af2685607458 --- /dev/null +++ b/arch/powerpc/platforms/pseries/kexec.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright 2006 Michael Ellerman, IBM Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <asm/machdep.h> | ||
11 | #include <asm/page.h> | ||
12 | #include <asm/firmware.h> | ||
13 | #include <asm/kexec.h> | ||
14 | #include <asm/mpic.h> | ||
15 | |||
16 | #include "pseries.h" | ||
17 | #include "xics.h" | ||
18 | #include "plpar_wrappers.h" | ||
19 | |||
20 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | ||
21 | { | ||
22 | /* Don't risk a hypervisor call if we're crashing */ | ||
23 | if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { | ||
24 | unsigned long addr; | ||
25 | |||
26 | addr = __pa(get_slb_shadow()); | ||
27 | if (unregister_slb_shadow(hard_smp_processor_id(), addr)) | ||
28 | printk("SLB shadow buffer deregistration of " | ||
29 | "cpu %u (hw_cpu_id %d) failed\n", | ||
30 | smp_processor_id(), | ||
31 | hard_smp_processor_id()); | ||
32 | |||
33 | addr = __pa(get_lppaca()); | ||
34 | if (unregister_vpa(hard_smp_processor_id(), addr)) { | ||
35 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | ||
36 | "failed\n", smp_processor_id(), | ||
37 | hard_smp_processor_id()); | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) | ||
43 | { | ||
44 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
45 | mpic_teardown_this_cpu(secondary); | ||
46 | } | ||
47 | |||
48 | void __init setup_kexec_cpu_down_mpic(void) | ||
49 | { | ||
50 | ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic; | ||
51 | } | ||
52 | |||
53 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | ||
54 | { | ||
55 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
56 | xics_teardown_cpu(secondary); | ||
57 | } | ||
58 | |||
59 | void __init setup_kexec_cpu_down_xics(void) | ||
60 | { | ||
61 | ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics; | ||
62 | } | ||
63 | |||
64 | static int __init pseries_kexec_setup(void) | ||
65 | { | ||
66 | ppc_md.machine_kexec = default_machine_kexec; | ||
67 | ppc_md.machine_kexec_prepare = default_machine_kexec_prepare; | ||
68 | ppc_md.machine_crash_shutdown = default_machine_crash_shutdown; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | __initcall(pseries_kexec_setup); | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 721436db3ef0..7496005566ef 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -502,23 +502,70 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
502 | BUG_ON(lpar_rc != H_SUCCESS); | 502 | BUG_ON(lpar_rc != H_SUCCESS); |
503 | } | 503 | } |
504 | 504 | ||
505 | /* Flag bits for H_BULK_REMOVE */ | ||
506 | #define HBR_REQUEST 0x4000000000000000UL | ||
507 | #define HBR_RESPONSE 0x8000000000000000UL | ||
508 | #define HBR_END 0xc000000000000000UL | ||
509 | #define HBR_AVPN 0x0200000000000000UL | ||
510 | #define HBR_ANDCOND 0x0100000000000000UL | ||
511 | |||
505 | /* | 512 | /* |
506 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie | 513 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie |
507 | * lock. | 514 | * lock. |
508 | */ | 515 | */ |
509 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | 516 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) |
510 | { | 517 | { |
511 | int i; | 518 | unsigned long i, pix, rc; |
512 | unsigned long flags = 0; | 519 | unsigned long flags = 0; |
513 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 520 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); |
514 | int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); | 521 | int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); |
522 | unsigned long param[9]; | ||
523 | unsigned long va; | ||
524 | unsigned long hash, index, shift, hidx, slot; | ||
525 | real_pte_t pte; | ||
526 | int psize; | ||
515 | 527 | ||
516 | if (lock_tlbie) | 528 | if (lock_tlbie) |
517 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | 529 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); |
518 | 530 | ||
519 | for (i = 0; i < number; i++) | 531 | psize = batch->psize; |
520 | flush_hash_page(batch->vaddr[i], batch->pte[i], | 532 | pix = 0; |
521 | batch->psize, local); | 533 | for (i = 0; i < number; i++) { |
534 | va = batch->vaddr[i]; | ||
535 | pte = batch->pte[i]; | ||
536 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { | ||
537 | hash = hpt_hash(va, shift); | ||
538 | hidx = __rpte_to_hidx(pte, index); | ||
539 | if (hidx & _PTEIDX_SECONDARY) | ||
540 | hash = ~hash; | ||
541 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
542 | slot += hidx & _PTEIDX_GROUP_IX; | ||
543 | if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { | ||
544 | pSeries_lpar_hpte_invalidate(slot, va, psize, | ||
545 | local); | ||
546 | } else { | ||
547 | param[pix] = HBR_REQUEST | HBR_AVPN | slot; | ||
548 | param[pix+1] = hpte_encode_v(va, psize) & | ||
549 | HPTE_V_AVPN; | ||
550 | pix += 2; | ||
551 | if (pix == 8) { | ||
552 | rc = plpar_hcall9(H_BULK_REMOVE, param, | ||
553 | param[0], param[1], param[2], | ||
554 | param[3], param[4], param[5], | ||
555 | param[6], param[7]); | ||
556 | BUG_ON(rc != H_SUCCESS); | ||
557 | pix = 0; | ||
558 | } | ||
559 | } | ||
560 | } pte_iterate_hashed_end(); | ||
561 | } | ||
562 | if (pix) { | ||
563 | param[pix] = HBR_END; | ||
564 | rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1], | ||
565 | param[2], param[3], param[4], param[5], | ||
566 | param[6], param[7]); | ||
567 | BUG_ON(rc != H_SUCCESS); | ||
568 | } | ||
522 | 569 | ||
523 | if (lock_tlbie) | 570 | if (lock_tlbie) |
524 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 571 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 715db5c89908..fa59124ce3fe 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -77,7 +77,7 @@ void __init pSeries_final_fixup(void) | |||
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Assume the winbond 82c105 is the IDE controller on a | 79 | * Assume the winbond 82c105 is the IDE controller on a |
80 | * p610. We should probably be more careful in case | 80 | * p610/p615/p630. We should probably be more careful in case |
81 | * someone tries to plug in a similar adapter. | 81 | * someone tries to plug in a similar adapter. |
82 | */ | 82 | */ |
83 | static void fixup_winbond_82c105(struct pci_dev* dev) | 83 | static void fixup_winbond_82c105(struct pci_dev* dev) |
@@ -98,6 +98,10 @@ static void fixup_winbond_82c105(struct pci_dev* dev) | |||
98 | if (dev->resource[i].flags & IORESOURCE_IO | 98 | if (dev->resource[i].flags & IORESOURCE_IO |
99 | && dev->bus->number == 0 && dev->devfn == 0x81) | 99 | && dev->bus->number == 0 && dev->devfn == 0x81) |
100 | dev->resource[i].flags &= ~IORESOURCE_IO; | 100 | dev->resource[i].flags &= ~IORESOURCE_IO; |
101 | if (dev->resource[i].start == 0 && dev->resource[i].end) { | ||
102 | dev->resource[i].flags = 0; | ||
103 | dev->resource[i].end = 0; | ||
104 | } | ||
101 | } | 105 | } |
102 | } | 106 | } |
103 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, | 107 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, |
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c new file mode 100644 index 000000000000..2624b71df73d --- /dev/null +++ b/arch/powerpc/platforms/pseries/power.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Interface for power-management for ppc64 compliant platform | ||
3 | * | ||
4 | * Manish Ahuja <mahuja@us.ibm.com> | ||
5 | * | ||
6 | * Feb 2007 | ||
7 | * | ||
8 | * Copyright (C) 2007 IBM Corporation. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; version 2 of the License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/kobject.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | |||
29 | unsigned long rtas_poweron_auto; /* default and normal state is 0 */ | ||
30 | |||
31 | static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf) | ||
32 | { | ||
33 | return sprintf(buf, "%lu\n", rtas_poweron_auto); | ||
34 | } | ||
35 | |||
36 | static ssize_t | ||
37 | auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n) | ||
38 | { | ||
39 | int ret; | ||
40 | unsigned long ups_restart; | ||
41 | ret = sscanf(buf, "%lu", &ups_restart); | ||
42 | |||
43 | if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){ | ||
44 | rtas_poweron_auto = ups_restart; | ||
45 | return n; | ||
46 | } | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | static struct subsys_attribute auto_poweron_attr = { | ||
51 | .attr = { | ||
52 | .name = __stringify(auto_poweron), | ||
53 | .mode = 0644, | ||
54 | }, | ||
55 | .show = auto_poweron_show, | ||
56 | .store = auto_poweron_store, | ||
57 | }; | ||
58 | |||
59 | #ifndef CONFIG_PM | ||
60 | decl_subsys(power,NULL,NULL); | ||
61 | |||
62 | static struct attribute *g[] = { | ||
63 | &auto_poweron_attr.attr, | ||
64 | NULL, | ||
65 | }; | ||
66 | |||
67 | static struct attribute_group attr_group = { | ||
68 | .attrs = g, | ||
69 | }; | ||
70 | |||
71 | static int __init pm_init(void) | ||
72 | { | ||
73 | int error = subsystem_register(&power_subsys); | ||
74 | if (!error) | ||
75 | error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group); | ||
76 | return error; | ||
77 | } | ||
78 | core_initcall(pm_init); | ||
79 | #else | ||
80 | extern struct subsystem power_subsys; | ||
81 | |||
82 | static int __init apo_pm_init(void) | ||
83 | { | ||
84 | return (subsys_create_file(&power_subsys, &auto_poweron_attr)); | ||
85 | } | ||
86 | __initcall(apo_pm_init); | ||
87 | #endif | ||
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h new file mode 100644 index 000000000000..22bc01989749 --- /dev/null +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright 2006 IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PSERIES_PSERIES_H | ||
11 | #define _PSERIES_PSERIES_H | ||
12 | |||
13 | extern void __init fw_feature_init(void); | ||
14 | |||
15 | struct pt_regs; | ||
16 | |||
17 | extern int pSeries_system_reset_exception(struct pt_regs *regs); | ||
18 | extern int pSeries_machine_check_exception(struct pt_regs *regs); | ||
19 | |||
20 | #ifdef CONFIG_SMP | ||
21 | extern void smp_init_pseries_mpic(void); | ||
22 | extern void smp_init_pseries_xics(void); | ||
23 | #else | ||
24 | static inline smp_init_pseries_mpic(void) { }; | ||
25 | static inline smp_init_pseries_xics(void) { }; | ||
26 | #endif | ||
27 | |||
28 | #ifdef CONFIG_KEXEC | ||
29 | extern void setup_kexec_cpu_down_xics(void); | ||
30 | extern void setup_kexec_cpu_down_mpic(void); | ||
31 | #else | ||
32 | static inline void setup_kexec_cpu_down_xics(void) { } | ||
33 | static inline void setup_kexec_cpu_down_mpic(void) { } | ||
34 | #endif | ||
35 | |||
36 | /* Poweron flag used for enabling auto ups restart */ | ||
37 | extern unsigned long rtas_poweron_auto; | ||
38 | |||
39 | #endif /* _PSERIES_PSERIES_H */ | ||
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index b1d3d161249e..edc038873113 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include <asm/udbg.h> | 51 | #include <asm/udbg.h> |
52 | #include <asm/firmware.h> | 52 | #include <asm/firmware.h> |
53 | 53 | ||
54 | #include "ras.h" | 54 | #include "pseries.h" |
55 | 55 | ||
56 | static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; | 56 | static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; |
57 | static DEFINE_SPINLOCK(ras_log_buf_lock); | 57 | static DEFINE_SPINLOCK(ras_log_buf_lock); |
diff --git a/arch/powerpc/platforms/pseries/ras.h b/arch/powerpc/platforms/pseries/ras.h deleted file mode 100644 index 0e66b0da55e2..000000000000 --- a/arch/powerpc/platforms/pseries/ras.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef _PSERIES_RAS_H | ||
2 | #define _PSERIES_RAS_H | ||
3 | |||
4 | struct pt_regs; | ||
5 | |||
6 | extern int pSeries_system_reset_exception(struct pt_regs *regs); | ||
7 | extern int pSeries_machine_check_exception(struct pt_regs *regs); | ||
8 | |||
9 | #endif /* _PSERIES_RAS_H */ | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 4ad33e41b008..5aa97aff3391 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -499,7 +499,7 @@ out: | |||
499 | return rv ? rv : count; | 499 | return rv ? rv : count; |
500 | } | 500 | } |
501 | 501 | ||
502 | static struct file_operations ofdt_fops = { | 502 | static const struct file_operations ofdt_fops = { |
503 | .write = ofdt_write | 503 | .write = ofdt_write |
504 | }; | 504 | }; |
505 | 505 | ||
@@ -513,7 +513,6 @@ static int proc_ppc64_create_ofdt(void) | |||
513 | 513 | ||
514 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); | 514 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); |
515 | if (ent) { | 515 | if (ent) { |
516 | ent->nlink = 1; | ||
517 | ent->data = NULL; | 516 | ent->data = NULL; |
518 | ent->size = 0; | 517 | ent->size = 0; |
519 | ent->proc_fops = &ofdt_fops; | 518 | ent->proc_fops = &ofdt_fops; |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 8ca2612221d6..77d0937d5c07 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -331,7 +331,7 @@ static unsigned int rtas_log_poll(struct file *file, poll_table * wait) | |||
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | 333 | ||
334 | struct file_operations proc_rtas_log_operations = { | 334 | const struct file_operations proc_rtas_log_operations = { |
335 | .read = rtas_log_read, | 335 | .read = rtas_log_read, |
336 | .poll = rtas_log_poll, | 336 | .poll = rtas_log_poll, |
337 | .open = rtas_log_open, | 337 | .open = rtas_log_open, |
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 45368a57d7dd..8e1ef168e2dd 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
@@ -184,7 +184,7 @@ static int scanlog_release(struct inode * inode, struct file * file) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | struct file_operations scanlog_fops = { | 187 | const struct file_operations scanlog_fops = { |
188 | .owner = THIS_MODULE, | 188 | .owner = THIS_MODULE, |
189 | .read = scanlog_read, | 189 | .read = scanlog_read, |
190 | .write = scanlog_write, | 190 | .write = scanlog_write, |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 042ecae107ac..34aff47b1f55 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <asm/dma.h> | 55 | #include <asm/dma.h> |
56 | #include <asm/machdep.h> | 56 | #include <asm/machdep.h> |
57 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
58 | #include <asm/kexec.h> | ||
59 | #include <asm/time.h> | 58 | #include <asm/time.h> |
60 | #include <asm/nvram.h> | 59 | #include <asm/nvram.h> |
61 | #include "xics.h" | 60 | #include "xics.h" |
@@ -65,10 +64,10 @@ | |||
65 | #include <asm/i8259.h> | 64 | #include <asm/i8259.h> |
66 | #include <asm/udbg.h> | 65 | #include <asm/udbg.h> |
67 | #include <asm/smp.h> | 66 | #include <asm/smp.h> |
67 | #include <asm/firmware.h> | ||
68 | 68 | ||
69 | #include "plpar_wrappers.h" | 69 | #include "plpar_wrappers.h" |
70 | #include "ras.h" | 70 | #include "pseries.h" |
71 | #include "firmware.h" | ||
72 | 71 | ||
73 | #ifdef DEBUG | 72 | #ifdef DEBUG |
74 | #define DBG(fmt...) udbg_printf(fmt) | 73 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -77,8 +76,6 @@ | |||
77 | #endif | 76 | #endif |
78 | 77 | ||
79 | /* move those away to a .h */ | 78 | /* move those away to a .h */ |
80 | extern void smp_init_pseries_mpic(void); | ||
81 | extern void smp_init_pseries_xics(void); | ||
82 | extern void find_udbg_vterm(void); | 79 | extern void find_udbg_vterm(void); |
83 | 80 | ||
84 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ | 81 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
@@ -221,42 +218,6 @@ static void pseries_lpar_enable_pmcs(void) | |||
221 | get_lppaca()->pmcregs_in_use = 1; | 218 | get_lppaca()->pmcregs_in_use = 1; |
222 | } | 219 | } |
223 | 220 | ||
224 | #ifdef CONFIG_KEXEC | ||
225 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | ||
226 | { | ||
227 | /* Don't risk a hypervisor call if we're crashing */ | ||
228 | if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { | ||
229 | unsigned long addr; | ||
230 | |||
231 | addr = __pa(get_slb_shadow()); | ||
232 | if (unregister_slb_shadow(hard_smp_processor_id(), addr)) | ||
233 | printk("SLB shadow buffer deregistration of " | ||
234 | "cpu %u (hw_cpu_id %d) failed\n", | ||
235 | smp_processor_id(), | ||
236 | hard_smp_processor_id()); | ||
237 | |||
238 | addr = __pa(get_lppaca()); | ||
239 | if (unregister_vpa(hard_smp_processor_id(), addr)) { | ||
240 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | ||
241 | "failed\n", smp_processor_id(), | ||
242 | hard_smp_processor_id()); | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) | ||
248 | { | ||
249 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
250 | mpic_teardown_this_cpu(secondary); | ||
251 | } | ||
252 | |||
253 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | ||
254 | { | ||
255 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
256 | xics_teardown_cpu(secondary); | ||
257 | } | ||
258 | #endif /* CONFIG_KEXEC */ | ||
259 | |||
260 | static void __init pseries_discover_pic(void) | 221 | static void __init pseries_discover_pic(void) |
261 | { | 222 | { |
262 | struct device_node *np; | 223 | struct device_node *np; |
@@ -269,21 +230,13 @@ static void __init pseries_discover_pic(void) | |||
269 | pSeries_mpic_node = of_node_get(np); | 230 | pSeries_mpic_node = of_node_get(np); |
270 | ppc_md.init_IRQ = pseries_mpic_init_IRQ; | 231 | ppc_md.init_IRQ = pseries_mpic_init_IRQ; |
271 | ppc_md.get_irq = mpic_get_irq; | 232 | ppc_md.get_irq = mpic_get_irq; |
272 | #ifdef CONFIG_KEXEC | 233 | setup_kexec_cpu_down_mpic(); |
273 | ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic; | ||
274 | #endif | ||
275 | #ifdef CONFIG_SMP | ||
276 | smp_init_pseries_mpic(); | 234 | smp_init_pseries_mpic(); |
277 | #endif | ||
278 | return; | 235 | return; |
279 | } else if (strstr(typep, "ppc-xicp")) { | 236 | } else if (strstr(typep, "ppc-xicp")) { |
280 | ppc_md.init_IRQ = xics_init_IRQ; | 237 | ppc_md.init_IRQ = xics_init_IRQ; |
281 | #ifdef CONFIG_KEXEC | 238 | setup_kexec_cpu_down_xics(); |
282 | ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics; | ||
283 | #endif | ||
284 | #ifdef CONFIG_SMP | ||
285 | smp_init_pseries_xics(); | 239 | smp_init_pseries_xics(); |
286 | #endif | ||
287 | return; | 240 | return; |
288 | } | 241 | } |
289 | } | 242 | } |
@@ -533,6 +486,34 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
533 | return PCI_PROBE_NORMAL; | 486 | return PCI_PROBE_NORMAL; |
534 | } | 487 | } |
535 | 488 | ||
489 | /** | ||
490 | * pSeries_power_off - tell firmware about how to power off the system. | ||
491 | * | ||
492 | * This function calls either the power-off rtas token in normal cases | ||
493 | * or the ibm,power-off-ups token (if present & requested) in case of | ||
494 | * a power failure. If power-off token is used, power on will only be | ||
495 | * possible with power button press. If ibm,power-off-ups token is used | ||
496 | * it will allow auto poweron after power is restored. | ||
497 | */ | ||
498 | void pSeries_power_off(void) | ||
499 | { | ||
500 | int rc; | ||
501 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | ||
502 | |||
503 | if (rtas_flash_term_hook) | ||
504 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
505 | |||
506 | if (rtas_poweron_auto == 0 || | ||
507 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { | ||
508 | rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); | ||
509 | printk(KERN_INFO "RTAS power-off returned %d\n", rc); | ||
510 | } else { | ||
511 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); | ||
512 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); | ||
513 | } | ||
514 | for (;;); | ||
515 | } | ||
516 | |||
536 | define_machine(pseries) { | 517 | define_machine(pseries) { |
537 | .name = "pSeries", | 518 | .name = "pSeries", |
538 | .probe = pSeries_probe, | 519 | .probe = pSeries_probe, |
@@ -543,7 +524,7 @@ define_machine(pseries) { | |||
543 | .pcibios_fixup = pSeries_final_fixup, | 524 | .pcibios_fixup = pSeries_final_fixup, |
544 | .pci_probe_mode = pSeries_pci_probe_mode, | 525 | .pci_probe_mode = pSeries_pci_probe_mode, |
545 | .restart = rtas_restart, | 526 | .restart = rtas_restart, |
546 | .power_off = rtas_power_off, | 527 | .power_off = pSeries_power_off, |
547 | .halt = rtas_halt, | 528 | .halt = rtas_halt, |
548 | .panic = rtas_os_term, | 529 | .panic = rtas_os_term, |
549 | .get_boot_time = rtas_get_boot_time, | 530 | .get_boot_time = rtas_get_boot_time, |
@@ -554,9 +535,4 @@ define_machine(pseries) { | |||
554 | .check_legacy_ioport = pSeries_check_legacy_ioport, | 535 | .check_legacy_ioport = pSeries_check_legacy_ioport, |
555 | .system_reset_exception = pSeries_system_reset_exception, | 536 | .system_reset_exception = pSeries_system_reset_exception, |
556 | .machine_check_exception = pSeries_machine_check_exception, | 537 | .machine_check_exception = pSeries_machine_check_exception, |
557 | #ifdef CONFIG_KEXEC | ||
558 | .machine_kexec = default_machine_kexec, | ||
559 | .machine_kexec_prepare = default_machine_kexec_prepare, | ||
560 | .machine_crash_shutdown = default_machine_crash_shutdown, | ||
561 | #endif | ||
562 | }; | 538 | }; |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 4408518eaebe..116305b22a2b 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <asm/vdso_datapage.h> | 48 | #include <asm/vdso_datapage.h> |
49 | 49 | ||
50 | #include "plpar_wrappers.h" | 50 | #include "plpar_wrappers.h" |
51 | #include "pseries.h" | ||
51 | 52 | ||
52 | #ifdef DEBUG | 53 | #ifdef DEBUG |
53 | #include <asm/udbg.h> | 54 | #include <asm/udbg.h> |