aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig13
-rw-r--r--arch/mips/kernel/i8259.c3
-rw-r--r--arch/mips/kernel/smtc.c63
-rw-r--r--arch/mips/mips-boards/malta/malta_smtc.c50
4 files changed, 129 insertions, 0 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3b807b4bc7cd..b09eee2281c5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1378,6 +1378,19 @@ config MIPS_MT_SMTC_IM_BACKSTOP
1378 impact on interrupt service overhead. Disable it only if you know 1378 impact on interrupt service overhead. Disable it only if you know
1379 what you are doing. 1379 what you are doing.
1380 1380
1381config MIPS_MT_SMTC_IRQAFF
1382 bool "Support IRQ affinity API"
1383 depends on MIPS_MT_SMTC
1384 default n
1385 help
1386 Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
1387 for SMTC Linux kernel. Requires platform support, of which
1388 an example can be found in the MIPS kernel i8259 and Malta
1389 platform code. It is recommended that MIPS_MT_SMTC_INSTANT_REPLAY
1390 be enabled if MIPS_MT_SMTC_IRQAFF is used. Adds overhead to
1391 interrupt dispatch, and should be used only if you know what
1392 you are doing.
1393
1381config MIPS_VPE_LOADER_TOM 1394config MIPS_VPE_LOADER_TOM
1382 bool "Load VPE program into memory hidden from linux" 1395 bool "Load VPE program into memory hidden from linux"
1383 depends on MIPS_VPE_LOADER 1396 depends on MIPS_VPE_LOADER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 3a2d255361bc..4f4359bfd180 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -39,6 +39,9 @@ static struct irq_chip i8259A_chip = {
39 .disable = disable_8259A_irq, 39 .disable = disable_8259A_irq,
40 .unmask = enable_8259A_irq, 40 .unmask = enable_8259A_irq,
41 .mask_ack = mask_and_ack_8259A, 41 .mask_ack = mask_and_ack_8259A,
42#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
43 .set_affinity = plat_set_irq_affinity,
44#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
42}; 45};
43 46
44/* 47/*
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index f09404377ef1..fe22387d58b1 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -606,6 +606,60 @@ int setup_irq_smtc(unsigned int irq, struct irqaction * new,
606 return setup_irq(irq, new); 606 return setup_irq(irq, new);
607} 607}
608 608
609#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
610/*
611 * Support for IRQ affinity to TCs
612 */
613
614void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity)
615{
616 /*
617 * If a "fast path" cache of quickly decodable affinity state
618 * is maintained, this is where it gets done, on a call up
619 * from the platform affinity code.
620 */
621}
622
623void smtc_forward_irq(unsigned int irq)
624{
625 int target;
626
627 /*
628 * OK wise guy, now figure out how to get the IRQ
629 * to be serviced on an authorized "CPU".
630 *
631 * Ideally, to handle the situation where an IRQ has multiple
632 * eligible CPUS, we would maintain state per IRQ that would
633 * allow a fair distribution of service requests. Since the
634 * expected use model is any-or-only-one, for simplicity
635 * and efficiency, we just pick the easiest one to find.
636 */
637
638 target = first_cpu(irq_desc[irq].affinity);
639
640 /*
641 * We depend on the platform code to have correctly processed
642 * IRQ affinity change requests to ensure that the IRQ affinity
643 * mask has been purged of bits corresponding to nonexistent and
644 * offline "CPUs", and to TCs bound to VPEs other than the VPE
645 * connected to the physical interrupt input for the interrupt
646 * in question. Otherwise we have a nasty problem with interrupt
647 * mask management. This is best handled in non-performance-critical
648 * platform IRQ affinity setting code, to minimize interrupt-time
649 * checks.
650 */
651
652 /* If no one is eligible, service locally */
653 if (target >= NR_CPUS) {
654 do_IRQ_no_affinity(irq);
655 return;
656 }
657
658 smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);
659}
660
661#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
662
609/* 663/*
610 * IPI model for SMTC is tricky, because interrupts aren't TC-specific. 664 * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
611 * Within a VPE one TC can interrupt another by different approaches. 665 * Within a VPE one TC can interrupt another by different approaches.
@@ -830,6 +884,15 @@ void ipi_decode(struct smtc_ipi *pipi)
830 break; 884 break;
831 } 885 }
832 break; 886 break;
887#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
888 case IRQ_AFFINITY_IPI:
889 /*
890 * Accept a "forwarded" interrupt that was initially
891 * taken by a TC who doesn't have affinity for the IRQ.
892 */
893 do_IRQ_no_affinity((int)arg_copy);
894 break;
895#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
833 default: 896 default:
834 printk("Impossible SMTC IPI Type 0x%x\n", type_copy); 897 printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
835 break; 898 break;
diff --git a/arch/mips/mips-boards/malta/malta_smtc.c b/arch/mips/mips-boards/malta/malta_smtc.c
index ae05d058cb37..5c980f4a48fe 100644
--- a/arch/mips/mips-boards/malta/malta_smtc.c
+++ b/arch/mips/mips-boards/malta/malta_smtc.c
@@ -88,3 +88,53 @@ void __cpuinit prom_smp_finish(void)
88void prom_cpus_done(void) 88void prom_cpus_done(void)
89{ 89{
90} 90}
91
92#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
93/*
94 * IRQ affinity hook
95 */
96
97
98void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity)
99{
100 cpumask_t tmask = affinity;
101 int cpu = 0;
102 void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff);
103
104 /*
105 * On the legacy Malta development board, all I/O interrupts
106 * are routed through the 8259 and combined in a single signal
107 * to the CPU daughterboard, and on the CoreFPGA2/3 34K models,
108 * that signal is brought to IP2 of both VPEs. To avoid racing
109 * concurrent interrupt service events, IP2 is enabled only on
110 * one VPE, by convention VPE0. So long as no bits are ever
111 * cleared in the affinity mask, there will never be any
112 * interrupt forwarding. But as soon as a program or operator
113 * sets affinity for one of the related IRQs, we need to make
114 * sure that we don't ever try to forward across the VPE boundry,
115 * at least not until we engineer a system where the interrupt
116 * _ack() or _end() function can somehow know that it corresponds
117 * to an interrupt taken on another VPE, and perform the appropriate
118 * restoration of Status.IM state using MFTR/MTTR instead of the
119 * normal local behavior. We also ensure that no attempt will
120 * be made to forward to an offline "CPU".
121 */
122
123 for_each_cpu_mask(cpu, affinity) {
124 if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))
125 cpu_clear(cpu, tmask);
126 }
127 irq_desc[irq].affinity = tmask;
128
129 if (cpus_empty(tmask))
130 /*
131 * We could restore a default mask here, but the
132 * runtime code can anyway deal with the null set
133 */
134 printk(KERN_WARNING
135 "IRQ affinity leaves no legal CPU for IRQ %d\n", irq);
136
137 /* Do any generic SMTC IRQ affinity setup */
138 smtc_set_irq_affinity(irq, tmask);
139}
140#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */