Commit c5fe9de7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 27a96c4f 243d3080
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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':
+6 −6
Original line number Diff line number Diff line
@@ -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>;
    };
+0 −1
Original line number Diff line number Diff line
@@ -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);
+101 −22
Original line number Diff line number Diff line
@@ -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,9 +5475,33 @@ 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();
	/*
	 * 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();
+1 −1
Original line number Diff line number Diff line
@@ -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;
Loading