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 | ||
