- 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:
Linus Torvalds 2022-01-30 15:12:02 +02:00
commit c5fe9de790
6 changed files with 121 additions and 36 deletions

View File

@ -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':

View File

@ -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>;
};

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}