Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Mar 2020 20:35:47 +0000 (14:35 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Mar 2020 20:35:47 +0000 (14:35 -0600)
Pull arm64 fixes from Will Deacon:
 "Here are another three arm64 fixes for 5.6, all pretty minor. Main
  thing is fixing a silly bug in the fsl_imx8_ddr PMU driver where we
  would zero the counters when disabling them.

   - Fix misreporting of ASID limit when KPTI is enabled

   - Fix busted NULL pointer checks for GICC structure in ACPI PMU code

   - Avoid nobbling the "fsl_imx8_ddr" PMU counters when disabling them"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: context: Fix ASID limit in boot messages
  drivers/perf: arm_pmu_acpi: Fix incorrect checking of gicc pointer
  drivers/perf: fsl_imx8_ddr: Correct the CLEAR bit definition

arch/arm64/mm/context.c
drivers/perf/arm_pmu_acpi.c
drivers/perf/fsl_imx8_ddr_perf.c

index 8ef73e8..d89bb22 100644 (file)
@@ -260,14 +260,26 @@ asmlinkage void post_ttbr_update_workaround(void)
                        CONFIG_CAVIUM_ERRATUM_27456));
 }
 
-static int asids_init(void)
+static int asids_update_limit(void)
 {
-       asid_bits = get_cpu_asid_bits();
+       unsigned long num_available_asids = NUM_USER_ASIDS;
+
+       if (arm64_kernel_unmapped_at_el0())
+               num_available_asids /= 2;
        /*
         * Expect allocation after rollover to fail if we don't have at least
         * one more ASID than CPUs. ASID #0 is reserved for init_mm.
         */
-       WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
+       WARN_ON(num_available_asids - 1 <= num_possible_cpus());
+       pr_info("ASID allocator initialised with %lu entries\n",
+               num_available_asids);
+       return 0;
+}
+arch_initcall(asids_update_limit);
+
+static int asids_init(void)
+{
+       asid_bits = get_cpu_asid_bits();
        atomic64_set(&asid_generation, ASID_FIRST_VERSION);
        asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map),
                           GFP_KERNEL);
@@ -282,8 +294,6 @@ static int asids_init(void)
         */
        if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
                set_kpti_asid_bits();
-
-       pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
        return 0;
 }
 early_initcall(asids_init);
index acce878..f5c7a84 100644 (file)
@@ -24,8 +24,6 @@ static int arm_pmu_acpi_register_irq(int cpu)
        int gsi, trigger;
 
        gicc = acpi_cpu_get_madt_gicc(cpu);
-       if (WARN_ON(!gicc))
-               return -EINVAL;
 
        gsi = gicc->performance_interrupt;
 
@@ -64,11 +62,10 @@ static void arm_pmu_acpi_unregister_irq(int cpu)
        int gsi;
 
        gicc = acpi_cpu_get_madt_gicc(cpu);
-       if (!gicc)
-               return;
 
        gsi = gicc->performance_interrupt;
-       acpi_unregister_gsi(gsi);
+       if (gsi)
+               acpi_unregister_gsi(gsi);
 }
 
 #if IS_ENABLED(CONFIG_ARM_SPE_PMU)
index 95dca2c..90884d1 100644 (file)
@@ -388,9 +388,10 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
 
        if (enable) {
                /*
-                * must disable first, then enable again
-                * otherwise, cycle counter will not work
-                * if previous state is enabled.
+                * cycle counter is special which should firstly write 0 then
+                * write 1 into CLEAR bit to clear it. Other counters only
+                * need write 0 into CLEAR bit and it turns out to be 1 by
+                * hardware. Below enable flow is harmless for all counters.
                 */
                writel(0, pmu->base + reg);
                val = CNTL_EN | CNTL_CLEAR;
@@ -398,7 +399,8 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
                writel(val, pmu->base + reg);
        } else {
                /* Disable counter */
-               writel(0, pmu->base + reg);
+               val = readl_relaxed(pmu->base + reg) & CNTL_EN_MASK;
+               writel(val, pmu->base + reg);
        }
 }