blob: 9485ae081dcd8efc14d412ad192b454809a44551 [file] [log] [blame]
Andrew Mortonc777ac52006-03-25 03:07:36 -08001
Christoph Hellwigd824e662006-04-10 22:54:04 -07002#include <linux/irq.h>
Yinghai Lu57b150c2009-04-27 17:59:53 -07003#include <linux/interrupt.h>
4
5#include "internals.h"
Andrew Mortonc777ac52006-03-25 03:07:36 -08006
Eric W. Biedermane7b946e2006-10-04 02:16:29 -07007void move_masked_irq(int irq)
Andrew Mortonc777ac52006-03-25 03:07:36 -08008{
Yinghai Lu08678b02008-08-19 20:50:05 -07009 struct irq_desc *desc = irq_to_desc(irq);
Thomas Gleixnerc96b3b32010-09-27 12:45:41 +000010 struct irq_chip *chip = desc->irq_data.chip;
Andrew Mortonc777ac52006-03-25 03:07:36 -080011
Thomas Gleixnerf230b6d2011-02-05 15:20:04 +010012 if (likely(!irqd_is_setaffinity_pending(&desc->irq_data)))
Andrew Mortonc777ac52006-03-25 03:07:36 -080013 return;
14
Bryan Holty501f2492006-03-25 03:07:37 -080015 /*
16 * Paranoia: cpu-local interrupts shouldn't be calling in here anyway.
17 */
18 if (CHECK_IRQ_PER_CPU(desc->status)) {
19 WARN_ON(1);
20 return;
21 }
22
Thomas Gleixnerf230b6d2011-02-05 15:20:04 +010023 irqd_clr_move_pending(&desc->irq_data);
Andrew Mortonc777ac52006-03-25 03:07:36 -080024
Mike Travis7f7ace02009-01-10 21:58:08 -080025 if (unlikely(cpumask_empty(desc->pending_mask)))
Andrew Mortonc777ac52006-03-25 03:07:36 -080026 return;
27
Thomas Gleixnerc96b3b32010-09-27 12:45:41 +000028 if (!chip->irq_set_affinity)
Andrew Mortonc777ac52006-03-25 03:07:36 -080029 return;
30
Thomas Gleixner239007b2009-11-17 16:46:45 +010031 assert_raw_spin_locked(&desc->lock);
Bryan Holty501f2492006-03-25 03:07:37 -080032
Andrew Mortonc777ac52006-03-25 03:07:36 -080033 /*
34 * If there was a valid mask to work with, please
35 * do the disable, re-program, enable sequence.
36 * This is *not* particularly important for level triggered
37 * but in a edge trigger case, we might be setting rte
38 * when an active trigger is comming in. This could
39 * cause some ioapics to mal-function.
40 * Being paranoid i guess!
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070041 *
42 * For correct operation this depends on the caller
43 * masking the irqs.
Andrew Mortonc777ac52006-03-25 03:07:36 -080044 */
Mike Travis7f7ace02009-01-10 21:58:08 -080045 if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
Yinghai Lu57b150c2009-04-27 17:59:53 -070046 < nr_cpu_ids))
Thomas Gleixnerc96b3b32010-09-27 12:45:41 +000047 if (!chip->irq_set_affinity(&desc->irq_data,
48 desc->pending_mask, false)) {
Thomas Gleixner6b8ff312010-10-01 12:58:38 +020049 cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
Thomas Gleixner591d2fb2009-07-21 11:09:39 +020050 irq_set_thread_affinity(desc);
Yinghai Lu57b150c2009-04-27 17:59:53 -070051 }
52
Mike Travis7f7ace02009-01-10 21:58:08 -080053 cpumask_clear(desc->pending_mask);
Andrew Mortonc777ac52006-03-25 03:07:36 -080054}
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070055
56void move_native_irq(int irq)
57{
Yinghai Lu08678b02008-08-19 20:50:05 -070058 struct irq_desc *desc = irq_to_desc(irq);
Thomas Gleixnerf1a06392011-01-28 08:47:15 +010059 bool masked;
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070060
Thomas Gleixnerf230b6d2011-02-05 15:20:04 +010061 if (likely(!irqd_is_setaffinity_pending(&desc->irq_data)))
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070062 return;
63
Thomas Gleixnerc1594b72011-02-07 22:11:30 +010064 if (unlikely(desc->istate & IRQS_DISABLED))
Eric W. Biederman2a786b42007-02-23 04:46:20 -070065 return;
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070066
Thomas Gleixnerf1a06392011-01-28 08:47:15 +010067 /*
68 * Be careful vs. already masked interrupts. If this is a
69 * threaded interrupt with ONESHOT set, we can end up with an
70 * interrupt storm.
71 */
Thomas Gleixner6e402622011-02-08 12:36:06 +010072 masked = desc->istate & IRQS_MASKED;
Thomas Gleixnerf1a06392011-01-28 08:47:15 +010073 if (!masked)
74 desc->irq_data.chip->irq_mask(&desc->irq_data);
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070075 move_masked_irq(irq);
Thomas Gleixnerf1a06392011-01-28 08:47:15 +010076 if (!masked)
77 desc->irq_data.chip->irq_unmask(&desc->irq_data);
Eric W. Biedermane7b946e2006-10-04 02:16:29 -070078}