aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/smtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/smtc.c')
-rw-r--r--arch/mips/kernel/smtc.c146
1 files changed, 103 insertions, 43 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index f09404377ef1..a8c1a698d588 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1,5 +1,6 @@
1/* Copyright (C) 2004 Mips Technologies, Inc */ 1/* Copyright (C) 2004 Mips Technologies, Inc */
2 2
3#include <linux/clockchips.h>
3#include <linux/kernel.h> 4#include <linux/kernel.h>
4#include <linux/sched.h> 5#include <linux/sched.h>
5#include <linux/cpumask.h> 6#include <linux/cpumask.h>
@@ -62,7 +63,7 @@ asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
62 * Clock interrupt "latch" buffers, per "CPU" 63 * Clock interrupt "latch" buffers, per "CPU"
63 */ 64 */
64 65
65unsigned int ipi_timer_latch[NR_CPUS]; 66static atomic_t ipi_timer_latch[NR_CPUS];
66 67
67/* 68/*
68 * Number of InterProcessor Interupt (IPI) message buffers to allocate 69 * Number of InterProcessor Interupt (IPI) message buffers to allocate
@@ -179,7 +180,7 @@ void __init sanitize_tlb_entries(void)
179 180
180static void smtc_configure_tlb(void) 181static void smtc_configure_tlb(void)
181{ 182{
182 int i,tlbsiz,vpes; 183 int i, tlbsiz, vpes;
183 unsigned long mvpconf0; 184 unsigned long mvpconf0;
184 unsigned long config1val; 185 unsigned long config1val;
185 186
@@ -296,8 +297,10 @@ int __init mipsmt_build_cpu_map(int start_cpu_slot)
296 __cpu_number_map[i] = i; 297 __cpu_number_map[i] = i;
297 __cpu_logical_map[i] = i; 298 __cpu_logical_map[i] = i;
298 } 299 }
300#ifdef CONFIG_MIPS_MT_FPAFF
299 /* Initialize map of CPUs with FPUs */ 301 /* Initialize map of CPUs with FPUs */
300 cpus_clear(mt_fpu_cpumask); 302 cpus_clear(mt_fpu_cpumask);
303#endif
301 304
302 /* One of those TC's is the one booting, and not a secondary... */ 305 /* One of those TC's is the one booting, and not a secondary... */
303 printk("%i available secondary CPU TC(s)\n", i - 1); 306 printk("%i available secondary CPU TC(s)\n", i - 1);
@@ -359,7 +362,7 @@ void mipsmt_prepare_cpus(void)
359 IPIQ[i].head = IPIQ[i].tail = NULL; 362 IPIQ[i].head = IPIQ[i].tail = NULL;
360 spin_lock_init(&IPIQ[i].lock); 363 spin_lock_init(&IPIQ[i].lock);
361 IPIQ[i].depth = 0; 364 IPIQ[i].depth = 0;
362 ipi_timer_latch[i] = 0; 365 atomic_set(&ipi_timer_latch[i], 0);
363 } 366 }
364 367
365 /* cpu_data index starts at zero */ 368 /* cpu_data index starts at zero */
@@ -369,7 +372,7 @@ void mipsmt_prepare_cpus(void)
369 cpu++; 372 cpu++;
370 373
371 /* Report on boot-time options */ 374 /* Report on boot-time options */
372 mips_mt_set_cpuoptions (); 375 mips_mt_set_cpuoptions();
373 if (vpelimit > 0) 376 if (vpelimit > 0)
374 printk("Limit of %d VPEs set\n", vpelimit); 377 printk("Limit of %d VPEs set\n", vpelimit);
375 if (tclimit > 0) 378 if (tclimit > 0)
@@ -420,7 +423,7 @@ void mipsmt_prepare_cpus(void)
420 * code. Leave it alone! 423 * code. Leave it alone!
421 */ 424 */
422 if (tc != 0) { 425 if (tc != 0) {
423 smtc_tc_setup(vpe,tc, cpu); 426 smtc_tc_setup(vpe, tc, cpu);
424 cpu++; 427 cpu++;
425 } 428 }
426 printk(" %d", tc); 429 printk(" %d", tc);
@@ -428,7 +431,7 @@ void mipsmt_prepare_cpus(void)
428 } 431 }
429 if (slop) { 432 if (slop) {
430 if (tc != 0) { 433 if (tc != 0) {
431 smtc_tc_setup(vpe,tc, cpu); 434 smtc_tc_setup(vpe, tc, cpu);
432 cpu++; 435 cpu++;
433 } 436 }
434 printk(" %d", tc); 437 printk(" %d", tc);
@@ -482,10 +485,12 @@ void mipsmt_prepare_cpus(void)
482 485
483 /* Set up coprocessor affinity CPU mask(s) */ 486 /* Set up coprocessor affinity CPU mask(s) */
484 487
488#ifdef CONFIG_MIPS_MT_FPAFF
485 for (tc = 0; tc < ntc; tc++) { 489 for (tc = 0; tc < ntc; tc++) {
486 if (cpu_data[tc].options & MIPS_CPU_FPU) 490 if (cpu_data[tc].options & MIPS_CPU_FPU)
487 cpu_set(tc, mt_fpu_cpumask); 491 cpu_set(tc, mt_fpu_cpumask);
488 } 492 }
493#endif
489 494
490 /* set up ipi interrupts... */ 495 /* set up ipi interrupts... */
491 496
@@ -567,7 +572,7 @@ void smtc_init_secondary(void)
567 if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && 572 if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
568 ((read_c0_tcbind() & TCBIND_CURVPE) 573 ((read_c0_tcbind() & TCBIND_CURVPE)
569 != cpu_data[smp_processor_id() - 1].vpe_id)){ 574 != cpu_data[smp_processor_id() - 1].vpe_id)){
570 write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ); 575 write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
571 } 576 }
572 577
573 local_irq_enable(); 578 local_irq_enable();
@@ -606,6 +611,60 @@ int setup_irq_smtc(unsigned int irq, struct irqaction * new,
606 return setup_irq(irq, new); 611 return setup_irq(irq, new);
607} 612}
608 613
614#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
615/*
616 * Support for IRQ affinity to TCs
617 */
618
619void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity)
620{
621 /*
622 * If a "fast path" cache of quickly decodable affinity state
623 * is maintained, this is where it gets done, on a call up
624 * from the platform affinity code.
625 */
626}
627
628void smtc_forward_irq(unsigned int irq)
629{
630 int target;
631
632 /*
633 * OK wise guy, now figure out how to get the IRQ
634 * to be serviced on an authorized "CPU".
635 *
636 * Ideally, to handle the situation where an IRQ has multiple
637 * eligible CPUS, we would maintain state per IRQ that would
638 * allow a fair distribution of service requests. Since the
639 * expected use model is any-or-only-one, for simplicity
640 * and efficiency, we just pick the easiest one to find.
641 */
642
643 target = first_cpu(irq_desc[irq].affinity);
644
645 /*
646 * We depend on the platform code to have correctly processed
647 * IRQ affinity change requests to ensure that the IRQ affinity
648 * mask has been purged of bits corresponding to nonexistent and
649 * offline "CPUs", and to TCs bound to VPEs other than the VPE
650 * connected to the physical interrupt input for the interrupt
651 * in question. Otherwise we have a nasty problem with interrupt
652 * mask management. This is best handled in non-performance-critical
653 * platform IRQ affinity setting code, to minimize interrupt-time
654 * checks.
655 */
656
657 /* If no one is eligible, service locally */
658 if (target >= NR_CPUS) {
659 do_IRQ_no_affinity(irq);
660 return;
661 }
662
663 smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);
664}
665
666#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
667
609/* 668/*
610 * IPI model for SMTC is tricky, because interrupts aren't TC-specific. 669 * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
611 * Within a VPE one TC can interrupt another by different approaches. 670 * Within a VPE one TC can interrupt another by different approaches.
@@ -648,7 +707,7 @@ static void smtc_ipi_qdump(void)
648 * be done with the atomic.h primitives). And since this is 707 * be done with the atomic.h primitives). And since this is
649 * MIPS MT, we can assume that we have LL/SC. 708 * MIPS MT, we can assume that we have LL/SC.
650 */ 709 */
651static __inline__ int atomic_postincrement(unsigned int *pv) 710static inline int atomic_postincrement(atomic_t *v)
652{ 711{
653 unsigned long result; 712 unsigned long result;
654 713
@@ -659,9 +718,9 @@ static __inline__ int atomic_postincrement(unsigned int *pv)
659 " addu %1, %0, 1 \n" 718 " addu %1, %0, 1 \n"
660 " sc %1, %2 \n" 719 " sc %1, %2 \n"
661 " beqz %1, 1b \n" 720 " beqz %1, 1b \n"
662 " sync \n" 721 __WEAK_LLSC_MB
663 : "=&r" (result), "=&r" (temp), "=m" (*pv) 722 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
664 : "m" (*pv) 723 : "m" (v->counter)
665 : "memory"); 724 : "memory");
666 725
667 return result; 726 return result;
@@ -689,6 +748,8 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
689 pipi->arg = (void *)action; 748 pipi->arg = (void *)action;
690 pipi->dest = cpu; 749 pipi->dest = cpu;
691 if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { 750 if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
751 if (type == SMTC_CLOCK_TICK)
752 atomic_inc(&ipi_timer_latch[cpu]);
692 /* If not on same VPE, enqueue and send cross-VPE interupt */ 753 /* If not on same VPE, enqueue and send cross-VPE interupt */
693 smtc_ipi_nq(&IPIQ[cpu], pipi); 754 smtc_ipi_nq(&IPIQ[cpu], pipi);
694 LOCK_CORE_PRA(); 755 LOCK_CORE_PRA();
@@ -730,6 +791,8 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
730 } 791 }
731 smtc_ipi_nq(&IPIQ[cpu], pipi); 792 smtc_ipi_nq(&IPIQ[cpu], pipi);
732 } else { 793 } else {
794 if (type == SMTC_CLOCK_TICK)
795 atomic_inc(&ipi_timer_latch[cpu]);
733 post_direct_ipi(cpu, pipi); 796 post_direct_ipi(cpu, pipi);
734 write_tc_c0_tchalt(0); 797 write_tc_c0_tchalt(0);
735 UNLOCK_CORE_PRA(); 798 UNLOCK_CORE_PRA();
@@ -747,6 +810,7 @@ static void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
747 unsigned long tcrestart; 810 unsigned long tcrestart;
748 extern u32 kernelsp[NR_CPUS]; 811 extern u32 kernelsp[NR_CPUS];
749 extern void __smtc_ipi_vector(void); 812 extern void __smtc_ipi_vector(void);
813//printk("%s: on %d for %d\n", __func__, smp_processor_id(), cpu);
750 814
751 /* Extract Status, EPC from halted TC */ 815 /* Extract Status, EPC from halted TC */
752 tcstatus = read_tc_c0_tcstatus(); 816 tcstatus = read_tc_c0_tcstatus();
@@ -797,25 +861,31 @@ static void ipi_call_interrupt(void)
797 smp_call_function_interrupt(); 861 smp_call_function_interrupt();
798} 862}
799 863
864DECLARE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
865
800void ipi_decode(struct smtc_ipi *pipi) 866void ipi_decode(struct smtc_ipi *pipi)
801{ 867{
868 unsigned int cpu = smp_processor_id();
869 struct clock_event_device *cd;
802 void *arg_copy = pipi->arg; 870 void *arg_copy = pipi->arg;
803 int type_copy = pipi->type; 871 int type_copy = pipi->type;
804 int dest_copy = pipi->dest; 872 int ticks;
805 873
806 smtc_ipi_nq(&freeIPIq, pipi); 874 smtc_ipi_nq(&freeIPIq, pipi);
807 switch (type_copy) { 875 switch (type_copy) {
808 case SMTC_CLOCK_TICK: 876 case SMTC_CLOCK_TICK:
809 irq_enter(); 877 irq_enter();
810 kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + cp0_compare_irq]++; 878 kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++;
811 /* Invoke Clock "Interrupt" */ 879 cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
812 ipi_timer_latch[dest_copy] = 0; 880 ticks = atomic_read(&ipi_timer_latch[cpu]);
813#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG 881 atomic_sub(ticks, &ipi_timer_latch[cpu]);
814 clock_hang_reported[dest_copy] = 0; 882 while (ticks) {
815#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ 883 cd->event_handler(cd);
816 local_timer_interrupt(0, NULL); 884 ticks--;
885 }
817 irq_exit(); 886 irq_exit();
818 break; 887 break;
888
819 case LINUX_SMP_IPI: 889 case LINUX_SMP_IPI:
820 switch ((int)arg_copy) { 890 switch ((int)arg_copy) {
821 case SMP_RESCHEDULE_YOURSELF: 891 case SMP_RESCHEDULE_YOURSELF:
@@ -830,6 +900,15 @@ void ipi_decode(struct smtc_ipi *pipi)
830 break; 900 break;
831 } 901 }
832 break; 902 break;
903#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
904 case IRQ_AFFINITY_IPI:
905 /*
906 * Accept a "forwarded" interrupt that was initially
907 * taken by a TC who doesn't have affinity for the IRQ.
908 */
909 do_IRQ_no_affinity((int)arg_copy);
910 break;
911#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
833 default: 912 default:
834 printk("Impossible SMTC IPI Type 0x%x\n", type_copy); 913 printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
835 break; 914 break;
@@ -858,25 +937,6 @@ void deferred_smtc_ipi(void)
858} 937}
859 938
860/* 939/*
861 * Send clock tick to all TCs except the one executing the funtion
862 */
863
864void smtc_timer_broadcast(void)
865{
866 int cpu;
867 int myTC = cpu_data[smp_processor_id()].tc_id;
868 int myVPE = cpu_data[smp_processor_id()].vpe_id;
869
870 smtc_cpu_stats[smp_processor_id()].timerints++;
871
872 for_each_online_cpu(cpu) {
873 if (cpu_data[cpu].vpe_id == myVPE &&
874 cpu_data[cpu].tc_id != myTC)
875 smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
876 }
877}
878
879/*
880 * Cross-VPE interrupts in the SMTC prototype use "software interrupts" 940 * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
881 * set via cross-VPE MTTR manipulation of the Cause register. It would be 941 * set via cross-VPE MTTR manipulation of the Cause register. It would be
882 * in some regards preferable to have external logic for "doorbell" hardware 942 * in some regards preferable to have external logic for "doorbell" hardware
@@ -1117,11 +1177,11 @@ void smtc_idle_loop_hook(void)
1117 for (tc = 0; tc < NR_CPUS; tc++) { 1177 for (tc = 0; tc < NR_CPUS; tc++) {
1118 /* Don't check ourself - we'll dequeue IPIs just below */ 1178 /* Don't check ourself - we'll dequeue IPIs just below */
1119 if ((tc != smp_processor_id()) && 1179 if ((tc != smp_processor_id()) &&
1120 ipi_timer_latch[tc] > timerq_limit) { 1180 atomic_read(&ipi_timer_latch[tc]) > timerq_limit) {
1121 if (clock_hang_reported[tc] == 0) { 1181 if (clock_hang_reported[tc] == 0) {
1122 pdb_msg += sprintf(pdb_msg, 1182 pdb_msg += sprintf(pdb_msg,
1123 "TC %d looks hung with timer latch at %d\n", 1183 "TC %d looks hung with timer latch at %d\n",
1124 tc, ipi_timer_latch[tc]); 1184 tc, atomic_read(&ipi_timer_latch[tc]));
1125 clock_hang_reported[tc]++; 1185 clock_hang_reported[tc]++;
1126 } 1186 }
1127 } 1187 }
@@ -1162,7 +1222,7 @@ void smtc_soft_dump(void)
1162 smtc_ipi_qdump(); 1222 smtc_ipi_qdump();
1163 printk("Timer IPI Backlogs:\n"); 1223 printk("Timer IPI Backlogs:\n");
1164 for (i=0; i < NR_CPUS; i++) { 1224 for (i=0; i < NR_CPUS; i++) {
1165 printk("%d: %d\n", i, ipi_timer_latch[i]); 1225 printk("%d: %d\n", i, atomic_read(&ipi_timer_latch[i]));
1166 } 1226 }
1167 printk("%d Recoveries of \"stolen\" FPU\n", 1227 printk("%d Recoveries of \"stolen\" FPU\n",
1168 atomic_read(&smtc_fpu_recoveries)); 1228 atomic_read(&smtc_fpu_recoveries));
@@ -1204,7 +1264,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1204 if (cpu_has_vtag_icache) 1264 if (cpu_has_vtag_icache)
1205 flush_icache_all(); 1265 flush_icache_all();
1206 /* Traverse all online CPUs (hack requires contigous range) */ 1266 /* Traverse all online CPUs (hack requires contigous range) */
1207 for (i = 0; i < num_online_cpus(); i++) { 1267 for_each_online_cpu(i) {
1208 /* 1268 /*
1209 * We don't need to worry about our own CPU, nor those of 1269 * We don't need to worry about our own CPU, nor those of
1210 * CPUs who don't share our TLB. 1270 * CPUs who don't share our TLB.
@@ -1233,7 +1293,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
1233 /* 1293 /*
1234 * SMTC shares the TLB within VPEs and possibly across all VPEs. 1294 * SMTC shares the TLB within VPEs and possibly across all VPEs.
1235 */ 1295 */
1236 for (i = 0; i < num_online_cpus(); i++) { 1296 for_each_online_cpu(i) {
1237 if ((smtc_status & SMTC_TLB_SHARED) || 1297 if ((smtc_status & SMTC_TLB_SHARED) ||
1238 (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) 1298 (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
1239 cpu_context(i, mm) = asid_cache(i) = asid; 1299 cpu_context(i, mm) = asid_cache(i) = asid;