]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Feb 2015 23:20:40 +0000 (15:20 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Feb 2015 23:20:40 +0000 (15:20 -0800)
Pull irqchip updates from Ingo Molnar:
 "Various irqchip driver updates, plus a genirq core update that allows
  the initial spreading of irqs amonst CPUs without having to do it from
  user-space"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  genirq: Fix null pointer reference in irq_set_affinity_hint()
  irqchip: gic: Allow interrupt level to be set for PPIs
  irqchip: mips-gic: Handle pending interrupts once in __gic_irq_dispatch()
  irqchip: Conexant CX92755 interrupts controller driver
  irqchip: Devicetree: document Conexant Digicolor irq binding
  irqchip: omap-intc: Remove unused legacy interface for omap2
  irqchip: omap-intc: Fix support for dm814 and dm816
  irqchip: mtk-sysirq: Get irq number from register resource size
  irqchip: renesas-intc-irqpin: r8a7779 IRLM setup support
  genirq: Set initial affinity in irq_set_affinity_hint()

1  2 
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-mips-gic.c

index 2ab290bec6552328c214037efc0f6eaa5dff715d,6e508038f31b0328cb41a0964df9b57bb0f3099b..1c6dea2fbc34ce2d7b00007250111166315d8b78
@@@ -238,7 -238,9 +238,9 @@@ static int gic_set_type(struct irq_dat
        if (irq < 16)
                return -EINVAL;
  
-       if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
+       /* SPIs have restrictions on the supported types */
+       if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
+                        type != IRQ_TYPE_EDGE_RISING)
                return -EINVAL;
  
        if (gic_irq_in_rdist(d)) {
                rwp_wait = gic_dist_wait_for_rwp;
        }
  
-       gic_configure_irq(irq, type, base, rwp_wait);
-       return 0;
+       return gic_configure_irq(irq, type, base, rwp_wait);
  }
  
  static u64 gic_mpidr_to_affinity(u64 mpidr)
@@@ -481,19 -481,15 +481,19 @@@ out
        return tlist;
  }
  
 +#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
 +      (MPIDR_AFFINITY_LEVEL(cluster_id, level) \
 +              << ICC_SGI1R_AFFINITY_## level ##_SHIFT)
 +
  static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
  {
        u64 val;
  
 -      val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48        |
 -             MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32        |
 -             irq << 24                                        |
 -             MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16        |
 -             tlist);
 +      val = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3)     |
 +             MPIDR_TO_SGI_AFFINITY(cluster_id, 2)     |
 +             irq << ICC_SGI1R_SGI_ID_SHIFT            |
 +             MPIDR_TO_SGI_AFFINITY(cluster_id, 1)     |
 +             tlist << ICC_SGI1R_TARGET_LIST_SHIFT);
  
        pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
        gic_write_sgi1r(val);
index 56b96c63dc4bbc5479a3f51ef712fcbb70b4f5b6,f3f9873dfb689648663882041aef7815adca8c7e..1daa7ca04577de0854f77b1ff4d31faf241e0baa
@@@ -37,7 -37,6 +37,7 @@@ static struct irq_domain *gic_irq_domai
  static int gic_shared_intrs;
  static int gic_vpes;
  static unsigned int gic_cpu_pin;
 +static unsigned int timer_cpu_pin;
  static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
  
  static void __gic_irq_dispatch(void);
@@@ -235,9 -234,9 +235,9 @@@ int gic_get_c0_perfcount_int(void
                                  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
  }
  
