diff options
author | Tudor Laurentiu <b10716@freescale.com> | 2014-08-19 07:25:03 -0400 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-09-04 19:47:57 -0400 |
commit | 543c043cbae79164aa087f96294cb37fc4a19a59 (patch) | |
tree | e07b8d0ea78b3ada50bbdab1e461fde195fac9a5 /arch/powerpc/sysdev/fsl_msi.c | |
parent | 834952314c8bae7331b0797a071958dda9bec60d (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.c | 56 |
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 | ||
244 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | 245 | static 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 | } | ||
323 | unlock: | ||
324 | raw_spin_unlock(&desc->lock); | ||
325 | } | 300 | } |
326 | 301 | ||
327 | static int fsl_of_msi_remove(struct platform_device *ofdev) | 302 | static 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++) |