From 32104b29cdf93f78ac37e681bd4547413466d13c Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 13 Aug 2006 20:37:26 -0400
Subject: [PARISC] PA7200 also supports prefetch for read

It seems PA7200 processors also suppress traps on loads to
%r0. This means we can prefetch for read on these cpus. Of course,
we can't support prefetch for write, since that requires
LOAD DOUBLEWORD which was added with PA2.0

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'arch')

diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6dd0ea8f88e0..d2101237442e 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -127,7 +127,7 @@ config PA11
 
 config PREFETCH
 	def_bool y
-	depends on PA8X00
+	depends on PA8X00 || PA7200
 
 config 64BIT
 	bool "64-bit kernel"
-- 
cgit v1.2.3


From c51d476af36d1e9634e77afccc4d48e344acf243 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 13 Aug 2006 20:39:48 -0400
Subject: [PARISC] Remove variables decls duplicated from
 asm-generic/sections.h

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/mm/init.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 25ad28d63e88..0667f2b4f977 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -31,10 +31,7 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-extern char _text;	/* start of kernel code, defined by linker */
 extern int  data_start;
-extern char _end;	/* end of BSS, defined by linker */
-extern char __init_begin, __init_end;
 
 #ifdef CONFIG_DISCONTIGMEM
 struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
@@ -319,8 +316,8 @@ static void __init setup_bootmem(void)
 
 	reserve_bootmem_node(NODE_DATA(0), 0UL,
 			(unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
-	reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
-			(unsigned long)(&_end - &_text));
+	reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
+			(unsigned long)(_end - _text));
 	reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
 			((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
 
@@ -355,8 +352,8 @@ static void __init setup_bootmem(void)
 #endif
 
 	data_resource.start =  virt_to_phys(&data_start);
-	data_resource.end = virt_to_phys(&_end)-1;
-	code_resource.start = virt_to_phys(&_text);
+	data_resource.end = virt_to_phys(_end) - 1;
+	code_resource.start = virt_to_phys(_text);
 	code_resource.end = virt_to_phys(&data_start)-1;
 
 	/* We don't know which region the kernel will be in, so try
@@ -385,12 +382,12 @@ void free_initmem(void)
 	 */
 	local_irq_disable();
 
-	memset(&__init_begin, 0x00, 
-		(unsigned long)&__init_end - (unsigned long)&__init_begin);
+	memset(__init_begin, 0x00,
+		(unsigned long)__init_end - (unsigned long)__init_begin);
 
 	flush_data_cache();
 	asm volatile("sync" : : );
-	flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
+	flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
 	asm volatile("sync" : : );
 
 	local_irq_enable();
@@ -398,8 +395,8 @@ void free_initmem(void)
 	
 	/* align __init_begin and __init_end to page size,
 	   ignoring linker script where we might have tried to save RAM */
-	init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
-	init_end   = PAGE_ALIGN((unsigned long)(&__init_end));
+	init_begin = PAGE_ALIGN((unsigned long)(__init_begin));
+	init_end   = PAGE_ALIGN((unsigned long)(__init_end));
 	for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
@@ -578,7 +575,7 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
 	extern const unsigned long fault_vector_20;
 	extern void * const linux_gateway_page;
 
-	ro_start = __pa((unsigned long)&_text);
+	ro_start = __pa((unsigned long)_text);
 	ro_end   = __pa((unsigned long)&data_start);
 	fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
 	gw_addr  = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
-- 
cgit v1.2.3


From 3d73cf5e18c47d416db4d0734245d3fb087603d9 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 13 Aug 2006 22:17:19 -0400
Subject: [PARISC] Abstract shift register left in .S

Abstract existing shift register left macros as shift register
right are. This lends itself to a nice clean up of some #ifdef
blocks in entry.S

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/entry.S    | 19 ++++---------------
 include/asm-parisc/assembly.h |  6 ++++--
 2 files changed, 8 insertions(+), 17 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 192357a3b9fe..d55b45d54f4d 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -30,6 +30,7 @@
 
 
 #include <asm/psw.h>
+#include <asm/cache.h>		/* for L1_CACHE_SHIFT */
 #include <asm/assembly.h>	/* for LDREG/STREG defines */
 #include <asm/pgtable.h>
 #include <asm/signal.h>
@@ -478,11 +479,7 @@
 	bb,>=,n		\pmd,_PxD_PRESENT_BIT,\fault
 	DEP		%r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
 	copy		\pmd,%r9
-#ifdef CONFIG_64BIT
-	shld		%r9,PxD_VALUE_SHIFT,\pmd
-#else
-	shlw		%r9,PxD_VALUE_SHIFT,\pmd
-#endif
+	SHLREG		%r9,PxD_VALUE_SHIFT,\pmd
 	EXTR		\va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
 	DEP		%r0,31,PAGE_SHIFT,\pmd  /* clear offset */
 	shladd		\index,BITS_PER_PTE_ENTRY,\pmd,\pmd
@@ -970,11 +967,7 @@ intr_return:
 	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
 	** irq_stat[] is defined using ____cacheline_aligned.
 	*/
-#ifdef CONFIG_64BIT
-	shld	%r1, 6, %r20
-#else
-	shlw	%r1, 5, %r20
-#endif
+	SHLREG	%r1,L1_CACHE_SHIFT,%r20
 	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
@@ -2115,11 +2108,7 @@ syscall_check_bh:
 	ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
 
 	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
-#ifdef CONFIG_64BIT
-	shld	%r26, 6, %r20
-#else
-	shlw	%r26, 5, %r20
-#endif
+	SHLREG	%r26,L1_CACHE_SHIFT,%r20
 	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
index 1a7bfe699e0c..5a1e0e8b1c32 100644
--- a/include/asm-parisc/assembly.h
+++ b/include/asm-parisc/assembly.h
@@ -29,7 +29,8 @@
 #define LDREGX  ldd,s
 #define LDREGM	ldd,mb
 #define STREGM	std,ma
-#define SHRREG  shrd
+#define SHRREG	shrd
+#define SHLREG	shld
 #define RP_OFFSET	16
 #define FRAME_SIZE	128
 #define CALLEE_REG_FRAME_SIZE	144
@@ -39,7 +40,8 @@
 #define LDREGX  ldwx,s
 #define LDREGM	ldwm
 #define STREGM	stwm
-#define SHRREG  shr
+#define SHRREG	shr
+#define SHLREG	shlw
 #define RP_OFFSET	20
 #define FRAME_SIZE	64
 #define CALLEE_REG_FRAME_SIZE	128
-- 
cgit v1.2.3


From 5cfe87d3f543d05a84a509d232330261f1b7bccf Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 13 Aug 2006 22:25:45 -0400
Subject: [PARISC] Fix up parisc irq handling for genirq changes

Clean up enough to get things compiling again in the interim.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/irq.c | 2 +-
 include/asm-parisc/irq.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 5b8803cc3d69..c53bfeb4bf94 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -209,7 +209,7 @@ int show_interrupts(struct seq_file *p, void *v)
 ** Then use that to get the Transaction address and data.
 */
 
-int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *type, void *data)
+int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
 	if (irq_desc[irq].action)
 		return -EBUSY;
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index 5cae260615a2..6e29cfa2812d 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -31,7 +31,7 @@ static __inline__ int irq_canonicalize(int irq)
 	return (irq == 2) ? 9 : irq;
 }
 
-struct hw_interrupt_type;
+struct irq_chip;
 
 /*
  * Some useful "we don't have to do anything here" handlers.  Should
@@ -46,7 +46,7 @@ extern unsigned int txn_alloc_data(unsigned int);
 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 hw_interrupt_type *, void *);
+extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
 extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest);
 
 /* soft power switch support (power.c) */
-- 
cgit v1.2.3


