diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-03 17:20:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-03 17:20:22 -0400 |
commit | 5306d766f15e72bc79c61d88f77e5a6b1fcc0e68 (patch) | |
tree | 14798d3026bb8b168b7d55d6090acedd55f69e23 | |
parent | 4340fa55298d17049e71c7a34e04647379c269f3 (diff) | |
parent | 7cc851039d643a2ee7df4d18177150f2c3a484f5 (diff) |
Merge tag 'powerpc-4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman:
- Handle RTAS delay requests in configure_bridge from Russell Currey
- Refactor the configure_bridge RTAS tokens from Russell Currey
- Fix definition of SIAR and SDAR registers from Thomas Huth
- Use privileged SPR number for MMCR2 from Thomas Huth
- Update LPCR only if it is powernv from Aneesh Kumar K.V
- Fix the reference bit update when handling hash fault from Aneesh
Kumar K.V
- Add missing tlb flush from Aneesh Kumar K.V
- Add POWER8NVL support to ibm,client-architecture-support call from
Thomas Huth
* tag 'powerpc-4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc/pseries: Add POWER8NVL support to ibm,client-architecture-support call
powerpc/mm/radix: Add missing tlb flush
powerpc/mm/hash: Fix the reference bit update when handling hash fault
powerpc/mm/radix: Update LPCR only if it is powernv
powerpc: Use privileged SPR number for MMCR2
powerpc: Fix definition of SIAR and SDAR registers
powerpc/pseries/eeh: Refactor the configure_bridge RTAS tokens
powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 22 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-book3s64.c | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-radix.c | 23 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 49 |
6 files changed, 68 insertions, 38 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index c1e82e968506..a0948f40bc7b 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -717,7 +717,7 @@ | |||
717 | #define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ | 717 | #define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ |
718 | #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ | 718 | #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ |
719 | #define SPRN_MMCR1 798 | 719 | #define SPRN_MMCR1 798 |
720 | #define SPRN_MMCR2 769 | 720 | #define SPRN_MMCR2 785 |
721 | #define SPRN_MMCRA 0x312 | 721 | #define SPRN_MMCRA 0x312 |
722 | #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ | 722 | #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ |
723 | #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL | 723 | #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL |
@@ -754,13 +754,13 @@ | |||
754 | #define SPRN_PMC6 792 | 754 | #define SPRN_PMC6 792 |
755 | #define SPRN_PMC7 793 | 755 | #define SPRN_PMC7 793 |
756 | #define SPRN_PMC8 794 | 756 | #define SPRN_PMC8 794 |
757 | #define SPRN_SIAR 780 | ||
758 | #define SPRN_SDAR 781 | ||
759 | #define SPRN_SIER 784 | 757 | #define SPRN_SIER 784 |
760 | #define SIER_SIPR 0x2000000 /* Sampled MSR_PR */ | 758 | #define SIER_SIPR 0x2000000 /* Sampled MSR_PR */ |
761 | #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */ | 759 | #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */ |
762 | #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */ | 760 | #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */ |
763 | #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */ | 761 | #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */ |
762 | #define SPRN_SIAR 796 | ||
763 | #define SPRN_SDAR 797 | ||
764 | #define SPRN_TACR 888 | 764 | #define SPRN_TACR 888 |
765 | #define SPRN_TCSCR 889 | 765 | #define SPRN_TCSCR 889 |
766 | #define SPRN_CSIGR 890 | 766 | #define SPRN_CSIGR 890 |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index da5192590c44..ccd2037c797f 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = { | |||
656 | W(0xffff0000), W(0x003e0000), /* POWER6 */ | 656 | W(0xffff0000), W(0x003e0000), /* POWER6 */ |
657 | W(0xffff0000), W(0x003f0000), /* POWER7 */ | 657 | W(0xffff0000), W(0x003f0000), /* POWER7 */ |
658 | W(0xffff0000), W(0x004b0000), /* POWER8E */ | 658 | W(0xffff0000), W(0x004b0000), /* POWER8E */ |
659 | W(0xffff0000), W(0x004c0000), /* POWER8NVL */ | ||
659 | W(0xffff0000), W(0x004d0000), /* POWER8 */ | 660 | W(0xffff0000), W(0x004d0000), /* POWER8 */ |
660 | W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ | 661 | W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ |
661 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ | 662 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 59268969a0bc..b2740c67e172 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = { | |||
159 | }, | 159 | }, |
160 | }; | 160 | }; |
161 | 161 | ||
162 | /* | ||
163 | * 'R' and 'C' update notes: | ||
164 | * - Under pHyp or KVM, the updatepp path will not set C, thus it *will* | ||
165 | * create writeable HPTEs without C set, because the hcall H_PROTECT | ||
166 | * that we use in that case will not update C | ||
167 | * - The above is however not a problem, because we also don't do that | ||
168 | * fancy "no flush" variant of eviction and we use H_REMOVE which will | ||
169 | * do the right thing and thus we don't have the race I described earlier | ||
170 | * | ||
171 | * - Under bare metal, we do have the race, so we need R and C set | ||
172 | * - We make sure R is always set and never lost | ||
173 | * - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping | ||
174 | */ | ||
162 | unsigned long htab_convert_pte_flags(unsigned long pteflags) | 175 | unsigned long htab_convert_pte_flags(unsigned long pteflags) |
163 | { | 176 | { |
164 | unsigned long rflags = 0; | 177 | unsigned long rflags = 0; |
@@ -186,9 +199,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags) | |||
186 | rflags |= 0x1; | 199 | rflags |= 0x1; |
187 | } | 200 | } |
188 | /* | 201 | /* |
189 | * Always add "C" bit for perf. Memory coherence is always enabled | 202 | * We can't allow hardware to update hpte bits. Hence always |
203 | * set 'R' bit and set 'C' if it is a write fault | ||
204 | * Memory coherence is always enabled | ||
190 | */ | 205 | */ |
191 | rflags |= HPTE_R_C | HPTE_R_M; | 206 | rflags |= HPTE_R_R | HPTE_R_M; |
207 | |||
208 | if (pteflags & _PAGE_DIRTY) | ||
209 | rflags |= HPTE_R_C; | ||
192 | /* | 210 | /* |
193 | * Add in WIG bits | 211 | * Add in WIG bits |
194 | */ | 212 | */ |
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c index eb4451144746..670318766545 100644 --- a/arch/powerpc/mm/pgtable-book3s64.c +++ b/arch/powerpc/mm/pgtable-book3s64.c | |||
@@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, | |||
33 | changed = !pmd_same(*(pmdp), entry); | 33 | changed = !pmd_same(*(pmdp), entry); |
34 | if (changed) { | 34 | if (changed) { |
35 | __ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry)); | 35 | __ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry)); |
36 | /* | 36 | flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); |
37 | * Since we are not supporting SW TLB systems, we don't | ||
38 | * have any thing similar to flush_tlb_page_nohash() | ||
39 | */ | ||
40 | } | 37 | } |
41 | return changed; | 38 | return changed; |
42 | } | 39 | } |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 18b2c11604fa..c939e6e57a9e 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
@@ -296,11 +296,6 @@ found: | |||
296 | void __init radix__early_init_mmu(void) | 296 | void __init radix__early_init_mmu(void) |
297 | { | 297 | { |
298 | unsigned long lpcr; | 298 | unsigned long lpcr; |
299 | /* | ||
300 | * setup LPCR UPRT based on mmu_features | ||
301 | */ | ||
302 | lpcr = mfspr(SPRN_LPCR); | ||
303 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); | ||
304 | 299 | ||
305 | #ifdef CONFIG_PPC_64K_PAGES | 300 | #ifdef CONFIG_PPC_64K_PAGES |
306 | /* PAGE_SIZE mappings */ | 301 | /* PAGE_SIZE mappings */ |
@@ -343,8 +338,11 @@ void __init radix__early_init_mmu(void) | |||
343 | __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT; | 338 | __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT; |
344 | 339 | ||
345 | radix_init_page_sizes(); | 340 | radix_init_page_sizes(); |
346 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | 341 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { |
342 | lpcr = mfspr(SPRN_LPCR); | ||
343 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); | ||
347 | radix_init_partition_table(); | 344 | radix_init_partition_table(); |
345 | } | ||
348 | 346 | ||
349 | radix_init_pgtable(); | 347 | radix_init_pgtable(); |
350 | } | 348 | } |
@@ -353,16 +351,15 @@ void radix__early_init_mmu_secondary(void) | |||
353 | { | 351 | { |
354 | unsigned long lpcr; | 352 | unsigned long lpcr; |
355 | /* | 353 | /* |
356 | * setup LPCR UPRT based on mmu_features | 354 | * update partition table control register and UPRT |
357 | */ | 355 | */ |
358 | lpcr = mfspr(SPRN_LPCR); | 356 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { |
359 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); | 357 | lpcr = mfspr(SPRN_LPCR); |
360 | /* | 358 | mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); |
361 | * update partition table control register, 64 K size. | 359 | |
362 | */ | ||
363 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
364 | mtspr(SPRN_PTCR, | 360 | mtspr(SPRN_PTCR, |
365 | __pa(partition_tb) | (PATB_SIZE_SHIFT - 12)); | 361 | __pa(partition_tb) | (PATB_SIZE_SHIFT - 12)); |
362 | } | ||
366 | } | 363 | } |
367 | 364 | ||
368 | void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base, | 365 | void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base, |
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index ac3ffd97e059..3998e0f9a03b 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2; | |||
53 | static int ibm_slot_error_detail; | 53 | static int ibm_slot_error_detail; |
54 | static int ibm_get_config_addr_info; | 54 | static int ibm_get_config_addr_info; |
55 | static int ibm_get_config_addr_info2; | 55 | static int ibm_get_config_addr_info2; |
56 | static int ibm_configure_bridge; | ||
57 | static int ibm_configure_pe; | 56 | static int ibm_configure_pe; |
58 | 57 | ||
59 | /* | 58 | /* |
@@ -81,7 +80,14 @@ static int pseries_eeh_init(void) | |||
81 | ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); | 80 | ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); |
82 | ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); | 81 | ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); |
83 | ibm_configure_pe = rtas_token("ibm,configure-pe"); | 82 | ibm_configure_pe = rtas_token("ibm,configure-pe"); |
84 | ibm_configure_bridge = rtas_token("ibm,configure-bridge"); | 83 | |
84 | /* | ||
85 | * ibm,configure-pe and ibm,configure-bridge have the same semantics, | ||
86 | * however ibm,configure-pe can be faster. If we can't find | ||
87 | * ibm,configure-pe then fall back to using ibm,configure-bridge. | ||
88 | */ | ||
89 | if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE) | ||
90 | ibm_configure_pe = rtas_token("ibm,configure-bridge"); | ||
85 | 91 | ||
86 | /* | 92 | /* |
87 | * Necessary sanity check. We needn't check "get-config-addr-info" | 93 | * Necessary sanity check. We needn't check "get-config-addr-info" |
@@ -93,8 +99,7 @@ static int pseries_eeh_init(void) | |||
93 | (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && | 99 | (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && |
94 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) || | 100 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) || |
95 | ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE || | 101 | ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE || |
96 | (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && | 102 | ibm_configure_pe == RTAS_UNKNOWN_SERVICE) { |
97 | ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) { | ||
98 | pr_info("EEH functionality not supported\n"); | 103 | pr_info("EEH functionality not supported\n"); |
99 | return -EINVAL; | 104 | return -EINVAL; |
100 | } | 105 | } |
@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) | |||
615 | { | 620 | { |
616 | int config_addr; | 621 | int config_addr; |
617 | int ret; | 622 | int ret; |
623 | /* Waiting 0.2s maximum before skipping configuration */ | ||
624 | int max_wait = 200; | ||
618 | 625 | ||
619 | /* Figure out the PE address */ | 626 | /* Figure out the PE address */ |
620 | config_addr = pe->config_addr; | 627 | config_addr = pe->config_addr; |
621 | if (pe->addr) | 628 | if (pe->addr) |
622 | config_addr = pe->addr; | 629 | config_addr = pe->addr; |
623 | 630 | ||
624 | /* Use new configure-pe function, if supported */ | 631 | while (max_wait > 0) { |
625 | if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { | ||
626 | ret = rtas_call(ibm_configure_pe, 3, 1, NULL, | 632 | ret = rtas_call(ibm_configure_pe, 3, 1, NULL, |
627 | config_addr, BUID_HI(pe->phb->buid), | 633 | config_addr, BUID_HI(pe->phb->buid), |
628 | BUID_LO(pe->phb->buid)); | 634 | BUID_LO(pe->phb->buid)); |
629 | } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { | ||
630 | ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, | ||
631 | config_addr, BUID_HI(pe->phb->buid), | ||
632 | BUID_LO(pe->phb->buid)); | ||
633 | } else { | ||
634 | return -EFAULT; | ||
635 | } | ||
636 | 635 | ||
637 | if (ret) | 636 | if (!ret) |
638 | pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", | 637 | return ret; |
639 | __func__, pe->phb->global_number, pe->addr, ret); | 638 | |
639 | /* | ||
640 | * If RTAS returns a delay value that's above 100ms, cut it | ||
641 | * down to 100ms in case firmware made a mistake. For more | ||
642 | * on how these delay values work see rtas_busy_delay_time | ||
643 | */ | ||
644 | if (ret > RTAS_EXTENDED_DELAY_MIN+2 && | ||
645 | ret <= RTAS_EXTENDED_DELAY_MAX) | ||
646 | ret = RTAS_EXTENDED_DELAY_MIN+2; | ||
647 | |||
648 | max_wait -= rtas_busy_delay_time(ret); | ||
649 | |||
650 | if (max_wait < 0) | ||
651 | break; | ||
652 | |||
653 | rtas_busy_delay(ret); | ||
654 | } | ||
640 | 655 | ||
656 | pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", | ||
657 | __func__, pe->phb->global_number, pe->addr, ret); | ||
641 | return ret; | 658 | return ret; |
642 | } | 659 | } |
643 | 660 | ||