diff options
Diffstat (limited to 'include/asm-mips/irq.h')
-rw-r--r-- | include/asm-mips/irq.h | 99 |
1 files changed, 89 insertions, 10 deletions
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h index 97102ebc54b1..a58f0eecc68f 100644 --- a/include/asm-mips/irq.h +++ b/include/asm-mips/irq.h | |||
@@ -24,7 +24,62 @@ static inline int irq_canonicalize(int irq) | |||
24 | #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ | 24 | #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #ifdef CONFIG_MIPS_MT_SMTC | ||
28 | |||
29 | struct irqaction; | ||
30 | |||
31 | extern unsigned long irq_hwmask[]; | ||
32 | extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, | ||
33 | unsigned long hwmask); | ||
34 | |||
35 | static inline void smtc_im_ack_irq(unsigned int irq) | ||
36 | { | ||
37 | if (irq_hwmask[irq] & ST0_IM) | ||
38 | set_c0_status(irq_hwmask[irq] & ST0_IM); | ||
39 | } | ||
40 | |||
41 | #else | ||
42 | |||
43 | static inline void smtc_im_ack_irq(unsigned int irq) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
48 | |||
49 | #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF | ||
50 | #include <linux/cpumask.h> | ||
51 | |||
52 | extern void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity); | ||
53 | extern void smtc_forward_irq(unsigned int irq); | ||
54 | |||
55 | /* | ||
56 | * IRQ affinity hook invoked at the beginning of interrupt dispatch | ||
57 | * if option is enabled. | ||
58 | * | ||
59 | * Up through Linux 2.6.22 (at least) cpumask operations are very | ||
60 | * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity | ||
61 | * used a "fast path" per-IRQ-descriptor cache of affinity information | ||
62 | * to reduce latency. As there is a project afoot to optimize the | ||
63 | * cpumask implementations, this version is optimistically assuming | ||
64 | * that cpumask.h macro overhead is reasonable during interrupt dispatch. | ||
65 | */ | ||
66 | #define IRQ_AFFINITY_HOOK(irq) \ | ||
67 | do { \ | ||
68 | if (!cpu_isset(smp_processor_id(), irq_desc[irq].affinity)) { \ | ||
69 | smtc_forward_irq(irq); \ | ||
70 | irq_exit(); \ | ||
71 | return; \ | ||
72 | } \ | ||
73 | } while (0) | ||
74 | |||
75 | #else /* Not doing SMTC affinity */ | ||
76 | |||
77 | #define IRQ_AFFINITY_HOOK(irq) do { } while (0) | ||
78 | |||
79 | #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ | ||
80 | |||
27 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP | 81 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP |
82 | |||
28 | /* | 83 | /* |
29 | * Clear interrupt mask handling "backstop" if irq_hwmask | 84 | * Clear interrupt mask handling "backstop" if irq_hwmask |
30 | * entry so indicates. This implies that the ack() or end() | 85 | * entry so indicates. This implies that the ack() or end() |
@@ -33,12 +88,27 @@ static inline int irq_canonicalize(int irq) | |||
33 | */ | 88 | */ |
34 | #define __DO_IRQ_SMTC_HOOK(irq) \ | 89 | #define __DO_IRQ_SMTC_HOOK(irq) \ |
35 | do { \ | 90 | do { \ |
91 | IRQ_AFFINITY_HOOK(irq); \ | ||
36 | if (irq_hwmask[irq] & 0x0000ff00) \ | 92 | if (irq_hwmask[irq] & 0x0000ff00) \ |
37 | write_c0_tccontext(read_c0_tccontext() & \ | 93 | write_c0_tccontext(read_c0_tccontext() & \ |
38 | ~(irq_hwmask[irq] & 0x0000ff00)); \ | 94 | ~(irq_hwmask[irq] & 0x0000ff00)); \ |
95 | } while (0) | ||
96 | |||
97 | #define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) \ | ||
98 | do { \ | ||
99 | if (irq_hwmask[irq] & 0x0000ff00) \ | ||
100 | write_c0_tccontext(read_c0_tccontext() & \ | ||
101 | ~(irq_hwmask[irq] & 0x0000ff00)); \ | ||
39 | } while (0) | 102 | } while (0) |
103 | |||
40 | #else | 104 | #else |
41 | #define __DO_IRQ_SMTC_HOOK(irq) do { } while (0) | 105 | |
106 | #define __DO_IRQ_SMTC_HOOK(irq) \ | ||
107 | do { \ | ||
108 | IRQ_AFFINITY_HOOK(irq); \ | ||
109 | } while (0) | ||
110 | #define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) do { } while (0) | ||
111 | |||
42 | #endif | 112 | #endif |
43 | 113 | ||
44 | /* | 114 | /* |
@@ -57,16 +127,25 @@ do { \ | |||
57 | irq_exit(); \ | 127 | irq_exit(); \ |
58 | } while (0) | 128 | } while (0) |
59 | 129 | ||
60 | extern void arch_init_irq(void); | 130 | #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF |
61 | extern void spurious_interrupt(void); | 131 | /* |
132 | * To avoid inefficient and in some cases pathological re-checking of | ||
133 | * IRQ affinity, we have this variant that skips the affinity check. | ||
134 | */ | ||
62 | 135 | ||
63 | #ifdef CONFIG_MIPS_MT_SMTC | ||
64 | struct irqaction; | ||
65 | 136 | ||
66 | extern unsigned long irq_hwmask[]; | 137 | #define do_IRQ_no_affinity(irq) \ |
67 | extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, | 138 | do { \ |
68 | unsigned long hwmask); | 139 | irq_enter(); \ |
69 | #endif /* CONFIG_MIPS_MT_SMTC */ | 140 | __NO_AFFINITY_IRQ_SMTC_HOOK(irq); \ |
141 | generic_handle_irq(irq); \ | ||
142 | irq_exit(); \ | ||
143 | } while (0) | ||
144 | |||
145 | #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ | ||
146 | |||
147 | extern void arch_init_irq(void); | ||
148 | extern void spurious_interrupt(void); | ||
70 | 149 | ||
71 | extern int allocate_irqno(void); | 150 | extern int allocate_irqno(void); |
72 | extern void alloc_legacy_irqno(void); | 151 | extern void alloc_legacy_irqno(void); |