Hi,
Leonid Komarianskyi <leonid_komarians...@epam.com> writes: > Currently, many common functions perform the same operations to calculate > GIC register addresses. This patch consolidates the similar code into > a separate helper function to improve maintainability and reduce duplication. > This refactoring also simplifies the implementation of eSPI support in future > changes. > > Signed-off-by: Leonid Komarianskyi <leonid_komarians...@epam.com> Reviewed-by: Volodymyr Babchuk <volodymyr_babc...@epam.com> > > --- > Changes in V2: > - no changes > --- > xen/arch/arm/gic-v3.c | 99 ++++++++++++++++++++++------------ > xen/arch/arm/include/asm/irq.h | 1 + > 2 files changed, 67 insertions(+), 33 deletions(-) > > diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c > index cd3e1acf79..8fd78aba44 100644 > --- a/xen/arch/arm/gic-v3.c > +++ b/xen/arch/arm/gic-v3.c > @@ -445,17 +445,62 @@ static void gicv3_dump_state(const struct vcpu *v) > } > } > > +static void __iomem *get_addr_by_offset(struct irq_desc *irqd, u32 offset) > +{ > + switch ( irqd->irq ) > + { > + case 0 ... (NR_GIC_LOCAL_IRQS - 1): > + switch ( offset ) > + { > + case GICD_ISENABLER: > + case GICD_ICENABLER: > + case GICD_ISPENDR: > + case GICD_ICPENDR: > + case GICD_ISACTIVER: > + case GICD_ICACTIVER: > + return (GICD_RDIST_SGI_BASE + offset); > + case GICD_ICFGR: > + return (GICD_RDIST_SGI_BASE + GICR_ICFGR1); > + case GICD_IPRIORITYR: > + return (GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + irqd->irq); > + default: > + break; > + } > + case NR_GIC_LOCAL_IRQS ... SPI_MAX_INTID: > + switch ( offset ) > + { > + case GICD_ISENABLER: > + case GICD_ICENABLER: > + case GICD_ISPENDR: > + case GICD_ICPENDR: > + case GICD_ISACTIVER: > + case GICD_ICACTIVER: > + return (GICD + offset + (irqd->irq / 32) * 4); > + case GICD_ICFGR: > + return (GICD + GICD_ICFGR + (irqd->irq / 16) * 4); > + case GICD_IROUTER: > + return (GICD + GICD_IROUTER + irqd->irq * 8); > + case GICD_IPRIORITYR: > + return (GICD + GICD_IPRIORITYR + irqd->irq); > + default: > + break; > + } > + default: > + break; > + } > + > + /* Something went wrong, we shouldn't be able to reach here */ > + panic("Invalid offset 0x%x for IRQ#%d", offset, irqd->irq); > + > + return NULL; > +} > + > static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset, bool > wait_for_rwp) > { > u32 mask = 1U << (irqd->irq % 32); > - void __iomem *base; > - > - if ( irqd->irq < NR_GIC_LOCAL_IRQS ) > - base = GICD_RDIST_SGI_BASE; > - else > - base = GICD; > + void __iomem *addr = get_addr_by_offset(irqd, offset); > > - writel_relaxed(mask, base + offset + (irqd->irq / 32) * 4); > + writel_relaxed(mask, addr); > > if ( wait_for_rwp ) > gicv3_wait_for_rwp(irqd->irq); > @@ -463,15 +508,9 @@ static void gicv3_poke_irq(struct irq_desc *irqd, u32 > offset, bool wait_for_rwp) > > static bool gicv3_peek_irq(struct irq_desc *irqd, u32 offset) > { > - void __iomem *base; > - unsigned int irq = irqd->irq; > - > - if ( irq >= NR_GIC_LOCAL_IRQS) > - base = GICD + (irq / 32) * 4; > - else > - base = GICD_RDIST_SGI_BASE; > + void __iomem *addr = get_addr_by_offset(irqd, offset); > > - return !!(readl(base + offset) & (1U << (irq % 32))); > + return !!(readl(addr) & (1U << (irqd->irq % 32))); > } > > static void gicv3_unmask_irq(struct irq_desc *irqd) > @@ -558,30 +597,26 @@ static inline uint64_t gicv3_mpidr_to_affinity(int cpu) > static void gicv3_set_irq_type(struct irq_desc *desc, unsigned int type) > { > uint32_t cfg, actual, edgebit; > - void __iomem *base; > - unsigned int irq = desc->irq; > + void __iomem *addr; > > /* SGI's are always edge-triggered not need to call GICD_ICFGR0 */ > - ASSERT(irq >= NR_GIC_SGI); > + ASSERT(desc->irq >= NR_GIC_SGI); > > spin_lock(&gicv3.lock); > > - if ( irq >= NR_GIC_LOCAL_IRQS) > - base = GICD + GICD_ICFGR + (irq / 16) * 4; > - else > - base = GICD_RDIST_SGI_BASE + GICR_ICFGR1; > + addr = get_addr_by_offset(desc, GICD_ICFGR); > > - cfg = readl_relaxed(base); > + cfg = readl_relaxed(addr); > > - edgebit = 2u << (2 * (irq % 16)); > + edgebit = 2u << (2 * (desc->irq % 16)); > if ( type & IRQ_TYPE_LEVEL_MASK ) > cfg &= ~edgebit; > else if ( type & IRQ_TYPE_EDGE_BOTH ) > cfg |= edgebit; > > - writel_relaxed(cfg, base); > + writel_relaxed(cfg, addr); > > - actual = readl_relaxed(base); > + actual = readl_relaxed(addr); > if ( ( cfg & edgebit ) ^ ( actual & edgebit ) ) > { > printk(XENLOG_WARNING "GICv3: WARNING: " > @@ -600,15 +635,12 @@ static void gicv3_set_irq_type(struct irq_desc *desc, > unsigned int type) > static void gicv3_set_irq_priority(struct irq_desc *desc, > unsigned int priority) > { > - unsigned int irq = desc->irq; > + void __iomem *addr; > > spin_lock(&gicv3.lock); > > - /* Set priority */ > - if ( irq < NR_GIC_LOCAL_IRQS ) > - writeb_relaxed(priority, GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + > irq); > - else > - writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq); > + addr = get_addr_by_offset(desc, GICD_IPRIORITYR); > + writeb_relaxed(priority, addr); > > spin_unlock(&gicv3.lock); > } > @@ -1273,6 +1305,7 @@ static void gicv3_irq_set_affinity(struct irq_desc > *desc, const cpumask_t *mask) > { > unsigned int cpu; > uint64_t affinity; > + void __iomem *addr = get_addr_by_offset(desc, GICD_IROUTER); > > ASSERT(!cpumask_empty(mask)); > > @@ -1284,7 +1317,7 @@ static void gicv3_irq_set_affinity(struct irq_desc > *desc, const cpumask_t *mask) > affinity &= ~GICD_IROUTER_SPI_MODE_ANY; > > if ( desc->irq >= NR_GIC_LOCAL_IRQS ) > - writeq_relaxed_non_atomic(affinity, (GICD + GICD_IROUTER + desc->irq > * 8)); > + writeq_relaxed_non_atomic(affinity, addr); > > spin_unlock(&gicv3.lock); > } > diff --git a/xen/arch/arm/include/asm/irq.h b/xen/arch/arm/include/asm/irq.h > index fce7e42a33..5bc6475eb4 100644 > --- a/xen/arch/arm/include/asm/irq.h > +++ b/xen/arch/arm/include/asm/irq.h > @@ -29,6 +29,7 @@ struct arch_irq_desc { > */ > #define NR_IRQS 1024 > > +#define SPI_MAX_INTID 1019 > #define LPI_OFFSET 8192 > > /* LPIs are always numbered starting at 8192, so 0 is a good invalid case. */ -- WBR, Volodymyr