diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-11 13:14:24 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-11 13:14:24 -0500 |
| commit | 21a7061c5ec300a8a12a0d6468eb7094e9c54a32 (patch) | |
| tree | c87ed9874098073fb3411a8fbb12f2b1acd02186 | |
| parent | 2b95550a4323e501e133dac1c9c9cad6ff17f4c1 (diff) | |
| parent | d128dfb514f55af040c38a6b3b131d72b6f115d0 (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.c | 28 | ||||
| -rw-r--r-- | drivers/irqchip/irq-mxs.c | 4 |
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 | ||
| 44 | static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq) | 45 | static 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 | ||
| 86 | static void keystone_irq_handler(struct irq_desc *desc) | 87 | static 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 | ||
| 123 | static int keystone_irq_map(struct irq_domain *h, unsigned int virq, | 124 | static 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 | ||
| 136 | static struct irq_chip asm9260_icoll_chip = { | 138 | static 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 | ||
| 142 | asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) | 146 | asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) |
