[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 01/10] xen/arm: gicv3: refactor obtaining GIC addresses for common operations
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_komarianskyi@xxxxxxxx> --- 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. */ -- 2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |