direct-io.hg

changeset 11953: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>
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