7c2deb190e144f914f4a8717ed5fb11971de79a3
[oweals/openwrt.git] / target / linux / lantiq / patches-4.14 / 0400-Revert-MIPS-smp-mt-Use-CPU-interrupt-controller-IPI-.patch
1 From 8fe9821b478e5c61fef4786b7ec96b6766af196d Mon Sep 17 00:00:00 2001
2 From: Mathias Kresin <dev@kresin.me>
3 Date: Mon, 8 Jan 2018 23:04:57 +0100
4 Subject: [PATCH] Revert "MIPS: smp-mt: Use CPU interrupt controller IPI IRQ
5  domain support"
6
7 The problem is that the Lantiq IRQ controller gets registered first and
8 it directly handles the MIPS native SW1/2 and HW0 - HW5 IRQs. It looks
9 like this controller already registers IRQ 0 - 7 and the generic driver
10 only gets the following IRQs starting later.
11
12 The upstream discussion can be found at https://www.linux-mips.org/archives/linux-mips/2017-05/msg00059.html
13
14 This reverts kernel commit 1eed40043579 ("MIPS: smp-mt: Use CPU interrupt
15 controller IPI IRQ domain support").
16
17 Signed-off-by: Mathias Kresin <dev@kresin.me>
18
19 ---
20  arch/mips/kernel/smp-mt.c       | 49 ++++++++++++++++++++++--
21  arch/mips/lantiq/irq.c          | 52 ++++++++++++++++++++++++++
22  arch/mips/mti-malta/malta-int.c | 83 +++++++++++++++++++++++++++++++++++++++--
23  3 files changed, 176 insertions(+), 8 deletions(-)
24
25 --- a/arch/mips/kernel/smp-mt.c
26 +++ b/arch/mips/kernel/smp-mt.c
27 @@ -83,8 +83,6 @@ static unsigned int __init smvp_vpe_init
28         if (tc != 0)
29                 smvp_copy_vpe_config();
30  
31 -       cpu_set_vpe_id(&cpu_data[ncpu], tc);
32 -
33         return ncpu;
34  }
35  
36 @@ -116,6 +114,49 @@ static void __init smvp_tc_init(unsigned
37         write_tc_c0_tchalt(TCHALT_H);
38  }
39  
40 +static void vsmp_send_ipi_single(int cpu, unsigned int action)
41 +{
42 +       int i;
43 +       unsigned long flags;
44 +       int vpflags;
45 +
46 +#ifdef CONFIG_MIPS_GIC
47 +       if (gic_present) {
48 +               mips_smp_send_ipi_single(cpu, action);
49 +               return;
50 +       }
51 +#endif
52 +       local_irq_save(flags);
53 +
54 +       vpflags = dvpe();       /* can't access the other CPU's registers whilst MVPE enabled */
55 +
56 +       switch (action) {
57 +       case SMP_CALL_FUNCTION:
58 +               i = C_SW1;
59 +               break;
60 +
61 +       case SMP_RESCHEDULE_YOURSELF:
62 +       default:
63 +               i = C_SW0;
64 +               break;
65 +       }
66 +
67 +       /* 1:1 mapping of vpe and tc... */
68 +       settc(cpu);
69 +       write_vpe_c0_cause(read_vpe_c0_cause() | i);
70 +       evpe(vpflags);
71 +
72 +       local_irq_restore(flags);
73 +}
74 +
75 +static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
76 +{
77 +       unsigned int i;
78 +
79 +       for_each_cpu(i, mask)
80 +               vsmp_send_ipi_single(i, action);
81 +}
82 +
83  static void vsmp_init_secondary(void)
84  {
85         /* This is Malta specific: IPI,performance and timer interrupts */
86 @@ -240,8 +281,8 @@ static void __init vsmp_prepare_cpus(uns
87  }
88  
89  const struct plat_smp_ops vsmp_smp_ops = {
90 -       .send_ipi_single        = mips_smp_send_ipi_single,
91 -       .send_ipi_mask          = mips_smp_send_ipi_mask,
92 +       .send_ipi_single        = vsmp_send_ipi_single,
93 +       .send_ipi_mask          = vsmp_send_ipi_mask,
94         .init_secondary         = vsmp_init_secondary,
95         .smp_finish             = vsmp_smp_finish,
96         .boot_secondary         = vsmp_boot_secondary,
97 --- a/arch/mips/lantiq/irq.c
98 +++ b/arch/mips/lantiq/irq.c
99 @@ -272,6 +272,47 @@ static void ltq_hw_irq_handler(struct ir
100         ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
101  }
102  
103 +#ifdef CONFIG_MIPS_MT_SMP
104 +void __init arch_init_ipiirq(int irq, struct irqaction *action)
105 +{
106 +       setup_irq(irq, action);
107 +       irq_set_handler(irq, handle_percpu_irq);
108 +}
109 +
110 +static void ltq_sw0_irqdispatch(void)
111 +{
112 +       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
113 +}
114 +
115 +static void ltq_sw1_irqdispatch(void)
116 +{
117 +       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
118 +}
119 +static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
120 +{
121 +       scheduler_ipi();
122 +       return IRQ_HANDLED;
123 +}
124 +
125 +static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
126 +{
127 +       generic_smp_call_function_interrupt();
128 +       return IRQ_HANDLED;
129 +}
130 +
131 +static struct irqaction irq_resched = {
132 +       .handler        = ipi_resched_interrupt,
133 +       .flags          = IRQF_PERCPU,
134 +       .name           = "IPI_resched"
135 +};
136 +
137 +static struct irqaction irq_call = {
138 +       .handler        = ipi_call_interrupt,
139 +       .flags          = IRQF_PERCPU,
140 +       .name           = "IPI_call"
141 +};
142 +#endif
143 +
144  asmlinkage void plat_irq_dispatch(void)
145  {
146         unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
147 @@ -359,6 +400,17 @@ int __init icu_of_init(struct device_nod
148                 (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
149                 &irq_domain_ops, 0);
150  
151 +#if defined(CONFIG_MIPS_MT_SMP)
152 +       if (cpu_has_vint) {
153 +               pr_info("Setting up IPI vectored interrupts\n");
154 +               set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch);
155 +               set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch);
156 +       }
157 +       arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
158 +               &irq_resched);
159 +       arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
160 +#endif
161 +
162  #ifndef CONFIG_MIPS_MT_SMP
163         set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
164                 IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
165 --- a/arch/mips/mti-malta/malta-int.c
166 +++ b/arch/mips/mti-malta/malta-int.c
167 @@ -144,6 +144,56 @@ static irqreturn_t corehi_handler(int ir
168         return IRQ_HANDLED;
169  }
170  
171 +#ifdef CONFIG_MIPS_MT_SMP
172 +
173 +#define MIPS_CPU_IPI_RESCHED_IRQ 0     /* SW int 0 for resched */
174 +#define C_RESCHED C_SW0
175 +#define MIPS_CPU_IPI_CALL_IRQ 1                /* SW int 1 for resched */
176 +#define C_CALL C_SW1
177 +static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
178 +
179 +static void ipi_resched_dispatch(void)
180 +{
181 +       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
182 +}
183 +
184 +static void ipi_call_dispatch(void)
185 +{
186 +       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
187 +}
188 +
189 +static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
190 +{
191 +#ifdef CONFIG_MIPS_VPE_APSP_API_CMP
192 +       if (aprp_hook)
193 +               aprp_hook();
194 +#endif
195 +
196 +       scheduler_ipi();
197 +
198 +       return IRQ_HANDLED;
199 +}
200 +
201 +static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
202 +{
203 +       generic_smp_call_function_interrupt();
204 +
205 +       return IRQ_HANDLED;
206 +}
207 +
208 +static struct irqaction irq_resched = {
209 +       .handler        = ipi_resched_interrupt,
210 +       .flags          = IRQF_PERCPU,
211 +       .name           = "IPI_resched"
212 +};
213 +
214 +static struct irqaction irq_call = {
215 +       .handler        = ipi_call_interrupt,
216 +       .flags          = IRQF_PERCPU,
217 +       .name           = "IPI_call"
218 +};
219 +#endif /* CONFIG_MIPS_MT_SMP */
220 +
221  static struct irqaction corehi_irqaction = {
222         .handler = corehi_handler,
223         .name = "CoreHi",
224 @@ -171,6 +221,12 @@ static msc_irqmap_t msc_eicirqmap[] __in
225  
226  static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
227  
228 +void __init arch_init_ipiirq(int irq, struct irqaction *action)
229 +{
230 +       setup_irq(irq, action);
231 +       irq_set_handler(irq, handle_percpu_irq);
232 +}
233 +
234  void __init arch_init_irq(void)
235  {
236         int corehi_irq;
237 @@ -216,11 +272,30 @@ void __init arch_init_irq(void)
238  
239         if (mips_gic_present()) {
240                 corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
241 -       } else if (cpu_has_veic) {
242 -               set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
243 -               corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
244         } else {
245 -               corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
246 +#if defined(CONFIG_MIPS_MT_SMP)
247 +               /* set up ipi interrupts */
248 +               if (cpu_has_veic) {
249 +                       set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
250 +                       set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
251 +                       cpu_ipi_resched_irq = MSC01E_INT_SW0;
252 +                       cpu_ipi_call_irq = MSC01E_INT_SW1;
253 +               } else {
254 +                       cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE +
255 +                               MIPS_CPU_IPI_RESCHED_IRQ;
256 +                       cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE +
257 +                               MIPS_CPU_IPI_CALL_IRQ;
258 +               }
259 +               arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
260 +               arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
261 +#endif
262 +               if (cpu_has_veic) {
263 +                       set_vi_handler(MSC01E_INT_COREHI,
264 +                                      corehi_irqdispatch);
265 +                       corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
266 +               } else {
267 +                       corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
268 +               }
269         }
270  
271         setup_irq(corehi_irq, &corehi_irqaction);