aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c43
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c17
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S10
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c7
-rw-r--r--arch/powerpc/platforms/pseries/smp.c5
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
178static 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
24static unsigned long get_memblock_size(void) 24unsigned 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 */
73unsigned long memory_block_size_bytes(void)
74{
75 return get_memblock_size();
76}
77
78#ifdef CONFIG_MEMORY_HOTREMOVE 67#ifdef CONFIG_MEMORY_HOTREMOVE
79static int pseries_remove_memory(u64 start, u64 size) 68static 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 *);
64struct pci_host_bridge; 64struct pci_host_bridge;
65int pseries_root_bridge_prepare(struct pci_host_bridge *bridge); 65int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
66 66
67unsigned 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)
510static int __init pSeries_init_panel(void) 510static 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)
96static inline int smp_startup_cpu(unsigned int lcpu) 97static 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