Commit 5306d766 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 4340fa55 7cc85103
...@@ -717,7 +717,7 @@ ...@@ -717,7 +717,7 @@
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ #define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
#define SPRN_MMCR1 798 #define SPRN_MMCR1 798
#define SPRN_MMCR2 769 #define SPRN_MMCR2 785
#define SPRN_MMCRA 0x312 #define SPRN_MMCRA 0x312
#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
...@@ -754,13 +754,13 @@ ...@@ -754,13 +754,13 @@
#define SPRN_PMC6 792 #define SPRN_PMC6 792
#define SPRN_PMC7 793 #define SPRN_PMC7 793
#define SPRN_PMC8 794 #define SPRN_PMC8 794
#define SPRN_SIAR 780
#define SPRN_SDAR 781
#define SPRN_SIER 784 #define SPRN_SIER 784
#define SIER_SIPR 0x2000000 /* Sampled MSR_PR */ #define SIER_SIPR 0x2000000 /* Sampled MSR_PR */
#define SIER_SIHV 0x1000000 /* Sampled MSR_HV */ #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
#define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */ #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
#define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */ #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
#define SPRN_SIAR 796
#define SPRN_SDAR 797
#define SPRN_TACR 888 #define SPRN_TACR 888
#define SPRN_TCSCR 889 #define SPRN_TCSCR 889
#define SPRN_CSIGR 890 #define SPRN_CSIGR 890
......
...@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = { ...@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
W(0xffff0000), W(0x003e0000), /* POWER6 */ W(0xffff0000), W(0x003e0000), /* POWER6 */
W(0xffff0000), W(0x003f0000), /* POWER7 */ W(0xffff0000), W(0x003f0000), /* POWER7 */
W(0xffff0000), W(0x004b0000), /* POWER8E */ W(0xffff0000), W(0x004b0000), /* POWER8E */
W(0xffff0000), W(0x004c0000), /* POWER8NVL */
W(0xffff0000), W(0x004d0000), /* POWER8 */ W(0xffff0000), W(0x004d0000), /* POWER8 */
W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
......
...@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = { ...@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = {
}, },
}; };
/*
* 'R' and 'C' update notes:
* - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
* create writeable HPTEs without C set, because the hcall H_PROTECT
* that we use in that case will not update C
* - The above is however not a problem, because we also don't do that
* fancy "no flush" variant of eviction and we use H_REMOVE which will
* do the right thing and thus we don't have the race I described earlier
*
* - Under bare metal, we do have the race, so we need R and C set
* - We make sure R is always set and never lost
* - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
*/
unsigned long htab_convert_pte_flags(unsigned long pteflags) unsigned long htab_convert_pte_flags(unsigned long pteflags)
{ {
unsigned long rflags = 0; unsigned long rflags = 0;
...@@ -186,9 +199,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags) ...@@ -186,9 +199,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
rflags |= 0x1; rflags |= 0x1;
} }
/* /*
* Always add "C" bit for perf. Memory coherence is always enabled * We can't allow hardware to update hpte bits. Hence always
* set 'R' bit and set 'C' if it is a write fault
* Memory coherence is always enabled
*/ */
rflags |= HPTE_R_C | HPTE_R_M; rflags |= HPTE_R_R | HPTE_R_M;
if (pteflags & _PAGE_DIRTY)
rflags |= HPTE_R_C;
/* /*
* Add in WIG bits * Add in WIG bits
*/ */
......
...@@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, ...@@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
changed = !pmd_same(*(pmdp), entry); changed = !pmd_same(*(pmdp), entry);
if (changed) { if (changed) {
__ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry)); __ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
/* flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
* Since we are not supporting SW TLB systems, we don't
* have any thing similar to flush_tlb_page_nohash()
*/
} }
return changed; return changed;
} }
......
...@@ -296,11 +296,6 @@ static void __init radix_init_page_sizes(void) ...@@ -296,11 +296,6 @@ static void __init radix_init_page_sizes(void)
void __init radix__early_init_mmu(void) void __init radix__early_init_mmu(void)
{ {
unsigned long lpcr; unsigned long lpcr;
/*
* setup LPCR UPRT based on mmu_features
*/
lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
/* PAGE_SIZE mappings */ /* PAGE_SIZE mappings */
...@@ -343,8 +338,11 @@ void __init radix__early_init_mmu(void) ...@@ -343,8 +338,11 @@ void __init radix__early_init_mmu(void)
__pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT; __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
radix_init_page_sizes(); radix_init_page_sizes();
if (!firmware_has_feature(FW_FEATURE_LPAR)) if (!firmware_has_feature(FW_FEATURE_LPAR)) {
lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
radix_init_partition_table(); radix_init_partition_table();
}
radix_init_pgtable(); radix_init_pgtable();
} }
...@@ -353,16 +351,15 @@ void radix__early_init_mmu_secondary(void) ...@@ -353,16 +351,15 @@ void radix__early_init_mmu_secondary(void)
{ {
unsigned long lpcr; unsigned long lpcr;
/* /*
* setup LPCR UPRT based on mmu_features * update partition table control register and UPRT
*/ */
lpcr = mfspr(SPRN_LPCR); if (!firmware_has_feature(FW_FEATURE_LPAR)) {
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT); lpcr = mfspr(SPRN_LPCR);
/* mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
* update partition table control register, 64 K size.
*/
if (!firmware_has_feature(FW_FEATURE_LPAR))
mtspr(SPRN_PTCR, mtspr(SPRN_PTCR,
__pa(partition_tb) | (PATB_SIZE_SHIFT - 12)); __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
}
} }
void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base, void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
......
...@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2; ...@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2;
static int ibm_slot_error_detail; static int ibm_slot_error_detail;
static int ibm_get_config_addr_info; static int ibm_get_config_addr_info;
static int ibm_get_config_addr_info2; static int ibm_get_config_addr_info2;
static int ibm_configure_bridge;
static int ibm_configure_pe; static int ibm_configure_pe;
/* /*
...@@ -81,7 +80,14 @@ static int pseries_eeh_init(void) ...@@ -81,7 +80,14 @@ static int pseries_eeh_init(void)
ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
ibm_configure_pe = rtas_token("ibm,configure-pe"); ibm_configure_pe = rtas_token("ibm,configure-pe");
ibm_configure_bridge = rtas_token("ibm,configure-bridge");
/*
* ibm,configure-pe and ibm,configure-bridge have the same semantics,
* however ibm,configure-pe can be faster. If we can't find
* ibm,configure-pe then fall back to using ibm,configure-bridge.
*/
if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE)
ibm_configure_pe = rtas_token("ibm,configure-bridge");
/* /*
* Necessary sanity check. We needn't check "get-config-addr-info" * Necessary sanity check. We needn't check "get-config-addr-info"
...@@ -93,8 +99,7 @@ static int pseries_eeh_init(void) ...@@ -93,8 +99,7 @@ static int pseries_eeh_init(void)
(ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) ||
ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE || ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE ||
(ibm_configure_pe == RTAS_UNKNOWN_SERVICE && ibm_configure_pe == RTAS_UNKNOWN_SERVICE) {
ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) {
pr_info("EEH functionality not supported\n"); pr_info("EEH functionality not supported\n");
return -EINVAL; return -EINVAL;
} }
...@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) ...@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
{ {
int config_addr; int config_addr;
int ret; int ret;
/* Waiting 0.2s maximum before skipping configuration */
int max_wait = 200;
/* Figure out the PE address */ /* Figure out the PE address */
config_addr = pe->config_addr; config_addr = pe->config_addr;
if (pe->addr) if (pe->addr)
config_addr = pe->addr; config_addr = pe->addr;
/* Use new configure-pe function, if supported */ while (max_wait > 0) {
if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
ret = rtas_call(ibm_configure_pe, 3, 1, NULL, ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
config_addr, BUID_HI(pe->phb->buid), config_addr, BUID_HI(pe->phb->buid),
BUID_LO(pe->phb->buid)); BUID_LO(pe->phb->buid));
} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
config_addr, BUID_HI(pe->phb->buid),
BUID_LO(pe->phb->buid));
} else {
return -EFAULT;
}
if (ret) if (!ret)
pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", return ret;
__func__, pe->phb->global_number, pe->addr, ret);
/*
* If RTAS returns a delay value that's above 100ms, cut it
* down to 100ms in case firmware made a mistake. For more
* on how these delay values work see rtas_busy_delay_time
*/
if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
ret <= RTAS_EXTENDED_DELAY_MAX)
ret = RTAS_EXTENDED_DELAY_MIN+2;
max_wait -= rtas_busy_delay_time(ret);
if (max_wait < 0)
break;
rtas_busy_delay(ret);
}
pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
__func__, pe->phb->global_number, pe->addr, ret);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment