diff options
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.patch | 217 |
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); - } |