Commit 9bd5386c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'irq-urgent-2023-05-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fixes from Thomas Gleixner:
 "A set of fixes for interrupt chip drivers:

   - Prevent loss of state in the MIPS GIC interrupt controller

   - Disable pseudo NMIs on Mediatek based Chromebooks as they have
     firmware issues which cause instantenous chrashes and freezes wen
     pseudo NMIs are used

   - Fix the error handling path in the MBIGEN driver and a defined but
     not used warning in the meson-gpio interrupt chip driver"

* tag 'irq-urgent-2023-05-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqchip/mbigen: Unify the error handling in mbigen_of_create_domain()
  irqchip/meson-gpio: Mark OF related data as maybe unused
  irqchip/mips-gic: Use raw spinlock for gic_lock
  irqchip/mips-gic: Don't touch vl_map if a local interrupt is not routable
  irqchip/gic-v3: Disable pseudo NMIs on Mediatek devices w/ firmware issues
  dt-bindings: interrupt-controller: arm,gic-v3: Add quirk for Mediatek SoCs w/ broken FW
parents 045049cb 4115af49
...@@ -166,6 +166,12 @@ properties: ...@@ -166,6 +166,12 @@ properties:
resets: resets:
maxItems: 1 maxItems: 1
mediatek,broken-save-restore-fw:
type: boolean
description:
Asserts that the firmware on this device has issues saving and restoring
GICR registers when the GIC redistributors are powered off.
dependencies: dependencies:
mbi-ranges: [ msi-controller ] mbi-ranges: [ msi-controller ]
msi-controller: [ mbi-ranges ] msi-controller: [ mbi-ranges ]
......
...@@ -16,7 +16,11 @@ void gic_enable_of_quirks(const struct device_node *np, ...@@ -16,7 +16,11 @@ void gic_enable_of_quirks(const struct device_node *np,
const struct gic_quirk *quirks, void *data) const struct gic_quirk *quirks, void *data)
{ {
for (; quirks->desc; quirks++) { for (; quirks->desc; quirks++) {
if (!of_device_is_compatible(np, quirks->compatible)) if (quirks->compatible &&
!of_device_is_compatible(np, quirks->compatible))
continue;
if (quirks->property &&
!of_property_read_bool(np, quirks->property))
continue; continue;
if (quirks->init(data)) if (quirks->init(data))
pr_info("GIC: enabling workaround for %s\n", pr_info("GIC: enabling workaround for %s\n",
...@@ -28,7 +32,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, ...@@ -28,7 +32,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data) void *data)
{ {
for (; quirks->desc; quirks++) { for (; quirks->desc; quirks++) {
if (quirks->compatible) if (quirks->compatible || quirks->property)
continue; continue;
if (quirks->iidr != (quirks->mask & iidr)) if (quirks->iidr != (quirks->mask & iidr))
continue; continue;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct gic_quirk { struct gic_quirk {
const char *desc; const char *desc;
const char *compatible; const char *compatible;
const char *property;
bool (*init)(void *data); bool (*init)(void *data);
u32 iidr; u32 iidr;
u32 mask; u32 mask;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2)
#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
...@@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data) ...@@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data)
return true; return true;
} }
static bool gic_enable_quirk_mtk_gicr(void *data)
{
struct gic_chip_data *d = data;
d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
return true;
}
static bool gic_enable_quirk_cavium_38539(void *data) static bool gic_enable_quirk_cavium_38539(void *data)
{ {
struct gic_chip_data *d = data; struct gic_chip_data *d = data;
...@@ -1792,6 +1802,11 @@ static const struct gic_quirk gic_quirks[] = { ...@@ -1792,6 +1802,11 @@ static const struct gic_quirk gic_quirks[] = {
.compatible = "qcom,msm8996-gic-v3", .compatible = "qcom,msm8996-gic-v3",
.init = gic_enable_quirk_msm8996, .init = gic_enable_quirk_msm8996,
}, },
{
.desc = "GICv3: Mediatek Chromebook GICR save problem",
.property = "mediatek,broken-save-restore-fw",
.init = gic_enable_quirk_mtk_gicr,
},
{ {
.desc = "GICv3: HIP06 erratum 161010803", .desc = "GICv3: HIP06 erratum 161010803",
.iidr = 0x0204043b, .iidr = 0x0204043b,
...@@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void) ...@@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void)
if (!gic_prio_masking_enabled()) if (!gic_prio_masking_enabled())
return; return;
if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
pr_warn("Skipping NMI enable due to firmware issues\n");
return;
}
ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL); ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
if (!ppi_nmi_refs) if (!ppi_nmi_refs)
return; return;
......
...@@ -240,26 +240,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev, ...@@ -240,26 +240,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
struct irq_domain *domain; struct irq_domain *domain;
struct device_node *np; struct device_node *np;
u32 num_pins; u32 num_pins;
int ret = 0;
parent = bus_get_dev_root(&platform_bus_type);
if (!parent)
return -ENODEV;
for_each_child_of_node(pdev->dev.of_node, np) { for_each_child_of_node(pdev->dev.of_node, np) {
if (!of_property_read_bool(np, "interrupt-controller")) if (!of_property_read_bool(np, "interrupt-controller"))
continue; continue;
parent = bus_get_dev_root(&platform_bus_type); child = of_platform_device_create(np, NULL, parent);
if (parent) { if (!child) {
child = of_platform_device_create(np, NULL, parent); ret = -ENOMEM;
put_device(parent); break;
if (!child) {
of_node_put(np);
return -ENOMEM;
}
} }
if (of_property_read_u32(child->dev.of_node, "num-pins", if (of_property_read_u32(child->dev.of_node, "num-pins",
&num_pins) < 0) { &num_pins) < 0) {
dev_err(&pdev->dev, "No num-pins property\n"); dev_err(&pdev->dev, "No num-pins property\n");
of_node_put(np); ret = -EINVAL;
return -EINVAL; break;
} }
domain = platform_msi_create_device_domain(&child->dev, num_pins, domain = platform_msi_create_device_domain(&child->dev, num_pins,
...@@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev, ...@@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
&mbigen_domain_ops, &mbigen_domain_ops,
mgn_chip); mgn_chip);
if (!domain) { if (!domain) {
of_node_put(np); ret = -ENOMEM;
return -ENOMEM; break;
} }
} }
return 0; put_device(parent);
if (ret)
of_node_put(np);
return ret;
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = { ...@@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = {
INIT_MESON_S4_COMMON_DATA(82) INIT_MESON_S4_COMMON_DATA(82)
}; };
static const struct of_device_id meson_irq_gpio_matches[] = { static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
{ .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params }, { .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
......
...@@ -50,7 +50,7 @@ void __iomem *mips_gic_base; ...@@ -50,7 +50,7 @@ void __iomem *mips_gic_base;
static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks); static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
static DEFINE_SPINLOCK(gic_lock); static DEFINE_RAW_SPINLOCK(gic_lock);
static struct irq_domain *gic_irq_domain; static struct irq_domain *gic_irq_domain;
static int gic_shared_intrs; static int gic_shared_intrs;
static unsigned int gic_cpu_pin; static unsigned int gic_cpu_pin;
...@@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) ...@@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
irq = GIC_HWIRQ_TO_SHARED(d->hwirq); irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
switch (type & IRQ_TYPE_SENSE_MASK) { switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
pol = GIC_POL_FALLING_EDGE; pol = GIC_POL_FALLING_EDGE;
...@@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) ...@@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
else else
irq_set_chip_handler_name_locked(d, &gic_level_irq_controller, irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
handle_level_irq, NULL); handle_level_irq, NULL);
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; return 0;
} }
...@@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, ...@@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
return -EINVAL; return -EINVAL;
/* Assumption : cpumask refers to a single CPU */ /* Assumption : cpumask refers to a single CPU */
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
/* Re-route this IRQ */ /* Re-route this IRQ */
write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu))); write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
...@@ -279,7 +279,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, ...@@ -279,7 +279,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
set_bit(irq, per_cpu_ptr(pcpu_masks, cpu)); set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
irq_data_update_effective_affinity(d, cpumask_of(cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu));
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
return IRQ_SET_MASK_OK; return IRQ_SET_MASK_OK;
} }
...@@ -357,12 +357,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d) ...@@ -357,12 +357,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
cd = irq_data_get_irq_chip_data(d); cd = irq_data_get_irq_chip_data(d);
cd->mask = false; cd->mask = false;
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vl_other(mips_cm_vp_id(cpu));
write_gic_vo_rmask(BIT(intr)); write_gic_vo_rmask(BIT(intr));
} }
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
} }
static void gic_unmask_local_irq_all_vpes(struct irq_data *d) static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
...@@ -375,12 +375,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d) ...@@ -375,12 +375,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
cd = irq_data_get_irq_chip_data(d); cd = irq_data_get_irq_chip_data(d);
cd->mask = true; cd->mask = true;
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vl_other(mips_cm_vp_id(cpu));
write_gic_vo_smask(BIT(intr)); write_gic_vo_smask(BIT(intr));
} }
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
} }
static void gic_all_vpes_irq_cpu_online(void) static void gic_all_vpes_irq_cpu_online(void)
...@@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void) ...@@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void)
unsigned long flags; unsigned long flags;
int i; int i;
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
for (i = 0; i < ARRAY_SIZE(local_intrs); i++) { for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
unsigned int intr = local_intrs[i]; unsigned int intr = local_intrs[i];
struct gic_all_vpes_chip_data *cd; struct gic_all_vpes_chip_data *cd;
if (!gic_local_irq_is_routable(intr))
continue;
cd = &gic_all_vpes_chip_data[intr]; cd = &gic_all_vpes_chip_data[intr];
write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
if (cd->mask) if (cd->mask)
write_gic_vl_smask(BIT(intr)); write_gic_vl_smask(BIT(intr));
} }
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
} }
static struct irq_chip gic_all_vpes_local_irq_controller = { static struct irq_chip gic_all_vpes_local_irq_controller = {
...@@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, ...@@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
data = irq_get_irq_data(virq); data = irq_get_irq_data(virq);
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin); write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu))); write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
irq_data_update_effective_affinity(data, cpumask_of(cpu)); irq_data_update_effective_affinity(data, cpumask_of(cpu));
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; return 0;
} }
...@@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, ...@@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
if (!gic_local_irq_is_routable(intr)) if (!gic_local_irq_is_routable(intr))
return -EPERM; return -EPERM;
spin_lock_irqsave(&gic_lock, flags); raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vl_other(mips_cm_vp_id(cpu));
write_gic_vo_map(mips_gic_vx_map_reg(intr), map); write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
} }
spin_unlock_irqrestore(&gic_lock, flags); raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0; return 0;
} }
......
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