
commit f0a6c68f69981214cb7858738dd2bc81475111f7 upstream. Fix the discrepancy between the two places we check for the CP0 counter erratum in along with the incorrect comparison of the R4400 revision number against 0x30 which matches none and consistently consider all R4000 and R4400 processors affected, as documented in processor errata publications[1][2][3], following the mapping between CP0 PRId register values and processor models: PRId | Processor Model ---------+-------------------- 00000422 | R4000 Revision 2.2 00000430 | R4000 Revision 3.0 00000440 | R4400 Revision 1.0 00000450 | R4400 Revision 2.0 00000460 | R4400 Revision 3.0 No other revision of either processor has ever been spotted. Contrary to what has been stated in commitce202cbb9e
("[MIPS] Assume R4000/R4400 newer than 3.0 don't have the mfc0 count bug") marking the CP0 counter as buggy does not preclude it from being used as either a clock event or a clock source device. It just cannot be used as both at a time, because in that case clock event interrupts will be occasionally lost, and the use as a clock event device takes precedence. Compare against 0x4ff in `can_use_mips_counter' so that a single machine instruction is produced. References: [1] "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", MIPS Technologies Inc., May 10, 1994, Erratum 53, p.13 [2] "MIPS R4400PC/SC Errata, Processor Revision 1.0", MIPS Technologies Inc., February 9, 1994, Erratum 21, p.4 [3] "MIPS R4400PC/SC Errata, Processor Revision 2.0 & 3.0", MIPS Technologies Inc., January 24, 1995, Erratum 14, p.3 Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk> Fixes:ce202cbb9e
("[MIPS] Assume R4000/R4400 newer than 3.0 don't have the mfc0 count bug") Cc: stable@vger.kernel.org # v2.6.24+ Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
104 lines
3.0 KiB
C
104 lines
3.0 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 1998, 1999, 2003 by Ralf Baechle
|
|
* Copyright (C) 2014 by Maciej W. Rozycki
|
|
*/
|
|
#ifndef _ASM_TIMEX_H
|
|
#define _ASM_TIMEX_H
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#include <asm/cpu.h>
|
|
#include <asm/cpu-features.h>
|
|
#include <asm/mipsregs.h>
|
|
#include <asm/cpu-type.h>
|
|
|
|
/*
|
|
* This is the clock rate of the i8253 PIT. A MIPS system may not have
|
|
* a PIT by the symbol is used all over the kernel including some APIs.
|
|
* So keeping it defined to the number for the PIT is the only sane thing
|
|
* for now.
|
|
*/
|
|
#define CLOCK_TICK_RATE 1193182
|
|
|
|
/*
|
|
* Standard way to access the cycle counter.
|
|
* Currently only used on SMP for scheduling.
|
|
*
|
|
* Only the low 32 bits are available as a continuously counting entity.
|
|
* But this only means we'll force a reschedule every 8 seconds or so,
|
|
* which isn't an evil thing.
|
|
*
|
|
* We know that all SMP capable CPUs have cycle counters.
|
|
*/
|
|
|
|
typedef unsigned int cycles_t;
|
|
|
|
/*
|
|
* On R4000/R4400 an erratum exists such that if the cycle counter is
|
|
* read in the exact moment that it is matching the compare register,
|
|
* no interrupt will be generated.
|
|
*
|
|
* There is a suggested workaround and also the erratum can't strike if
|
|
* the compare interrupt isn't being used as the clock source device.
|
|
* However for now the implementaton of this function doesn't get these
|
|
* fine details right.
|
|
*/
|
|
static inline int can_use_mips_counter(unsigned int prid)
|
|
{
|
|
int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY;
|
|
|
|
if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter)
|
|
return 0;
|
|
else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r)
|
|
return 1;
|
|
else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp))
|
|
return 1;
|
|
/* Make sure we don't peek at cpu_data[0].options in the fast path! */
|
|
if (!__builtin_constant_p(cpu_has_counter))
|
|
asm volatile("" : "=m" (cpu_data[0].options));
|
|
if (likely(cpu_has_counter &&
|
|
prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15))))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static inline cycles_t get_cycles(void)
|
|
{
|
|
if (can_use_mips_counter(read_c0_prid()))
|
|
return read_c0_count();
|
|
else
|
|
return 0; /* no usable counter */
|
|
}
|
|
|
|
/*
|
|
* Like get_cycles - but where c0_count is not available we desperately
|
|
* use c0_random in an attempt to get at least a little bit of entropy.
|
|
*
|
|
* R6000 and R6000A neither have a count register nor a random register.
|
|
* That leaves no entropy source in the CPU itself.
|
|
*/
|
|
static inline unsigned long random_get_entropy(void)
|
|
{
|
|
unsigned int prid = read_c0_prid();
|
|
unsigned int imp = prid & PRID_IMP_MASK;
|
|
|
|
if (can_use_mips_counter(prid))
|
|
return read_c0_count();
|
|
else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
|
|
return read_c0_random();
|
|
else
|
|
return 0; /* no usable register */
|
|
}
|
|
#define random_get_entropy random_get_entropy
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _ASM_TIMEX_H */
|