From 20f4d3cb9b94ce3fec9a6135b9ad075b82b24f41 Mon Sep 17 00:00:00 2001
From: James Bottomley <jejb@parisc-linux.org>
Date: Wed, 23 Aug 2006 09:00:04 -0700
Subject: [PARISC] parisc specific kmap API implementation for pa8800

This patch fixes the pa8800 at a gross level (there are still other
subtle incoherency issues which can still cause crashes and HPMCs).

What it does is try to force eject inequivalent aliases before they
become visible to the L2 cache (which is where we get the incoherence
problems).

A new function (parisc_requires_coherency) is introduced in
asm/processor.h to identify the pa8x00 processors (8800 and 8900)
which have the issue.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/cache.c      | 45 ++++++++++++++++++++++++++++++++++++++++-
 include/asm-parisc/cacheflush.h | 30 +++++++++++++++++++++++----
 include/asm-parisc/page.h       | 22 ++++----------------
 include/asm-parisc/processor.h  | 13 ++++++++++++
 4 files changed, 87 insertions(+), 23 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index bc7c4a4e26a1..7e8d697aef36 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -91,7 +91,8 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 
 		flush_kernel_dcache_page(page);
 		clear_bit(PG_dcache_dirty, &page->flags);
-	}
+	} else if (parisc_requires_coherency())
+		flush_kernel_dcache_page(page);
 }
 
 void
@@ -370,3 +371,45 @@ void parisc_setup_cache_timing(void)
 
 	printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
 }
+
+extern void purge_kernel_dcache_page(unsigned long);
+extern void clear_user_page_asm(void *page, unsigned long vaddr);
+
+void
+clear_user_page(void *page, unsigned long vaddr, struct page *pg)
+{
+	purge_kernel_dcache_page((unsigned long)page);
+	purge_tlb_start();
+	pdtlb_kernel(page);
+	purge_tlb_end();
+	clear_user_page_asm(page, vaddr);
+}
+
+void flush_kernel_dcache_page_addr(void *addr)
+{
+	flush_kernel_dcache_page_asm(addr);
+	purge_tlb_start();
+	pdtlb_kernel(addr);
+	purge_tlb_end();
+}
+EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
+
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+		    struct page *pg)
+{
+	/* no coherency needed (all in kmap/kunmap) */
+	copy_user_page_asm(vto, vfrom);
+	if (!parisc_requires_coherency())
+		flush_kernel_dcache_page_asm(vto);
+}
+EXPORT_SYMBOL(copy_user_page);
+
+#ifdef CONFIG_PA8X00
+
+void kunmap_parisc(void *addr)
+{
+	if (parisc_requires_coherency())
+		flush_kernel_dcache_page_addr(addr);
+}
+EXPORT_SYMBOL(kunmap_parisc);
+#endif
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 0b459cdfbd6f..2bc41f2e0271 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -191,16 +191,38 @@ flush_anon_page(struct page *page, unsigned long vmaddr)
 }
 #define ARCH_HAS_FLUSH_ANON_PAGE
 
-static inline void
-flush_kernel_dcache_page(struct page *page)
+#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_asm(page_address(page));
+	flush_kernel_dcache_page_addr(page_address(page));
 }
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);
 #endif
 
+#ifdef CONFIG_PA8X00
+/* Only pa8800, pa8900 needs this */
+#define ARCH_HAS_KMAP
+
+void kunmap_parisc(void *addr);
+
+static inline void *kmap(struct page *page)
+{
+	might_sleep();
+	return page_address(page);
+}
+
+#define kunmap(page)			kunmap_parisc(page_address(page))
+
+#define kmap_atomic(page, idx)		page_address(page)
+
+#define kunmap_atomic(addr, idx)	kunmap_parisc(addr)
+
+#define kmap_atomic_pfn(pfn, idx)	page_address(pfn_to_page(pfn))
+#define kmap_atomic_to_page(ptr)	virt_to_page(ptr)
+#endif
+
 #endif /* _PARISC_CACHEFLUSH_H */
 
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 57d6d82756dd..3567208191e3 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -26,24 +26,10 @@
 
 struct page;
 
-extern void purge_kernel_dcache_page(unsigned long);
-extern void copy_user_page_asm(void *to, void *from);
-extern void clear_user_page_asm(void *page, unsigned long vaddr);
-
-static inline void
-copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg)
-{
-	copy_user_page_asm(vto, vfrom);
-	flush_kernel_dcache_page_asm(vto);
-	/* XXX: ppc flushes icache too, should we? */
-}
-
-static inline void
-clear_user_page(void *page, unsigned long vaddr, struct page *pg)
-{
-	purge_kernel_dcache_page((unsigned long)page);
-	clear_user_page_asm(page, vaddr);
-}
+void copy_user_page_asm(void *to, void *from);
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+			   struct page *pg);
+void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 
 /*
  * These are used to make use of C type-checking..
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index c72b8fa49686..4313618c98ee 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -332,6 +332,19 @@ extern unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()	barrier()
 
+/* 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)
+{
+#ifdef CONFIG_PA8X00
+	/* FIXME: also pa8900 - when we see one */
+	return boot_cpu_data.cpu_type == mako;
+#else
+	return 0;
+#endif
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_PARISC_PROCESSOR_H */
-- 
cgit v1.2.3


From df570b9c284701d08b22aa00cbfcf870b7f1b7c1 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 27 Aug 2006 11:04:26 -0400
Subject: [PARISC] Switch is_compat_task to use TIF_32BIT

Stop using PER_LINUX32 to designate processes needing
compaterizing. Convert is_compat_task to use TIF_32BIT and
set TIF_32BIT in binfmt_elf32.c

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/binfmt_elf32.c | 24 +-----------------------
 arch/parisc/kernel/signal.c       |  5 ++---
 include/asm-parisc/compat.h       |  4 ++--
 include/asm-parisc/processor.h    |  2 +-
 4 files changed, 6 insertions(+), 29 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c
index d1833f164bbe..1e64e7b88110 100644
--- a/arch/parisc/kernel/binfmt_elf32.c
+++ b/arch/parisc/kernel/binfmt_elf32.c
@@ -87,7 +87,7 @@ struct elf_prpsinfo32
  */
 
 #define SET_PERSONALITY(ex, ibcs2) \
-	current->personality = PER_LINUX32; \
+	set_thread_flag(TIF_32BIT); \
 	current->thread.map_base = DEFAULT_MAP_BASE32; \
 	current->thread.task_size = DEFAULT_TASK_SIZE32 \
 
@@ -102,25 +102,3 @@ cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
 }
 
 #include "../../../fs/binfmt_elf.c"
-
-/* Set up a separate execution domain for ELF32 binaries running
- * on an ELF64 kernel */
-
-static struct exec_domain parisc32_exec_domain = { 
-	.name = "Linux/ELF32",
-	.pers_low = PER_LINUX32,
-	.pers_high = PER_LINUX32,
-};      
-
-static int __init parisc32_exec_init(void)
-{
-	/* steal the identity signal mappings from the default domain */
-	parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
-	parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
-
-	register_exec_domain(&parisc32_exec_domain);
-
-	return 0;
-}
-
-__initcall(parisc32_exec_init);
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index bb83880c5ee3..ee6653edeb7a 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -26,7 +26,6 @@
 #include <linux/stddef.h>
 #include <linux/compat.h>
 #include <linux/elf.h>
-#include <linux/personality.h>
 #include <asm/ucontext.h>
 #include <asm/rt_sigframe.h>
 #include <asm/uaccess.h>
