- 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) (from Marc Zyngier) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmH2c9sACgkQEsHwGGHe VUo6Sg//a69glfbs6zPFVFe26vQuSlpFXBgsErSkjaSQiOogk6gEZVjhZJOSbPB0 jLdFbe4E3tvYeB2k5kZv60O/dXgTOiHgyOgVFJxK5AKL5mG8miINR6xOI7Ol5mqA qWJJx26+hphao0Rx/uicY/mJoWR1Q2vMr52gwckhNUuejMZukCps1deenU63cSSt /wOiAx8YUQYmK7UvlshQnC+bY6OmzttUugX1a9CiMehivk/qpv+nTfl3GNi1WtkU witsnRmAboRPBL3Cdb9dQcWPm+5Hp/z7Z3ItFT5ca851JU6qYk9Utb9GXeTCmvAX gKCMtfmk6F1jvHWLaUct8KWlWGs9F+OPk4P+1bVSa0NPfRxodKNp/iGIcjLZSdVf Uv3djaztZFeQ3pi26or+2rWbvWiz1bxaCvUxl3v5urHy2m2Ie8HqbHg7zM1Qf6lt 1EFVkEMkVZIUD+9y2jvhgCEAy6KaOL1c7Vs9GAKh1jfv3PNB29WPB6L20g2vKXju uocAS2acpkHLKm3VhWoLYRtI57UWbPoMaqAFyK6oxs3LGuYRvyZyxxc4ccxue/A6 tUgOmhawnvI6QVmCCRAWaCtb5wz7oPy1vxWoLEzJMqWQolgkg9lqL94TM+0a361K HqYA/ck69LN/Sps7kaSvF//t9DVpa0OQQtY5ODfLs/X3KxPgdOQ= =BFYG -----END PGP SIGNATURE----- Merge tag 'irq_urgent_for_v5.17_rc2_p2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull irq fixes from Borislav Petkov: - 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) * tag 'irq_urgent_for_v5.17_rc2_p2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: dt-bindings: interrupt-controller: sifive,plic: Group interrupt tuples dt-bindings: interrupt-controller: sifive,plic: Fix number of interrupts dt-bindings: irqchip: renesas-irqc: Add R-Car V3U support irqchip/gic-v3-its: Reset each ITS's BASERn register before probe irqchip/gic-v3-its: Fix build for !SMP irqchip/loongson-pch-ms: Use bitmap_free() to free bitmap irqchip/realtek-rtl: Service all pending interrupts irqchip/realtek-rtl: Fix off-by-one in routing irqchip/realtek-rtl: Map control data to virq irqchip/apple-aic: Drop unused ipi_hwirq field
This commit is contained in:
commit
c5fe9de790
|
@ -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 @@ dom_err:
|
|||
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 @@ out:
|
|||
* 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue