irqchip fixes for Linux 5.7, take #2
- 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 -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAl6ZZBsPHG1hekBrZXJu ZWwub3JnAAoJECPQ0LrRPXpDUkcP/iw7geZx+5A/2hVTAF27SWdq9GNrDCcsRXQy XcV/OVdCsblzpGBsSMgMdmZxB4RRq+w33XNR+7fplwZpHiTyg/51sivhOnDyhrKI jiy0/yvb3JDIEPNouMRggDNtrhpzsJaXu9ENO//W2SBR6lgkFz3Ux1nv1+EF26J+ L0m4anvKkk/kLlbuxRPBC8ADP8h6uEoLESCJ+telIDCY6lKSOh7wTaeRVi24D4jL 4JqQXULMpMhEp8i9DSTqzktHWQo/wuPqVRStqULvAZG7Q2t18hI+OTRHGoyaY3WC Mhz5yh/t+UTJhSzXNGeN2P4EkwCva4LNajd+fe4tlrxi/z6TZzIsonATdQj0fQDe Ju4IjbHkEZxQ9jk1uckBA9jS4NdcT9HOQcnCoWMHIclwD4/GLx+Lq9/l3g7kmRR/ fquptoLMjzRH9GX/W6Uy2e6qRyaPfm9e3d9RrtqiUCMOhSolLYooKKsG4i3zVzKC yggZQeIUrV8+x+xB4VNbUV0pMh6BSUWAD5Kmjky7eM902XPlRotVqTDsOfht2aeU 2NVa1rZ7ElylDZSzYpHVTa6+TISb1phtKhGoXejt6h/Y+cCSaKGKB1mQnJWuLgEz 7uMGB7qohPqV2sWUDxtzVYD6W6OuLsBWcbHyNqin1S5lHzLm8lqUrIEo6URdVhes UGqiwAbI =a+I2 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
b5963029d9
|
@ -416,7 +416,7 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = {
|
|||
.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 bcm7038_l1_chip *intc;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/dma-iommu.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/log2.h>
|
||||
|
@ -3672,6 +3673,20 @@ out:
|
|||
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)
|
||||
{
|
||||
void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
|
||||
|
@ -3702,6 +3717,8 @@ static void its_vpe_schedule(struct its_vpe *vpe)
|
|||
val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
|
||||
val |= GICR_VPENDBASER_Valid;
|
||||
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
|
||||
|
||||
its_wait_vpt_parse_complete();
|
||||
}
|
||||
|
||||
static void its_vpe_deschedule(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);
|
||||
|
||||
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
|
||||
|
||||
its_wait_vpt_parse_complete();
|
||||
}
|
||||
|
||||
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,
|
|||
* not on the host (since they can only be targetting a vPE).
|
||||
* Tell the kernel we've done whatever it asked for.
|
||||
*/
|
||||
irq_data_update_effective_affinity(d, mask_val);
|
||||
return IRQ_SET_MASK_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) |
|
||||
gic_data.rdists.has_rvpeid);
|
||||
gic_data.rdists.has_vpend_valid_dirty &= !!(typer & GICR_TYPER_DIRTY);
|
||||
|
||||
/* Detect non-sensical configurations */
|
||||
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)
|
|||
if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
|
||||
gic_data.ppi_nr = 0;
|
||||
pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
|
||||
pr_info("%sVLPI support, %sdirect LPI support, %sRVPEID support\n",
|
||||
!gic_data.rdists.has_vlpis ? "no " : "",
|
||||
!gic_data.rdists.has_direct_lpi ? "no " : "",
|
||||
!gic_data.rdists.has_rvpeid ? "no " : "");
|
||||
if (gic_data.rdists.has_vlpis)
|
||||
pr_info("GICv4 features: %s%s%s\n",
|
||||
gic_data.rdists.has_direct_lpi ? "DirectLPI " : "",
|
||||
gic_data.rdists.has_rvpeid ? "RVPEID " : "",
|
||||
gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
|
||||
}
|
||||
|
||||
/* Check whether it's single security state view */
|
||||
|
@ -1620,6 +1622,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
|
|||
gic_data.rdists.has_rvpeid = true;
|
||||
gic_data.rdists.has_vlpis = 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)) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -220,10 +220,16 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
|
|||
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 = {
|
||||
.translate = mbigen_domain_translate,
|
||||
.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,
|
||||
|
|
|
@ -144,12 +144,17 @@ struct meson_gpio_irq_controller {
|
|||
static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
|
||||
unsigned int reg, u32 mask, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
|
||||
spin_lock_irqsave(&ctl->lock, flags);
|
||||
|
||||
tmp = readl_relaxed(ctl->base + reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= val;
|
||||
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)
|
||||
|
@ -196,14 +201,15 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
|
|||
unsigned long hwirq,
|
||||
u32 **channel_hwirq)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int idx;
|
||||
|
||||
spin_lock(&ctl->lock);
|
||||
spin_lock_irqsave(&ctl->lock, flags);
|
||||
|
||||
/* Find a free channel */
|
||||
idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
|
||||
if (idx >= NUM_CHANNEL) {
|
||||
spin_unlock(&ctl->lock);
|
||||
spin_unlock_irqrestore(&ctl->lock, flags);
|
||||
pr_err("No channel available\n");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
@ -211,6 +217,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
|
|||
/* Mark the channel as used */
|
||||
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
|
||||
* to the appropriate input of the GIC
|
||||
|
@ -225,8 +233,6 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
|
|||
*/
|
||||
*channel_hwirq = &(ctl->channel_irqs[idx]);
|
||||
|
||||
spin_unlock(&ctl->lock);
|
||||
|
||||
pr_debug("hwirq %lu assigned to channel %d - irq %u\n",
|
||||
hwirq, idx, **channel_hwirq);
|
||||
|
||||
|
@ -287,13 +293,9 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
|
|||
val |= REG_EDGE_POL_LOW(params, idx);
|
||||
}
|
||||
|
||||
spin_lock(&ctl->lock);
|
||||
|
||||
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
|
||||
REG_EDGE_POL_MASK(params, idx), val);
|
||||
|
||||
spin_unlock(&ctl->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ struct mvebu_icu_irq_data {
|
|||
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,
|
||||
struct mvebu_icu_msi_data *msi_data,
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#define CONTEXT_THRESHOLD 0x00
|
||||
#define CONTEXT_CLAIM 0x04
|
||||
|
||||
#define PLIC_DISABLE_THRESHOLD 0xf
|
||||
#define PLIC_DISABLE_THRESHOLD 0x7
|
||||
#define PLIC_ENABLE_THRESHOLD 0
|
||||
|
||||
struct plic_priv {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define VINT_ENABLE_SET_OFFSET 0x0
|
||||
#define VINT_ENABLE_CLR_OFFSET 0x8
|
||||
#define VINT_STATUS_OFFSET 0x18
|
||||
#define VINT_STATUS_MASKED_OFFSET 0x20
|
||||
|
||||
/**
|
||||
* 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)
|
|||
chained_irq_enter(irq_desc_get_chip(desc), desc);
|
||||
|
||||
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) {
|
||||
virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
|
||||
|
|
|
@ -243,6 +243,7 @@
|
|||
|
||||
#define GICR_TYPER_PLPIS (1U << 0)
|
||||
#define GICR_TYPER_VLPIS (1U << 1)
|
||||
#define GICR_TYPER_DIRTY (1U << 2)
|
||||
#define GICR_TYPER_DirectLPIS (1U << 3)
|
||||
#define GICR_TYPER_LAST (1U << 4)
|
||||
#define GICR_TYPER_RVPEID (1U << 7)
|
||||
|
@ -686,6 +687,7 @@ struct rdists {
|
|||
bool has_vlpis;
|
||||
bool has_rvpeid;
|
||||
bool has_direct_lpi;
|
||||
bool has_vpend_valid_dirty;
|
||||
};
|
||||
|
||||
struct irq_domain;
|
||||
|
|
Loading…
Reference in New Issue