arm-cci: Add routines to save/restore all counters
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Tue, 23 Feb 2016 10:49:50 +0000 (10:49 +0000)
committerWill Deacon <will.deacon@arm.com>
Mon, 29 Feb 2016 23:23:16 +0000 (23:23 +0000)
Adds helper routines to disable the counter controls for
all the counters on the CCI PMU and restore it back, by
preserving the original state in caller provided mask.

Cc: Punit Agrawal <punit.agrawal@arm.com>
Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
drivers/bus/arm-cci.c

index d289037..7ce7da0 100644 (file)
@@ -718,6 +718,44 @@ static void pmu_set_event(struct cci_pmu *cci_pmu, int idx, unsigned long event)
        pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL);
 }
 
+/*
+ * For all counters on the CCI-PMU, disable any 'enabled' counters,
+ * saving the changed counters in the mask, so that we can restore
+ * it later using pmu_restore_counters. The mask is private to the
+ * caller. We cannot rely on the used_mask maintained by the CCI_PMU
+ * as it only tells us if the counter is assigned to perf_event or not.
+ * The state of the perf_event cannot be locked by the PMU layer, hence
+ * we check the individual counter status (which can be locked by
+ * cci_pm->hw_events->pmu_lock).
+ *
+ * @mask should be initialised to empty by the caller.
+ */
+static void __maybe_unused
+pmu_save_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
+{
+       int i;
+
+       for (i = 0; i < cci_pmu->num_cntrs; i++) {
+               if (pmu_counter_is_enabled(cci_pmu, i)) {
+                       set_bit(i, mask);
+                       pmu_disable_counter(cci_pmu, i);
+               }
+       }
+}
+
+/*
+ * Restore the status of the counters. Reversal of the pmu_save_counters().
+ * For each counter set in the mask, enable the counter back.
+ */
+static void __maybe_unused
+pmu_restore_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
+{
+       int i;
+
+       for_each_set_bit(i, mask, cci_pmu->num_cntrs)
+               pmu_enable_counter(cci_pmu, i);
+}
+
 /*
  * Returns the number of programmable counters actually implemented
  * by the cci