- static unsigned int gic_get_int(void)
+ static void gic_handle_shared_int(void)
  {
-       unsigned int i;
+       unsigned int i, intr, virq;
        unsigned long *pcpu_mask;
        unsigned long pending_reg, intrmask_reg;
        DECLARE_BITMAP(pending, GIC_MAX_INTRS);
        bitmap_and(pending, pending, intrmask, gic_shared_intrs);
        bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
  
-       return find_first_bit(pending, gic_shared_intrs);
+       intr = find_first_bit(pending, gic_shared_intrs);
+       while (intr != gic_shared_intrs) {
+               virq = irq_linear_revmap(gic_irq_domain,
+                                        GIC_SHARED_TO_HWIRQ(intr));
+               do_IRQ(virq);
+               /* go to next pending bit */
+               bitmap_clear(pending, intr, 1);
+               intr = find_first_bit(pending, gic_shared_intrs);
+       }
  }
  
  static void gic_mask_irq(struct irq_data *d)
@@@ -386,16 -394,26 +395,26 @@@ static struct irq_chip gic_edge_irq_con
  #endif
  };
  
- static unsigned int gic_get_local_int(void)
+ static void gic_handle_local_int(void)
  {
        unsigned long pending, masked;
+       unsigned int intr, virq;
  
        pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
        masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
  
        bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
  
-       return find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
+       intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
+       while (intr != GIC_NUM_LOCAL_INTRS) {
+               virq = irq_linear_revmap(gic_irq_domain,
+                                        GIC_LOCAL_TO_HWIRQ(intr));
+               do_IRQ(virq);
+               /* go to next pending bit */
+               bitmap_clear(&pending, intr, 1);
+               intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
+       }
  }
  
  static void gic_mask_local_irq(struct irq_data *d)
@@@ -454,19 -472,8 +473,8 @@@ static struct irq_chip gic_all_vpes_loc
  
  static void __gic_irq_dispatch(void)
  {
-       unsigned int intr, virq;
-       while ((intr = gic_get_local_int()) != GIC_NUM_LOCAL_INTRS) {
-               virq = irq_linear_revmap(gic_irq_domain,
-                                        GIC_LOCAL_TO_HWIRQ(intr));
-               do_IRQ(virq);
-       }
-       while ((intr = gic_get_int()) != gic_shared_intrs) {
-               virq = irq_linear_revmap(gic_irq_domain,
-                                        GIC_SHARED_TO_HWIRQ(intr));
-               do_IRQ(virq);
-       }
+       gic_handle_local_int();
+       gic_handle_shared_int();
  }
  
  static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
@@@ -617,8 -624,6 +625,8 @@@ static int gic_local_irq_domain_map(str
                        gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
                        break;
                case GIC_LOCAL_INT_TIMER:
 +                      /* CONFIG_MIPS_CMP workaround (see __gic_init) */
 +                      val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
                        gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
                        break;
                case GIC_LOCAL_INT_PERFCTR:
@@@ -716,36 -721,12 +724,36 @@@ static void __init __gic_init(unsigned 
        if (cpu_has_veic) {
                /* Always use vector 1 in EIC mode */
                gic_cpu_pin = 0;
 +              timer_cpu_pin = gic_cpu_pin;
                set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
                               __gic_irq_dispatch);
        } else {
                gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
                irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
                                        gic_irq_dispatch);
 +              /*
 +               * With the CMP implementation of SMP (deprecated), other CPUs
 +               * are started by the bootloader and put into a timer based
 +               * waiting poll loop. We must not re-route those CPU's local
 +               * timer interrupts as the wait instruction will never finish,
 +               * so just handle whatever CPU interrupt it is routed to by
 +               * default.
 +               *
 +               * This workaround should be removed when CMP support is
 +               * dropped.
 +               */
 +              if (IS_ENABLED(CONFIG_MIPS_CMP) &&
 +                  gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
 +                      timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
 +                                                       GIC_VPE_TIMER_MAP)) &
 +                                      GIC_MAP_MSK;
 +                      irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
 +                                              GIC_CPU_PIN_OFFSET +
 +                                              timer_cpu_pin,
 +                                              gic_irq_dispatch);
 +              } else {
 +                      timer_cpu_pin = gic_cpu_pin;
 +              }
        }
  
        gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS +