Skip to content

Commit

Permalink
Merge tag 'irqchip-fixes-5.15-1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/maz/arm-platforms into irq/urgent

Pull irqchip fixes from Marc Zyngier:

 - Work around a bad GIC integration on a Renesas platform, where the
   interconnect cannot deal with byte-sized MMIO accesses

 - Cleanup another Renesas driver abusing the comma operator

 - Fix a potential GICv4 memory leak on an error path

 - Make the type of 'size' consistent with the rest of the code in
   __irq_domain_add()

 - Fix a regression in the Armada 370-XP IPI path

 - Fix the build for the obviously unloved goldfish-pic

 - Some documentation fixes

Link: https://lore.kernel.org/r/20210924090933.2766857-1-maz@kernel.org
  • Loading branch information
Thomas Gleixner committed Sep 24, 2021
2 parents e4e737b + b78f269 commit f9bfed3
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 17 deletions.
5 changes: 3 additions & 2 deletions Documentation/core-api/irq/irq-domain.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ for IRQ numbers that are passed to struct device registrations. In that
case the Linux IRQ numbers cannot be dynamically assigned and the legacy
mapping should be used.

As the name implies, the *_legacy() functions are deprecated and only
As the name implies, the \*_legacy() functions are deprecated and only
exist to ease the support of ancient platforms. No new users should be
added.
added. Same goes for the \*_simple() functions when their use results
in the legacy behaviour.

The legacy map assumes a contiguous range of IRQ numbers has already
been allocated for the controller and that the IRQ number can be
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ config MESON_IRQ_GPIO
config GOLDFISH_PIC
bool "Goldfish programmable interrupt controller"
depends on MIPS && (GOLDFISH || COMPILE_TEST)
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
help
Say yes here to enable Goldfish interrupt controller driver used
Expand Down
4 changes: 2 additions & 2 deletions drivers/irqchip/irq-armada-370-xp.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,16 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d,
ARMADA_370_XP_SW_TRIG_INT_OFFS);
}

static void armada_370_xp_ipi_eoi(struct irq_data *d)
static void armada_370_xp_ipi_ack(struct irq_data *d)
{
writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
}

static struct irq_chip ipi_irqchip = {
.name = "IPI",
.irq_ack = armada_370_xp_ipi_ack,
.irq_mask = armada_370_xp_ipi_mask,
.irq_unmask = armada_370_xp_ipi_unmask,
.irq_eoi = armada_370_xp_ipi_eoi,
.ipi_send_mask = armada_370_xp_ipi_send_mask,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -4501,7 +4501,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq

if (err) {
if (i > 0)
its_vpe_irq_domain_free(domain, virq, i - 1);
its_vpe_irq_domain_free(domain, virq, i);

its_lpi_free(bitmap, base, nr_ids);
its_free_prop_table(vprop_page);
Expand Down
52 changes: 51 additions & 1 deletion drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ static DEFINE_RAW_SPINLOCK(cpu_map_lock);

#endif

static DEFINE_STATIC_KEY_FALSE(needs_rmw_access);

/*
* The GIC mapping of CPU interfaces does not necessarily match
* the logical CPU numbering. Let's use a mapping as returned
Expand Down Expand Up @@ -774,6 +776,25 @@ static int gic_pm_init(struct gic_chip_data *gic)
#endif

#ifdef CONFIG_SMP
static void rmw_writeb(u8 bval, void __iomem *addr)
{
static DEFINE_RAW_SPINLOCK(rmw_lock);
unsigned long offset = (unsigned long)addr & 3UL;
unsigned long shift = offset * 8;
unsigned long flags;
u32 val;

raw_spin_lock_irqsave(&rmw_lock, flags);

addr -= offset;
val = readl_relaxed(addr);
val &= ~GENMASK(shift + 7, shift);
val |= bval << shift;
writel_relaxed(val, addr);

raw_spin_unlock_irqrestore(&rmw_lock, flags);
}

static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
Expand All @@ -788,7 +809,10 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;

writeb_relaxed(gic_cpu_map[cpu], reg);
if (static_branch_unlikely(&needs_rmw_access))
rmw_writeb(gic_cpu_map[cpu], reg);
else
writeb_relaxed(gic_cpu_map[cpu], reg);
irq_data_update_effective_affinity(d, cpumask_of(cpu));

return IRQ_SET_MASK_OK_DONE;
Expand Down Expand Up @@ -1375,6 +1399,30 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
return true;
}

static bool gic_enable_rmw_access(void *data)
{
/*
* The EMEV2 class of machines has a broken interconnect, and
* locks up on accesses that are less than 32bit. So far, only
* the affinity setting requires it.
*/
if (of_machine_is_compatible("renesas,emev2")) {
static_branch_enable(&needs_rmw_access);
return true;
}

return false;
}

static const struct gic_quirk gic_quirks[] = {
{
.desc = "broken byte access",
.compatible = "arm,pl390",
.init = gic_enable_rmw_access,
},
{ },
};

static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
{
if (!gic || !node)
Expand All @@ -1391,6 +1439,8 @@ static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
gic->percpu_offset = 0;

gic_enable_of_quirks(node, gic_quirks, gic);

return 0;

error:
Expand Down
6 changes: 3 additions & 3 deletions drivers/irqchip/irq-mbigen.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/* The maximum IRQ pin number of mbigen chip(start from 0) */
#define MAXIMUM_IRQ_PIN_NUM 1407

/**
/*
* In mbigen vector register
* bit[21:12]: event id value
* bit[11:0]: device id
Expand All @@ -39,14 +39,14 @@
/* offset of vector register in mbigen node */
#define REG_MBIGEN_VEC_OFFSET 0x200

/**
/*
* offset of clear register in mbigen node
* This register is used to clear the status
* of interrupt
*/
#define REG_MBIGEN_CLEAR_OFFSET 0xa000

/**
/*
* offset of interrupt type register
* This register is used to configure interrupt
* trigger type
Expand Down
12 changes: 6 additions & 6 deletions drivers/irqchip/irq-renesas-rza1.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,12 @@ static int rza1_irqc_probe(struct platform_device *pdev)
goto out_put_node;
}

priv->chip.name = "rza1-irqc",
priv->chip.irq_mask = irq_chip_mask_parent,
priv->chip.irq_unmask = irq_chip_unmask_parent,
priv->chip.irq_eoi = rza1_irqc_eoi,
priv->chip.irq_retrigger = irq_chip_retrigger_hierarchy,
priv->chip.irq_set_type = rza1_irqc_set_type,
priv->chip.name = "rza1-irqc";
priv->chip.irq_mask = irq_chip_mask_parent;
priv->chip.irq_unmask = irq_chip_unmask_parent;
priv->chip.irq_eoi = rza1_irqc_eoi;
priv->chip.irq_retrigger = irq_chip_retrigger_hierarchy;
priv->chip.irq_set_type = rza1_irqc_set_type;
priv->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;

priv->irq_domain = irq_domain_add_hierarchy(parent, 0, IRQC_NUM_IRQ,
Expand Down
2 changes: 1 addition & 1 deletion include/linux/irqdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
}

void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size,
irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
Expand Down
2 changes: 1 addition & 1 deletion kernel/irq/irqdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode);
* Allocates and initializes an irq_domain structure.
* Returns pointer to IRQ domain, or NULL on failure.
*/
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size,
irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data)
Expand Down

0 comments on commit f9bfed3

Please sign in to comment.