diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-12-20 18:20:38 +0300 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2017-08-31 17:31:38 +0300 |
commit | f6a91da7c788ac7345305ee291d0b205d2f5a70f (patch) | |
tree | 559000b999db33baa125b9ea604757058ec62f9c /drivers/irqchip | |
parent | 3171a47a22eedfb6e97803fb193fc98cdb61d90f (diff) | |
download | linux-f6a91da7c788ac7345305ee291d0b205d2f5a70f.tar.xz |
irqchip/gic-v3-its: Add VPE interrupt masking
When masking/unmasking a doorbell interrupt, it is necessary
to issue an invalidation to the corresponding redistributor.
We use the DirectLPI feature by writting directly to the corresponding
redistributor.
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index ab25b57866cd..9040fb41d446 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2336,8 +2336,41 @@ static int its_vpe_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) } } +static void its_vpe_send_inv(struct irq_data *d) +{ + struct its_vpe *vpe = irq_data_get_irq_chip_data(d); + void __iomem *rdbase; + + rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base; + gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_INVLPIR); + while (gic_read_lpir(rdbase + GICR_SYNCR) & 1) + cpu_relax(); +} + +static void its_vpe_mask_irq(struct irq_data *d) +{ + /* + * We need to unmask the LPI, which is described by the parent + * irq_data. Instead of calling into the parent (which won't + * exactly do the right thing, let's simply use the + * parent_data pointer. Yes, I'm naughty. + */ + lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0); + its_vpe_send_inv(d); +} + +static void its_vpe_unmask_irq(struct irq_data *d) +{ + /* Same hack as above... */ + lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED); + its_vpe_send_inv(d); +} + 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_vcpu_affinity = its_vpe_set_vcpu_affinity, }; |