@@ -433,13 +432,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (in_syscall) {
 		regs->gr[31] = haddr;
 #ifdef __LP64__
-		if (personality(current->personality) == PER_LINUX)
+		if (!test_thread_flag(TIF_32BIT))
 			sigframe_size |= 1;
 #endif
 	} else {
 		unsigned long psw = USER_PSW;
 #ifdef __LP64__
-		if (personality(current->personality) == PER_LINUX)
+		if (!test_thread_flag(TIF_32BIT))
 			psw |= PSW_W;
 #endif
 
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 71b4eeea205a..fe8579023531 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -5,7 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/personality.h>
+#include <linux/thread_info.h>
 
 #define COMPAT_USER_HZ 100
 
@@ -152,7 +152,7 @@ static __inline__ void __user *compat_alloc_user_space(long len)
 
 static inline int __is_compat_task(struct task_struct *t)
 {
-	return personality(t->personality) == PER_LINUX32;
+	return test_ti_thread_flag(t->thread_info, TIF_32BIT);
 }
 
 static inline int is_compat_task(void)
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index 4313618c98ee..fd7866dc8c83 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -278,7 +278,7 @@ on downward growing arches, it looks like this:
  */
 
 #ifdef __LP64__
-#define USER_WIDE_MODE	(personality(current->personality) == PER_LINUX)
+#define USER_WIDE_MODE	(!test_thread_flag(TIF_32BIT))
 #else
 #define USER_WIDE_MODE	0
 #endif
-- 
cgit v1.2.3


From 75a4958154f5d0028d5464f2479b4297d55cf4a3 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Sun, 27 Aug 2006 11:12:13 -0400
Subject: [PARISC] Allow overriding personality with sys_personality

And now suddenly, linux32 works on parisc...

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/sys_parisc.c    | 45 ++++++++++++++++++++++++++++++++++++++
 arch/parisc/kernel/syscall_table.S |  4 ++--
 2 files changed, 47 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 8b5df98e2b31..1db5588ceacf 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -31,6 +31,8 @@
 #include <linux/shm.h>
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/personality.h>
 
 int sys_pipe(int __user *fildes)
 {
@@ -248,3 +250,46 @@ asmlinkage int sys_free_hugepages(unsigned long addr)
 {
 	return -EINVAL;
 }
+
+long parisc_personality(unsigned long personality)
+{
+	long err;
+
+	if (personality(current->personality) == PER_LINUX32
+	    && personality == PER_LINUX)
+		personality = PER_LINUX32;
+
+	err = sys_personality(personality);
+	if (err == PER_LINUX32)
+		err = PER_LINUX;
+
+	return err;
+}
+
+static inline int override_machine(char __user *mach) {
+#ifdef CONFIG_COMPAT
+	if (personality(current->personality) == PER_LINUX32) {
+		if (__put_user(0, mach + 6) ||
+		    __put_user(0, mach + 7))
+			return -EFAULT;
+	}
+
+	return 0;
+#else /*!CONFIG_COMPAT*/
+	return 0;
+#endif /*CONFIG_COMPAT*/
+}
+
+long parisc_newuname(struct new_utsname __user *utsname)
+{
+	int err = 0;
+
+	down_read(&uts_sem);
+	if (copy_to_user(utsname, &system_utsname, sizeof(*utsname)))
+		err = -EFAULT;
+	up_read(&uts_sem);
+
+	err = override_machine(utsname->machine);
+
+	return (long)err;
+}
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index e27b432f90a8..701d66a596e8 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -132,7 +132,7 @@
 	ENTRY_SAME(socketpair)
 	ENTRY_SAME(setpgid)
 	ENTRY_SAME(send)
-	ENTRY_SAME(newuname)
+	ENTRY_OURS(newuname)
 	ENTRY_SAME(umask)		/* 60 */
 	ENTRY_SAME(chroot)
 	ENTRY_SAME(ustat)
@@ -221,7 +221,7 @@
 	ENTRY_SAME(fchdir)
 	ENTRY_SAME(bdflush)
 	ENTRY_SAME(sysfs)		/* 135 */
-	ENTRY_SAME(personality)
+	ENTRY_OURS(personality)
 	ENTRY_SAME(ni_syscall)	/* for afs_syscall */
 	ENTRY_SAME(setfsuid)
 	ENTRY_SAME(setfsgid)
-- 
cgit v1.2.3


From 9c2c54574e724589858ad656a507be29f9034943 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@parisc-linux.org>
Date: Mon, 28 Aug 2006 15:42:07 -0400
Subject: [PARISC] [BUGFIX] nullify branch delay slot of the jump back to

intr_restore in intr_do_preempt. This prevents the execution
of an unwanted insn...

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/entry.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d55b45d54f4d..340b5e8d67ba 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1069,7 +1069,7 @@ intr_do_preempt:
 	BL	preempt_schedule_irq, %r2
 	nop
 
-	b	intr_restore		/* ssm PSW_SM_I done by intr_restore */
+	b,n	intr_restore		/* ssm PSW_SM_I done by intr_restore */
 #endif /* CONFIG_PREEMPT */
 
 	.import do_signal,code
-- 
cgit v1.2.3


From 7908a0c72ee78ba5476c2a773d808c77593719c6 Mon Sep 17 00:00:00 2001
From: Grant Grundler <grundler@gsyprf11.external.hp.com>
Date: Fri, 1 Sep 2006 14:18:39 -0700
Subject: [PARISC] Prevent processor_probe() from clobbering cpu_data[0]

processor_probe() shouldn't clobber cpu_data[0]
cpu_data[0].it_value (used by timer_interrupt()) is already set.

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/processor.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 99d7fca93104..fb81e5687e7c 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -143,8 +143,9 @@ static int __init processor_probe(struct parisc_device *dev)
 	p = &cpu_data[cpuid];
 	boot_cpu_data.cpu_count++;
 
-	/* initialize counters */
-	memset(p, 0, sizeof(struct cpuinfo_parisc));
+	/* initialize counters - CPU 0 gets it_value set in time_init() */
+	if (cpuid)
+		memset(p, 0, sizeof(struct cpuinfo_parisc));
 
 	p->loops_per_jiffy = loops_per_jiffy;
 	p->dev = dev;		/* Save IODC data in case we need it */
-- 
cgit v1.2.3


From 56f335c89e28c488b1bfea3e5e697fce805c784d Mon Sep 17 00:00:00 2001
From: Grant Grundler <grundler@gsyprf11.external.hp.com>
Date: Sun, 3 Sep 2006 00:02:16 -0700
Subject: [PARISC] Add new function to start local Interval Timer,
 start_cpu_itimer()

I couldn't find where the itimer was getting started for slave CPUs.
CPU 0 (master) itimer was started in time_init() (arch/parisc/kernel/time.c).
start_cpu_itimer() code was striped from time_init().
Slaves now start their itimer in smp_cpu_init().

This is a first step towards making gettimeoffset() work for SMP.
Next step will be to determine the CR16 (cycle counter)
offsets for each CPU relative to the master (CPU 0).

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/smp.c  |  4 +++-
 arch/parisc/kernel/time.c | 20 +++++++++++---------
 2 files changed, 14 insertions(+), 10 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 98e40959a564..f33e8de438dc 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -430,8 +430,9 @@ smp_do_timer(struct pt_regs *regs)
 static void __init
 smp_cpu_init(int cpunum)
 {
-	extern int init_per_cpu(int);  /* arch/parisc/kernel/setup.c */
+	extern int init_per_cpu(int);  /* arch/parisc/kernel/processor.c */
 	extern void init_IRQ(void);    /* arch/parisc/kernel/irq.c */
+	extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */
 
 	/* Set modes and Enable floating point coprocessor */
 	(void) init_per_cpu(cpunum);
@@ -457,6 +458,7 @@ smp_cpu_init(int cpunum)
 	enter_lazy_tlb(&init_mm, current);
 
 	init_IRQ();   /* make sure no IRQ's are enabled or pending */
+	start_cpu_itimer();
 }
 
 
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index ab641d67f551..47831c2cd093 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -223,22 +223,24 @@ unsigned long long sched_clock(void)
 }
 
 
+void __init start_cpu_itimer(void)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long next_tick = mfctl(16) + clocktick;
+
+	mtctl(next_tick, 16);		/* kick off Interval Timer (CR16) */
+
+	cpu_data[cpu].it_value = next_tick;
+}
+
 void __init time_init(void)
 {
-	unsigned long next_tick;
 	static struct pdc_tod tod_data;
 
 	clocktick = (100 * PAGE0->mem_10msec) / HZ;
 	halftick = clocktick / 2;
 
-	/* Setup clock interrupt timing */
-
-	next_tick = mfctl(16);
-	next_tick += clocktick;
-	cpu_data[smp_processor_id()].it_value = next_tick;
-
-	/* kick off Itimer (CR16) */
-	mtctl(next_tick, 16);
+	start_cpu_itimer();	/* get CPU 0 started */
 
 	if(pdc_tod_read(&tod_data) == 0) {
 		write_seqlock_irq(&xtime_lock);
-- 
cgit v1.2.3


From bed583f76e1d5fbb5a6fdf27a0f7b2ae235f7e99 Mon Sep 17 00:00:00 2001
From: Grant Grundler <grundler@gsyprf11.external.hp.com>
Date: Fri, 8 Sep 2006 23:29:22 -0700
Subject: [PARISC] Rewrite timer_interrupt() and gettimeoffset() using
 "unsigned" math.

It's just a bit easier to follow and timer code is complex enough.

So far, only tested on A500-5x (64-bit SMP), ie: gettimeoffset() code
hasn't been tested at all.

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/time.c | 140 +++++++++++++++++++++++++++++++---------------
 1 file changed, 96 insertions(+), 44 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 47831c2cd093..fd425e1abe66 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -32,8 +32,8 @@
 
 #include <linux/timex.h>
 
-static long clocktick __read_mostly;	/* timer cycles per tick */
-static long halftick __read_mostly;
+static unsigned long clocktick __read_mostly;	/* timer cycles per tick */
+static unsigned long halftick __read_mostly;
 
 #ifdef CONFIG_SMP
 extern void smp_do_timer(struct pt_regs *regs);
@@ -41,34 +41,77 @@ extern void smp_do_timer(struct pt_regs *regs);
 
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	long now;
-	long next_tick;
-	int nticks;
+	unsigned long now;
+	unsigned long next_tick;
+	unsigned long cycles_elapsed;
+        unsigned long cycles_remainder;
+	unsigned long ticks_elapsed = 1;	/* at least one elapsed */
 	int cpu = smp_processor_id();
 
 	profile_tick(CPU_PROFILING, regs);
 
-	now = mfctl(16);
-	/* initialize next_tick to time at last clocktick */
+	/* Initialize next_tick to the expected tick time. */
 	next_tick = cpu_data[cpu].it_value;
 
-	/* since time passes between the interrupt and the mfctl()
-	 * above, it is never true that last_tick + clocktick == now.  If we
-	 * never miss a clocktick, we could set next_tick = last_tick + clocktick
-	 * but maybe we'll miss ticks, hence the loop.
-	 *
-	 * Variables are *signed*.
+	/* Get current interval timer.
+	 * CR16 reads as 64 bits in CPU wide mode.
+	 * CR16 reads as 32 bits in CPU narrow mode.
 	 */
+	now = mfctl(16);
 
-	nticks = 0;
-	while((next_tick - now) < halftick) {
-		next_tick += clocktick;
-		nticks++;
+	cycles_elapsed = now - next_tick;
+
+	/* Determine how much time elapsed.  */
+	if (now < next_tick) {
+		/* Scenario 2: CR16 wrapped after clock tick.
+		 * 1's complement will give us the "elapse cycles".
+		 *
+		 * This "cr16 wrapped" cruft is primarily for 32-bit kernels.
+		 * So think "unsigned long is u32" when reading the code.
+		 * And yes, of course 64-bit will someday wrap, but only
+	  	 * every 198841 days on a 1GHz machine.
+		 */
+		cycles_elapsed = ~cycles_elapsed;   /* off by one cycle - don't care */
 	}
+
+	ticks_elapsed += cycles_elapsed / clocktick;
+	cycles_remainder = cycles_elapsed % clocktick;
+
+	/* Can we differentiate between "early CR16" (aka Scenario 1) and
+	 * "long delay" (aka Scenario 3)? I don't think so.
+	 *
+	 * We expected timer_interrupt to be delivered at least a few hundred
+	 * cycles after the IT fires. But it's arbitrary how much time passes
+	 * before we call it "late". I've picked one second.
+	 */
+	if (ticks_elapsed > HZ) {
+		/* Scenario 3: very long delay?  bad in any case */
+		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed! run ntpdate"
+			" ticks %ld cycles %lX rem %lX"
+			" next/now %lX/%lX\n",
+			cpu,
+			ticks_elapsed, cycles_elapsed, cycles_remainder,
+			next_tick, now );
+
+		ticks_elapsed = 1;	/* hack to limit damage in loop below */
+	}
+
+
+	/* Determine when (in CR16 cycles) next IT interrupt will fire.
+	 * We want IT to fire modulo clocktick even if we miss/skip some.
+	 * But those interrupts don't in fact get delivered that regularly.
+	 */
+	next_tick = now + (clocktick - cycles_remainder);
+
+	/* Program the IT when to deliver the next interrupt. */
+        /* Only bottom 32-bits of next_tick are written to cr16.  */
 	mtctl(next_tick, 16);
 	cpu_data[cpu].it_value = next_tick;
 
-	while (nticks--) {
+	/* Now that we are done mucking with unreliable delivery of interrupts,
+	 * go do system house keeping.
+	 */
+	while (ticks_elapsed--) {
 #ifdef CONFIG_SMP
 		smp_do_timer(regs);
 #else
@@ -121,21 +164,41 @@ gettimeoffset (void)
 	 *    Once parisc-linux learns the cr16 difference between processors,
 	 *    this could be made to work.
 	 */
-	long last_tick;
-	long elapsed_cycles;
+	unsigned long now;
+	unsigned long prev_tick;
+	unsigned long next_tick;
+	unsigned long elapsed_cycles;
+	unsigned long usec;
 
-	/* it_value is the intended time of the next tick */
-	last_tick = cpu_data[smp_processor_id()].it_value;
+	next_tick = cpu_data[smp_processor_id()].it_value;
+	now = mfctl(16);	/* Read the hardware interval timer.  */
 
-	/* Subtract one tick and account for possible difference between
-	 * when we expected the tick and when it actually arrived.
-	 * (aka wall vs real)
-	 */
-	last_tick -= clocktick * (jiffies - wall_jiffies + 1);
-	elapsed_cycles = mfctl(16) - last_tick;
+	prev_tick = next_tick - clocktick;
+
+	/* Assume Scenario 1: "now" is later than prev_tick.  */
+	elapsed_cycles = now - prev_tick;
+
+	if (now < prev_tick) {
+		/* Scenario 2: CR16 wrapped!
+		 * 1's complement is close enough.
+		 */
+		elapsed_cycles = ~elapsed_cycles;
+	}
 
-	/* the precision of this math could be improved */
-	return elapsed_cycles / (PAGE0->mem_10msec / 10000);
+	if (elapsed_cycles > (HZ * clocktick)) {
+		/* Scenario 3: clock ticks are missing. */
+		printk (KERN_CRIT "gettimeoffset(CPU %d): missing ticks!"
+			"cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
+			cpuid,
+			elapsed_cycles, prev_tick, now, next_tick, clocktick);
+	}
+
+	/* FIXME: Can we improve the precision? Not with PAGE0. */
+	usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
+
+	/* add in "lost" jiffies */
+	usec += clocktick * (jiffies - wall_jiffies);
+	return usec;
 #else
 	return 0;
 #endif
@@ -146,6 +209,7 @@ do_gettimeofday (struct timeval *tv)
 {
 	unsigned long flags, seq, usec, sec;
 
+	/* Hold xtime_lock and adjust timeval.  */
 	do {
 		seq = read_seqbegin_irqsave(&xtime_lock, flags);
 		usec = gettimeoffset();
@@ -153,25 +217,13 @@ do_gettimeofday (struct timeval *tv)
 		usec += (xtime.tv_nsec / 1000);
 	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-	if (unlikely(usec > LONG_MAX)) {
-		/* This can happen if the gettimeoffset adjustment is
-		 * negative and xtime.tv_nsec is smaller than the
-		 * adjustment */
-		printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec);
-		usec += USEC_PER_SEC;
-		--sec;
-		/* This should never happen, it means the negative
-		 * time adjustment was more than a second, so there's
-		 * something seriously wrong */
-		BUG_ON(usec > LONG_MAX);
-	}
-
-
+	/* Move adjusted usec's into sec's.  */
 	while (usec >= USEC_PER_SEC) {
 		usec -= USEC_PER_SEC;
 		++sec;
 	}
 
+	/* Return adjusted result.  */
 	tv->tv_sec = sec;
 	tv->tv_usec = usec;
 }
-- 
cgit v1.2.3


From 6b799d9222fef265802b0b6dcc4fb982cc8f55ca Mon Sep 17 00:00:00 2001
From: Grant Grundler <grundler@gsyprf11.external.hp.com>
Date: Mon, 4 Sep 2006 13:56:11 -0700
Subject: [PARISC] remove halftick and copy clocktick to local var (gcc can
 optimize usage)

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/time.c | 46 +++++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 15 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index fd425e1abe66..c43e847a4b8f 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -33,7 +33,6 @@
 #include <linux/timex.h>
 
 static unsigned long clocktick __read_mostly;	/* timer cycles per tick */
-static unsigned long halftick __read_mostly;
 
 #ifdef CONFIG_SMP
 extern void smp_do_timer(struct pt_regs *regs);
@@ -48,6 +47,9 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	unsigned long ticks_elapsed = 1;	/* at least one elapsed */
 	int cpu = smp_processor_id();
 
+	/* gcc can optimize for "read-only" case with a local clocktick */
+	unsigned long local_ct = clocktick;
+
 	profile_tick(CPU_PROFILING, regs);
 
 	/* Initialize next_tick to the expected tick time. */
@@ -74,8 +76,16 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		cycles_elapsed = ~cycles_elapsed;   /* off by one cycle - don't care */
 	}
 
-	ticks_elapsed += cycles_elapsed / clocktick;
-	cycles_remainder = cycles_elapsed % clocktick;
+	if (likely(cycles_elapsed < local_ct)) {
+		/* ticks_elapsed = 1 -- We already assumed one tick elapsed. */
+		cycles_remainder = cycles_elapsed;
+	} else {
+		/* more than one tick elapsed. Do "expensive" math. */
+		ticks_elapsed += cycles_elapsed / local_ct;
+
+		/* Faster version of "remainder = elapsed % clocktick" */
+		cycles_remainder = cycles_elapsed - (ticks_elapsed * local_ct);
+	}
 
 	/* Can we differentiate between "early CR16" (aka Scenario 1) and
 	 * "long delay" (aka Scenario 3)? I don't think so.
@@ -86,14 +96,12 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	 */
 	if (ticks_elapsed > HZ) {
 		/* Scenario 3: very long delay?  bad in any case */
-		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed! run ntpdate"
+		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
 			" ticks %ld cycles %lX rem %lX"
 			" next/now %lX/%lX\n",
 			cpu,
 			ticks_elapsed, cycles_elapsed, cycles_remainder,
 			next_tick, now );
-
-		ticks_elapsed = 1;	/* hack to limit damage in loop below */
 	}
 
 
@@ -101,12 +109,19 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	 * We want IT to fire modulo clocktick even if we miss/skip some.
 	 * But those interrupts don't in fact get delivered that regularly.
 	 */
-	next_tick = now + (clocktick - cycles_remainder);
+	next_tick = now + (local_ct - cycles_remainder);
+
+	/* Skip one clocktick on purpose if we are likely to miss next_tick.
+	 * We'll catch what we missed on the tick after that.
+	 * We should never need 0x1000 cycles to read CR16, calc the
+	 * new next_tick, then write CR16 back. */
+	if (!((local_ct - cycles_remainder) >> 12))
+		next_tick += local_ct;
 
 	/* Program the IT when to deliver the next interrupt. */
         /* Only bottom 32-bits of next_tick are written to cr16.  */
-	mtctl(next_tick, 16);
 	cpu_data[cpu].it_value = next_tick;
+	mtctl(next_tick, 16);
 
 	/* Now that we are done mucking with unreliable delivery of interrupts,
 	 * go do system house keeping.
@@ -169,35 +184,37 @@ gettimeoffset (void)
 	unsigned long next_tick;
 	unsigned long elapsed_cycles;
 	unsigned long usec;
+	unsigned long cpuid = smp_processor_id();
+	unsigned long local_ct = clocktick;
 
-	next_tick = cpu_data[smp_processor_id()].it_value;
+	next_tick = cpu_data[cpuid].it_value;
 	now = mfctl(16);	/* Read the hardware interval timer.  */
 
-	prev_tick = next_tick - clocktick;
+	prev_tick = next_tick - local_ct;
 
 	/* Assume Scenario 1: "now" is later than prev_tick.  */
 	elapsed_cycles = now - prev_tick;
 
 	if (now < prev_tick) {
 		/* Scenario 2: CR16 wrapped!
-		 * 1's complement is close enough.
+		 * ones complement is off-by-one. Don't care.
 		 */
 		elapsed_cycles = ~elapsed_cycles;
 	}
 
-	if (elapsed_cycles > (HZ * clocktick)) {
+	if (elapsed_cycles > (HZ * local_ct)) {
 		/* Scenario 3: clock ticks are missing. */
 		printk (KERN_CRIT "gettimeoffset(CPU %d): missing ticks!"
 			"cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
 			cpuid,
-			elapsed_cycles, prev_tick, now, next_tick, clocktick);
+			 elapsed_cycles, prev_tick, now, next_tick, local_ct);
 	}
 
 	/* FIXME: Can we improve the precision? Not with PAGE0. */
 	usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
 
 	/* add in "lost" jiffies */
-	usec += clocktick * (jiffies - wall_jiffies);
+	usec += local_ct * (jiffies - wall_jiffies);
 	return usec;
 #else
 	return 0;
@@ -290,7 +307,6 @@ void __init time_init(void)
 	static struct pdc_tod tod_data;
 
 	clocktick = (100 * PAGE0->mem_10msec) / HZ;
-	halftick = clocktick / 2;
 
 	start_cpu_itimer();	/* get CPU 0 started */
 
-- 
cgit v1.2.3


From 6e5dc42b5add25c94ce0e95da87122f91b4bfdb3 Mon Sep 17 00:00:00 2001
From: Grant Grundler <grundler@gsyprf11.external.hp.com>
Date: Sun, 10 Sep 2006 12:57:55 -0700
Subject: [PARISC] Further updates to timer_interrupt()

This version (relative to the current tree):
o eliminates "while (ticks_elapsed)" loop. It's not needed.
o drop "ticks_elapsed" completely from timer_interrupt().
o Estimates elapsed cycles (based on HZ) to see which kind of
  math we want to use to calculate "cycles_remainder".
o Fixes a bug where we would loose a tick if we decided
  we wanted to skip one interrupt.

Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/time.c | 127 ++++++++++++++++++++++++----------------------
 1 file changed, 65 insertions(+), 62 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index c43e847a4b8f..9d642d820fe9 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -43,12 +43,11 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	unsigned long now;
 	unsigned long next_tick;
 	unsigned long cycles_elapsed;
-        unsigned long cycles_remainder;
-	unsigned long ticks_elapsed = 1;	/* at least one elapsed */
-	int cpu = smp_processor_id();
+	unsigned long cycles_remainder;
+	unsigned int cpu = smp_processor_id();
 
 	/* gcc can optimize for "read-only" case with a local clocktick */
-	unsigned long local_ct = clocktick;
+	unsigned long cpt = clocktick;
 
 	profile_tick(CPU_PROFILING, regs);
 
@@ -63,28 +62,16 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	cycles_elapsed = now - next_tick;
 
-	/* Determine how much time elapsed.  */
-	if (now < next_tick) {
-		/* Scenario 2: CR16 wrapped after clock tick.
-		 * 1's complement will give us the "elapse cycles".
-		 *
-		 * This "cr16 wrapped" cruft is primarily for 32-bit kernels.
-		 * So think "unsigned long is u32" when reading the code.
-		 * And yes, of course 64-bit will someday wrap, but only
-	  	 * every 198841 days on a 1GHz machine.
+	if ((cycles_elapsed >> 5) < cpt) {
+		/* use "cheap" math (add/subtract) instead
+		 * of the more expensive div/mul method
 		 */
-		cycles_elapsed = ~cycles_elapsed;   /* off by one cycle - don't care */
-	}
-
-	if (likely(cycles_elapsed < local_ct)) {
-		/* ticks_elapsed = 1 -- We already assumed one tick elapsed. */
 		cycles_remainder = cycles_elapsed;
+		while (cycles_remainder > cpt) {
+			cycles_remainder -= cpt;
+		}
 	} else {
-		/* more than one tick elapsed. Do "expensive" math. */
-		ticks_elapsed += cycles_elapsed / local_ct;
-
-		/* Faster version of "remainder = elapsed % clocktick" */
-		cycles_remainder = cycles_elapsed - (ticks_elapsed * local_ct);
+		cycles_remainder = cycles_elapsed % cpt;
 	}
 
 	/* Can we differentiate between "early CR16" (aka Scenario 1) and
@@ -94,51 +81,65 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	 * cycles after the IT fires. But it's arbitrary how much time passes
 	 * before we call it "late". I've picked one second.
 	 */
-	if (ticks_elapsed > HZ) {
+/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
+#if HZ == 1000
+	if (cycles_elapsed > (cpt << 10) )
+#elif HZ == 250
+	if (cycles_elapsed > (cpt << 8) )
+#elif HZ == 100
+	if (cycles_elapsed > (cpt << 7) )
+#else
+#warn WTF is HZ set to anyway?
+	if (cycles_elapsed > (HZ * cpt) )
+#endif
+	{
 		/* Scenario 3: very long delay?  bad in any case */
 		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
-			" ticks %ld cycles %lX rem %lX"
+			" cycles %lX rem %lX "
 			" next/now %lX/%lX\n",
 			cpu,
-			ticks_elapsed, cycles_elapsed, cycles_remainder,
+			cycles_elapsed, cycles_remainder,
 			next_tick, now );
 	}
 
+	/* convert from "division remainder" to "remainder of clock tick" */
+	cycles_remainder = cpt - cycles_remainder;
 
 	/* Determine when (in CR16 cycles) next IT interrupt will fire.
 	 * We want IT to fire modulo clocktick even if we miss/skip some.
 	 * But those interrupts don't in fact get delivered that regularly.
 	 */
-	next_tick = now + (local_ct - cycles_remainder);
+	next_tick = now + cycles_remainder;
+
+	cpu_data[cpu].it_value = next_tick;
 
 	/* Skip one clocktick on purpose if we are likely to miss next_tick.
-	 * We'll catch what we missed on the tick after that.
-	 * We should never need 0x1000 cycles to read CR16, calc the
-	 * new next_tick, then write CR16 back. */
-	if (!((local_ct - cycles_remainder) >> 12))
-		next_tick += local_ct;
+	 * We want to avoid the new next_tick being less than CR16.
+	 * If that happened, itimer wouldn't fire until CR16 wrapped.
+	 * We'll catch the tick we missed on the tick after that.
+	 */
+	if (!(cycles_remainder >> 13))
+		next_tick += cpt;
 
 	/* Program the IT when to deliver the next interrupt. */
         /* Only bottom 32-bits of next_tick are written to cr16.  */
-	cpu_data[cpu].it_value = next_tick;
 	mtctl(next_tick, 16);
 
-	/* Now that we are done mucking with unreliable delivery of interrupts,
-	 * go do system house keeping.
+
+	/* Done mucking with unreliable delivery of interrupts.
+	 * Go do system house keeping.
 	 */
-	while (ticks_elapsed--) {
 #ifdef CONFIG_SMP
-		smp_do_timer(regs);
+	smp_do_timer(regs);
 #else
-		update_process_times(user_mode(regs));
+	update_process_times(user_mode(regs));
 #endif
-		if (cpu == 0) {
-			write_seqlock(&xtime_lock);
-			do_timer(1);
-			write_sequnlock(&xtime_lock);
-		}
+	if (cpu == 0) {
+		write_seqlock(&xtime_lock);
+		do_timer(regs);
+		write_sequnlock(&xtime_lock);
 	}
-    
+
 	/* check soft power switch status */
 	if (cpu == 0 && !atomic_read(&power_tasklet.count))
 		tasklet_schedule(&power_tasklet);
@@ -164,14 +165,12 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 
 
-/*** converted from ia64 ***/
 /*
  * Return the number of micro-seconds that elapsed since the last
  * update to wall time (aka xtime).  The xtime_lock
  * must be at least read-locked when calling this routine.
  */
-static inline unsigned long
-gettimeoffset (void)
+static inline unsigned long gettimeoffset (void)
 {
 #ifndef CONFIG_SMP
 	/*
@@ -185,36 +184,40 @@ gettimeoffset (void)
 	unsigned long elapsed_cycles;
 	unsigned long usec;
 	unsigned long cpuid = smp_processor_id();
-	unsigned long local_ct = clocktick;
+	unsigned long cpt = clocktick;
 
 	next_tick = cpu_data[cpuid].it_value;
 	now = mfctl(16);	/* Read the hardware interval timer.  */
 
-	prev_tick = next_tick - local_ct;
+	prev_tick = next_tick - cpt;
 
 	/* Assume Scenario 1: "now" is later than prev_tick.  */
 	elapsed_cycles = now - prev_tick;
 
-	if (now < prev_tick) {
-		/* Scenario 2: CR16 wrapped!
-		 * ones complement is off-by-one. Don't care.
-		 */
-		elapsed_cycles = ~elapsed_cycles;
-	}
-
-	if (elapsed_cycles > (HZ * local_ct)) {
+/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
+#if HZ == 1000
+	if (elapsed_cycles > (cpt << 10) )
+#elif HZ == 250
+	if (elapsed_cycles > (cpt << 8) )
+#elif HZ == 100
+	if (elapsed_cycles > (cpt << 7) )
+#else
+#warn WTF is HZ set to anyway?
+	if (elapsed_cycles > (HZ * cpt) )
+#endif
+	{
 		/* Scenario 3: clock ticks are missing. */
-		printk (KERN_CRIT "gettimeoffset(CPU %d): missing ticks!"
-			"cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
-			cpuid,
-			 elapsed_cycles, prev_tick, now, next_tick, local_ct);
+		printk (KERN_CRIT "gettimeoffset(CPU %ld): missing %ld ticks!"
+			" cycles %lX prev/now/next %lX/%lX/%lX  clock %lX\n",
+			cpuid, elapsed_cycles / cpt,
+			elapsed_cycles, prev_tick, now, next_tick, cpt);
 	}
 
 	/* FIXME: Can we improve the precision? Not with PAGE0. */
 	usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
 
 	/* add in "lost" jiffies */
-	usec += local_ct * (jiffies - wall_jiffies);
+	usec += cpt * (jiffies - wall_jiffies);
 	return usec;
 #else
 	return 0;
-- 
cgit v1.2.3


From 7085689ed135f94108e46c372015c6f5cd3372a3 Mon Sep 17 00:00:00 2001
From: James Bottomley <jejb@parisc-linux.org>
Date: Sat, 9 Sep 2006 12:36:25 -0700
Subject: [PARISC] Allow nested interrupts

Our prior mode of operation didn't allow nested interrupts
because it makes the interrupt code much simpler.  However,
nested interrupts are better for latency.

This code uses the EIEM register to simulate level interrupts
and thus achieve nesting.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/irq.c | 149 +++++++++++++++++++++++++++--------------------
 arch/parisc/kernel/smp.c |   3 +
 drivers/parisc/iosapic.c |   3 +-
 include/asm-parisc/irq.h |   2 +
 4 files changed, 93 insertions(+), 64 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index c53bfeb4bf94..9bdd0197ceb7 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -45,6 +45,17 @@ extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
 */
 static volatile unsigned long cpu_eiem = 0;
 
+/*
+** ack bitmap ... habitually set to 1, but reset to zero
+** between ->ack() and ->end() of the interrupt to prevent
+** re-interruption of a processing interrupt.
+*/
+static volatile unsigned long global_ack_eiem = ~0UL;
+/*
+** Local bitmap, same as above but for per-cpu interrupts
+*/
+static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
+
 static void cpu_disable_irq(unsigned int irq)
 {
 	unsigned long eirr_bit = EIEM_MASK(irq);
@@ -62,13 +73,6 @@ static void cpu_enable_irq(unsigned int irq)
 
 	cpu_eiem |= eirr_bit;
 
-	/* FIXME: while our interrupts aren't nested, we cannot reset
-	 * the eiem mask if we're already in an interrupt.  Once we
-	 * implement nested interrupts, this can go away
-	 */
-	if (!in_interrupt())
-		set_eiem(cpu_eiem);
-
 	/* This is just a simple NOP IPI.  But what it does is cause
 	 * all the other CPUs to do a set_eiem(cpu_eiem) at the end
 	 * of the interrupt handler */
@@ -84,13 +88,45 @@ static unsigned int cpu_startup_irq(unsigned int irq)
 void no_ack_irq(unsigned int irq) { }
 void no_end_irq(unsigned int irq) { }
 
+void cpu_ack_irq(unsigned int irq)
+{
+	unsigned long mask = EIEM_MASK(irq);
+	int cpu = smp_processor_id();
+
+	/* Clear in EIEM so we can no longer process */
+	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+		per_cpu(local_ack_eiem, cpu) &= ~mask;
+	else
+		global_ack_eiem &= ~mask;
+
+	/* disable the interrupt */
+	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+	/* and now ack it */
+	mtctl(mask, 23);
+}
+
+void cpu_end_irq(unsigned int irq)
+{
+	unsigned long mask = EIEM_MASK(irq);
+	int cpu = smp_processor_id();
+
+	/* set it in the eiems---it's no longer in process */
+	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+		per_cpu(local_ack_eiem, cpu) |= mask;
+	else
+		global_ack_eiem |= mask;
+
+	/* enable the interrupt */
+	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+}
+
 #ifdef CONFIG_SMP
 int cpu_check_affinity(unsigned int irq, cpumask_t *dest)
 {
 	int cpu_dest;
 
 	/* timer and ipi have to always be received on all CPUs */
-	if (irq == TIMER_IRQ || irq == IPI_IRQ) {
+	if (CHECK_IRQ_PER_CPU(irq)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
 		irq_desc[irq].affinity = CPU_MASK_ALL;
@@ -119,8 +155,8 @@ static struct hw_interrupt_type cpu_interrupt_type = {
 	.shutdown	= cpu_disable_irq,
 	.enable		= cpu_enable_irq,
 	.disable	= cpu_disable_irq,
-	.ack		= no_ack_irq,
-	.end		= no_end_irq,
+	.ack		= cpu_ack_irq,
+	.end		= cpu_end_irq,
 #ifdef CONFIG_SMP
 	.set_affinity	= cpu_set_affinity_irq,
 #endif
@@ -298,82 +334,69 @@ unsigned int txn_alloc_data(unsigned int virt_irq)
 	return virt_irq - CPU_IRQ_BASE;
 }
 
+static inline int eirr_to_irq(unsigned long eirr)
+{
+#ifdef CONFIG_64BIT
+	int bit = fls64(eirr);
+#else
+	int bit = fls(eirr);
+#endif
+	return (BITS_PER_LONG - bit) + TIMER_IRQ;
+}
+
 /* ONLY called from entry.S:intr_extint() */
 void do_cpu_irq_mask(struct pt_regs *regs)
 {
 	unsigned long eirr_val;
-
-	irq_enter();
-
-	/*
-	 * Don't allow TIMER or IPI nested interrupts.
-	 * Allowing any single interrupt to nest can lead to that CPU
-	 * handling interrupts with all enabled interrupts unmasked.
-	 */
-	set_eiem(0UL);
-
-	/* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
-	 * 2) We loop here on EIRR contents in order to avoid
-	 *    nested interrupts or having to take another interrupt
-	 *    when we could have just handled it right away.
-	 */
-	for (;;) {
-		unsigned long bit = (1UL << (BITS_PER_LONG - 1));
-		unsigned int irq;
-		eirr_val = mfctl(23) & cpu_eiem;
-		if (!eirr_val)
-			break;
-
-		mtctl(eirr_val, 23); /* reset bits we are going to process */
-
-		/* Work our way from MSb to LSb...same order we alloc EIRs */
-		for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
+	int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
-			cpumask_t dest = irq_desc[irq].affinity;
+	cpumask_t dest;
 #endif
-			if (!(bit & eirr_val))
-				continue;
 
-			/* clear bit in mask - can exit loop sooner */
-			eirr_val &= ~bit;
+	local_irq_disable();
+	irq_enter();
 
-#ifdef CONFIG_SMP
-			/* FIXME: because generic set affinity mucks
-			 * with the affinity before sending it to us
-			 * we can get the situation where the affinity is
-			 * wrong for our CPU type interrupts */
-			if (irq != TIMER_IRQ && irq != IPI_IRQ &&
-			    !cpu_isset(smp_processor_id(), dest)) {
-				int cpu = first_cpu(dest);
-
-				printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
-				       irq, smp_processor_id(), cpu);
-				gsc_writel(irq + CPU_IRQ_BASE,
-					   cpu_data[cpu].hpa);
-				continue;
-			}
-#endif
+	eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem &
+		per_cpu(local_ack_eiem, cpu);
+	if (!eirr_val)
+		goto set_out;
+	irq = eirr_to_irq(eirr_val);
 
-			__do_IRQ(irq, regs);
-		}
+#ifdef CONFIG_SMP
+	dest = irq_desc[irq].affinity;
+	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
+	    !cpu_isset(smp_processor_id(), dest)) {
+		int cpu = first_cpu(dest);
+
+		printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
+		       irq, smp_processor_id(), cpu);
+		gsc_writel(irq + CPU_IRQ_BASE,
+			   cpu_data[cpu].hpa);
+		goto set_out;
 	}
+#endif
+	__do_IRQ(irq, regs);
 
-	set_eiem(cpu_eiem);	/* restore original mask */
+ out:
 	irq_exit();
-}
+	return;
 
+ set_out:
+	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+	goto out;
+}
 
 static struct irqaction timer_action = {
 	.handler = timer_interrupt,
 	.name = "timer",
-	.flags = IRQF_DISABLED,
+	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU,
 };
 
 #ifdef CONFIG_SMP
 static struct irqaction ipi_action = {
 	.handler = ipi_interrupt,
 	.name = "IPI",
-	.flags = IRQF_DISABLED,
+	.flags = IRQF_DISABLED | IRQF_PERCPU,
 };
 #endif
 
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index f33e8de438dc..faad338f310e 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -262,6 +262,9 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 					this_cpu, which);
 				return IRQ_NONE;
 			} /* Switch */
+		/* let in any pending interrupts */
+		local_irq_enable();
+		local_irq_disable();
 		} /* while (ops) */
 	}
 	return IRQ_HANDLED;
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 1fbda77cefc2..90489ade632e 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -692,6 +692,7 @@ static void iosapic_end_irq(unsigned int irq)
 	DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
 			vi->eoi_addr, vi->eoi_data);
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
+	cpu_end_irq(irq);
 }
 
 static unsigned int iosapic_startup_irq(unsigned int irq)
