Commit b5963029 authored by Thomas Gleixner's avatar Thomas Gleixner

Merge tag 'irqchip-fixes-5.7-2' of...

Merge tag 'irqchip-fixes-5.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent

Pull irqchip fixes from Marc Zyngier:

 - Fix the mbigen driver to properly free its MSI descriptors on teardown
 - Fix the TI INTA driver to avoid handling spurious interrupts from masked interrupts
 - Fix the SiFive PLIC driver to use the correct interrupt priority mask
 - Fix the Amlogic Meson gpio driver creative locking
 - Fix the GICv4.1 virtual SGI set_affinity callback to update the effective affinity
 - Allow the GICv4.x driver to synchronize with the HW pending table parsing
 - Fix a couple of missing static attributes
parents 07d8350e 44a987d0
...@@ -416,7 +416,7 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = { ...@@ -416,7 +416,7 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = {
.map = bcm7038_l1_map, .map = bcm7038_l1_map,
}; };
int __init bcm7038_l1_of_init(struct device_node *dn, static int __init bcm7038_l1_of_init(struct device_node *dn,
struct device_node *parent) struct device_node *parent)
{ {
struct bcm7038_l1_chip *intc; struct bcm7038_l1_chip *intc;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/dma-iommu.h> #include <linux/dma-iommu.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/log2.h> #include <linux/log2.h>
...@@ -3672,6 +3673,20 @@ static int its_vpe_set_affinity(struct irq_data *d, ...@@ -3672,6 +3673,20 @@ static int its_vpe_set_affinity(struct irq_data *d,
return IRQ_SET_MASK_OK_DONE; return IRQ_SET_MASK_OK_DONE;
} }
static void its_wait_vpt_parse_complete(void)
{
void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
u64 val;
if (!gic_rdists->has_vpend_valid_dirty)
return;
WARN_ON_ONCE(readq_relaxed_poll_timeout(vlpi_base + GICR_VPENDBASER,
val,
!(val & GICR_VPENDBASER_Dirty),
10, 500));
}
static void its_vpe_schedule(struct its_vpe *vpe) static void its_vpe_schedule(struct its_vpe *vpe)
{ {
void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
...@@ -3702,6 +3717,8 @@ static void its_vpe_schedule(struct its_vpe *vpe) ...@@ -3702,6 +3717,8 @@ static void its_vpe_schedule(struct its_vpe *vpe)
val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0; val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
val |= GICR_VPENDBASER_Valid; val |= GICR_VPENDBASER_Valid;
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
its_wait_vpt_parse_complete();
} }
static void its_vpe_deschedule(struct its_vpe *vpe) static void its_vpe_deschedule(struct its_vpe *vpe)
...@@ -3910,6 +3927,8 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, ...@@ -3910,6 +3927,8 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id); val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER); gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
its_wait_vpt_parse_complete();
} }
static void its_vpe_4_1_deschedule(struct its_vpe *vpe, static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
...@@ -4035,6 +4054,7 @@ static int its_sgi_set_affinity(struct irq_data *d, ...@@ -4035,6 +4054,7 @@ static int its_sgi_set_affinity(struct irq_data *d,
* not on the host (since they can only be targetting a vPE). * not on the host (since they can only be targetting a vPE).
* Tell the kernel we've done whatever it asked for. * Tell the kernel we've done whatever it asked for.
*/ */
irq_data_update_effective_affinity(d, mask_val);
return IRQ_SET_MASK_OK; return IRQ_SET_MASK_OK;
} }
......
...@@ -873,6 +873,7 @@ static int __gic_update_rdist_properties(struct redist_region *region, ...@@ -873,6 +873,7 @@ static int __gic_update_rdist_properties(struct redist_region *region,
gic_data.rdists.has_rvpeid &= !!(typer & GICR_TYPER_RVPEID); gic_data.rdists.has_rvpeid &= !!(typer & GICR_TYPER_RVPEID);
gic_data.rdists.has_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) | gic_data.rdists.has_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) |
gic_data.rdists.has_rvpeid); gic_data.rdists.has_rvpeid);
gic_data.rdists.has_vpend_valid_dirty &= !!(typer & GICR_TYPER_DIRTY);
/* Detect non-sensical configurations */ /* Detect non-sensical configurations */
if (WARN_ON_ONCE(gic_data.rdists.has_rvpeid && !gic_data.rdists.has_vlpis)) { if (WARN_ON_ONCE(gic_data.rdists.has_rvpeid && !gic_data.rdists.has_vlpis)) {
...@@ -893,10 +894,11 @@ static void gic_update_rdist_properties(void) ...@@ -893,10 +894,11 @@ static void gic_update_rdist_properties(void)
if (WARN_ON(gic_data.ppi_nr == UINT_MAX)) if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
gic_data.ppi_nr = 0; gic_data.ppi_nr = 0;
pr_info("%d PPIs implemented\n", gic_data.ppi_nr); pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
pr_info("%sVLPI support, %sdirect LPI support, %sRVPEID support\n", if (gic_data.rdists.has_vlpis)
!gic_data.rdists.has_vlpis ? "no " : "", pr_info("GICv4 features: %s%s%s\n",
!gic_data.rdists.has_direct_lpi ? "no " : "", gic_data.rdists.has_direct_lpi ? "DirectLPI " : "",
!gic_data.rdists.has_rvpeid ? "no " : ""); gic_data.rdists.has_rvpeid ? "RVPEID " : "",
gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
} }
/* Check whether it's single security state view */ /* Check whether it's single security state view */
...@@ -1620,6 +1622,7 @@ static int __init gic_init_bases(void __iomem *dist_base, ...@@ -1620,6 +1622,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
gic_data.rdists.has_rvpeid = true; gic_data.rdists.has_rvpeid = true;
gic_data.rdists.has_vlpis = true; gic_data.rdists.has_vlpis = true;
gic_data.rdists.has_direct_lpi = true; gic_data.rdists.has_direct_lpi = true;
gic_data.rdists.has_vpend_valid_dirty = true;
if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) { if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
err = -ENOMEM; err = -ENOMEM;
......
...@@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain, ...@@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
return 0; return 0;
} }
static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs)
{
platform_msi_domain_free(domain, virq, nr_irqs);
}
static const struct irq_domain_ops mbigen_domain_ops = { static const struct irq_domain_ops mbigen_domain_ops = {
.translate = mbigen_domain_translate, .translate = mbigen_domain_translate,
.alloc = mbigen_irq_domain_alloc, .alloc = mbigen_irq_domain_alloc,
.free = irq_domain_free_irqs_common, .free = mbigen_irq_domain_free,
}; };
static int mbigen_of_create_domain(struct platform_device *pdev, static int mbigen_of_create_domain(struct platform_device *pdev,
......
...@@ -144,12 +144,17 @@ struct meson_gpio_irq_controller { ...@@ -144,12 +144,17 @@ struct meson_gpio_irq_controller {
static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl, static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
unsigned int reg, u32 mask, u32 val) unsigned int reg, u32 mask, u32 val)
{ {
unsigned long flags;
u32 tmp; u32 tmp;
spin_lock_irqsave(&ctl->lock, flags);
tmp = readl_relaxed(ctl->base + reg); tmp = readl_relaxed(ctl->base + reg);
tmp &= ~mask; tmp &= ~mask;
tmp |= val; tmp |= val;
writel_relaxed(tmp, ctl->base + reg); writel_relaxed(tmp, ctl->base + reg);
spin_unlock_irqrestore(&ctl->lock, flags);
} }
static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl) static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl)
...@@ -196,14 +201,15 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, ...@@ -196,14 +201,15 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
unsigned long hwirq, unsigned long hwirq,
u32 **channel_hwirq) u32 **channel_hwirq)
{ {
unsigned long flags;
unsigned int idx; unsigned int idx;
spin_lock(&ctl->lock); spin_lock_irqsave(&ctl->lock, flags);
/* Find a free channel */ /* Find a free channel */
idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL); idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
if (idx >= NUM_CHANNEL) { if (idx >= NUM_CHANNEL) {
spin_unlock(&ctl->lock); spin_unlock_irqrestore(&ctl->lock, flags);
pr_err("No channel available\n"); pr_err("No channel available\n");
return -ENOSPC; return -ENOSPC;
} }
...@@ -211,6 +217,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, ...@@ -211,6 +217,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
/* Mark the channel as used */ /* Mark the channel as used */
set_bit(idx, ctl->channel_map); set_bit(idx, ctl->channel_map);
spin_unlock_irqrestore(&ctl->lock, flags);
/* /*
* Setup the mux of the channel to route the signal of the pad * Setup the mux of the channel to route the signal of the pad
* to the appropriate input of the GIC * to the appropriate input of the GIC
...@@ -225,8 +233,6 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, ...@@ -225,8 +233,6 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
*/ */
*channel_hwirq = &(ctl->channel_irqs[idx]); *channel_hwirq = &(ctl->channel_irqs[idx]);
spin_unlock(&ctl->lock);
pr_debug("hwirq %lu assigned to channel %d - irq %u\n", pr_debug("hwirq %lu assigned to channel %d - irq %u\n",
hwirq, idx, **channel_hwirq); hwirq, idx, **channel_hwirq);
...@@ -287,13 +293,9 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, ...@@ -287,13 +293,9 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
val |= REG_EDGE_POL_LOW(params, idx); val |= REG_EDGE_POL_LOW(params, idx);
} }
spin_lock(&ctl->lock);
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
REG_EDGE_POL_MASK(params, idx), val); REG_EDGE_POL_MASK(params, idx), val);
spin_unlock(&ctl->lock);
return 0; return 0;
} }
......
...@@ -66,7 +66,7 @@ struct mvebu_icu_irq_data { ...@@ -66,7 +66,7 @@ struct mvebu_icu_irq_data {
unsigned int type; unsigned int type;
}; };
DEFINE_STATIC_KEY_FALSE(legacy_bindings); static DEFINE_STATIC_KEY_FALSE(legacy_bindings);
static void mvebu_icu_init(struct mvebu_icu *icu, static void mvebu_icu_init(struct mvebu_icu *icu,
struct mvebu_icu_msi_data *msi_data, struct mvebu_icu_msi_data *msi_data,
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#define CONTEXT_THRESHOLD 0x00 #define CONTEXT_THRESHOLD 0x00
#define CONTEXT_CLAIM 0x04 #define CONTEXT_CLAIM 0x04
#define PLIC_DISABLE_THRESHOLD 0xf #define PLIC_DISABLE_THRESHOLD 0x7
#define PLIC_ENABLE_THRESHOLD 0 #define PLIC_ENABLE_THRESHOLD 0
struct plic_priv { struct plic_priv {
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define VINT_ENABLE_SET_OFFSET 0x0 #define VINT_ENABLE_SET_OFFSET 0x0
#define VINT_ENABLE_CLR_OFFSET 0x8 #define VINT_ENABLE_CLR_OFFSET 0x8
#define VINT_STATUS_OFFSET 0x18 #define VINT_STATUS_OFFSET 0x18
#define VINT_STATUS_MASKED_OFFSET 0x20
/** /**
* struct ti_sci_inta_event_desc - Description of an event coming to * struct ti_sci_inta_event_desc - Description of an event coming to
...@@ -116,7 +117,7 @@ static void ti_sci_inta_irq_handler(struct irq_desc *desc) ...@@ -116,7 +117,7 @@ static void ti_sci_inta_irq_handler(struct irq_desc *desc)
chained_irq_enter(irq_desc_get_chip(desc), desc); chained_irq_enter(irq_desc_get_chip(desc), desc);
val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 + val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 +
VINT_STATUS_OFFSET); VINT_STATUS_MASKED_OFFSET);
for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) { for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) {
virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq); virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
......
...@@ -243,6 +243,7 @@ ...@@ -243,6 +243,7 @@
#define GICR_TYPER_PLPIS (1U << 0) #define GICR_TYPER_PLPIS (1U << 0)
#define GICR_TYPER_VLPIS (1U << 1) #define GICR_TYPER_VLPIS (1U << 1)
#define GICR_TYPER_DIRTY (1U << 2)
#define GICR_TYPER_DirectLPIS (1U << 3) #define GICR_TYPER_DirectLPIS (1U << 3)
#define GICR_TYPER_LAST (1U << 4) #define GICR_TYPER_LAST (1U << 4)
#define GICR_TYPER_RVPEID (1U << 7) #define GICR_TYPER_RVPEID (1U << 7)
...@@ -686,6 +687,7 @@ struct rdists { ...@@ -686,6 +687,7 @@ struct rdists {
bool has_vlpis; bool has_vlpis;
bool has_rvpeid; bool has_rvpeid;
bool has_direct_lpi; bool has_direct_lpi;
bool has_vpend_valid_dirty;
}; };
struct irq_domain; struct irq_domain;
......
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