aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-11 13:14:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-11 13:14:24 -0500
commit21a7061c5ec300a8a12a0d6468eb7094e9c54a32 (patch)
treec87ed9874098073fb3411a8fbb12f2b1acd02186
parent2b95550a4323e501e133dac1c9c9cad6ff17f4c1 (diff)
parentd128dfb514f55af040c38a6b3b131d72b6f115d0 (diff)
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Ingo Molnar: "Two last minute ARM irqchip driver fixes" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/mxs: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND irqchip/keystone: Fix "scheduling while atomic" on rt
-rw-r--r--drivers/irqchip/irq-keystone.c28
-rw-r--r--drivers/irqchip/irq-mxs.c4
2 files changed, 23 insertions, 9 deletions
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index 54a5e870a8f5..efbcf8435185 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -19,9 +19,9 @@
19#include <linux/bitops.h> 19#include <linux/bitops.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/moduleparam.h> 21#include <linux/moduleparam.h>
22#include <linux/interrupt.h>
22#include <linux/irqdomain.h> 23#include <linux/irqdomain.h>
23#include <linux/irqchip.h> 24#include <linux/irqchip.h>
24#include <linux/irqchip/chained_irq.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_platform.h> 26#include <linux/of_platform.h>
27#include <linux/mfd/syscon.h> 27#include <linux/mfd/syscon.h>
@@ -39,6 +39,7 @@ struct keystone_irq_device {
39 struct irq_domain *irqd; 39 struct irq_domain *irqd;
40 struct regmap *devctrl_regs; 40 struct regmap *devctrl_regs;
41 u32 devctrl_offset; 41 u32 devctrl_offset;
42 raw_spinlock_t wa_lock;
42}; 43};
43 44
44static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq) 45static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
@@ -83,17 +84,15 @@ static void keystone_irq_ack(struct irq_data *d)
83 /* nothing to do here */ 84 /* nothing to do here */
84} 85}
85 86
86static void keystone_irq_handler(struct irq_desc *desc) 87static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
87{ 88{
88 unsigned int irq = irq_desc_get_irq(desc); 89 struct keystone_irq_device *kirq = keystone_irq;
89 struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc); 90 unsigned long wa_lock_flags;
90 unsigned long pending; 91 unsigned long pending;
91 int src, virq; 92 int src, virq;
92 93
93 dev_dbg(kirq->dev, "start irq %d\n", irq); 94 dev_dbg(kirq->dev, "start irq %d\n", irq);
94 95
95 chained_irq_enter(irq_desc_get_chip(desc), desc);
96
97 pending = keystone_irq_readl(kirq); 96 pending = keystone_irq_readl(kirq);
98 keystone_irq_writel(kirq, pending); 97 keystone_irq_writel(kirq, pending);
99 98
@@ -111,13 +110,15 @@ static void keystone_irq_handler(struct irq_desc *desc)
111 if (!virq) 110 if (!virq)
112 dev_warn(kirq->dev, "spurious irq detected hwirq %d, virq %d\n", 111 dev_warn(kirq->dev, "spurious irq detected hwirq %d, virq %d\n",
113 src, virq); 112 src, virq);
113 raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
114 generic_handle_irq(virq); 114 generic_handle_irq(virq);
115 raw_spin_unlock_irqrestore(&kirq->wa_lock,
116 wa_lock_flags);
115 } 117 }
116 } 118 }
117 119
118 chained_irq_exit(irq_desc_get_chip(desc), desc);
119
120 dev_dbg(kirq->dev, "end irq %d\n", irq); 120 dev_dbg(kirq->dev, "end irq %d\n", irq);
121 return IRQ_HANDLED;
121} 122}
122 123
123static int keystone_irq_map(struct irq_domain *h, unsigned int virq, 124static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
@@ -182,9 +183,16 @@ static int keystone_irq_probe(struct platform_device *pdev)
182 return -ENODEV; 183 return -ENODEV;
183 } 184 }
184 185
186 raw_spin_lock_init(&kirq->wa_lock);
187
185 platform_set_drvdata(pdev, kirq); 188 platform_set_drvdata(pdev, kirq);
186 189
187 irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq); 190 ret = request_irq(kirq->irq, keystone_irq_handler,
191 0, dev_name(dev), kirq);
192 if (ret) {
193 irq_domain_remove(kirq->irqd);
194 return ret;
195 }
188 196
189 /* clear all source bits */ 197 /* clear all source bits */
190 keystone_irq_writel(kirq, ~0x0); 198 keystone_irq_writel(kirq, ~0x0);
@@ -199,6 +207,8 @@ static int keystone_irq_remove(struct platform_device *pdev)
199 struct keystone_irq_device *kirq = platform_get_drvdata(pdev); 207 struct keystone_irq_device *kirq = platform_get_drvdata(pdev);
200 int hwirq; 208 int hwirq;
201 209
210 free_irq(kirq->irq, kirq);
211
202 for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++) 212 for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++)
203 irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq)); 213 irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq));
204 214
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 17304705f2cf..05fa9f7af53c 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -131,12 +131,16 @@ static struct irq_chip mxs_icoll_chip = {
131 .irq_ack = icoll_ack_irq, 131 .irq_ack = icoll_ack_irq,
132 .irq_mask = icoll_mask_irq, 132 .irq_mask = icoll_mask_irq,
133 .irq_unmask = icoll_unmask_irq, 133 .irq_unmask = icoll_unmask_irq,
134 .flags = IRQCHIP_MASK_ON_SUSPEND |
135 IRQCHIP_SKIP_SET_WAKE,
134}; 136};
135 137
136static struct irq_chip asm9260_icoll_chip = { 138static struct irq_chip asm9260_icoll_chip = {
137 .irq_ack = icoll_ack_irq, 139 .irq_ack = icoll_ack_irq,
138 .irq_mask = asm9260_mask_irq, 140 .irq_mask = asm9260_mask_irq,
139 .irq_unmask = asm9260_unmask_irq, 141 .irq_unmask = asm9260_unmask_irq,
142 .flags = IRQCHIP_MASK_ON_SUSPEND |
143 IRQCHIP_SKIP_SET_WAKE,
140}; 144};
141 145
142asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) 146asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)