diff options
Diffstat (limited to 'arch/mips/kernel/smtc.c')
| -rw-r--r-- | arch/mips/kernel/smtc.c | 76 | 
1 files changed, 68 insertions, 8 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 15b5f3cfd20..1d47843d3cc 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS];  static struct smtc_ipi_q freeIPIq; +/* + * Number of FPU contexts for each VPE + */ + +static int smtc_nconf1[MAX_SMTC_VPES]; + +  /* Forward declarations */  void ipi_decode(struct smtc_ipi *); @@ -174,9 +181,9 @@ static int __init tintq(char *str)  __setup("tintq=", tintq); -static int imstuckcount[2][8]; +static int imstuckcount[MAX_SMTC_VPES][8];  /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ -static int vpemask[2][8] = { +static int vpemask[MAX_SMTC_VPES][8] = {  	{0, 0, 1, 0, 0, 0, 0, 1},  	{0, 0, 0, 0, 0, 0, 0, 1}  }; @@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot)  static void smtc_tc_setup(int vpe, int tc, int cpu)  { +	static int cp1contexts[MAX_SMTC_VPES]; + +	/* +	 * Make a local copy of the available FPU contexts in order +	 * to keep track of TCs that can have one. +	 */ +	if (tc == 1) +	{ +		/* +		 * FIXME: Multi-core SMTC hasn't been tested and the +		 *        maximum number of VPEs may change. +		 */ +		cp1contexts[0] = smtc_nconf1[0] - 1; +		cp1contexts[1] = smtc_nconf1[1]; +	} +  	settc(tc);  	write_tc_c0_tchalt(TCHALT_H);  	mips_ihb(); @@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)  	 * an active IPI queue.  	 */  	write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); -	/* Bind tc to vpe */ + +	/* Bind TC to VPE. */  	write_tc_c0_tcbind(vpe); +  	/* In general, all TCs should have the same cpu_data indications. */  	memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); -	/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */ -	if (cpu_data[0].cputype == CPU_34K || -	    cpu_data[0].cputype == CPU_1004K) + +	/* Check to see if there is a FPU context available for this TC. */ +	if (!cp1contexts[vpe])  		cpu_data[cpu].options &= ~MIPS_CPU_FPU; +	else +		cp1contexts[vpe]--; + +	/* Store the TC and VPE into the cpu_data structure. */  	cpu_data[cpu].vpe_id = vpe;  	cpu_data[cpu].tc_id = tc; -	/* Multi-core SMTC hasn't been tested, but be prepared */ + +	/* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */  	cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;  }  /* - * Tweak to get Count registes in as close a sync as possible.  The + * Tweak to get Count registers synced as closely as possible. The   * value seems good for 34K-class cores.   */ @@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus)  	smtc_configure_tlb();  	for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { +		/* Get number of CP1 contexts for each VPE. */ +		if (tc == 0) +		{ +			/* +			 * Do not call settc() for TC0 or the FPU context +			 * value will be incorrect. Besides, we know that +			 * we are TC0 anyway. +			 */ +			smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & +				VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); +			if (nvpe == 2) +			{ +				settc(1); +				smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & +					VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); +				settc(0); +			} +		}  		if (tcpervpe[vpe] == 0)  			continue;  		if (vpe != 0) @@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus)  			 */  			if (tc != 0) {  				smtc_tc_setup(vpe, tc, cpu); +				if (vpe != 0) { +					/* +					 * Set MVP bit (possibly again).  Do it +					 * here to catch CPUs that have no TCs +					 * bound to the VPE at reset.  In that +					 * case, a TC must be bound to the VPE +					 * before we can set VPEControl[MVP] +					 */ +					write_vpe_c0_vpeconf0( +						read_vpe_c0_vpeconf0() | +						VPECONF0_MVP); +				}  				cpu++;  			}  			printk(" %d", tc);  |