aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
authorTudor Laurentiu <b10716@freescale.com>2014-08-19 07:25:03 -0400
committerScott Wood <scottwood@freescale.com>2014-09-04 19:47:57 -0400
commit543c043cbae79164aa087f96294cb37fc4a19a59 (patch)
treee07b8d0ea78b3ada50bbdab1e461fde195fac9a5 /arch/powerpc/sysdev/fsl_msi.c
parent834952314c8bae7331b0797a071958dda9bec60d (diff)
powerpc/fsl_msi: change the irq handler from chained to normal
As we do for other fsl-mpic related cascaded irqchips (e.g. error ints, mpic timers), use a normal irq handler for msi irqs too. This brings some advantages such as mask/unmask/ack/eoi and irq state taken care behind the scenes, kstats updates a.s.o plus access to features provided by mpic, such as affinity. Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@freescale.com> Cc: Scott Wood <scottwood@freescale.com> Cc: Mihai Caraman <mihai.caraman@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c56
1 files changed, 18 insertions, 38 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 05a0dd918de2..0cfc32a63039 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -18,6 +18,7 @@
18#include <linux/pci.h> 18#include <linux/pci.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/of_platform.h> 20#include <linux/of_platform.h>
21#include <linux/interrupt.h>
21#include <sysdev/fsl_soc.h> 22#include <sysdev/fsl_soc.h>
22#include <asm/prom.h> 23#include <asm/prom.h>
23#include <asm/hw_irq.h> 24#include <asm/hw_irq.h>
@@ -241,40 +242,24 @@ out_free:
241 return rc; 242 return rc;
242} 243}
243 244
244static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 245static irqreturn_t fsl_msi_cascade(int irq, void *data)
245{ 246{
246 struct irq_chip *chip = irq_desc_get_chip(desc);
247 struct irq_data *idata = irq_desc_get_irq_data(desc);
248 unsigned int cascade_irq; 247 unsigned int cascade_irq;
249 struct fsl_msi *msi_data; 248 struct fsl_msi *msi_data;
250 int msir_index = -1; 249 int msir_index = -1;
251 u32 msir_value = 0; 250 u32 msir_value = 0;
252 u32 intr_index; 251 u32 intr_index;
253 u32 have_shift = 0; 252 u32 have_shift = 0;
254 struct fsl_msi_cascade_data *cascade_data; 253 struct fsl_msi_cascade_data *cascade_data = data;
254 irqreturn_t ret = IRQ_NONE;
255 255
256 cascade_data = irq_get_handler_data(irq);
257 msi_data = cascade_data->msi_data; 256 msi_data = cascade_data->msi_data;
258 257
259 raw_spin_lock(&desc->lock);
260 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
261 if (chip->irq_mask_ack)
262 chip->irq_mask_ack(idata);
263 else {
264 chip->irq_mask(idata);
265 chip->irq_ack(idata);
266 }
267 }
268
269 if (unlikely(irqd_irq_inprogress(idata)))
270 goto unlock;
271
272 msir_index = cascade_data->index; 258 msir_index = cascade_data->index;
273 259
274 if (msir_index >= NR_MSI_REG_MAX) 260 if (msir_index >= NR_MSI_REG_MAX)
275 cascade_irq = NO_IRQ; 261 cascade_irq = NO_IRQ;
276 262
277 irqd_set_chained_irq_inprogress(idata);
278 switch (msi_data->feature & FSL_PIC_IP_MASK) { 263 switch (msi_data->feature & FSL_PIC_IP_MASK) {
279 case FSL_PIC_IP_MPIC: 264 case FSL_PIC_IP_MPIC:
280 msir_value = fsl_msi_read(msi_data->msi_regs, 265 msir_value = fsl_msi_read(msi_data->msi_regs,
@@ -303,25 +288,15 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
303 cascade_irq = irq_linear_revmap(msi_data->irqhost, 288 cascade_irq = irq_linear_revmap(msi_data->irqhost,
304 msi_hwirq(msi_data, msir_index, 289 msi_hwirq(msi_data, msir_index,
305 intr_index + have_shift)); 290 intr_index + have_shift));
306 if (cascade_irq != NO_IRQ) 291 if (cascade_irq != NO_IRQ) {
307 generic_handle_irq(cascade_irq); 292 generic_handle_irq(cascade_irq);
293 ret = IRQ_HANDLED;
294 }
308 have_shift += intr_index + 1; 295 have_shift += intr_index + 1;
309 msir_value = msir_value >> (intr_index + 1); 296 msir_value = msir_value >> (intr_index + 1);
310 } 297 }
311 irqd_clr_chained_irq_inprogress(idata);
312 298
313 switch (msi_data->feature & FSL_PIC_IP_MASK) { 299 return ret;
314 case FSL_PIC_IP_MPIC:
315 case FSL_PIC_IP_VMPIC:
316 chip->irq_eoi(idata);
317 break;
318 case FSL_PIC_IP_IPIC:
319 if (!irqd_irq_disabled(idata) && chip->irq_unmask)
320 chip->irq_unmask(idata);
321 break;
322 }
323unlock:
324 raw_spin_unlock(&desc->lock);
325} 300}
326 301
327static int fsl_of_msi_remove(struct platform_device *ofdev) 302static int fsl_of_msi_remove(struct platform_device *ofdev)
@@ -336,9 +311,8 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
336 virq = msi->cascade_array[i]->virq; 311 virq = msi->cascade_array[i]->virq;
337 312
338 BUG_ON(virq == NO_IRQ); 313 BUG_ON(virq == NO_IRQ);
339 BUG_ON(msi->cascade_array[i] !=
340 irq_get_handler_data(virq));
341 314
315 free_irq(virq, msi->cascade_array[i]);
342 kfree(msi->cascade_array[i]); 316 kfree(msi->cascade_array[i]);
343 irq_dispose_mapping(virq); 317 irq_dispose_mapping(virq);
344 } 318 }
@@ -358,7 +332,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
358 int offset, int irq_index) 332 int offset, int irq_index)
359{ 333{
360 struct fsl_msi_cascade_data *cascade_data = NULL; 334 struct fsl_msi_cascade_data *cascade_data = NULL;
361 int virt_msir, i; 335 int virt_msir, i, ret;
362 336
363 virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index); 337 virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
364 if (virt_msir == NO_IRQ) { 338 if (virt_msir == NO_IRQ) {
@@ -377,8 +351,14 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
377 cascade_data->msi_data = msi; 351 cascade_data->msi_data = msi;
378 cascade_data->virq = virt_msir; 352 cascade_data->virq = virt_msir;
379 msi->cascade_array[irq_index] = cascade_data; 353 msi->cascade_array[irq_index] = cascade_data;
380 irq_set_handler_data(virt_msir, cascade_data); 354
381 irq_set_chained_handler(virt_msir, fsl_msi_cascade); 355 ret = request_irq(virt_msir, fsl_msi_cascade, 0,
356 "fsl-msi-cascade", cascade_data);
357 if (ret) {
358 dev_err(&dev->dev, "failed to request_irq(%d), ret = %d\n",
359 virt_msir, ret);
360 return ret;
361 }
382 362
383 /* Release the hwirqs corresponding to this MSI register */ 363 /* Release the hwirqs corresponding to this MSI register */
384 for (i = 0; i < IRQS_PER_MSI_REG; i++) 364 for (i = 0; i < IRQS_PER_MSI_REG; i++)