diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/Kconfig | 1 | ||||
-rw-r--r-- | arch/parisc/include/asm/cacheflush.h | 31 | ||||
-rw-r--r-- | arch/parisc/include/asm/irq.h | 13 | ||||
-rw-r--r-- | arch/parisc/include/asm/pgtable.h | 14 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 109 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 217 | ||||
-rw-r--r-- | arch/parisc/kernel/irq.c | 64 | ||||
-rw-r--r-- | arch/parisc/kernel/pacache.S | 245 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mpic.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_dn.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 15 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 85 | ||||
-rw-r--r-- | arch/sparc/include/asm/irq_32.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/asm/irq_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/unistd.h | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/of_device_common.c | 27 | ||||
-rw-r--r-- | arch/sparc/kernel/systbls_32.S | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/systbls_64.S | 4 |
19 files changed, 444 insertions, 406 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index fed2946f733..fafdf30bea9 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -15,6 +15,7 @@ config PARISC select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select IRQ_PER_CPU + select GENERIC_HARDIRQS_NO_DEPRECATED help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index f388a85bba1..d18328b3f93 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_page_asm(void *); void flush_kernel_icache_page(void *); -void flush_user_dcache_page(unsigned long); -void flush_user_icache_page(unsigned long); void flush_user_dcache_range(unsigned long, unsigned long); void flush_user_icache_range(unsigned long, unsigned long); @@ -37,6 +35,13 @@ void flush_cache_all_local(void); void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page_addr(void *addr); +static inline void flush_kernel_dcache_page(struct page *page) +{ + flush_kernel_dcache_page_addr(page_address(page)); +} + #define flush_kernel_dcache_range(start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); /* vmap range flushes and invalidates. Architecturally, we don't need @@ -50,6 +55,16 @@ static inline void flush_kernel_vmap_range(void *vaddr, int size) } static inline void invalidate_kernel_vmap_range(void *vaddr, int size) { + unsigned long start = (unsigned long)vaddr; + void *cursor = vaddr; + + for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) { + struct page *page = vmalloc_to_page(cursor); + + if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) + flush_kernel_dcache_page(page); + } + flush_kernel_dcache_range_asm(start, start + size); } #define flush_cache_vmap(start, end) flush_cache_all() @@ -90,19 +105,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); +/* defined in pacache.S exported in cache.c used by flush_anon_page */ +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); + #define ARCH_HAS_FLUSH_ANON_PAGE static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) { if (PageAnon(page)) - flush_user_dcache_page(vmaddr); -} - -#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE -void flush_kernel_dcache_page_addr(void *addr); -static inline void flush_kernel_dcache_page(struct page *page) -{ - flush_kernel_dcache_page_addr(page_address(page)); + flush_dcache_page_asm(page_to_phys(page), vmaddr); } #ifdef CONFIG_DEBUG_RODATA diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h index c67dccf2e31..1073599a7be 100644 --- a/arch/parisc/include/asm/irq.h +++ b/arch/parisc/include/asm/irq.h @@ -32,15 +32,10 @@ static __inline__ int irq_canonicalize(int irq) } struct irq_chip; +struct irq_data; -/* - * Some useful "we don't have to do anything here" handlers. Should - * probably be provided by the generic code. - */ -void no_ack_irq(unsigned int irq); -void no_end_irq(unsigned int irq); -void cpu_ack_irq(unsigned int irq); -void cpu_eoi_irq(unsigned int irq); +void cpu_ack_irq(struct irq_data *d); +void cpu_eoi_irq(struct irq_data *d); extern int txn_alloc_irq(unsigned int nbits); extern int txn_claim_irq(int); @@ -49,7 +44,7 @@ extern unsigned long txn_alloc_addr(unsigned int); extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *); -extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest); +extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 6f1f65d3c0e..5d7b8ce9fdf 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -138,8 +138,7 @@ struct vm_area_struct; #define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */ #define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */ #define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */ -#define _PAGE_FLUSH_BIT 21 /* (0x400) Software: translation valid */ - /* for cache flushing only */ +/* bit 21 was formerly the FLUSH bit but is now unused */ #define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */ /* N.B. The bits are defined in terms of a 32 bit word above, so the */ @@ -173,7 +172,6 @@ struct vm_area_struct; #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT)) #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT)) #define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT)) -#define _PAGE_FLUSH (1 << xlate_pabit(_PAGE_FLUSH_BIT)) #define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT)) #define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT)) @@ -213,7 +211,6 @@ struct vm_area_struct; #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) -#define PAGE_FLUSH __pgprot(_PAGE_FLUSH) /* @@ -261,7 +258,7 @@ extern unsigned long *empty_zero_page; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) -#define pte_none(x) ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH)) +#define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) @@ -444,13 +441,10 @@ struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; - pte_t pte; spin_lock(&pa_dbit_lock); - pte = old_pte = *ptep; - pte_val(pte) &= ~_PAGE_PRESENT; - pte_val(pte) |= _PAGE_FLUSH; - set_pte_at(mm,addr,ptep,pte); + old_pte = *ptep; + pte_clear(mm,addr,ptep); spin_unlock(&pa_dbit_lock); return old_pte; diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index d054f3da3ff..3f11331c277 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -27,12 +27,17 @@ #include <asm/pgalloc.h> #include <asm/processor.h> #include <asm/sections.h> +#include <asm/shmparam.h> int split_tlb __read_mostly; int dcache_stride __read_mostly; int icache_stride __read_mostly; EXPORT_SYMBOL(dcache_stride); +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); +EXPORT_SYMBOL(flush_dcache_page_asm); +void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); + /* On some machines (e.g. ones with the Merced bus), there can be * only a single PxTLB broadcast at a time; this must be guaranteed @@ -259,81 +264,13 @@ void disable_sr_hashing(void) panic("SpaceID hashing is still on!\n"); } -/* Simple function to work out if we have an existing address translation - * for a user space vma. */ -static inline int translation_exists(struct vm_area_struct *vma, - unsigned long addr, unsigned long pfn) -{ - pgd_t *pgd = pgd_offset(vma->vm_mm, addr); - pmd_t *pmd; - pte_t pte; - - if(pgd_none(*pgd)) - return 0; - - pmd = pmd_offset(pgd, addr); - if(pmd_none(*pmd) || pmd_bad(*pmd)) - return 0; - - /* We cannot take the pte lock here: flush_cache_page is usually - * called with pte lock already held. Whereas flush_dcache_page - * takes flush_dcache_mmap_lock, which is lower in the hierarchy: - * the vma itself is secure, but the pte might come or go racily. - */ - pte = *pte_offset_map(pmd, addr); - /* But pte_unmap() does nothing on this architecture */ - - /* Filter out coincidental file entries and swap entries */ - if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT))) - return 0; - - return pte_pfn(pte) == pfn; -} - -/* Private function to flush a page from the cache of a non-current - * process. cr25 contains the Page Directory of the current user - * process; we're going to hijack both it and the user space %sr3 to - * temporarily make the non-current process current. We have to do - * this because cache flushing may cause a non-access tlb miss which - * the handlers have to fill in from the pgd of the non-current - * process. */ static inline void -flush_user_cache_page_non_current(struct vm_area_struct *vma, - unsigned long vmaddr) +__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, + unsigned long physaddr) { - /* save the current process space and pgd */ - unsigned long space = mfsp(3), pgd = mfctl(25); - - /* we don't mind taking interrupts since they may not - * do anything with user space, but we can't - * be preempted here */ - preempt_disable(); - - /* make us current */ - mtctl(__pa(vma->vm_mm->pgd), 25); - mtsp(vma->vm_mm->context, 3); - - flush_user_dcache_page(vmaddr); - if(vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - - /* put the old current process back */ - mtsp(space, 3); - mtctl(pgd, 25); - preempt_enable(); -} - - -static inline void -__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - if (likely(vma->vm_mm->context == mfsp(3))) { - flush_user_dcache_page(vmaddr); - if (vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - } else { - flush_user_cache_page_non_current(vma, vmaddr); - } + flush_dcache_page_asm(physaddr, vmaddr); + if (vma->vm_flags & VM_EXEC) + flush_icache_page_asm(physaddr, vmaddr); } void flush_dcache_page(struct page *page) @@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page) struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; - unsigned long addr; + unsigned long addr, old_addr = 0; pgoff_t pgoff; - unsigned long pfn = page_to_pfn(page); - if (mapping && !mapping_mapped(mapping)) { set_bit(PG_dcache_dirty, &page->flags); @@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page) offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; - /* Flush instructions produce non access tlb misses. - * On PA, we nullify these instructions rather than - * taking a page fault if the pte doesn't exist. - * This is just for speed. If the page translation - * isn't there, there's no point exciting the - * nadtlb handler into a nullification frenzy. - * - * Make sure we really have this page: the private - * mappings may cover this area but have COW'd this - * particular page. - */ - if (translation_exists(mpnt, addr, pfn)) { - __flush_cache_page(mpnt, addr); - break; + if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { + __flush_cache_page(mpnt, addr, page_to_phys(page)); + if (old_addr) + printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); + old_addr = addr; } } flush_dcache_mmap_unlock(mapping); @@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long { BUG_ON(!vma->vm_mm->context); - if (likely(translation_exists(vma, vmaddr, pfn))) - __flush_cache_page(vma, vmaddr); + __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6337adef30f..e5477092a5d 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -225,22 +225,13 @@ #ifndef CONFIG_64BIT /* * naitlb miss interruption handler (parisc 1.1 - 32 bit) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_11 code mfctl %isr,spc - b itlb_miss_11 + b naitlb_miss_11 mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -248,26 +239,17 @@ /* * naitlb miss interruption handler (parisc 2.0) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_20 code mfctl %isr,spc #ifdef CONFIG_64BIT - b itlb_miss_20w + b naitlb_miss_20w #else - b itlb_miss_20 + b naitlb_miss_20 #endif mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -581,7 +563,24 @@ copy \va,\tmp1 depi 0,31,23,\tmp1 cmpb,COND(<>),n \tmp,\tmp1,\fault - ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot + mfctl %cr19,\tmp /* iir */ + /* get the opcode (first six bits) into \tmp */ + extrw,u \tmp,5,6,\tmp + /* + * Only setting the T bit prevents data cache movein + * Setting access rights to zero prevents instruction cache movein + * + * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go + * to type field and _PAGE_READ goes to top bit of PL1 + */ + ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot + /* + * so if the opcode is one (i.e. this is a memory management + * instruction) nullify the next load so \prot is only T. + * Otherwise this is a normal data operation + */ + cmpiclr,= 0x01,\tmp,%r0 + ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot depd,z \prot,8,7,\prot /* * OK, it is in the temp alias region, check whether "from" or "to". @@ -631,11 +630,7 @@ ENTRY(fault_vector_20) def 13 def 14 dtlb_20 15 -#if 0 naitlb_20 16 -#else - def 16 -#endif nadtlb_20 17 def 18 def 19 @@ -678,11 +673,7 @@ ENTRY(fault_vector_11) def 13 def 14 dtlb_11 15 -#if 0 naitlb_11 16 -#else - def 16 -#endif nadtlb_11 17 def 18 def 19 @@ -1203,7 +1194,7 @@ nadtlb_miss_20w: get_pgd spc,ptp space_check spc,t0,nadtlb_fault - L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w + L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w update_ptep ptp,pte,t0,t1 @@ -1214,16 +1205,8 @@ nadtlb_miss_20w: rfir nop -nadtlb_check_flush_20w: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - depdi,z 7,7,3,prot - depdi 1,10,1,prot - - /* Drop prot bits from pte and convert to page addr for idtlbt */ - convert_for_tlb_insert20 pte +nadtlb_check_alias_20w: + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate idtlbt pte,prot @@ -1255,25 +1238,7 @@ dtlb_miss_11: nop dtlb_check_alias_11: - - /* Check to see if fault is in the temporary alias region */ - - cmpib,<>,n 0,spc,dtlb_fault /* forward */ - ldil L%(TMPALIAS_MAP_START),t0 - copy va,t1 - depwi 0,31,23,t1 - cmpb,<>,n t0,t1,dtlb_fault /* forward */ - ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot - depw,z prot,8,7,prot - - /* - * OK, it is in the temp alias region, check whether "from" or "to". - * Check "subtle" note in pacache.S re: r23/r26. - */ - - extrw,u,= va,9,1,r0 - or,tr %r23,%r0,pte /* If "from" use "from" page */ - or %r26,%r0,pte /* else "to", use "to" page */ + do_alias spc,t0,t1,va,pte,prot,dtlb_fault idtlba pte,(va) idtlbp prot,(va) @@ -1286,7 +1251,7 @@ nadtlb_miss_11: space_check spc,t0,nadtlb_fault - L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 + L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 update_ptep ptp,pte,t0,t1 @@ -1304,26 +1269,11 @@ nadtlb_miss_11: rfir nop -nadtlb_check_flush_11: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - zdepi 7,7,3,prot - depi 1,10,1,prot +nadtlb_check_alias_11: + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate - /* Get rid of prot bits and convert to page addr for idtlba */ - - depi 0,31,ASM_PFN_PTE_SHIFT,pte - SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte - - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ - mtsp spc,%sr1 - - idtlba pte,(%sr1,va) - idtlbp prot,(%sr1,va) - - mtsp t0, %sr1 /* Restore sr1 */ + idtlba pte,(va) + idtlbp prot,(va) rfir nop @@ -1359,7 +1309,7 @@ nadtlb_miss_20: space_check spc,t0,nadtlb_fault - L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 + L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 update_ptep ptp,pte,t0,t1 @@ -1372,21 +1322,14 @@ nadtlb_miss_20: rfir nop -nadtlb_check_flush_20: - bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate - - /* Insert a "flush only" translation */ - - depdi,z 7,7,3,prot - depdi 1,10,1,prot - - /* Drop prot bits from pte and convert to page addr for idtlbt */ - convert_for_tlb_insert20 pte +nadtlb_check_alias_20: + do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate idtlbt pte,prot rfir nop + #endif nadtlb_emulate: @@ -1484,6 +1427,36 @@ itlb_miss_20w: rfir nop +naitlb_miss_20w: + + /* + * I miss is a little different, since we allow users to fault + * on the gateway page which is in the kernel address space. + */ + + space_adjust spc,va,t0 + get_pgd spc,ptp + space_check spc,t0,naitlb_fault + + L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb spc,pte,prot + + iitlbt pte,prot + + rfir + nop + +naitlb_check_alias_20w: + do_alias spc,t0,t1,va,pte,prot,naitlb_fault + + iitlbt pte,prot + + rfir + nop + #else itlb_miss_11: @@ -1508,6 +1481,38 @@ itlb_miss_11: rfir nop +naitlb_miss_11: + get_pgd spc,ptp + + space_check spc,t0,naitlb_fault + + L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb_11 spc,pte,prot + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + iitlba pte,(%sr1,va) + iitlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +naitlb_check_alias_11: + do_alias spc,t0,t1,va,pte,prot,itlb_fault + + iitlba pte,(%sr0, va) + iitlbp prot,(%sr0, va) + + rfir + nop + + itlb_miss_20: get_pgd spc,ptp @@ -1526,6 +1531,32 @@ itlb_miss_20: rfir nop +naitlb_miss_20: + get_pgd spc,ptp + + space_check spc,t0,naitlb_fault + + L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 + + update_ptep ptp,pte,t0,t1 + + make_insert_tlb spc,pte,prot + + f_extend pte,t0 + + iitlbt pte,prot + + rfir + nop + +naitlb_check_alias_20: + do_alias spc,t0,t1,va,pte,prot,naitlb_fault + + iitlbt pte,prot + + rfir + nop + #endif #ifdef CONFIG_64BIT @@ -1662,6 +1693,10 @@ nadtlb_fault: b intr_save ldi 17,%r8 +naitlb_fault: + b intr_save + ldi 16,%r8 + dtlb_fault: b intr_save ldi 15,%r8 diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index d7d94b845dc..cb450e1e79b 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -52,9 +52,9 @@ static volatile unsigned long cpu_eiem = 0; */ static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL; -static void cpu_mask_irq(unsigned int irq) +static void cpu_mask_irq(struct irq_data *d) { - unsigned long eirr_bit = EIEM_MASK(irq); + unsigned long eirr_bit = EIEM_MASK(d->irq); cpu_eiem &= ~eirr_bit; /* Do nothing on the other CPUs. If they get this interrupt, @@ -63,7 +63,7 @@ static void cpu_mask_irq(unsigned int irq) * then gets disabled */ } -static void cpu_unmask_irq(unsigned int irq) +static void __cpu_unmask_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); @@ -75,9 +75,14 @@ static void cpu_unmask_irq(unsigned int irq) smp_send_all_nop(); } -void cpu_ack_irq(unsigned int irq) +static void cpu_unmask_irq(struct irq_data *d) +{ + __cpu_unmask_irq(d->irq); +} + +void cpu_ack_irq(struct irq_data *d) { - unsigned long mask = EIEM_MASK(irq); + unsigned long mask = EIEM_MASK(d->irq); int cpu = smp_processor_id(); /* Clear in EIEM so we can no longer process */ @@ -90,9 +95,9 @@ void cpu_ack_irq(unsigned int irq) mtctl(mask, 23); } -void cpu_eoi_irq(unsigned int irq) +void cpu_eoi_irq(struct irq_data *d) { - unsigned long mask = EIEM_MASK(irq); + unsigned long mask = EIEM_MASK(d->irq); int cpu = smp_processor_id(); /* set it in the eiems---it's no longer in process */ @@ -103,15 +108,16 @@ void cpu_eoi_irq(unsigned int irq) } #ifdef CONFIG_SMP -int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) +int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest) { int cpu_dest; /* timer and ipi have to always be received on all CPUs */ - if (CHECK_IRQ_PER_CPU(irq)) { + if (CHECK_IRQ_PER_CPU(irq_to_desc(d->irq)->status)) { /* Bad linux design decision. The mask has already - * been set; we must reset it */ - cpumask_setall(irq_desc[irq].affinity); + * been set; we must reset it. Will fix - tglx + */ + cpumask_setall(d->affinity); return -EINVAL; } @@ -121,33 +127,34 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) return cpu_dest; } -static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) +static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest, + bool force) { int cpu_dest; - cpu_dest = cpu_check_affinity(irq, dest); + cpu_dest = cpu_check_affinity(d, dest); if (cpu_dest < 0) return -1; - cpumask_copy(irq_desc[irq].affinity, dest); + cpumask_copy(d->affinity, dest); return 0; } #endif static struct irq_chip cpu_interrupt_type = { - .name = "CPU", - .mask = cpu_mask_irq, - .unmask = cpu_unmask_irq, - .ack = cpu_ack_irq, - .eoi = cpu_eoi_irq, + .name = "CPU", + .irq_mask = cpu_mask_irq, + .irq_unmask = cpu_unmask_irq, + .irq_ack = cpu_ack_irq, + .irq_eoi = cpu_eoi_irq, #ifdef CONFIG_SMP - .set_affinity = cpu_set_affinity_irq, + .irq_set_affinity = cpu_set_affinity_irq, #endif /* XXX: Needs to be written. We managed without it so far, but * we really ought to write it. */ - .retrigger = NULL, + .irq_retrigger = NULL, }; int show_interrupts(struct seq_file *p, void *v) @@ -181,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #endif - seq_printf(p, " %14s", irq_desc[i].chip->name); + seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name); #ifndef PARISC_IRQ_CR16_COUNTS seq_printf(p, " %s", action->name); @@ -233,14 +240,14 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data) { if (irq_desc[irq].action) return -EBUSY; - if (irq_desc[irq].chip != &cpu_interrupt_type) + if (get_irq_chip(irq) != &cpu_interrupt_type) return -EBUSY; /* for iosapic interrupts */ if (type) { set_irq_chip_and_handler(irq, type, handle_percpu_irq); set_irq_chip_data(irq, data); - cpu_unmask_irq(irq); + __cpu_unmask_irq(irq); } return 0; } @@ -289,7 +296,8 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); + struct irq_data *d = irq_get_irq_data(irq); + cpumask_copy(d->affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -333,6 +341,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) unsigned long eirr_val; int irq, cpu = smp_processor_id(); #ifdef CONFIG_SMP + struct irq_desc *desc; cpumask_t dest; #endif @@ -346,8 +355,9 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - cpumask_copy(&dest, irq_desc[irq].affinity); - if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && + desc = irq_to_desc(irq); + cpumask_copy(&dest, desc->irq_data.affinity); + if (CHECK_IRQ_PER_CPU(desc->status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 09b77b2553c..a85823668cb 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -608,93 +608,131 @@ ENTRY(__clear_user_page_asm) .procend ENDPROC(__clear_user_page_asm) -ENTRY(flush_kernel_dcache_page_asm) +ENTRY(flush_dcache_page_asm) .proc .callinfo NO_CALLS .entry + ldil L%(TMPALIAS_MAP_START), %r28 +#ifdef CONFIG_64BIT +#if (TMPALIAS_MAP_START >= 0x80000000) + depdi 0, 31,32, %r28 /* clear any sign extension */ + /* FIXME: page size dependend */ +#endif + extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ + depdi 0, 63,12, %r28 /* Clear any offset bits */ +#else + extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ + depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ + depwi 0, 31,12, %r28 /* Clear any offset bits */ +#endif + + /* Purge any old translation */ + + pdtlb 0(%r28) + ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 + ldw R%dcache_stride(%r1), %r1 #ifdef CONFIG_64BIT depdi,z 1, 63-PAGE_SHIFT,1, %r25 #else depwi,z 1, 31-PAGE_SHIFT,1, %r25 #endif - add %r26, %r25, %r25 - sub %r25, %r23, %r25 - - -1: fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - fdc,m %r23(%r26) - cmpb,COND(<<) %r26, %r25,1b - fdc,m %r23(%r26) + add %r28, %r25, %r25 + sub %r25, %r1, %r25 + + +1: fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + fdc,m %r1(%r28) + cmpb,COND(<<) %r28, %r25,1b + fdc,m %r1(%r28) sync bv %r0(%r2) - nop + pdtlb (%r25) .exit .procend -ENDPROC(flush_kernel_dcache_page_asm) - -ENTRY(flush_user_dcache_page) +ENDPROC(flush_dcache_page_asm) + +ENTRY(flush_icache_page_asm) .proc .callinfo NO_CALLS .entry - ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 - + ldil L%(TMPALIAS_MAP_START), %r28 #ifdef CONFIG_64BIT - depdi,z 1,63-PAGE_SHIFT,1, %r25 +#if (TMPALIAS_MAP_START >= 0x80000000) + depdi 0, 31,32, %r28 /* clear any sign extension */ + /* FIXME: page size dependend */ +#endif + extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ + depdi 0, 63,12, %r28 /* Clear any offset bits */ #else - depwi,z 1,31-PAGE_SHIFT,1, %r25 + extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ + depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ + depwi 0, 31,12, %r28 /* Clear any offset bits */ #endif - add %r26, %r25, %r25 - sub %r25, %r23, %r25 + /* Purge any old translation */ -1: fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - fdc,m %r23(%sr3, %r26) - cmpb,COND(<<) %r26, %r25,1b - fdc,m %r23(%sr3, %r26) + pitlb (%sr0,%r28) + + ldil L%icache_stride, %r1 + ldw R%icache_stride(%r1), %r1 + +#ifdef CONFIG_64BIT + depdi,z 1, 63-PAGE_SHIFT,1, %r25 +#else + depwi,z 1, 31-PAGE_SHIFT,1, %r25 +#endif + add %r28, %r25, %r25 + sub %r25, %r1, %r25 + + +1: fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + fic,m %r1(%r28) + cmpb,COND(<<) %r28, %r25,1b + fic,m %r1(%r28) sync bv %r0(%r2) - nop + pitlb (%sr0,%r25) .exit .procend -ENDPROC(flush_user_dcache_page) +ENDPROC(flush_icache_page_asm) -ENTRY(flush_user_icache_page) +ENTRY(flush_kernel_dcache_page_asm) .proc .callinfo NO_CALLS .entry @@ -711,23 +749,23 @@ ENTRY(flush_user_icache_page) sub %r25, %r23, %r25 -1: fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) - fic,m %r23(%sr3, %r26) +1: fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) cmpb,COND(<<) %r26, %r25,1b - fic,m %r23(%sr3, %r26) + fdc,m %r23(%r26) sync bv %r0(%r2) @@ -735,8 +773,7 @@ ENTRY(flush_user_icache_page) .exit .procend -ENDPROC(flush_user_icache_page) - +ENDPROC(flush_kernel_dcache_page_asm) ENTRY(purge_kernel_dcache_page) .proc @@ -780,69 +817,6 @@ ENTRY(purge_kernel_dcache_page) .procend ENDPROC(purge_kernel_dcache_page) -#if 0 - /* Currently not used, but it still is a possible alternate - * solution. - */ - -ENTRY(flush_alias_page) - .proc - .callinfo NO_CALLS - .entry - - tophys_r1 %r26 - - ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT - extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,12, %r28 /* Clear any offset bits */ -#endif - - /* Purge any old translation */ - - pdtlb 0(%r28) - - ldil L%dcache_stride, %r1 - ldw R%dcache_stride(%r1), %r23 - -#ifdef CONFIG_64BIT - depdi,z 1, 63-PAGE_SHIFT,1, %r29 -#else - depwi,z 1, 31-PAGE_SHIFT,1, %r29 -#endif - add %r28, %r29, %r29 - sub %r29, %r23, %r29 - -1: fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - fdc,m %r23(%r28) - cmpb,COND(<<) %r28, %r29, 1b - fdc,m %r23(%r28) - - sync - bv %r0(%r2) - nop - .exit - - .procend -#endif .export flush_user_dcache_range_asm @@ -865,7 +839,6 @@ flush_user_dcache_range_asm: .exit .procend -ENDPROC(flush_alias_page) ENTRY(flush_kernel_dcache_range_asm) .proc diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index 946ec4947da..7005ee0b074 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -367,6 +367,10 @@ struct mpic #define MPIC_SINGLE_DEST_CPU 0x00001000 /* Enable CoreInt delivery of interrupts */ #define MPIC_ENABLE_COREINT 0x00002000 +/* Disable resetting of the MPIC. + * NOTE: This flag trumps MPIC_WANTS_RESET. + */ +#define MPIC_NO_RESET 0x00004000 /* MPIC HW modification ID */ #define MPIC_REGSET_MASK 0xf0000000 diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 0175a676b34..48223f9b872 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -125,8 +125,10 @@ extern int ptrace_put_reg(struct task_struct *task, int regno, #endif /* ! __powerpc64__ */ #define TRAP(regs) ((regs)->trap & ~0xF) #ifdef __powerpc64__ +#define NV_REG_POISON 0xdeadbeefdeadbeefUL #define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) #else +#define NV_REG_POISON 0xdeadbeef #define CHECK_FULL_REGS(regs) \ do { \ if ((regs)->trap & 1) \ diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 29852688cea..d225d99fe39 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -176,11 +176,14 @@ static void *is_devfn_node(struct device_node *dn, void *data) */ struct device_node *fetch_dev_dn(struct pci_dev *dev) { - struct device_node *orig_dn = dev->dev.of_node; + struct pci_controller *phb = dev->sysdata; struct device_node *dn; unsigned long searchval = (dev->bus->number << 8) | dev->devfn; - dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval); + if (WARN_ON(!phb)) + return NULL; + + dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval); if (dn) dev->dev.of_node = dn; return dn; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 90653699829..895b082f1e4 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { - int ret; + int i, ret; if (target->thread.regs == NULL) return -EIO; - CHECK_FULL_REGS(target->thread.regs); + if (!FULL_REGS(target->thread.regs)) { + /* We have a partial register set. Fill 14-31 with bogus values */ + for (i = 14; i < 32; i++) + target->thread.regs->gpr[i] = NV_REG_POISON; + } ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, target->thread.regs, @@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target, compat_ulong_t *k = kbuf; compat_ulong_t __user *u = ubuf; compat_ulong_t reg; + int i; if (target->thread.regs == NULL) return -EIO; - CHECK_FULL_REGS(target->thread.regs); + if (!FULL_REGS(target->thread.regs)) { + /* We have a partial register set. Fill 14-31 with bogus values */ + for (i = 14; i < 32; i++) + target->thread.regs->gpr[i] = NV_REG_POISON; + } pos /= sizeof(reg); count /= sizeof(reg); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index eb7021815e2..0f7c6718d26 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -147,6 +147,16 @@ static u32 mpic_infos[][MPIC_IDX_END] = { #endif /* CONFIG_MPIC_WEIRD */ +static inline unsigned int mpic_processor_id(struct mpic *mpic) +{ + unsigned int cpu = 0; + + if (mpic->flags & MPIC_PRIMARY) + cpu = hard_smp_processor_id(); + + return cpu; +} + /* * Register accessor functions */ @@ -210,19 +220,14 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) { - unsigned int cpu = 0; + unsigned int cpu = mpic_processor_id(mpic); - if (mpic->flags & MPIC_PRIMARY) - cpu = hard_smp_processor_id(); return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg); } static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) { - unsigned int cpu = 0; - - if (mpic->flags & MPIC_PRIMARY) - cpu = hard_smp_processor_id(); + unsigned int cpu = mpic_processor_id(mpic); _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value); } @@ -913,6 +918,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector) mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); } +void mpic_set_destination(unsigned int virq, unsigned int cpuid) +{ + struct mpic *mpic = mpic_from_irq(virq); + unsigned int src = mpic_irq_to_hw(virq); + + DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", + mpic, virq, src, cpuid); + + if (src >= mpic->irq_count) + return; + + mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); +} + static struct irq_chip mpic_irq_chip = { .irq_mask = mpic_mask_irq, .irq_unmask = mpic_unmask_irq, @@ -993,6 +1012,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, /* Set default irq type */ set_irq_type(virq, IRQ_TYPE_NONE); + /* If the MPIC was reset, then all vectors have already been + * initialized. Otherwise, a per source lazy initialization + * is done here. + */ + if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) { + mpic_set_vector(virq, hw); + mpic_set_destination(virq, mpic_processor_id(mpic)); + mpic_irq_set_priority(virq, 8); + } + return 0; } @@ -1040,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = { .xlate = mpic_host_xlate, }; +static int mpic_reset_prohibited(struct device_node *node) +{ + return node && of_get_property(node, "pic-no-reset", NULL); +} + /* * Exported functions */ @@ -1160,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); /* Reset */ - if (flags & MPIC_WANTS_RESET) { + + /* When using a device-node, reset requests are only honored if the MPIC + * is allowed to reset. + */ + if (mpic_reset_prohibited(node)) + mpic->flags |= MPIC_NO_RESET; + + if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { + printk(KERN_DEBUG "mpic: Resetting\n"); mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | MPIC_GREG_GCONF_RESET); @@ -1320,22 +1362,21 @@ void __init mpic_init(struct mpic *mpic) mpic_pasemi_msi_init(mpic); - if (mpic->flags & MPIC_PRIMARY) - cpu = hard_smp_processor_id(); - else - cpu = 0; + cpu = mpic_processor_id(mpic); - for (i = 0; i < mpic->num_sources; i++) { - /* start with vector = source number, and masked */ - u32 vecpri = MPIC_VECPRI_MASK | i | - (8 << MPIC_VECPRI_PRIORITY_SHIFT); + if (!(mpic->flags & MPIC_NO_RESET)) { + for (i = 0; i < mpic->num_sources; i++) { + /* start with vector = source number, and masked */ + u32 vecpri = MPIC_VECPRI_MASK | i | + (8 << MPIC_VECPRI_PRIORITY_SHIFT); - /* check if protected */ - if (mpic->protected && test_bit(i, mpic->protected)) - continue; - /* init hw */ - mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); - mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); + /* check if protected */ + if (mpic->protected && test_bit(i, mpic->protected)) + continue; + /* init hw */ + mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); + mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); + } } /* Init spurious vector */ diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index cbf4801deaa..eced3e3ebd3 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h @@ -13,4 +13,7 @@ #define irq_canonicalize(irq) (irq) extern void __init init_IRQ(void); + +#define NO_IRQ 0xffffffff + #endif diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 4f09666f079..16dcae6d56e 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -97,4 +97,6 @@ extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ #define ARCH_HAS_NMI_WATCHDOG +#define NO_IRQ 0xffffffff + #endif diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 03eb5a8f6f9..2f475d7c0b5 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -400,8 +400,11 @@ #define __NR_fanotify_init 329 #define __NR_fanotify_mark 330 #define __NR_prlimit64 331 +#define __NR_name_to_handle_at 332 +#define __NR_open_by_handle_at 333 +#define __NR_clock_adjtime 334 -#define NR_syscalls 332 +#define NR_syscalls 335 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 49ddff56cb0..cb15bbf8a20 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -22,6 +22,33 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) } EXPORT_SYMBOL(irq_of_parse_and_map); +int of_address_to_resource(struct device_node *node, int index, + struct resource *r) +{ + struct platform_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_resources) + return -EINVAL; + + memcpy(r, &op->archdata.resource[index], sizeof(*r)); + return 0; +} +EXPORT_SYMBOL_GPL(of_address_to_resource); + +void __iomem *of_iomap(struct device_node *node, int index) +{ + struct platform_device *op = of_find_device_by_node(node); + struct resource *r; + + if (!op || index >= op->num_resources) + return NULL; + + r = &op->archdata.resource[index]; + + return of_ioremap(r, 0, resource_size(r), (char *) r->name); +} +EXPORT_SYMBOL(of_iomap); + /* Take the archdata values for IOMMU, STC, and HOSTDATA found in * BUS and propagate to all child platform_device objects. */ diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index ec396e1916b..4b86eaf04fe 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -83,5 +83,5 @@ sys_call_table: /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init -/*330*/ .long sys_fanotify_mark, sys_prlimit64 +/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 8cfcaa54958..0331bafdf3a 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -84,7 +84,7 @@ sys_call_table32: .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init -/*330*/ .word sys32_fanotify_mark, sys_prlimit64 +/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime #endif /* CONFIG_COMPAT */ @@ -160,4 +160,4 @@ sys_call_table: .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init -/*330*/ .word sys_fanotify_mark, sys_prlimit64 +/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime |