Skip to content

Commit

Permalink
irqchip/gic-v3: Make distributor priorities variables
Browse files Browse the repository at this point in the history
In subsequent patches the GICv3 driver will choose the regular interrupt
priority at boot time.

In preparation for using dynamic priorities, place the priorities in
variables and update the code to pass these as parameters. Users of
GICD_INT_DEF_PRI_X4 are modified to replicate the priority byte using
REPEAT_BYTE_U32().

There should be no functional change as a result of this patch.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Alexandru Elisei <alexandru.elisei@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Tested-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240617111841.2529370-4-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Mark Rutland authored and ctmarinas committed Jun 24, 2024
1 parent e95c64a commit a6156e7
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 30 deletions.
10 changes: 6 additions & 4 deletions drivers/irqchip/irq-gic-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/kernel.h>

#include "irq-gic-common.h"

Expand Down Expand Up @@ -87,7 +88,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
return ret;
}

void gic_dist_config(void __iomem *base, int gic_irqs)
void gic_dist_config(void __iomem *base, int gic_irqs, u8 priority)
{
unsigned int i;

Expand All @@ -102,7 +103,8 @@ void gic_dist_config(void __iomem *base, int gic_irqs)
* Set priority on all global interrupts.
*/
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
writel_relaxed(REPEAT_BYTE_U32(priority),
base + GIC_DIST_PRI + i);

/*
* Deactivate and disable all SPIs. Leave the PPI and SGIs
Expand All @@ -116,7 +118,7 @@ void gic_dist_config(void __iomem *base, int gic_irqs)
}
}

void gic_cpu_config(void __iomem *base, int nr)
void gic_cpu_config(void __iomem *base, int nr, u8 priority)
{
int i;

Expand All @@ -135,6 +137,6 @@ void gic_cpu_config(void __iomem *base, int nr)
* Set priority on PPI and SGI interrupts
*/
for (i = 0; i < nr; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4,
writel_relaxed(REPEAT_BYTE_U32(priority),
base + GIC_DIST_PRI + i * 4 / 4);
}
4 changes: 2 additions & 2 deletions drivers/irqchip/irq-gic-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ struct gic_quirk {

int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base);
void gic_dist_config(void __iomem *base, int gic_irqs);
void gic_cpu_config(void __iomem *base, int nr);
void gic_dist_config(void __iomem *base, int gic_irqs, u8 priority);
void gic_cpu_config(void __iomem *base, int nr, u8 priority);
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data);
void gic_enable_of_quirks(const struct device_node *np,
Expand Down
11 changes: 6 additions & 5 deletions drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static u32 lpi_id_bits;
#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)

#define LPI_PROP_DEFAULT_PRIO GICD_INT_DEF_PRI
static u8 __ro_after_init lpi_prop_prio;

/*
* Collection structure - just an ID, and a redistributor address to
Expand Down Expand Up @@ -1926,7 +1926,7 @@ static int its_vlpi_unmap(struct irq_data *d)
/* and restore the physical one */
irqd_clr_forwarded_to_vcpu(d);
its_send_mapti(its_dev, d->hwirq, event);
lpi_update_config(d, 0xff, (LPI_PROP_DEFAULT_PRIO |
lpi_update_config(d, 0xff, (lpi_prop_prio |
LPI_PROP_ENABLED |
LPI_PROP_GROUP1));

Expand Down Expand Up @@ -2181,8 +2181,8 @@ static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)

static void gic_reset_prop_table(void *va)
{
/* Priority 0xa0, Group-1, disabled */
memset(va, LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);
/* Regular IRQ priority, Group-1, disabled */
memset(va, lpi_prop_prio | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);

/* Make sure the GIC will observe the written configuration */
gic_flush_dcache_to_poc(va, LPI_PROPBASE_SZ);
Expand Down Expand Up @@ -5650,7 +5650,7 @@ int __init its_lpi_memreserve_init(void)
}

int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
struct irq_domain *parent_domain)
struct irq_domain *parent_domain, u8 irq_prio)
{
struct device_node *of_node;
struct its_node *its;
Expand All @@ -5660,6 +5660,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,

gic_rdists = rdists;

lpi_prop_prio = irq_prio;
its_parent = parent_domain;
of_node = to_of_node(handle);
if (of_node)
Expand Down
19 changes: 11 additions & 8 deletions drivers/irqchip/irq-gic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/kstrtox.h>
#include <linux/of.h>
#include <linux/of_address.h>
Expand All @@ -36,7 +37,8 @@

#include "irq-gic-common.h"

#define GICD_INT_NMI_PRI (GICD_INT_DEF_PRI & ~0x80)
static u8 dist_prio_irq __ro_after_init = GICD_INT_DEF_PRI;
static u8 dist_prio_nmi __ro_after_init = GICD_INT_DEF_PRI & ~0x80;

#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
Expand Down Expand Up @@ -556,7 +558,7 @@ static int gic_irq_nmi_setup(struct irq_data *d)
desc->handle_irq = handle_fasteoi_nmi;
}

gic_irq_set_prio(d, GICD_INT_NMI_PRI);
gic_irq_set_prio(d, dist_prio_nmi);

