Merge tag 'irqchip-fixes-5.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorThomas Gleixner <tglx@linutronix.de>
Sat, 29 Jan 2022 20:03:20 +0000 (21:03 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 29 Jan 2022 20:03:20 +0000 (21:03 +0100)
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
1  2 
Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
drivers/irqchip/irq-apple-aic.c
drivers/irqchip/irq-gic-v3-its.c

index 28b6b17fe4b267782f35bd0c9bd482542665facf,058997c4e3cd487ccbd34b0a60bb9dee056675db..0dfa6b26e09910a802384dccacee8f4a64bb9fd9
@@@ -45,7 -45,6 +45,7 @@@ properties
      items:
        - enum:
            - sifive,fu540-c000-plic
 +          - starfive,jh7100-plic
            - canaan,k210-plic
        - const: sifive,plic-1.0.0
  
@@@ -62,6 -61,7 +62,7 @@@
  
    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 -90,11 +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>;
      };
index 2543ef65825b903438f16331de4c92f864fe125e,53c4783b5b9b8091453cf627d7b05723d816bf05..38091ebb940330675c306df56c1e5adc4a893682
@@@ -178,7 -178,6 +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);
@@@ -707,7 -706,7 +706,7 @@@ static const struct irq_domain_ops aic_
        .free = aic_ipi_free,
  };
  
 -static int aic_init_smp(struct aic_irq_chip *irqc, struct device_node *node)
 +static int __init aic_init_smp(struct aic_irq_chip *irqc, struct device_node *node)
  {
        struct irq_domain *ipi_domain;
        int base_ipi;
index d25b7a864bbbbb5f55bd6363ec2b80a29ce6d196,220fa45c22f406dc8431de5882e36f71b26090ed..9e93ff2b63751fb9a95e6b0b25b916d1d7599c83
@@@ -746,7 -746,7 +746,7 @@@ static struct its_collection *its_build
  
        its_fixup_cmd(cmd);
  
 -      return NULL;
 +      return desc->its_invall_cmd.col;
  }
  
  static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
@@@ -4856,6 -4856,38 +4856,38 @@@ static struct syscore_ops its_syscore_o
        .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 +4995,14 @@@ static int __init its_probe_one(struct 
  {
        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 +5258,31 @@@ static int its_cpu_memreserve_lpi(unsig
  
  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 +5293,26 @@@ static int __init its_of_probe(struct d
        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 +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