Commit f9bfed3a authored by Thomas Gleixner's avatar Thomas Gleixner

Merge tag 'irqchip-fixes-5.15-1' of...

Merge tag 'irqchip-fixes-5.15-1' of git://git.kernel.org/pub/scm/linux/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
parents e4e737bb b78f2692
...@@ -175,9 +175,10 @@ for IRQ numbers that are passed to struct device registrations. In that ...@@ -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 case the Linux IRQ numbers cannot be dynamically assigned and the legacy
mapping should be used. 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 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 The legacy map assumes a contiguous range of IRQ numbers has already
been allocated for the controller and that the IRQ number can be been allocated for the controller and that the IRQ number can be
......
...@@ -409,6 +409,7 @@ config MESON_IRQ_GPIO ...@@ -409,6 +409,7 @@ config MESON_IRQ_GPIO
config GOLDFISH_PIC config GOLDFISH_PIC
bool "Goldfish programmable interrupt controller" bool "Goldfish programmable interrupt controller"
depends on MIPS && (GOLDFISH || COMPILE_TEST) depends on MIPS && (GOLDFISH || COMPILE_TEST)
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN select IRQ_DOMAIN
help help
Say yes here to enable Goldfish interrupt controller driver used Say yes here to enable Goldfish interrupt controller driver used
......
...@@ -359,16 +359,16 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, ...@@ -359,16 +359,16 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d,
ARMADA_370_XP_SW_TRIG_INT_OFFS); 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); writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
} }
static struct irq_chip ipi_irqchip = { static struct irq_chip ipi_irqchip = {
.name = "IPI", .name = "IPI",
.irq_ack = armada_370_xp_ipi_ack,
.irq_mask = armada_370_xp_ipi_mask, .irq_mask = armada_370_xp_ipi_mask,
.irq_unmask = armada_370_xp_ipi_unmask, .irq_unmask = armada_370_xp_ipi_unmask,
.irq_eoi = armada_370_xp_ipi_eoi,
.ipi_send_mask = armada_370_xp_ipi_send_mask, .ipi_send_mask = armada_370_xp_ipi_send_mask,
}; };
......
...@@ -4501,7 +4501,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq ...@@ -4501,7 +4501,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
if (err) { if (err) {
if (i > 0) 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_lpi_free(bitmap, base, nr_ids);
its_free_prop_table(vprop_page); its_free_prop_table(vprop_page);
......
...@@ -107,6 +107,8 @@ static DEFINE_RAW_SPINLOCK(cpu_map_lock); ...@@ -107,6 +107,8 @@ static DEFINE_RAW_SPINLOCK(cpu_map_lock);
#endif #endif
static DEFINE_STATIC_KEY_FALSE(needs_rmw_access);
/* /*
* The GIC mapping of CPU interfaces does not necessarily match * The GIC mapping of CPU interfaces does not necessarily match
* the logical CPU numbering. Let's use a mapping as returned * the logical CPU numbering. Let's use a mapping as returned
...@@ -774,6 +776,25 @@ static int gic_pm_init(struct gic_chip_data *gic) ...@@ -774,6 +776,25 @@ static int gic_pm_init(struct gic_chip_data *gic)
#endif #endif
#ifdef CONFIG_SMP #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, static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force) bool force)
{ {
...@@ -788,7 +809,10 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, ...@@ -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) if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL; 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)); irq_data_update_effective_affinity(d, cpumask_of(cpu));
return IRQ_SET_MASK_OK_DONE; return IRQ_SET_MASK_OK_DONE;
...@@ -1375,6 +1399,30 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base) ...@@ -1375,6 +1399,30 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
return true; 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) static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
{ {
if (!gic || !node) if (!gic || !node)
...@@ -1391,6 +1439,8 @@ static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node) ...@@ -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)) if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
gic->percpu_offset = 0; gic->percpu_offset = 0;
gic_enable_of_quirks(node, gic_quirks, gic);
return 0; return 0;
error: error:
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* The maximum IRQ pin number of mbigen chip(start from 0) */ /* The maximum IRQ pin number of mbigen chip(start from 0) */
#define MAXIMUM_IRQ_PIN_NUM 1407 #define MAXIMUM_IRQ_PIN_NUM 1407
/** /*
* In mbigen vector register * In mbigen vector register
* bit[21:12]: event id value * bit[21:12]: event id value
* bit[11:0]: device id * bit[11:0]: device id
...@@ -39,14 +39,14 @@ ...@@ -39,14 +39,14 @@
/* offset of vector register in mbigen node */ /* offset of vector register in mbigen node */
#define REG_MBIGEN_VEC_OFFSET 0x200 #define REG_MBIGEN_VEC_OFFSET 0x200
/** /*
* offset of clear register in mbigen node * offset of clear register in mbigen node
* This register is used to clear the status * This register is used to clear the status
* of interrupt * of interrupt
*/ */
#define REG_MBIGEN_CLEAR_OFFSET 0xa000 #define REG_MBIGEN_CLEAR_OFFSET 0xa000
/** /*
* offset of interrupt type register * offset of interrupt type register
* This register is used to configure interrupt * This register is used to configure interrupt
* trigger type * trigger type
......
...@@ -223,12 +223,12 @@ static int rza1_irqc_probe(struct platform_device *pdev) ...@@ -223,12 +223,12 @@ static int rza1_irqc_probe(struct platform_device *pdev)
goto out_put_node; goto out_put_node;
} }
priv->chip.name = "rza1-irqc", priv->chip.name = "rza1-irqc";
priv->chip.irq_mask = irq_chip_mask_parent, priv->chip.irq_mask = irq_chip_mask_parent;
priv->chip.irq_unmask = irq_chip_unmask_parent, priv->chip.irq_unmask = irq_chip_unmask_parent;
priv->chip.irq_eoi = rza1_irqc_eoi, priv->chip.irq_eoi = rza1_irqc_eoi;
priv->chip.irq_retrigger = irq_chip_retrigger_hierarchy, priv->chip.irq_retrigger = irq_chip_retrigger_hierarchy;
priv->chip.irq_set_type = rza1_irqc_set_type, priv->chip.irq_set_type = rza1_irqc_set_type;
priv->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE; priv->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
priv->irq_domain = irq_domain_add_hierarchy(parent, 0, IRQC_NUM_IRQ, priv->irq_domain = irq_domain_add_hierarchy(parent, 0, IRQC_NUM_IRQ,
......
...@@ -251,7 +251,7 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa) ...@@ -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); 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, irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops, const struct irq_domain_ops *ops,
void *host_data); void *host_data);
......
...@@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); ...@@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode);
* Allocates and initializes an irq_domain structure. * Allocates and initializes an irq_domain structure.
* Returns pointer to IRQ domain, or NULL on failure. * 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, irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops, const struct irq_domain_ops *ops,
void *host_data) void *host_data)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment