diff options
Diffstat (limited to 'arch/mips/kernel/cevt-r4k.c')
| -rw-r--r-- | arch/mips/kernel/cevt-r4k.c | 38 | 
1 files changed, 19 insertions, 19 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 98c5a9737c1..e2d8e199be3 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -103,19 +103,10 @@ static int c0_compare_int_pending(void)  /*   * 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. + * so wait up to worst case number of cycle counter ticks for timer interrupt + * changes to propagate to the cause register.   */ - -#define compare_change_hazard() \ -	do { \ -		irq_disable_hazard(); \ -		irq_disable_hazard(); \ -		irq_disable_hazard(); \ -		irq_disable_hazard(); \ -	} while (0) +#define COMPARE_INT_SEEN_TICKS 50  int c0_compare_int_usable(void)  { @@ -126,8 +117,12 @@ int c0_compare_int_usable(void)  	 * IP7 already pending?  Try to clear it by acking the timer.  	 */  	if (c0_compare_int_pending()) { -		write_c0_compare(read_c0_count()); -		compare_change_hazard(); +		cnt = read_c0_count(); +		write_c0_compare(cnt); +		back_to_back_c0_hazard(); +		while (read_c0_count() < (cnt  + COMPARE_INT_SEEN_TICKS)) +			if (!c0_compare_int_pending()) +				break;  		if (c0_compare_int_pending())  			return 0;  	} @@ -136,7 +131,7 @@ int c0_compare_int_usable(void)  		cnt = read_c0_count();  		cnt += delta;  		write_c0_compare(cnt); -		compare_change_hazard(); +		back_to_back_c0_hazard();  		if ((int)(read_c0_count() - cnt) < 0)  		    break;  		/* increase delta if the timer was already expired */ @@ -145,12 +140,17 @@ int c0_compare_int_usable(void)  	while ((int)(read_c0_count() - cnt) <= 0)  		;	/* Wait for expiry  */ -	compare_change_hazard(); +	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS)) +		if (c0_compare_int_pending()) +			break;  	if (!c0_compare_int_pending())  		return 0; - -	write_c0_compare(read_c0_count()); -	compare_change_hazard(); +	cnt = read_c0_count(); +	write_c0_compare(cnt); +	back_to_back_c0_hazard(); +	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS)) +		if (!c0_compare_int_pending()) +			break;  	if (c0_compare_int_pending())  		return 0;  |