mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
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. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmRzBAQTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoT/7D/9CDePULfT8t58VwpS/ZXGB1pAYhyWX FyQnxGeFz+H0NEylhB5LhqkmCFq60IZ+fBIYS9LmBU9GSJIvVXnp62SOPDmFmMwj fAj6y5JfpOxVZNb8SJ+JGVvwm2henRvOgeYKB4R/APk37dJcWzPruv/E64J7z0BC IeqFdq2cvkTnEDgE3Fnt6kZ2/iS8gd+Vtp/O/+pzqbt3u3vcogygSpNE8WE8Y+WE fF2+97EZx4oQRwIltNjaLBeW63ycQzx2+UCMy/84QYsTfi/wlquGcKWrBYwx+CDf XqrYMK6dMXW22o3VyrMxM6Jrd4raU7KsxWWOpqhClNabQjNbNgFdnMH56lJPFoqx 84tr2+RnxL1bGHQDiiQtCgBfRe0BGm82qUlQkKDXwcmBIDNm2rfeE1xGG6fHsylk lPT3dQBR3DvG5EkxKIe3BF6ZPlwhmCe76zsU1Dcf2tVoDZhN66Ck+/7VboTS1Ibb d/iR5gId0NUc3KFGQCPzo4roY2p+sp/PqZNm+U5aLZbfmFHsDPCQoh/N17y3Trh/ A4UuVwIy1JklosXvozb040M/rPIPZoei12nEQARYCR2VxafLO3d3OuE9Kp5tzOwb jCD4Img53VzYcf5KTcj0FgHcPNL18+dRZ3/vn1X27BlPWKRjfTTVOcQbs6cyZuo4 TmjaMYwX2vR7tQ== =OHtk -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
9bd5386c65
@ -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 ]
|
||||
|
@ -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",
|
||||
@ -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;
|
||||
|
@ -13,6 +13,7 @@
|
||||
struct gic_quirk {
|
||||
const char *desc;
|
||||
const char *compatible;
|
||||
const char *property;
|
||||
bool (*init)(void *data);
|
||||
u32 iidr;
|
||||
u32 mask;
|
||||
|
@ -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)
|
||||
|
||||
@ -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;
|
||||
@ -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,
|
||||
@ -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;
|
||||
|
@ -240,26 +240,27 @@ 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,
|
||||
@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
|
||||
&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
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
@ -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)));
|
||||
@ -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;
|
||||
}
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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 = {
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user