return 0;
}
Expand Down Expand Up @@ -591,7 +593,7 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
desc->handle_irq = handle_fasteoi_irq;
}

gic_irq_set_prio(d, GICD_INT_DEF_PRI);
gic_irq_set_prio(d, dist_prio_irq);
}

static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
Expand Down Expand Up @@ -753,7 +755,7 @@ static bool gic_rpr_is_nmi_prio(void)
if (!gic_supports_nmi())
return false;

return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(GICD_INT_NMI_PRI));
return unlikely(gic_read_rpr() == GICD_INT_RPR_PRI(dist_prio_nmi));
}

static bool gic_irqnr_is_special(u32 irqnr)
Expand Down Expand Up @@ -937,10 +939,11 @@ static void __init gic_dist_init(void)
writel_relaxed(0, base + GICD_ICFGRnE + i / 4);

for (i = 0; i < GIC_ESPI_NR; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
writel_relaxed(REPEAT_BYTE_U32(dist_prio_irq),
base + GICD_IPRIORITYRnE + i);

/* Now do the common stuff */
gic_dist_config(base, GIC_LINE_NR);
gic_dist_config(base, GIC_LINE_NR, dist_prio_irq);

val = GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1;
if (gic_data.rdists.gicd_typer2 & GICD_TYPER2_nASSGIcap) {
Expand Down Expand Up @@ -1282,7 +1285,7 @@ static void gic_cpu_init(void)
for (i = 0; i < gic_data.ppi_nr + SGI_NR; i += 32)
writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);

gic_cpu_config(rbase, gic_data.ppi_nr + SGI_NR);
gic_cpu_config(rbase, gic_data.ppi_nr + SGI_NR, dist_prio_irq);
gic_redist_wait_for_rwp();

/* initialise system registers */
Expand Down Expand Up @@ -2066,7 +2069,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
gic_cpu_pm_init();

if (gic_dist_supports_lpis()) {
its_init(handle, &gic_data.rdists, gic_data.domain);
its_init(handle, &gic_data.rdists, gic_data.domain, dist_prio_irq);
its_cpu_init();
its_lpi_memreserve_init();
} else {
Expand Down
8 changes: 4 additions & 4 deletions drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ static void gic_dist_init(struct gic_chip_data *gic)
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);

gic_dist_config(base, gic_irqs);
gic_dist_config(base, gic_irqs, GICD_INT_DEF_PRI);

writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL);
}
Expand Down Expand Up @@ -516,7 +516,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
gic_cpu_map[i] &= ~cpu_mask;
}

gic_cpu_config(dist_base, 32);
gic_cpu_config(dist_base, 32, GICD_INT_DEF_PRI);

writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
gic_cpu_if_up(gic);
Expand Down Expand Up @@ -608,7 +608,7 @@ void gic_dist_restore(struct gic_chip_data *gic)
dist_base + GIC_DIST_CONFIG + i * 4);

for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
writel_relaxed(GICD_INT_DEF_PRI_X4,
writel_relaxed(REPEAT_BYTE_U32(GICD_INT_DEF_PRI),
dist_base + GIC_DIST_PRI + i * 4);

for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
Expand Down Expand Up @@ -697,7 +697,7 @@ void gic_cpu_restore(struct gic_chip_data *gic)
writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);

for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
writel_relaxed(GICD_INT_DEF_PRI_X4,
writel_relaxed(REPEAT_BYTE_U32(GICD_INT_DEF_PRI),
dist_base + GIC_DIST_PRI + i * 4);

writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
Expand Down
4 changes: 2 additions & 2 deletions drivers/irqchip/irq-hip04.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ static void __init hip04_irq_dist_init(struct hip04_irq_data *intc)
for (i = 32; i < nr_irqs; i += 2)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + ((i * 2) & ~3));

gic_dist_config(base, nr_irqs);
gic_dist_config(base, nr_irqs, GICD_INT_DEF_PRI);

writel_relaxed(1, base + GIC_DIST_CTRL);
}
Expand All @@ -287,7 +287,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask;

gic_cpu_config(dist_base, 32);
gic_cpu_config(dist_base, 32, GICD_INT_DEF_PRI);

writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
Expand Down
4 changes: 0 additions & 4 deletions include/linux/irqchip/arm-gic-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#include <linux/irqchip/arm-vgic-info.h>

#define GICD_INT_DEF_PRI 0xa0
#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\
(GICD_INT_DEF_PRI << 16) |\
(GICD_INT_DEF_PRI << 8) |\
GICD_INT_DEF_PRI)

struct irq_domain;
struct fwnode_handle;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/irqchip/arm-gic-v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ struct fwnode_handle;
int __init its_lpi_memreserve_init(void);
int its_cpu_init(void);
int its_init(struct fwnode_handle *handle, struct rdists *rdists,
struct irq_domain *domain);
struct irq_domain *domain, u8 irq_prio);
int mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent);

static inline bool gic_enable_sre(void)
Expand Down

0 comments on commit a6156e7

Please sign in to comment.