irqchip: gic-v3: ipipe: enable pipelined interrupts
authorGilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Sun, 3 Dec 2017 16:28:59 +0000 (17:28 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 27 Apr 2018 09:21:34 +0000 (11:21 +0200)
drivers/irqchip/irq-gic-v3.c

index 3b35271114eef1424162d7e0b517253d7732485a..ec129349049397e7d4c216e9efcf08ee321d19ee 100644 (file)
@@ -200,7 +200,12 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
 
 static void gic_mask_irq(struct irq_data *d)
 {
+       unsigned long flags;
+
+       flags = hard_cond_local_irq_save();
+       ipipe_lock_irq(d->irq);
        gic_poke_irq(d, GICD_ICENABLER);
+       hard_cond_local_irq_restore(flags);
 }
 
 static void gic_eoimode1_mask_irq(struct irq_data *d)
@@ -220,7 +225,12 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
+       unsigned long flags;
+
+       flags = hard_cond_local_irq_save();
        gic_poke_irq(d, GICD_ISENABLER);
+       ipipe_unlock_irq(d->irq);
+       hard_cond_local_irq_restore(flags);
 }
 
 static int gic_irq_set_irqchip_state(struct irq_data *d,
@@ -294,6 +304,27 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
        gic_write_dir(gic_irq(d));
 }
 
+#ifdef CONFIG_IPIPE
+static void gic_hold_irq(struct irq_data *d)
+{
+       struct irq_chip *chip = irq_data_get_irq_chip(d);
+
+       gic_poke_irq(d, GICD_ICENABLER);
+
+       if (chip->irq_eoi == gic_eoimode1_eoi_irq) {
+               if (irqd_is_forwarded_to_vcpu(d))
+                       gic_poke_irq(d, GICD_ICACTIVER);
+               gic_eoimode1_eoi_irq(d);
+       } else
+               gic_eoi_irq(d);
+}
+
+static void gic_release_irq(struct irq_data *d)
+{
+       gic_poke_irq(d, GICD_ISENABLER);
+}
+#endif /* CONFIG_IPIPE */
+
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
        unsigned int irq = gic_irq(d);
@@ -356,7 +387,7 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
                        else
                                isb();
 
-                       err = handle_domain_irq(gic_data.domain, irqnr, regs);
+                       err = ipipe_handle_domain_irq(gic_data.domain, irqnr, regs);
                        if (err) {
                                WARN_ONCE(true, "Unexpected interrupt received!\n");
                                if (static_key_true(&supports_deactivate)) {
@@ -380,7 +411,7 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
                         * that any shared data read by handle_IPI will
                         * be read after the ACK.
                         */
-                       handle_IPI(irqnr, regs);
+                       ipipe_handle_multi_ipi(irqnr, regs);
 #else
                        WARN_ONCE(true, "Unexpected SGI received!\n");
 #endif
@@ -769,10 +800,14 @@ static struct irq_chip gic_chip = {
        .irq_unmask             = gic_unmask_irq,
        .irq_eoi                = gic_eoi_irq,
        .irq_set_type           = gic_set_type,
+#ifdef CONFIG_IPIPE
+       .irq_hold               = gic_hold_irq,
+       .irq_release            = gic_release_irq,
+#endif
        .irq_set_affinity       = gic_set_affinity,
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_PIPELINE_SAFE,
 };
 
 static struct irq_chip gic_eoimode1_chip = {
@@ -781,11 +816,15 @@ static struct irq_chip gic_eoimode1_chip = {
        .irq_unmask             = gic_unmask_irq,
        .irq_eoi                = gic_eoimode1_eoi_irq,
        .irq_set_type           = gic_set_type,
+#ifdef CONFIG_IPIPE
+       .irq_hold               = gic_hold_irq,
+       .irq_release            = gic_release_irq,
+#endif
        .irq_set_affinity       = gic_set_affinity,
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
        .irq_set_vcpu_affinity  = gic_irq_set_vcpu_affinity,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_PIPELINE_SAFE,
 };
 
 #define GIC_ID_NR              (1U << gic_data.rdists.id_bits)