diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 13:20:54 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 13:20:54 -0800 |
commit | a4eff16c54886c11972d6396ce8447b99e097343 (patch) | |
tree | eae80ceb9c2827946f31e4bddc6f9c3a9da7b17a /arch | |
parent | 0cbeafb245ca568bc0765645aa64f0451b716657 (diff) | |
parent | b0e551313ebde17764f3a5ed273df524d1e7e690 (diff) | |
download | lwn-a4eff16c54886c11972d6396ce8447b99e097343.tar.gz lwn-a4eff16c54886c11972d6396ce8447b99e097343.zip |
Merge branch 'parisc-4.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parsic updates from Helge Deller:
"This patchset includes two major fixes which are both scheduled for
stable:
First, __ARCH_SI_PREAMBLE_SIZE was defined with a wrong value.
Second, huge page pte and TLB changes needed protection with a
spinlock. Other than that there are just some trivial optimizations
and cleanups"
* 'parisc-4.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Protect huge page pte changes with spinlocks
parisc: Imporove debug info about space registers and TLB configuration
parisc: Drop parisc-specific NSIGTRAP define
parisc: Fix __ARCH_SI_PREAMBLE_SIZE
parisc: Reduce overhead of parisc_requires_coherency()
parisc: Initialize PCI bridge cache line and default latency
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/include/asm/hugetlb.h | 20 | ||||
-rw-r--r-- | arch/parisc/include/asm/pci.h | 1 | ||||
-rw-r--r-- | arch/parisc/include/asm/pdc.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/processor.h | 17 | ||||
-rw-r--r-- | arch/parisc/include/uapi/asm/siginfo.h | 7 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 26 | ||||
-rw-r--r-- | arch/parisc/kernel/pci.c | 26 | ||||
-rw-r--r-- | arch/parisc/kernel/processor.c | 10 | ||||
-rw-r--r-- | arch/parisc/mm/hugetlbpage.c | 60 |
9 files changed, 123 insertions, 46 deletions
diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h index 7d56a9ccb752..a65d888716c4 100644 --- a/arch/parisc/include/asm/hugetlb.h +++ b/arch/parisc/include/asm/hugetlb.h @@ -54,24 +54,12 @@ static inline pte_t huge_pte_wrprotect(pte_t pte) return pte_wrprotect(pte); } -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - pte_t old_pte = *ptep; - set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); -} +void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep); -static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, +int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, - pte_t pte, int dirty) -{ - int changed = !pte_same(*ptep, pte); - if (changed) { - set_huge_pte_at(vma->vm_mm, addr, ptep, pte); - flush_tlb_page(vma, addr); - } - return changed; -} + pte_t pte, int dirty); static inline pte_t huge_ptep_get(pte_t *ptep) { diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index 71889ea72740..89c53bfff055 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h @@ -167,6 +167,7 @@ static inline void pcibios_register_hba(struct pci_hba_data *x) { } #endif +extern void pcibios_init_bridge(struct pci_dev *); /* * pcibios_assign_all_busses() is used in drivers/pci/pci.c:pci_do_scan_bus() diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 7eb616e4bf8a..451906d78136 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -63,7 +63,7 @@ struct pdc_tlb_cf { /* for PDC_CACHE (I/D-TLB's) */ tc_page : 1, /* 0 = 2K page-size-machine, 1 = 4k page size */ tc_cst : 3, /* 0 = incoherent operations, else coherent operations */ tc_aid : 5, /* ITLB: width of access ids of processor (encoded!) */ - tc_pad1 : 8; /* ITLB: width of space-registers (encoded) */ + tc_sr : 8; /* ITLB: width of space-registers (encoded) */ }; struct pdc_cache_info { /* main-PDC_CACHE-structure (caches & TLB's) */ diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 7e759ecb1343..2e674e13e005 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -311,18 +311,17 @@ extern unsigned long get_wchan(struct task_struct *p); #define cpu_relax() barrier() #define cpu_relax_lowlatency() cpu_relax() -/* Used as a macro to identify the combined VIPT/PIPT cached - * CPUs which require a guarantee of coherency (no inequivalent - * aliases with different data, whether clean or not) to operate */ -static inline int parisc_requires_coherency(void) -{ +/* + * parisc_requires_coherency() is used to identify the combined VIPT/PIPT + * cached CPUs which require a guarantee of coherency (no inequivalent aliases + * with different data, whether clean or not) to operate + */ #ifdef CONFIG_PA8X00 - return (boot_cpu_data.cpu_type == mako) || - (boot_cpu_data.cpu_type == mako2); +extern int _parisc_requires_coherency; +#define parisc_requires_coherency() _parisc_requires_coherency #else - return 0; +#define parisc_requires_coherency() (0) #endif -} #endif /* __ASSEMBLY__ */ diff --git a/arch/parisc/include/uapi/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h index d7034728f377..8fd10f85c50e 100644 --- a/arch/parisc/include/uapi/asm/siginfo.h +++ b/arch/parisc/include/uapi/asm/siginfo.h @@ -1,9 +1,10 @@ #ifndef _PARISC_SIGINFO_H #define _PARISC_SIGINFO_H -#include <asm-generic/siginfo.h> +#if defined(__LP64__) +#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#endif -#undef NSIGTRAP -#define NSIGTRAP 4 +#include <asm-generic/siginfo.h> #endif diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index cda6dbbe9842..91c2a39cd5aa 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -172,6 +172,24 @@ parisc_cache_init(void) cache_info.ic_count, cache_info.ic_loop); + printk("IT base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx off_base 0x%lx off_stride 0x%lx off_count 0x%lx\n", + cache_info.it_sp_base, + cache_info.it_sp_stride, + cache_info.it_sp_count, + cache_info.it_loop, + cache_info.it_off_base, + cache_info.it_off_stride, + cache_info.it_off_count); + + printk("DT base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx off_base 0x%lx off_stride 0x%lx off_count 0x%lx\n", + cache_info.dt_sp_base, + cache_info.dt_sp_stride, + cache_info.dt_sp_count, + cache_info.dt_loop, + cache_info.dt_off_base, + cache_info.dt_off_stride, + cache_info.dt_off_count); + printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n", *(unsigned long *) (&cache_info.ic_conf), cache_info.ic_conf.cc_alias, @@ -184,19 +202,19 @@ parisc_cache_init(void) cache_info.ic_conf.cc_cst, cache_info.ic_conf.cc_hv); - printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n", + printk("D-TLB conf: sh %d page %d cst %d aid %d sr %d\n", cache_info.dt_conf.tc_sh, cache_info.dt_conf.tc_page, cache_info.dt_conf.tc_cst, cache_info.dt_conf.tc_aid, - cache_info.dt_conf.tc_pad1); + cache_info.dt_conf.tc_sr); - printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n", + printk("I-TLB conf: sh %d page %d cst %d aid %d sr %d\n", cache_info.it_conf.tc_sh, cache_info.it_conf.tc_page, cache_info.it_conf.tc_cst, cache_info.it_conf.tc_aid, - cache_info.it_conf.tc_pad1); + cache_info.it_conf.tc_sr); #endif split_tlb = 0; diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index c99f3dde455c..0903c6abd7a4 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -170,6 +170,32 @@ void pcibios_set_master(struct pci_dev *dev) (0x80 << 8) | pci_cache_line_size); } +/* + * pcibios_init_bridge() initializes cache line and default latency + * for pci controllers and pci-pci bridges + */ +void __init pcibios_init_bridge(struct pci_dev *dev) +{ + unsigned short bridge_ctl, bridge_ctl_new; + + /* We deal only with pci controllers and pci-pci bridges. */ + if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + return; + + /* PCI-PCI bridge - set the cache line and default latency + * (32) for primary and secondary buses. + */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); + + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); + + bridge_ctl_new = bridge_ctl | PCI_BRIDGE_CTL_PARITY | + PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_MASTER_ABORT; + dev_info(&dev->dev, "Changing bridge control from 0x%08x to 0x%08x\n", + bridge_ctl, bridge_ctl_new); + + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl_new); +} /* * pcibios align resources() is called every time generic PCI code diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index b68d977ce30f..e81ccf1716e9 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -44,6 +44,10 @@ struct system_cpuinfo_parisc boot_cpu_data __read_mostly; EXPORT_SYMBOL(boot_cpu_data); +#ifdef CONFIG_PA8X00 +int _parisc_requires_coherency __read_mostly; +EXPORT_SYMBOL(_parisc_requires_coherency); +#endif DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data); @@ -277,8 +281,12 @@ void __init collect_boot_cpu_data(void) boot_cpu_data.cpu_type = parisc_get_cpu_type(boot_cpu_data.hversion); boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; -} +#ifdef CONFIG_PA8X00 + _parisc_requires_coherency = (boot_cpu_data.cpu_type == mako) || + (boot_cpu_data.cpu_type == mako2); +#endif +} /** diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c index f6fdc77a72bd..54ba39262b82 100644 --- a/arch/parisc/mm/hugetlbpage.c +++ b/arch/parisc/mm/hugetlbpage.c @@ -105,15 +105,13 @@ static inline void purge_tlb_entries_huge(struct mm_struct *mm, unsigned long ad addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT; for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) { - mtsp(mm->context, 1); - pdtlb(addr); - if (unlikely(split_tlb)) - pitlb(addr); + purge_tlb_entries(mm, addr); addr += (1UL << REAL_HPAGE_SHIFT); } } -void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, +/* __set_huge_pte_at() must be called holding the pa_tlb_lock. */ +static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { unsigned long addr_start; @@ -123,14 +121,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, addr_start = addr; for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { - /* Directly write pte entry. We could call set_pte_at(mm, addr, ptep, entry) - * instead, but then we get double locking on pa_tlb_lock. */ - *ptep = entry; + set_pte(ptep, entry); ptep++; - /* Drop the PAGE_SIZE/non-huge tlb entry */ - purge_tlb_entries(mm, addr); - addr += PAGE_SIZE; pte_val(entry) += PAGE_SIZE; } @@ -138,18 +131,61 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, purge_tlb_entries_huge(mm, addr_start); } +void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t entry) +{ + unsigned long flags; + + purge_tlb_start(flags); + __set_huge_pte_at(mm, addr, ptep, entry); + purge_tlb_end(flags); +} + pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { + unsigned long flags; pte_t entry; + purge_tlb_start(flags); entry = *ptep; - set_huge_pte_at(mm, addr, ptep, __pte(0)); + __set_huge_pte_at(mm, addr, ptep, __pte(0)); + purge_tlb_end(flags); return entry; } + +void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long flags; + pte_t old_pte; + + purge_tlb_start(flags); + old_pte = *ptep; + __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); + purge_tlb_end(flags); +} + +int huge_ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep, + pte_t pte, int dirty) +{ + unsigned long flags; + int changed; + + purge_tlb_start(flags); + changed = !pte_same(*ptep, pte); + if (changed) { + __set_huge_pte_at(vma->vm_mm, addr, ptep, pte); + } + purge_tlb_end(flags); + return changed; +} + + int pmd_huge(pmd_t pmd) { return 0; |