diff mbox series

[Xen-devel,19/57] ARM: GICv3: poke_irq: make RWP optional

Message ID 20180305160415.16760-20-andre.przywara@linaro.org
State Superseded
Headers show
Series New VGIC(-v2) implementation | expand

Commit Message

Andre Przywara March 5, 2018, 4:03 p.m. UTC
A GICv3 hardware implementation can be implemented in several parts that
communicate with each other (think multi-socket systems).
To make sure that critical settings have arrived at all endpoints, some
bits are tracked using the RWP bit in the GICD_CTLR register, which
signals whether a register write is still in progress.
However this only applies to *some* registers, namely the bits in the
GICD_ICENABLER (disabling interrupts) and some bits in the GICD_CTLR
register (cf. Arm IHI 0069D, 8.9.4: RWP, bit[31]).
But our gicv3_poke_irq() was always polling this bit before returning,
resulting in pointless MMIO reads for many registers.
Add an option to gicv3_poke_irq() to state whether we want to wait for
this bit and use it accordingly to match the spec.

Signed-off-by: Andre Przywara <andre.przywara@linaro.org>
---
Changelog RFC ... v1:
- new patch

 xen/arch/arm/gic-v3.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

Comments

Julien Grall March 6, 2018, 3:37 p.m. UTC | #1
Hi Andre,

On 05/03/18 16:03, Andre Przywara wrote:
> A GICv3 hardware implementation can be implemented in several parts that
> communicate with each other (think multi-socket systems).
> To make sure that critical settings have arrived at all endpoints, some
> bits are tracked using the RWP bit in the GICD_CTLR register, which
> signals whether a register write is still in progress.
> However this only applies to *some* registers, namely the bits in the
> GICD_ICENABLER (disabling interrupts) and some bits in the GICD_CTLR
> register (cf. Arm IHI 0069D, 8.9.4: RWP, bit[31]).
> But our gicv3_poke_irq() was always polling this bit before returning,
> resulting in pointless MMIO reads for many registers.
> Add an option to gicv3_poke_irq() to state whether we want to wait for
> this bit and use it accordingly to match the spec.
> 
> Signed-off-by: Andre Przywara <andre.przywara@linaro.org>
> ---
> Changelog RFC ... v1:
> - new patch
> 
>   xen/arch/arm/gic-v3.c | 12 +++++++-----
>   1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index 3e381d031b..44dfba2267 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -428,9 +428,9 @@ static void gicv3_dump_state(const struct vcpu *v)
>       }
>   }
>   
> -static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset)
> +static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset, bool wait_for_rwp)
>   {
> -    u32 mask = 1 << (irqd->irq % 32);
> +    u32 mask = 1U << (irqd->irq % 32);

Do you mind adding a word about 1U in the commit message?

With that:

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,
diff mbox series

Patch

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 3e381d031b..44dfba2267 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -428,9 +428,9 @@  static void gicv3_dump_state(const struct vcpu *v)
     }
 }
 
-static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset)
+static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset, bool wait_for_rwp)
 {
-    u32 mask = 1 << (irqd->irq % 32);
+    u32 mask = 1U << (irqd->irq % 32);
     void __iomem *base;
 
     if ( irqd->irq < NR_GIC_LOCAL_IRQS )
@@ -439,17 +439,19 @@  static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset)
         base = GICD;
 
     writel_relaxed(mask, base + offset + (irqd->irq / 32) * 4);
-    gicv3_wait_for_rwp(irqd->irq);
+
+    if ( wait_for_rwp )
+        gicv3_wait_for_rwp(irqd->irq);
 }
 
 static void gicv3_unmask_irq(struct irq_desc *irqd)
 {
-    gicv3_poke_irq(irqd, GICD_ISENABLER);
+    gicv3_poke_irq(irqd, GICD_ISENABLER, false);
 }
 
 static void gicv3_mask_irq(struct irq_desc *irqd)
 {
-    gicv3_poke_irq(irqd, GICD_ICENABLER);
+    gicv3_poke_irq(irqd, GICD_ICENABLER, true);
 }
 
 static void gicv3_eoi_irq(struct irq_desc *irqd)