@@ -728,7 +729,7 @@ static struct hw_interrupt_type iosapic_interrupt_type = {
 	.shutdown =	iosapic_disable_irq,
 	.enable =	iosapic_enable_irq,
 	.disable =	iosapic_disable_irq,
-	.ack =		no_ack_irq,
+	.ack =		cpu_ack_irq,
 	.end =		iosapic_end_irq,
 #ifdef CONFIG_SMP
 	.set_affinity =	iosapic_set_affinity_irq,
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index 6e29cfa2812d..399c81981ed5 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -39,6 +39,8 @@ struct irq_chip;
  */
 void no_ack_irq(unsigned int irq);
 void no_end_irq(unsigned int irq);
+void cpu_ack_irq(unsigned int irq);
+void cpu_end_irq(unsigned int irq);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
-- 
cgit v1.2.3


From 8a63674f70ac443d166b746d6c04154f8ee9de7b Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Tue, 12 Sep 2006 05:17:59 -0600
Subject: [PARISC] Add hardware found in the rp8400

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/hardware.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'arch')

diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 3058bffd8a2c..18ba4cb9159b 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -231,6 +231,7 @@ static struct hp_hardware hp_hardware_list[] __initdata = {
 	{HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"},
 	{HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
 	{HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"},
+	{HPHW_NPROC,0x5EB,0x4,0x91,"Perf/Leone 875 W2+"},
 	{HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
 	{HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
 	{HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
@@ -584,8 +585,10 @@ static struct hp_hardware hp_hardware_list[] __initdata = {
 	{HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, 
 	{HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, 
 	{HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, 
+	{HPHW_FABRIC, 0x005, 0x000AA, 0x80, "Keystone DNA Central Agent"},
 	{HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"}, 
 	{HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, 
+	{HPHW_FABRIC, 0x005, 0x000AB, 0x00, "Keystone TOGO Fabric Crossbar"},
 	{HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, 
 	{HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, 
 	{HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"}, 
-- 
cgit v1.2.3


From 01232e932988fcf6ad87be49f69e633dd652a46d Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Tue, 19 Sep 2006 16:37:01 -0600
Subject: [PARISC] Fix iounmap compile warning

iounmap's argument needs to be both const and volatile, otherwise we'll
get warnings that we're discarding pointer qualifiers

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/mm/ioremap.c | 2 +-
 include/asm-parisc/io.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 27384567a1d0..47a1d2ac9419 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -188,7 +188,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
 }
 EXPORT_SYMBOL(__ioremap);
 
-void iounmap(void __iomem *addr)
+void iounmap(const volatile void __iomem *addr)
 {
 	if (addr > high_memory)
 		return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index b9eb245b8874..c1963ce19dd2 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -134,7 +134,7 @@ extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 }
 #define ioremap_nocache(off, sz)	ioremap((off), (sz))
 
-extern void iounmap(void __iomem *addr);
+extern void iounmap(const volatile void __iomem *addr);
 
 static inline unsigned char __raw_readb(const volatile void __iomem *addr)
 {
-- 
cgit v1.2.3


From 32f468139209459c3293a0895cf5b8e66ccc30a5 Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Tue, 19 Sep 2006 16:44:38 -0600
Subject: [PARISC] Fix HPUX compat compile with current GCC

GCC no longer allows a cast as lvalue; fix the same way fs/readdir.c was

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/hpux/fs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'arch')

diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index 6e79dbf3f6bd..2d58b92b57e3 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -96,7 +96,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
 	put_user(namlen, &dirent->d_namlen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void __user *)dirent + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
-- 
cgit v1.2.3


From d207ac0f7c9736782bfa51cff2109b74d26c3622 Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Tue, 19 Sep 2006 19:32:42 -0600
Subject: [PARISC] Fix CONFIG_DEBUG_SPINLOCK

Joel Soete points out that we refer to pa_tlb_lock but only define it if
CONFIG_SMP which breaks a uniprocessor build with CONFIG_DEBUG_SPINLOCK
enabled.  No module refers to pa_tlb_lock, so we can delete the export.

Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/cache.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 7e8d697aef36..e91c2be7236a 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -35,15 +35,12 @@ int icache_stride __read_mostly;
 EXPORT_SYMBOL(dcache_stride);
 
 
-#if defined(CONFIG_SMP)
 /* 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
  * by software.  We put a spinlock around all TLB flushes  to
  * ensure this.
  */
 DEFINE_SPINLOCK(pa_tlb_lock);
-EXPORT_SYMBOL(pa_tlb_lock);
-#endif
 
 struct pdc_cache_info cache_info __read_mostly;
 #ifndef CONFIG_PA20
-- 
cgit v1.2.3


From 8d0b7d1055bedca784b143b0af9b37bd971b7cd2 Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <matthew@wil.cx>
Date: Wed, 20 Sep 2006 21:44:09 -0600
Subject: [PARISC] Export clear_user_page to modules

Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/cache.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index e91c2be7236a..0be51e92a2fc 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -372,8 +372,7 @@ void parisc_setup_cache_timing(void)
 extern void purge_kernel_dcache_page(unsigned long);
 extern void clear_user_page_asm(void *page, unsigned long vaddr);
 
-void
-clear_user_page(void *page, unsigned long vaddr, struct page *pg)
+void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
 	purge_kernel_dcache_page((unsigned long)page);
 	purge_tlb_start();
@@ -381,6 +380,7 @@ clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 	purge_tlb_end();
 	clear_user_page_asm(page, vaddr);
 }
+EXPORT_SYMBOL(clear_user_page);
 
 void flush_kernel_dcache_page_addr(void *addr)
 {
-- 
cgit v1.2.3


From 22fced881122f7fc6f5f259dca03ac6d5c601404 Mon Sep 17 00:00:00 2001
From: Helge Deller <deller@parisc-linux.org>
Date: Sat, 30 Sep 2006 15:45:58 +0200
Subject: [PARISC] Honour "panic_on_oops" sysctl

Signed-off-by: Helge Deller <deller@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/traps.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'arch')

diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 77b28cb8aca6..65cd6ca32fed 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/timer.h>
+#include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/smp.h>
@@ -245,6 +246,15 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
 		current->comm, current->pid, str, err);
 	show_regs(regs);
 
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops) {
+		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+		ssleep(5);
+		panic("Fatal exception");
+	}
+
 	/* Wot's wrong wif bein' racy? */
 	if (current->thread.flags & PARISC_KERNEL_DEATH) {
 		printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
-- 
cgit v1.2.3


From 5f024a251f0b3b179bbc8fc62f3a650e49359db5 Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@osdl.org>
Date: Sun, 1 Oct 2006 16:17:13 -0400
Subject: [PARISC] Kill wall_jiffies use

wall_jiffies and jiffies are now equal, so this is a noop...

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
---
 arch/parisc/kernel/time.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'arch')

diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 9d642d820fe9..b3496b592a2d 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -215,9 +215,6 @@ static inline unsigned long gettimeoffset (void)
 
 	/* FIXME: Can we improve the precision? Not with PAGE0. */
 	usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec;
-
-	/* add in "lost" jiffies */
-	usec += cpt * (jiffies - wall_jiffies);
 	return usec;
 #else
 	return 0;
-- 
cgit v1.2.3