Commit 243d3080 authored by Thomas Gleixner's avatar Thomas Gleixner

Merge tag 'irqchip-fixes-5.17-1' of...

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

Pull irqchip fixes from Marc Zyngier:

  - Drop an unused private data field in the AIC driver

  - Various fixes to the realtek-rtl driver

  - Make the GICv3 ITS driver compile again in !SMP configurations

  - Force reset of the GICv3 ITSs at probe time to avoid issues during kexec

  - Yet another kfree/bitmap_free conversion

  - Various DT updates (Renesas, SiFive)

Link: https://lore.kernel.org/r/20220128174217.517041-1-maz@kernel.org
parents a0af3d11 c89e5eb7
......@@ -36,6 +36,7 @@ properties:
- renesas,intc-ex-r8a77980 # R-Car V3H
- renesas,intc-ex-r8a77990 # R-Car E3
- renesas,intc-ex-r8a77995 # R-Car D3
- renesas,intc-ex-r8a779a0 # R-Car V3U
- const: renesas,irqc
'#interrupt-cells':
......
......@@ -62,6 +62,7 @@ properties:
interrupts-extended:
minItems: 1
maxItems: 15872
description:
Specifies which contexts are connected to the PLIC, with "-1" specifying
that a context is not present. Each node pointed to should be a
......@@ -90,12 +91,11 @@ examples:
#interrupt-cells = <1>;
compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
interrupt-controller;
interrupts-extended = <
&cpu0_intc 11
&cpu1_intc 11 &cpu1_intc 9
&cpu2_intc 11 &cpu2_intc 9
&cpu3_intc 11 &cpu3_intc 9
&cpu4_intc 11 &cpu4_intc 9>;
interrupts-extended = <&cpu0_intc 11>,
<&cpu1_intc 11>, <&cpu1_intc 9>,
<&cpu2_intc 11>, <&cpu2_intc 9>,
<&cpu3_intc 11>, <&cpu3_intc 9>,
<&cpu4_intc 11>, <&cpu4_intc 9>;
reg = <0xc000000 0x4000000>;
riscv,ndev = <10>;
};
......@@ -178,7 +178,6 @@ struct aic_irq_chip {
struct irq_domain *hw_domain;
struct irq_domain *ipi_domain;
int nr_hw;
int ipi_hwirq;
};
static DEFINE_PER_CPU(uint32_t, aic_fiq_unmasked);
......
......@@ -4856,6 +4856,38 @@ static struct syscore_ops its_syscore_ops = {
.resume = its_restore_enable,
};
static void __init __iomem *its_map_one(struct resource *res, int *err)
{
void __iomem *its_base;
u32 val;
its_base = ioremap(res->start, SZ_64K);
if (!its_base) {
pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
*err = -ENOMEM;
return NULL;
}
val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
if (val != 0x30 && val != 0x40) {
pr_warn("ITS@%pa: No ITS detected, giving up\n", &res->start);
*err = -ENODEV;
goto out_unmap;
}
*err = its_force_quiescent(its_base);
if (*err) {
pr_warn("ITS@%pa: Failed to quiesce, giving up\n", &res->start);
goto out_unmap;
}
return its_base;
out_unmap:
iounmap(its_base);
return NULL;
}
static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
{
struct irq_domain *inner_domain;
......@@ -4963,29 +4995,14 @@ static int __init its_probe_one(struct resource *res,
{
struct its_node *its;
void __iomem *its_base;
u32 val, ctlr;
u64 baser, tmp, typer;
struct page *page;
u32 ctlr;
int err;
its_base = ioremap(res->start, SZ_64K);
if (!its_base) {
pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
return -ENOMEM;
}
val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
if (val != 0x30 && val != 0x40) {
pr_warn("ITS@%pa: No ITS detected, giving up\n", &res->start);
err = -ENODEV;
goto out_unmap;
}
err = its_force_quiescent(its_base);
if (err) {
pr_warn("ITS@%pa: Failed to quiesce, giving up\n", &res->start);
goto out_unmap;
}
its_base = its_map_one(res, &err);
if (!its_base)
return err;
pr_info("ITS %pR\n", res);
......@@ -5241,13 +5258,31 @@ static int its_cpu_memreserve_lpi(unsigned int cpu)
out:
/* Last CPU being brought up gets to issue the cleanup */
if (cpumask_equal(&cpus_booted_once_mask, cpu_possible_mask))
if (!IS_ENABLED(CONFIG_SMP) ||
cpumask_equal(&cpus_booted_once_mask, cpu_possible_mask))
schedule_work(&rdist_memreserve_cpuhp_cleanup_work);
gic_data_rdist()->flags |= RD_LOCAL_MEMRESERVE_DONE;
return ret;
}
/* Mark all the BASER registers as invalid before they get reprogrammed */
static int __init its_reset_one(struct resource *res)
{
void __iomem *its_base;
int err, i;
its_base = its_map_one(res, &err);
if (!its_base)
return err;
for (i = 0; i < GITS_BASER_NR_REGS; i++)
gits_write_baser(0, its_base + GITS_BASER + (i << 3));
iounmap(its_base);
return 0;
}
static const struct of_device_id its_device_id[] = {
{ .compatible = "arm,gic-v3-its", },
{},
......@@ -5258,6 +5293,26 @@ static int __init its_of_probe(struct device_node *node)
struct device_node *np;
struct resource res;
/*
* Make sure *all* the ITS are reset before we probe any, as
* they may be sharing memory. If any of the ITS fails to
* reset, don't even try to go any further, as this could
* result in something even worse.
*/
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
int err;
if (!of_device_is_available(np) ||
!of_property_read_bool(np, "msi-controller") ||
of_address_to_resource(np, 0, &res))
continue;
err = its_reset_one(&res);
if (err)
return err;
}
for (np = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
if (!of_device_is_available(np))
......@@ -5420,11 +5475,35 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
return err;
}
static int __init its_acpi_reset(union acpi_subtable_headers *header,
const unsigned long end)
{
struct acpi_madt_generic_translator *its_entry;
struct resource res;
its_entry = (struct acpi_madt_generic_translator *)header;
res = (struct resource) {
.start = its_entry->base_address,
.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1,
.flags = IORESOURCE_MEM,
};
return its_reset_one(&res);
}
static void __init its_acpi_probe(void)
{
acpi_table_parse_srat_its();
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
gic_acpi_parse_madt_its, 0);
/*
* Make sure *all* the ITS are reset before we probe any, as
* they may be sharing memory. If any of the ITS fails to
* reset, don't even try to go any further, as this could
* result in something even worse.
*/
if (acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
its_acpi_reset, 0) > 0)
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
gic_acpi_parse_madt_its, 0);
acpi_its_srat_maps_free();
}
#else
......
......@@ -241,7 +241,7 @@ static int pch_msi_init(struct device_node *node,
return 0;
err_map:
kfree(priv->msi_map);
bitmap_free(priv->msi_map);
err_priv:
kfree(priv);
return ret;
......
......@@ -62,7 +62,7 @@ static struct irq_chip realtek_ictl_irq = {
static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq);
irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
return 0;
}
......@@ -76,16 +76,20 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *domain;
unsigned int pending;
unsigned long pending;
unsigned int soc_int;
chained_irq_enter(chip, desc);
pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
if (unlikely(!pending)) {
spurious_interrupt();
goto out;
}
domain = irq_desc_get_handler_data(desc);
generic_handle_domain_irq(domain, __ffs(pending));
for_each_set_bit(soc_int, &pending, 32)
generic_handle_domain_irq(domain, soc_int);
out:
chained_irq_exit(chip, desc);
......@@ -95,7 +99,8 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
* SoC interrupts are cascaded to MIPS CPU interrupts according to the
* interrupt-map in the device tree. Each SoC interrupt gets 4 bits for
* the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts
* thus go into 4 IRRs.
* thus go into 4 IRRs. A routing value of '0' means the interrupt is left
* disconnected. Routing values {1..15} connect to output lines {0..14}.
*/
static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)
{
......@@ -134,7 +139,7 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do
of_node_put(cpu_ictl);
cpu_int = be32_to_cpup(imap + 2);
if (cpu_int > 7)
if (cpu_int > 7 || cpu_int < 2)
return -EINVAL;
if (!(mips_irqs_set & BIT(cpu_int))) {
......@@ -143,7 +148,8 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do
mips_irqs_set |= BIT(cpu_int);
}
regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32;
/* Use routing values (1..6) for CPU interrupts (2..7) */
regs[(soc_int * 4) / 32] |= (cpu_int - 1) << (soc_int * 4) % 32;
imap += 3;
}
......
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