Skip to content

Commit

Permalink
Merge tag 'irq-urgent-2023-05-28' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed May 28, 2023
2 parents 045049c + 4115af4 commit 9bd5386
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ properties:
resets:
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:
mbi-ranges: [ msi-controller ]
msi-controller: [ mbi-ranges ]
Expand Down
8 changes: 6 additions & 2 deletions drivers/irqchip/irq-gic-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ void gic_enable_of_quirks(const struct device_node *np,
const struct gic_quirk *quirks, void *data)
{
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;
if (quirks->init(data))
pr_info("GIC: enabling workaround for %s\n",
Expand All @@ -28,7 +32,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data)
{
for (; quirks->desc; quirks++) {
if (quirks->compatible)
if (quirks->compatible || quirks->property)
continue;
if (quirks->iidr != (quirks->mask & iidr))
continue;
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/irq-gic-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
struct gic_quirk {
const char *desc;
const char *compatible;
const char *property;
bool (*init)(void *data);
u32 iidr;
u32 mask;
Expand Down
20 changes: 20 additions & 0 deletions drivers/irqchip/irq-gic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
#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)

Expand Down Expand Up @@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data)
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)
{
struct gic_chip_data *d = data;
Expand Down Expand Up @@ -1792,6 +1802,11 @@ static const struct gic_quirk gic_quirks[] = {
.compatible = "qcom,msm8996-gic-v3",
.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",
.iidr = 0x0204043b,
Expand Down Expand Up @@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void)
if (!gic_prio_masking_enabled())
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);
if (!ppi_nmi_refs)
return;
Expand Down
31 changes: 18 additions & 13 deletions drivers/irqchip/irq-mbigen.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,39 +240,44 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
struct irq_domain *domain;
struct device_node *np;
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) {
if (!of_property_read_bool(np, "interrupt-controller"))
continue;

parent = bus_get_dev_root(&platform_bus_type);
if (parent) {
child = of_platform_device_create(np, NULL, parent);
put_device(parent);
if (!child) {
of_node_put(np);
return -ENOMEM;
}
child = of_platform_device_create(np, NULL, parent);
if (!child) {
ret = -ENOMEM;
break;
}

if (of_property_read_u32(child->dev.of_node, "num-pins",
&num_pins) < 0) {
dev_err(&pdev->dev, "No num-pins property\n");
of_node_put(np);
return -EINVAL;
ret = -EINVAL;
break;
}

domain = platform_msi_create_device_domain(&child->dev, num_pins,
mbigen_write_msg,
&mbigen_domain_ops,
mgn_chip);
if (!domain) {
of_node_put(np);
return -ENOMEM;
ret = -ENOMEM;
break;
}
}

return 0;
put_device(parent);
if (ret)
of_node_put(np);

return ret;
}

#ifdef CONFIG_ACPI
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-meson-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = {
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,meson8b-gpio-intc", .data = &meson8b_params },
{ .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
Expand Down
32 changes: 17 additions & 15 deletions drivers/irqchip/irq-mips-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void __iomem *mips_gic_base;

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 int gic_shared_intrs;
static unsigned int gic_cpu_pin;
Expand Down Expand Up @@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)

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) {
case IRQ_TYPE_EDGE_FALLING:
pol = GIC_POL_FALLING_EDGE;
Expand Down Expand Up @@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
else
irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
handle_level_irq, NULL);
spin_unlock_irqrestore(&gic_lock, flags);
raw_spin_unlock_irqrestore(&gic_lock, flags);

return 0;
}
Expand All @@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
return -EINVAL;

/* Assumption : cpumask refers to a single CPU */
spin_lock_irqsave(&gic_lock, flags);
raw_spin_lock_irqsave(&gic_lock, flags);

/* Re-route this IRQ */
write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
Expand All @@ -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));

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;
}
Expand Down Expand Up @@ -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->mask = false;

spin_lock_irqsave(&gic_lock, flags);
raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu));
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)
Expand All @@ -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->mask = true;

spin_lock_irqsave(&gic_lock, flags);
raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu));
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)
Expand All @@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void)
unsigned long flags;
int i;

spin_lock_irqsave(&gic_lock, flags);
raw_spin_lock_irqsave(&gic_lock, flags);

for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
unsigned int intr = local_intrs[i];
struct gic_all_vpes_chip_data *cd;

if (!gic_local_irq_is_routable(intr))
continue;
cd = &gic_all_vpes_chip_data[intr];
write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
if (cd->mask)
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 = {
Expand Down Expand Up @@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int 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_vp(intr, BIT(mips_cm_vp_id(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;
}
Expand Down Expand Up @@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
if (!gic_local_irq_is_routable(intr))
return -EPERM;

spin_lock_irqsave(&gic_lock, flags);
raw_spin_lock_irqsave(&gic_lock, flags);
for_each_online_cpu(cpu) {
write_gic_vl_other(mips_cm_vp_id(cpu));
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;
}
Expand Down

0 comments on commit 9bd5386

Please sign in to comment.