diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 43 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hotplug-memory.c | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall.S | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pseries.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 5 |
6 files changed, 62 insertions, 22 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 8a8f0472d98f..0bec0c02c5e7 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -175,6 +175,36 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap) | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int pseries_eeh_find_ecap(struct device_node *dn, int cap) | ||
179 | { | ||
180 | struct pci_dn *pdn = PCI_DN(dn); | ||
181 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | ||
182 | u32 header; | ||
183 | int pos = 256; | ||
184 | int ttl = (4096 - 256) / 8; | ||
185 | |||
186 | if (!edev || !edev->pcie_cap) | ||
187 | return 0; | ||
188 | if (rtas_read_config(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) | ||
189 | return 0; | ||
190 | else if (!header) | ||
191 | return 0; | ||
192 | |||
193 | while (ttl-- > 0) { | ||
194 | if (PCI_EXT_CAP_ID(header) == cap && pos) | ||
195 | return pos; | ||
196 | |||
197 | pos = PCI_EXT_CAP_NEXT(header); | ||
198 | if (pos < 256) | ||
199 | break; | ||
200 | |||
201 | if (rtas_read_config(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
178 | /** | 208 | /** |
179 | * pseries_eeh_of_probe - EEH probe on the given device | 209 | * pseries_eeh_of_probe - EEH probe on the given device |
180 | * @dn: OF node | 210 | * @dn: OF node |
@@ -220,7 +250,9 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
220 | * or PCIe switch downstream port. | 250 | * or PCIe switch downstream port. |
221 | */ | 251 | */ |
222 | edev->class_code = class_code; | 252 | edev->class_code = class_code; |
253 | edev->pcix_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_PCIX); | ||
223 | edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); | 254 | edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); |
255 | edev->aer_cap = pseries_eeh_find_ecap(dn, PCI_EXT_CAP_ID_ERR); | ||
224 | edev->mode &= 0xFFFFFF00; | 256 | edev->mode &= 0xFFFFFF00; |
225 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { | 257 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { |
226 | edev->mode |= EEH_DEV_BRIDGE; | 258 | edev->mode |= EEH_DEV_BRIDGE; |
@@ -464,6 +496,7 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) | |||
464 | } else { | 496 | } else { |
465 | result = EEH_STATE_NOT_SUPPORT; | 497 | result = EEH_STATE_NOT_SUPPORT; |
466 | } | 498 | } |
499 | break; | ||
467 | default: | 500 | default: |
468 | result = EEH_STATE_NOT_SUPPORT; | 501 | result = EEH_STATE_NOT_SUPPORT; |
469 | } | 502 | } |
@@ -499,11 +532,19 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option) | |||
499 | /* If fundamental-reset not supported, try hot-reset */ | 532 | /* If fundamental-reset not supported, try hot-reset */ |
500 | if (option == EEH_RESET_FUNDAMENTAL && | 533 | if (option == EEH_RESET_FUNDAMENTAL && |
501 | ret == -8) { | 534 | ret == -8) { |
535 | option = EEH_RESET_HOT; | ||
502 | ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, | 536 | ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, |
503 | config_addr, BUID_HI(pe->phb->buid), | 537 | config_addr, BUID_HI(pe->phb->buid), |
504 | BUID_LO(pe->phb->buid), EEH_RESET_HOT); | 538 | BUID_LO(pe->phb->buid), option); |
505 | } | 539 | } |
506 | 540 | ||
541 | /* We need reset hold or settlement delay */ | ||
542 | if (option == EEH_RESET_FUNDAMENTAL || | ||
543 | option == EEH_RESET_HOT) | ||
544 | msleep(EEH_PE_RST_HOLD_TIME); | ||
545 | else | ||
546 | msleep(EEH_PE_RST_SETTLE_TIME); | ||
547 | |||
507 | return ret; | 548 | return ret; |
508 | } | 549 | } |
509 | 550 | ||
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 7f75c94af822..7995135170a3 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
22 | #include <asm/sparsemem.h> | 22 | #include <asm/sparsemem.h> |
23 | 23 | ||
24 | static unsigned long get_memblock_size(void) | 24 | unsigned long pseries_memory_block_size(void) |
25 | { | 25 | { |
26 | struct device_node *np; | 26 | struct device_node *np; |
27 | unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE; | 27 | unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE; |
@@ -64,17 +64,6 @@ static unsigned long get_memblock_size(void) | |||
64 | return memblock_size; | 64 | return memblock_size; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* WARNING: This is going to override the generic definition whenever | ||
68 | * pseries is built-in regardless of what platform is active at boot | ||
69 | * time. This is fine for now as this is the only "option" and it | ||
70 | * should work everywhere. If not, we'll have to turn this into a | ||
71 | * ppc_md. callback | ||
72 | */ | ||
73 | unsigned long memory_block_size_bytes(void) | ||
74 | { | ||
75 | return get_memblock_size(); | ||
76 | } | ||
77 | |||
78 | #ifdef CONFIG_MEMORY_HOTREMOVE | 67 | #ifdef CONFIG_MEMORY_HOTREMOVE |
79 | static int pseries_remove_memory(u64 start, u64 size) | 68 | static int pseries_remove_memory(u64 start, u64 size) |
80 | { | 69 | { |
@@ -105,7 +94,7 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz | |||
105 | if (!pfn_valid(start_pfn)) | 94 | if (!pfn_valid(start_pfn)) |
106 | goto out; | 95 | goto out; |
107 | 96 | ||
108 | block_sz = memory_block_size_bytes(); | 97 | block_sz = pseries_memory_block_size(); |
109 | sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE; | 98 | sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE; |
110 | nid = memory_add_physaddr_to_nid(base); | 99 | nid = memory_add_physaddr_to_nid(base); |
111 | 100 | ||
@@ -201,7 +190,7 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr) | |||
201 | u32 *p; | 190 | u32 *p; |
202 | int i, rc = -EINVAL; | 191 | int i, rc = -EINVAL; |
203 | 192 | ||
204 | memblock_size = get_memblock_size(); | 193 | memblock_size = pseries_memory_block_size(); |
205 | if (!memblock_size) | 194 | if (!memblock_size) |
206 | return -EINVAL; | 195 | return -EINVAL; |
207 | 196 | ||
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 444fe7759e55..99ecf0a5a929 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -49,7 +49,7 @@ END_FTR_SECTION(0, 1); \ | |||
49 | std r0,16(r1); \ | 49 | std r0,16(r1); \ |
50 | addi r4,r1,STK_PARAM(FIRST_REG); \ | 50 | addi r4,r1,STK_PARAM(FIRST_REG); \ |
51 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | 51 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ |
52 | bl .__trace_hcall_entry; \ | 52 | bl __trace_hcall_entry; \ |
53 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 53 | addi r1,r1,STACK_FRAME_OVERHEAD; \ |
54 | ld r0,16(r1); \ | 54 | ld r0,16(r1); \ |
55 | ld r3,STK_PARAM(R3)(r1); \ | 55 | ld r3,STK_PARAM(R3)(r1); \ |
@@ -83,7 +83,7 @@ END_FTR_SECTION(0, 1); \ | |||
83 | mr r3,r6; \ | 83 | mr r3,r6; \ |
84 | std r0,16(r1); \ | 84 | std r0,16(r1); \ |
85 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | 85 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ |
86 | bl .__trace_hcall_exit; \ | 86 | bl __trace_hcall_exit; \ |
87 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 87 | addi r1,r1,STACK_FRAME_OVERHEAD; \ |
88 | ld r0,16(r1); \ | 88 | ld r0,16(r1); \ |
89 | ld r3,STK_PARAM(R3)(r1); \ | 89 | ld r3,STK_PARAM(R3)(r1); \ |
@@ -106,7 +106,7 @@ END_FTR_SECTION(0, 1); \ | |||
106 | 106 | ||
107 | .text | 107 | .text |
108 | 108 | ||
109 | _GLOBAL(plpar_hcall_norets) | 109 | _GLOBAL_TOC(plpar_hcall_norets) |
110 | HMT_MEDIUM | 110 | HMT_MEDIUM |
111 | 111 | ||
112 | mfcr r0 | 112 | mfcr r0 |
@@ -122,7 +122,7 @@ _GLOBAL(plpar_hcall_norets) | |||
122 | mtcrf 0xff,r0 | 122 | mtcrf 0xff,r0 |
123 | blr /* return r3 = status */ | 123 | blr /* return r3 = status */ |
124 | 124 | ||
125 | _GLOBAL(plpar_hcall) | 125 | _GLOBAL_TOC(plpar_hcall) |
126 | HMT_MEDIUM | 126 | HMT_MEDIUM |
127 | 127 | ||
128 | mfcr r0 | 128 | mfcr r0 |
@@ -188,7 +188,7 @@ _GLOBAL(plpar_hcall_raw) | |||
188 | 188 | ||
189 | blr /* return r3 = status */ | 189 | blr /* return r3 = status */ |
190 | 190 | ||
191 | _GLOBAL(plpar_hcall9) | 191 | _GLOBAL_TOC(plpar_hcall9) |
192 | HMT_MEDIUM | 192 | HMT_MEDIUM |
193 | 193 | ||
194 | mfcr r0 | 194 | mfcr r0 |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 99219530ea4a..361add62abf1 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -64,4 +64,6 @@ extern int dlpar_detach_node(struct device_node *); | |||
64 | struct pci_host_bridge; | 64 | struct pci_host_bridge; |
65 | int pseries_root_bridge_prepare(struct pci_host_bridge *bridge); | 65 | int pseries_root_bridge_prepare(struct pci_host_bridge *bridge); |
66 | 66 | ||
67 | unsigned long pseries_memory_block_size(void); | ||
68 | |||
67 | #endif /* _PSERIES_PSERIES_H */ | 69 | #endif /* _PSERIES_PSERIES_H */ |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 099d2df976a2..f2f40e64658f 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -510,7 +510,11 @@ static void __init pSeries_setup_arch(void) | |||
510 | static int __init pSeries_init_panel(void) | 510 | static int __init pSeries_init_panel(void) |
511 | { | 511 | { |
512 | /* Manually leave the kernel version on the panel. */ | 512 | /* Manually leave the kernel version on the panel. */ |
513 | #ifdef __BIG_ENDIAN__ | ||
513 | ppc_md.progress("Linux ppc64\n", 0); | 514 | ppc_md.progress("Linux ppc64\n", 0); |
515 | #else | ||
516 | ppc_md.progress("Linux ppc64le\n", 0); | ||
517 | #endif | ||
514 | ppc_md.progress(init_utsname()->version, 0); | 518 | ppc_md.progress(init_utsname()->version, 0); |
515 | 519 | ||
516 | return 0; | 520 | return 0; |
@@ -806,4 +810,7 @@ define_machine(pseries) { | |||
806 | #ifdef CONFIG_KEXEC | 810 | #ifdef CONFIG_KEXEC |
807 | .machine_kexec = pSeries_machine_kexec, | 811 | .machine_kexec = pSeries_machine_kexec, |
808 | #endif | 812 | #endif |
813 | #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE | ||
814 | .memory_block_size = pseries_memory_block_size, | ||
815 | #endif | ||
809 | }; | 816 | }; |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 24f58cb0a543..a3555b10c1a5 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/xics.h> | 44 | #include <asm/xics.h> |
45 | #include <asm/dbell.h> | 45 | #include <asm/dbell.h> |
46 | #include <asm/plpar_wrappers.h> | 46 | #include <asm/plpar_wrappers.h> |
47 | #include <asm/code-patching.h> | ||
47 | 48 | ||
48 | #include "pseries.h" | 49 | #include "pseries.h" |
49 | #include "offline_states.h" | 50 | #include "offline_states.h" |
@@ -96,8 +97,8 @@ int smp_query_cpu_stopped(unsigned int pcpu) | |||
96 | static inline int smp_startup_cpu(unsigned int lcpu) | 97 | static inline int smp_startup_cpu(unsigned int lcpu) |
97 | { | 98 | { |
98 | int status; | 99 | int status; |
99 | unsigned long start_here = __pa((u32)*((unsigned long *) | 100 | unsigned long start_here = |
100 | generic_secondary_smp_init)); | 101 | __pa(ppc_function_entry(generic_secondary_smp_init)); |
101 | unsigned int pcpu; | 102 | unsigned int pcpu; |
102 | int start_cpu; | 103 | int start_cpu; |
103 | 104 | ||