ia64/xen-unstable
changeset 11712:6e7cc23ab18c
[IA64] backport check_sal_cache_flush()
Backport check_sal_cache_flush() from Linux/ia64. This checks for
SAL_CACHE_FLUSH implementations that drop interrupts and calls
PAL_CACHE_FLUSH instead. This should only be necessary on hp
rx5670 systems.
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Backport check_sal_cache_flush() from Linux/ia64. This checks for
SAL_CACHE_FLUSH implementations that drop interrupts and calls
PAL_CACHE_FLUSH instead. This should only be necessary on hp
rx5670 systems.
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author | awilliam@xenbuild.aw |
---|---|
date | Mon Oct 02 21:53:07 2006 -0600 (2006-10-02) |
parents | 5727c3c4070e |
children | 5f077cd6f58c |
files | xen/arch/ia64/linux-xen/sal.c xen/include/asm-ia64/linux-xen/asm/processor.h xen/include/asm-ia64/linux/asm/sal.h |
line diff
1.1 --- a/xen/arch/ia64/linux-xen/sal.c Mon Oct 02 21:42:59 2006 -0600 1.2 +++ b/xen/arch/ia64/linux-xen/sal.c Mon Oct 02 21:53:07 2006 -0600 1.3 @@ -16,8 +16,10 @@ 1.4 1.5 #ifdef XEN 1.6 #include <linux/smp.h> 1.7 +#include <asm/hw_irq.h> 1.8 #include <xen/lib.h> 1.9 #endif 1.10 +#include <asm/delay.h> 1.11 #include <asm/page.h> 1.12 #include <asm/sal.h> 1.13 #include <asm/pal.h> 1.14 @@ -218,6 +220,77 @@ chk_nointroute_opt(void) 1.15 static void __init sal_desc_ap_wakeup(void *p) { } 1.16 #endif 1.17 1.18 +/* 1.19 + * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading 1.20 + * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as 1.21 + * "in-service" and masks other interrupts of equal or lower priority. 1.22 + * 1.23 + * HP internal defect reports: F1859, F2775, F3031. 1.24 + */ 1.25 +static int sal_cache_flush_drops_interrupts; 1.26 + 1.27 +static void __init 1.28 +check_sal_cache_flush (void) 1.29 +{ 1.30 + unsigned long flags, itv; 1.31 + int cpu; 1.32 + u64 vector; 1.33 + 1.34 + cpu = get_cpu(); 1.35 + local_irq_save(flags); 1.36 + 1.37 + /* 1.38 + * Schedule a timer interrupt, wait until it's reported, and see if 1.39 + * SAL_CACHE_FLUSH drops it. 1.40 + */ 1.41 + itv = ia64_get_itv(); 1.42 + BUG_ON((itv & (1 << 16)) == 0); 1.43 + 1.44 + ia64_set_itv(IA64_TIMER_VECTOR); 1.45 + ia64_set_itm(ia64_get_itc() + 1000); 1.46 + 1.47 + while (!ia64_get_irr(IA64_TIMER_VECTOR)) 1.48 + cpu_relax(); 1.49 + 1.50 + ia64_sal_cache_flush(3); 1.51 + 1.52 + if (ia64_get_irr(IA64_TIMER_VECTOR)) { 1.53 + vector = ia64_get_ivr(); 1.54 + ia64_eoi(); 1.55 + } else { 1.56 + sal_cache_flush_drops_interrupts = 1; 1.57 + printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; " 1.58 + "PAL_CACHE_FLUSH will be used instead\n"); 1.59 + ia64_eoi(); 1.60 + } 1.61 + 1.62 + ia64_set_itv(itv); 1.63 + local_irq_restore(flags); 1.64 + put_cpu(); 1.65 +} 1.66 + 1.67 +s64 1.68 +ia64_sal_cache_flush (u64 cache_type) 1.69 +{ 1.70 + struct ia64_sal_retval isrv; 1.71 + 1.72 + if (sal_cache_flush_drops_interrupts) { 1.73 + unsigned long flags; 1.74 + u64 progress; 1.75 + s64 rc; 1.76 + 1.77 + progress = 0; 1.78 + local_irq_save(flags); 1.79 + rc = ia64_pal_cache_flush(cache_type, 1.80 + PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL); 1.81 + local_irq_restore(flags); 1.82 + return rc; 1.83 + } 1.84 + 1.85 + SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 1.86 + return isrv.status; 1.87 +} 1.88 + 1.89 void __init 1.90 ia64_sal_init (struct ia64_sal_systab *systab) 1.91 { 1.92 @@ -271,6 +344,8 @@ ia64_sal_init (struct ia64_sal_systab *s 1.93 } 1.94 p += SAL_DESC_SIZE(*p); 1.95 } 1.96 + 1.97 + check_sal_cache_flush(); 1.98 } 1.99 1.100 int
2.1 --- a/xen/include/asm-ia64/linux-xen/asm/processor.h Mon Oct 02 21:42:59 2006 -0600 2.2 +++ b/xen/include/asm-ia64/linux-xen/asm/processor.h Mon Oct 02 21:53:07 2006 -0600 2.3 @@ -89,6 +89,7 @@ 2.4 2.5 #ifdef XEN 2.6 #include <asm/xenprocessor.h> 2.7 +#include <xen/bitops.h> 2.8 #else 2.9 /* like above but expressed as bitfields for more efficient access: */ 2.10 struct ia64_psr { 2.11 @@ -571,6 +572,23 @@ ia64_eoi (void) 2.12 2.13 #define cpu_relax() ia64_hint(ia64_hint_pause) 2.14 2.15 +static inline int 2.16 +ia64_get_irr(unsigned int vector) 2.17 +{ 2.18 + unsigned int reg = vector / 64; 2.19 + unsigned int bit = vector % 64; 2.20 + u64 irr; 2.21 + 2.22 + switch (reg) { 2.23 + case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break; 2.24 + case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break; 2.25 + case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break; 2.26 + case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break; 2.27 + } 2.28 + 2.29 + return test_bit(bit, &irr); 2.30 +} 2.31 + 2.32 static inline void 2.33 ia64_set_lrr0 (unsigned long val) 2.34 {
3.1 --- a/xen/include/asm-ia64/linux/asm/sal.h Mon Oct 02 21:42:59 2006 -0600 3.2 +++ b/xen/include/asm-ia64/linux/asm/sal.h Mon Oct 02 21:53:07 2006 -0600 3.3 @@ -657,15 +657,7 @@ ia64_sal_freq_base (unsigned long which, 3.4 return isrv.status; 3.5 } 3.6 3.7 -/* Flush all the processor and platform level instruction and/or data caches */ 3.8 -static inline s64 3.9 -ia64_sal_cache_flush (u64 cache_type) 3.10 -{ 3.11 - struct ia64_sal_retval isrv; 3.12 - SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 3.13 - return isrv.status; 3.14 -} 3.15 - 3.16 +extern s64 ia64_sal_cache_flush (u64 cache_type); 3.17 3.18 /* Initialize all the processor and platform level instruction and data caches */ 3.19 static inline s64