Patch adds cpu hotplug support. First online cpu in a node is picked as
designated thread to read the Nest pmu counter data, and at the time of
hotplug, next online cpu from the same node is picked up.

Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Anshuman Khandual <khand...@linux.vnet.ibm.com>
Cc: Stephane Eranian <eran...@google.com>
Cc: Preeti U Murthy <pre...@linux.vnet.ibm.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/nest-pmu.c | 84 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/arch/powerpc/perf/nest-pmu.c b/arch/powerpc/perf/nest-pmu.c
index d4413bb..3e7010e 100644
--- a/arch/powerpc/perf/nest-pmu.c
+++ b/arch/powerpc/perf/nest-pmu.c
@@ -30,6 +30,86 @@ static struct attribute_group cpumask_nest_pmu_attr_group = {
        .attrs = cpumask_nest_pmu_attrs,
 };
 
+static void nest_init(void *dummy)
+{
+       opal_nest_ima_control(P8_NEST_ENGINE_START);
+}
+
+static void nest_change_cpu_context(int old_cpu, int new_cpu)
+{
+       int i;
+
+       for (i=0; per_nestpmu_arr[i] != NULL; i++)
+               perf_pmu_migrate_context(&per_nestpmu_arr[i]->pmu,
+                                               old_cpu, new_cpu);
+       return;
+}
+
+static void nest_exit_cpu(int cpu)
+{
+       int i, nid, target = -1;
+       const struct cpumask *l_cpumask;
+       int src_chipid;
+
+       if (!cpumask_test_and_clear_cpu(cpu, &cpu_mask_nest_pmu))
+               return;
+
+       nid = cpu_to_node(cpu);
+       src_chipid = topology_physical_package_id(cpu);
+       l_cpumask = cpumask_of_node(nid);
+       for_each_cpu(i, l_cpumask) {
+               if (i == cpu)
+                       continue;
+               if (src_chipid == topology_physical_package_id(i)) {
+                       target = i;
+                       break;
+               }
+       }
+
+       cpumask_set_cpu(target, &cpu_mask_nest_pmu);
+       nest_change_cpu_context (cpu, target);
+       return;
+}
+
+static void nest_init_cpu(int cpu)
+{
+       int i, src_chipid;
+
+       src_chipid = topology_physical_package_id(cpu);
+       for_each_cpu(i, &cpu_mask_nest_pmu)
+               if (src_chipid == topology_physical_package_id(i))
+                       return;
+
+       cpumask_set_cpu(cpu, &cpu_mask_nest_pmu);
+       nest_change_cpu_context ( -1, cpu);
+       return;
+}
+
+static int nest_cpu_notifier(struct notifier_block *self,
+                               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_FAILED:
+       case CPU_STARTING:
+               nest_init_cpu(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               nest_exit_cpu(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block nest_cpu_nb = {
+       .notifier_call  = nest_cpu_notifier,
+       .priority       = CPU_PRI_PERF + 1,
+}
+
 void cpumask_chip(void)
 {
        const struct cpumask *l_cpumask;
@@ -47,6 +127,10 @@ void cpumask_chip(void)
                cpumask_set_cpu(cpu, &cpu_mask_nest_pmu);
        }
 
+       on_each_cpu_mask(&cpu_mask_nest_pmu, (smp_call_func_t)nest_init, NULL, 
1);
+
+       __register_cpu_notifier(&nest_cpu_nb);
+
        cpu_notifier_register_done();
 }
 
-- 
1.9.1

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to