irqchip/gic-v3-its: Allow doorbell interrupts to be injected/cleared
authorMarc Zyngier <marc.zyngier@arm.com>
Mon, 31 Jul 2017 13:47:24 +0000 (14:47 +0100)
committerMarc Zyngier <marc.zyngier@arm.com>
Thu, 31 Aug 2017 14:31:39 +0000 (15:31 +0100)
While the doorbell interrupts are usually driven by the HW itself,
having a way to trigger them independently has proved to be a
really useful debug feature. As it is actually very little code,
let's add it to the VPE irqchip operations.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
drivers/irqchip/irq-gic-v3-its.c

index f5068a95d3c4c9f0ffab665bef735c03233422a4..21ee33e81c741ed69ccbfbce80601ffb9708fdcf 100644 (file)
@@ -2504,12 +2504,43 @@ static void its_vpe_unmask_irq(struct irq_data *d)
        its_vpe_send_inv(d);
 }
 
+static int its_vpe_set_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which,
+                                    bool state)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+       if (which != IRQCHIP_STATE_PENDING)
+               return -EINVAL;
+
+       if (gic_rdists->has_direct_lpi) {
+               void __iomem *rdbase;
+
+               rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
+               if (state) {
+                       gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_SETLPIR);
+               } else {
+                       gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_CLRLPIR);
+                       while (gic_read_lpir(rdbase + GICR_SYNCR) & 1)
+                               cpu_relax();
+               }
+       } else {
+               if (state)
+                       its_vpe_send_cmd(vpe, its_send_int);
+               else
+                       its_vpe_send_cmd(vpe, its_send_clear);
+       }
+
+       return 0;
+}
+
 static struct irq_chip its_vpe_irq_chip = {
        .name                   = "GICv4-vpe",
        .irq_mask               = its_vpe_mask_irq,
        .irq_unmask             = its_vpe_unmask_irq,
        .irq_eoi                = irq_chip_eoi_parent,
        .irq_set_affinity       = its_vpe_set_affinity,
+       .irq_set_irqchip_state  = its_vpe_set_irqchip_state,
        .irq_set_vcpu_affinity  = its_vpe_set_vcpu_affinity,
 };