diff options
author | Steven J. Hill <sjhill@mips.com> | 2012-04-09 11:58:39 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-07-23 08:55:53 -0400 |
commit | 889a4c7b33607bf03c04b8f2d5607fd4274f47f3 (patch) | |
tree | 5e34ba915e741e4cf346d35fd53b2f5c3f956560 /arch/mips/kernel | |
parent | 2244f1286509673c0b40fb9504a9be0b7b633aeb (diff) |
MIPS: SMTC: Support for Multi-threaded FPUs
Signed-off-by: Steven J. Hill <sjhill@mips.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3603/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 76 |
2 files changed, 71 insertions, 9 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1268392f1d27..31637d8c8738 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void) | |||
102 | 102 | ||
103 | #ifdef CONFIG_MIPS_MT_SMTC | 103 | #ifdef CONFIG_MIPS_MT_SMTC |
104 | /* Only do cpu_probe for first TC of CPU */ | 104 | /* Only do cpu_probe for first TC of CPU */ |
105 | if ((read_c0_tcbind() & TCBIND_CURTC) == 0) | 105 | if ((read_c0_tcbind() & TCBIND_CURTC) != 0) |
106 | __cpu_name[smp_processor_id()] = __cpu_name[0]; | ||
107 | else | ||
106 | #endif /* CONFIG_MIPS_MT_SMTC */ | 108 | #endif /* CONFIG_MIPS_MT_SMTC */ |
107 | cpu_probe(); | 109 | cpu_probe(); |
108 | cpu_report(); | 110 | cpu_report(); |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 15b5f3cfd20c..1d47843d3cc0 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS]; | |||
86 | static struct smtc_ipi_q freeIPIq; | 86 | static struct smtc_ipi_q freeIPIq; |
87 | 87 | ||
88 | 88 | ||
89 | /* | ||
90 | * Number of FPU contexts for each VPE | ||
91 | */ | ||
92 | |||
93 | static int smtc_nconf1[MAX_SMTC_VPES]; | ||
94 | |||
95 | |||
89 | /* Forward declarations */ | 96 | /* Forward declarations */ |
90 | 97 | ||
91 | void ipi_decode(struct smtc_ipi *); | 98 | void ipi_decode(struct smtc_ipi *); |
@@ -174,9 +181,9 @@ static int __init tintq(char *str) | |||
174 | 181 | ||
175 | __setup("tintq=", tintq); | 182 | __setup("tintq=", tintq); |
176 | 183 | ||
177 | static int imstuckcount[2][8]; | 184 | static int imstuckcount[MAX_SMTC_VPES][8]; |
178 | /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ | 185 | /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ |
179 | static int vpemask[2][8] = { | 186 | static int vpemask[MAX_SMTC_VPES][8] = { |
180 | {0, 0, 1, 0, 0, 0, 0, 1}, | 187 | {0, 0, 1, 0, 0, 0, 0, 1}, |
181 | {0, 0, 0, 0, 0, 0, 0, 1} | 188 | {0, 0, 0, 0, 0, 0, 0, 1} |
182 | }; | 189 | }; |
@@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot) | |||
331 | 338 | ||
332 | static void smtc_tc_setup(int vpe, int tc, int cpu) | 339 | static void smtc_tc_setup(int vpe, int tc, int cpu) |
333 | { | 340 | { |
341 | static int cp1contexts[MAX_SMTC_VPES]; | ||
342 | |||
343 | /* | ||
344 | * Make a local copy of the available FPU contexts in order | ||
345 | * to keep track of TCs that can have one. | ||
346 | */ | ||
347 | if (tc == 1) | ||
348 | { | ||
349 | /* | ||
350 | * FIXME: Multi-core SMTC hasn't been tested and the | ||
351 | * maximum number of VPEs may change. | ||
352 | */ | ||
353 | cp1contexts[0] = smtc_nconf1[0] - 1; | ||
354 | cp1contexts[1] = smtc_nconf1[1]; | ||
355 | } | ||
356 | |||
334 | settc(tc); | 357 | settc(tc); |
335 | write_tc_c0_tchalt(TCHALT_H); | 358 | write_tc_c0_tchalt(TCHALT_H); |
336 | mips_ihb(); | 359 | mips_ihb(); |
@@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) | |||
343 | * an active IPI queue. | 366 | * an active IPI queue. |
344 | */ | 367 | */ |
345 | write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); | 368 | write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); |
346 | /* Bind tc to vpe */ | 369 | |
370 | /* Bind TC to VPE. */ | ||
347 | write_tc_c0_tcbind(vpe); | 371 | write_tc_c0_tcbind(vpe); |
372 | |||
348 | /* In general, all TCs should have the same cpu_data indications. */ | 373 | /* In general, all TCs should have the same cpu_data indications. */ |
349 | memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); | 374 | memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); |
350 | /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */ | 375 | |
351 | if (cpu_data[0].cputype == CPU_34K || | 376 | /* Check to see if there is a FPU context available for this TC. */ |
352 | cpu_data[0].cputype == CPU_1004K) | 377 | if (!cp1contexts[vpe]) |
353 | cpu_data[cpu].options &= ~MIPS_CPU_FPU; | 378 | cpu_data[cpu].options &= ~MIPS_CPU_FPU; |
379 | else | ||
380 | cp1contexts[vpe]--; | ||
381 | |||
382 | /* Store the TC and VPE into the cpu_data structure. */ | ||
354 | cpu_data[cpu].vpe_id = vpe; | 383 | cpu_data[cpu].vpe_id = vpe; |
355 | cpu_data[cpu].tc_id = tc; | 384 | cpu_data[cpu].tc_id = tc; |
356 | /* Multi-core SMTC hasn't been tested, but be prepared */ | 385 | |
386 | /* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */ | ||
357 | cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; | 387 | cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; |
358 | } | 388 | } |
359 | 389 | ||
360 | /* | 390 | /* |
361 | * Tweak to get Count registes in as close a sync as possible. The | 391 | * Tweak to get Count registers synced as closely as possible. The |
362 | * value seems good for 34K-class cores. | 392 | * value seems good for 34K-class cores. |
363 | */ | 393 | */ |
364 | 394 | ||
@@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus) | |||
466 | smtc_configure_tlb(); | 496 | smtc_configure_tlb(); |
467 | 497 | ||
468 | for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { | 498 | for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { |
499 | /* Get number of CP1 contexts for each VPE. */ | ||
500 | if (tc == 0) | ||
501 | { | ||
502 | /* | ||
503 | * Do not call settc() for TC0 or the FPU context | ||
504 | * value will be incorrect. Besides, we know that | ||
505 | * we are TC0 anyway. | ||
506 | */ | ||
507 | smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & | ||
508 | VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); | ||
509 | if (nvpe == 2) | ||
510 | { | ||
511 | settc(1); | ||
512 | smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & | ||
513 | VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); | ||
514 | settc(0); | ||
515 | } | ||
516 | } | ||
469 | if (tcpervpe[vpe] == 0) | 517 | if (tcpervpe[vpe] == 0) |
470 | continue; | 518 | continue; |
471 | if (vpe != 0) | 519 | if (vpe != 0) |
@@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus) | |||
479 | */ | 527 | */ |
480 | if (tc != 0) { | 528 | if (tc != 0) { |
481 | smtc_tc_setup(vpe, tc, cpu); | 529 | smtc_tc_setup(vpe, tc, cpu); |
530 | if (vpe != 0) { | ||
531 | /* | ||
532 | * Set MVP bit (possibly again). Do it | ||
533 | * here to catch CPUs that have no TCs | ||
534 | * bound to the VPE at reset. In that | ||
535 | * case, a TC must be bound to the VPE | ||
536 | * before we can set VPEControl[MVP] | ||
537 | */ | ||
538 | write_vpe_c0_vpeconf0( | ||
539 | read_vpe_c0_vpeconf0() | | ||
540 | VPECONF0_MVP); | ||
541 | } | ||
482 | cpu++; | 542 | cpu++; |
483 | } | 543 | } |
484 | printk(" %d", tc); | 544 | printk(" %d", tc); |