[MIPS] IRQ Affinity Support for SMTC on Malta Platform
Signed-off-by: Kevin D. Kissell <kevink@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
···13781378 impact on interrupt service overhead. Disable it only if you know13791379 what you are doing.1380138013811381+config MIPS_MT_SMTC_IRQAFF13821382+ bool "Support IRQ affinity API"13831383+ depends on MIPS_MT_SMTC13841384+ default n13851385+ help13861386+ Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)13871387+ for SMTC Linux kernel. Requires platform support, of which13881388+ an example can be found in the MIPS kernel i8259 and Malta13891389+ platform code. It is recommended that MIPS_MT_SMTC_INSTANT_REPLAY13901390+ be enabled if MIPS_MT_SMTC_IRQAFF is used. Adds overhead to13911391+ interrupt dispatch, and should be used only if you know what13921392+ you are doing.13931393+13811394config MIPS_VPE_LOADER_TOM13821395 bool "Load VPE program into memory hidden from linux"13831396 depends on MIPS_VPE_LOADER
···606606 return setup_irq(irq, new);607607}608608609609+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF610610+/*611611+ * Support for IRQ affinity to TCs612612+ */613613+614614+void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity)615615+{616616+ /*617617+ * If a "fast path" cache of quickly decodable affinity state618618+ * is maintained, this is where it gets done, on a call up619619+ * from the platform affinity code.620620+ */621621+}622622+623623+void smtc_forward_irq(unsigned int irq)624624+{625625+ int target;626626+627627+ /*628628+ * OK wise guy, now figure out how to get the IRQ629629+ * to be serviced on an authorized "CPU".630630+ *631631+ * Ideally, to handle the situation where an IRQ has multiple632632+ * eligible CPUS, we would maintain state per IRQ that would633633+ * allow a fair distribution of service requests. Since the634634+ * expected use model is any-or-only-one, for simplicity635635+ * and efficiency, we just pick the easiest one to find.636636+ */637637+638638+ target = first_cpu(irq_desc[irq].affinity);639639+640640+ /*641641+ * We depend on the platform code to have correctly processed642642+ * IRQ affinity change requests to ensure that the IRQ affinity643643+ * mask has been purged of bits corresponding to nonexistent and644644+ * offline "CPUs", and to TCs bound to VPEs other than the VPE645645+ * connected to the physical interrupt input for the interrupt646646+ * in question. Otherwise we have a nasty problem with interrupt647647+ * mask management. This is best handled in non-performance-critical648648+ * platform IRQ affinity setting code, to minimize interrupt-time649649+ * checks.650650+ */651651+652652+ /* If no one is eligible, service locally */653653+ if (target >= NR_CPUS) {654654+ do_IRQ_no_affinity(irq);655655+ return;656656+ }657657+658658+ smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);659659+}660660+661661+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */662662+609663/*610664 * IPI model for SMTC is tricky, because interrupts aren't TC-specific.611665 * Within a VPE one TC can interrupt another by different approaches.···884830 break;885831 }886832 break;833833+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF834834+ case IRQ_AFFINITY_IPI:835835+ /*836836+ * Accept a "forwarded" interrupt that was initially837837+ * taken by a TC who doesn't have affinity for the IRQ.838838+ */839839+ do_IRQ_no_affinity((int)arg_copy);840840+ break;841841+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */887842 default:888843 printk("Impossible SMTC IPI Type 0x%x\n", type_copy);889844 break;
+50
arch/mips/mips-boards/malta/malta_smtc.c
···8888void prom_cpus_done(void)8989{9090}9191+9292+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF9393+/*9494+ * IRQ affinity hook9595+ */9696+9797+9898+void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity)9999+{100100+ cpumask_t tmask = affinity;101101+ int cpu = 0;102102+ void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff);103103+104104+ /*105105+ * On the legacy Malta development board, all I/O interrupts106106+ * are routed through the 8259 and combined in a single signal107107+ * to the CPU daughterboard, and on the CoreFPGA2/3 34K models,108108+ * that signal is brought to IP2 of both VPEs. To avoid racing109109+ * concurrent interrupt service events, IP2 is enabled only on110110+ * one VPE, by convention VPE0. So long as no bits are ever111111+ * cleared in the affinity mask, there will never be any112112+ * interrupt forwarding. But as soon as a program or operator113113+ * sets affinity for one of the related IRQs, we need to make114114+ * sure that we don't ever try to forward across the VPE boundry,115115+ * at least not until we engineer a system where the interrupt116116+ * _ack() or _end() function can somehow know that it corresponds117117+ * to an interrupt taken on another VPE, and perform the appropriate118118+ * restoration of Status.IM state using MFTR/MTTR instead of the119119+ * normal local behavior. We also ensure that no attempt will120120+ * be made to forward to an offline "CPU".121121+ */122122+123123+ for_each_cpu_mask(cpu, affinity) {124124+ if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))125125+ cpu_clear(cpu, tmask);126126+ }127127+ irq_desc[irq].affinity = tmask;128128+129129+ if (cpus_empty(tmask))130130+ /*131131+ * We could restore a default mask here, but the132132+ * runtime code can anyway deal with the null set133133+ */134134+ printk(KERN_WARNING135135+ "IRQ affinity leaves no legal CPU for IRQ %d\n", irq);136136+137137+ /* Do any generic SMTC IRQ affinity setup */138138+ smtc_set_irq_affinity(irq, tmask);139139+}140140+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
+65-2
include/asm-mips/irq.h
···46464747#endif /* CONFIG_MIPS_MT_SMTC */48484949+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF5050+#include <linux/cpumask.h>5151+5252+extern void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity);5353+extern void smtc_forward_irq(unsigned int irq);5454+5555+/*5656+ * IRQ affinity hook invoked at the beginning of interrupt dispatch5757+ * if option is enabled.5858+ *5959+ * Up through Linux 2.6.22 (at least) cpumask operations are very6060+ * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity6161+ * used a "fast path" per-IRQ-descriptor cache of affinity information6262+ * to reduce latency. As there is a project afoot to optimize the6363+ * cpumask implementations, this version is optimistically assuming6464+ * that cpumask.h macro overhead is reasonable during interrupt dispatch.6565+ */6666+#define IRQ_AFFINITY_HOOK(irq) \6767+do { \6868+ if (!cpu_isset(smp_processor_id(), irq_desc[irq].affinity)) { \6969+ smtc_forward_irq(irq); \7070+ irq_exit(); \7171+ return; \7272+ } \7373+} while (0)7474+7575+#else /* Not doing SMTC affinity */7676+7777+#define IRQ_AFFINITY_HOOK(irq) do { } while (0)7878+7979+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */8080+4981#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP50825183/*···8856 */8957#define __DO_IRQ_SMTC_HOOK(irq) \9058do { \5959+ IRQ_AFFINITY_HOOK(irq); \9160 if (irq_hwmask[irq] & 0x0000ff00) \9261 write_c0_tccontext(read_c0_tccontext() & \9393- ~(irq_hwmask[irq] & 0x0000ff00)); \6262+ ~(irq_hwmask[irq] & 0x0000ff00)); \9463} while (0)6464+6565+#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) \6666+do { \6767+ if (irq_hwmask[irq] & 0x0000ff00) \6868+ write_c0_tccontext(read_c0_tccontext() & \6969+ ~(irq_hwmask[irq] & 0x0000ff00)); \7070+} while (0)7171+9572#else96739797-#define __DO_IRQ_SMTC_HOOK(irq) do { } while (0)7474+#define __DO_IRQ_SMTC_HOOK(irq) \7575+do { \7676+ IRQ_AFFINITY_HOOK(irq); \7777+} while (0)7878+#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) do { } while (0)7979+9880#endif998110082/*···12680 generic_handle_irq(irq); \12781 irq_exit(); \12882} while (0)8383+8484+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF8585+/*8686+ * To avoid inefficient and in some cases pathological re-checking of8787+ * IRQ affinity, we have this variant that skips the affinity check.8888+ */8989+9090+9191+#define do_IRQ_no_affinity(irq) \9292+do { \9393+ irq_enter(); \9494+ __NO_AFFINITY_IRQ_SMTC_HOOK(irq); \9595+ generic_handle_irq(irq); \9696+ irq_exit(); \9797+} while (0)9898+9999+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */129100130101extern void arch_init_irq(void);131102extern void spurious_interrupt(void);
+1
include/asm-mips/smtc_ipi.h
···34343535#define LINUX_SMP_IPI 13636#define SMTC_CLOCK_TICK 23737+#define IRQ_AFFINITY_IPI 337383839/*3940 * A queue of IPI messages