66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/arch/mips/kernel/cevt-r4k.c
 | |
| +++ b/arch/mips/kernel/cevt-r4k.c
 | |
| @@ -13,6 +13,22 @@
 | |
|  #include <asm/smtc_ipi.h>
 | |
|  #include <asm/time.h>
 | |
|  
 | |
| +/*
 | |
| + * Compare interrupt can be routed and latched outside the core,
 | |
| + * so a single execution hazard barrier may not be enough to give
 | |
| + * it time to clear as seen in the Cause register.  4 time the
 | |
| + * pipeline depth seems reasonably conservative, and empirically
 | |
| + * works better in configurations with high CPU/bus clock ratios.
 | |
| + */
 | |
| +
 | |
| +#define compare_change_hazard() \
 | |
| +	do { \
 | |
| +		irq_disable_hazard(); \
 | |
| +		irq_disable_hazard(); \
 | |
| +		irq_disable_hazard(); \
 | |
| +		irq_disable_hazard(); \
 | |
| +	} while (0)
 | |
| +
 | |
|  static int mips_next_event(unsigned long delta,
 | |
|                             struct clock_event_device *evt)
 | |
|  {
 | |
| @@ -28,6 +44,7 @@ static int mips_next_event(unsigned long
 | |
|  	cnt = read_c0_count();
 | |
|  	cnt += delta;
 | |
|  	write_c0_compare(cnt);
 | |
| +	compare_change_hazard();
 | |
|  	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
 | |
|  #ifdef CONFIG_MIPS_MT_SMTC
 | |
|  	evpe(vpflags);
 | |
| @@ -187,7 +204,7 @@ static int c0_compare_int_usable(void)
 | |
|  	 */
 | |
|  	if (c0_compare_int_pending()) {
 | |
|  		write_c0_compare(read_c0_count());
 | |
| -		irq_disable_hazard();
 | |
| +		compare_change_hazard();
 | |
|  		if (c0_compare_int_pending())
 | |
|  			return 0;
 | |
|  	}
 | |
| @@ -196,7 +213,7 @@ static int c0_compare_int_usable(void)
 | |
|  		cnt = read_c0_count();
 | |
|  		cnt += delta;
 | |
|  		write_c0_compare(cnt);
 | |
| -		irq_disable_hazard();
 | |
| +		compare_change_hazard();
 | |
|  		if ((int)(read_c0_count() - cnt) < 0)
 | |
|  		    break;
 | |
|  		/* increase delta if the timer was already expired */
 | |
| @@ -205,11 +222,12 @@ static int c0_compare_int_usable(void)
 | |
|  	while ((int)(read_c0_count() - cnt) <= 0)
 | |
|  		;	/* Wait for expiry  */
 | |
|  
 | |
| +	compare_change_hazard();
 | |
|  	if (!c0_compare_int_pending())
 | |
|  		return 0;
 | |
|  
 | |
|  	write_c0_compare(read_c0_count());
 | |
| -	irq_disable_hazard();
 | |
| +	compare_change_hazard();
 | |
|  	if (c0_compare_int_pending())
 | |
|  		return 0;
 | |
|  
 |