summaryrefslogtreecommitdiff
path: root/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch')
-rw-r--r--target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch217
1 files changed, 0 insertions, 217 deletions
diff --git a/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch b/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
deleted file mode 100644
index 4345d3e..0000000
--- a/target/linux/sunxi/patches-3.14/136-1-irqchip-sun4i-fixes.patch
+++ /dev/null
@@ -1,217 +0,0 @@
-From 843da234cfc0e7014f9e2da82786a485e0820665 Mon Sep 17 00:00:00 2001
-From: Thomas Gleixner <tglx@linutronix.de>
-Date: Thu, 13 Mar 2014 15:32:05 +0100
-Subject: [PATCH] irq: Add a new IRQCHIP_EOI_THREADED flag
-
-This flag must be used in combination with handle_fasteoi_irq, when set
-handle_fasteoi_irq will delay the calling of chip->irq_eoi until the threaded
-handler has run.
-
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Tested-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- include/linux/irq.h | 3 +++
- kernel/irq/chip.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
- kernel/irq/internals.h | 1 +
- kernel/irq/manage.c | 2 +-
- 4 files changed, 45 insertions(+), 9 deletions(-)
-
---- a/include/linux/irq.h
-+++ b/include/linux/irq.h
-@@ -349,6 +349,8 @@ struct irq_chip {
- * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
- * when irq enabled
- * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
-+ * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
-+ * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
- */
- enum {
- IRQCHIP_SET_TYPE_MASKED = (1 << 0),
-@@ -357,6 +359,7 @@ enum {
- IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
- IRQCHIP_SKIP_SET_WAKE = (1 << 4),
- IRQCHIP_ONESHOT_SAFE = (1 << 5),
-+ IRQCHIP_EOI_THREADED = (1 << 6),
- };
-
- /* This include will go away once we isolated irq_desc usage to core code */
---- a/kernel/irq/chip.c
-+++ b/kernel/irq/chip.c
-@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
- }
- }
-
-+void unmask_threaded_irq(struct irq_desc *desc)
-+{
-+ struct irq_chip *chip = desc->irq_data.chip;
-+
-+ if (chip->flags & IRQCHIP_EOI_THREADED)
-+ chip->irq_eoi(&desc->irq_data);
-+
-+ if (chip->irq_unmask) {
-+ chip->irq_unmask(&desc->irq_data);
-+ irq_state_clr_masked(desc);
-+ }
-+}
-+
- /*
- * handle_nested_irq - Handle a nested irq from a irq thread
- * @irq: the interrupt number
-@@ -435,6 +448,27 @@ static inline void preflow_handler(struc
- static inline void preflow_handler(struct irq_desc *desc) { }
- #endif
-
-+static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
-+{
-+ if (!(desc->istate & IRQS_ONESHOT)) {
-+ chip->irq_eoi(&desc->irq_data);
-+ return;
-+ }
-+ /*
-+ * We need to unmask in the following cases:
-+ * - Oneshot irq which did not wake the thread (caused by a
-+ * spurious interrupt or a primary handler handling it
-+ * completely).
-+ */
-+ if (!irqd_irq_disabled(&desc->irq_data) &&
-+ irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
-+ chip->irq_eoi(&desc->irq_data);
-+ unmask_irq(desc);
-+ } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
-+ chip->irq_eoi(&desc->irq_data);
-+ }
-+}
-+
- /**
- * handle_fasteoi_irq - irq handler for transparent controllers
- * @irq: the interrupt number
-@@ -448,6 +482,8 @@ static inline void preflow_handler(struc
- void
- handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
- {
-+ struct irq_chip *chip = desc->irq_data.chip;
-+
- raw_spin_lock(&desc->lock);
-
- if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
-@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, str
- preflow_handler(desc);
- handle_irq_event(desc);
-
-- if (desc->istate & IRQS_ONESHOT)
-- cond_unmask_irq(desc);
-+ cond_unmask_eoi_irq(desc, chip);
-
--out_eoi:
-- desc->irq_data.chip->irq_eoi(&desc->irq_data);
--out_unlock:
- raw_spin_unlock(&desc->lock);
- return;
- out:
-- if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
-- goto out_eoi;
-- goto out_unlock;
-+ if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
-+ chip->irq_eoi(&desc->irq_data);
-+ raw_spin_unlock(&desc->lock);
- }
-
- /**
---- a/kernel/irq/internals.h
-+++ b/kernel/irq/internals.h
-@@ -73,6 +73,7 @@ extern void irq_percpu_enable(struct irq
- extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
- extern void mask_irq(struct irq_desc *desc);
- extern void unmask_irq(struct irq_desc *desc);
-+extern void unmask_threaded_irq(struct irq_desc *desc);
-
- extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
-
---- a/kernel/irq/manage.c
-+++ b/kernel/irq/manage.c
-@@ -713,7 +713,7 @@ again:
-
- if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data))
-- unmask_irq(desc);
-+ unmask_threaded_irq(desc);
-
- out_unlock:
- raw_spin_unlock_irq(&desc->lock);
---- a/drivers/irqchip/irq-sun4i.c
-+++ b/drivers/irqchip/irq-sun4i.c
-@@ -41,13 +41,11 @@ static asmlinkage void __exception_irq_e
- static void sun4i_irq_ack(struct irq_data *irqd)
- {
- unsigned int irq = irqd_to_hwirq(irqd);
-- unsigned int irq_off = irq % 32;
-- int reg = irq / 32;
-- u32 val;
-
-- val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-- writel(val | (1 << irq_off),
-- sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
-+ if (irq != 0)
-+ return; /* Only IRQ 0 / the ENMI needs to be acked */
-+
-+ writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
- }
-
- static void sun4i_irq_mask(struct irq_data *irqd)
-@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_
-
- static struct irq_chip sun4i_irq_chip = {
- .name = "sun4i_irq",
-- .irq_ack = sun4i_irq_ack,
-+ .irq_eoi = sun4i_irq_ack,
- .irq_mask = sun4i_irq_mask,
- .irq_unmask = sun4i_irq_unmask,
-+ .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
- };
-
- static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
- {
-- irq_set_chip_and_handler(virq, &sun4i_irq_chip,
-- handle_level_irq);
-+ irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct d
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
-
-- /* Mask all the interrupts */
-+ /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
- writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
-@@ -140,10 +138,24 @@ static asmlinkage void __exception_irq_e
- {
- u32 irq, hwirq;
-
-+ /*
-+ * hwirq == 0 can mean one of 3 things:
-+ * 1) no more irqs pending
-+ * 2) irq 0 pending
-+ * 3) spurious irq
-+ * So if we immediately get a reading of 0, check the irq-pending reg
-+ * to differentiate between 2 and 3. We only do this once to avoid
-+ * the extra check in the common case of 1 hapening after having
-+ * read the vector-reg once.
-+ */
- hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
-- while (hwirq != 0) {
-+ if (hwirq == 0 &&
-+ !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
-+ return;
-+
-+ do {
- irq = irq_find_mapping(sun4i_irq_domain, hwirq);
- handle_IRQ(irq, regs);
- hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
-- }
-+ } while (hwirq != 0);
- }