Since thread-imc internally use the core-imc hardware infrastructure
and is depended on it, having thread-imc in the kernel in the
absence of core-imc is trivial. Patch disables thread-imc, if
core-imc is not registered.

Signed-off-by: Anju T Sudhakar <a...@linux.vnet.ibm.com>
Reviewed-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/imc-pmu.h        |  1 +
 arch/powerpc/perf/imc-pmu.c               | 12 ++++++++++++
 arch/powerpc/platforms/powernv/opal-imc.c |  9 +++++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/powerpc/include/asm/imc-pmu.h 
b/arch/powerpc/include/asm/imc-pmu.h
index d76cb11..69f516e 100644
--- a/arch/powerpc/include/asm/imc-pmu.h
+++ b/arch/powerpc/include/asm/imc-pmu.h
@@ -128,4 +128,5 @@ extern int init_imc_pmu(struct device_node *parent,
                                struct imc_pmu *pmu_ptr, int pmu_id);
 extern void thread_imc_disable(void);
 extern int get_max_nest_dev(void);
+extern void unregister_thread_imc(void);
 #endif /* __ASM_POWERPC_IMC_PMU_H */
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index f563d30..d1977b6 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -40,6 +40,7 @@ static struct imc_pmu *core_imc_pmu;
 /* Thread IMC data structures and variables */
 
 static DEFINE_PER_CPU(u64 *, thread_imc_mem);
+static struct imc_pmu *thread_imc_pmu;
 static int thread_imc_mem_size;
 
 struct imc_pmu *imc_event_to_pmu(struct perf_event *event)
@@ -1228,6 +1229,16 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu 
*pmu_ptr)
        }
 }
 
+/*
+ * Function to unregister thread-imc if core-imc
+ * is not registered.
+ */
+void unregister_thread_imc(void)
+{
+       imc_common_cpuhp_mem_free(thread_imc_pmu);
+       imc_common_mem_free(thread_imc_pmu);
+       perf_pmu_unregister(&thread_imc_pmu->pmu);
+}
 
 /*
  * imc_mem_init : Function to support memory allocation for core imc.
@@ -1296,6 +1307,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct 
device_node *parent,
                        }
                }
 
+               thread_imc_pmu = pmu_ptr;
                break;
        default:
                return -EINVAL;
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c 
b/arch/powerpc/platforms/powernv/opal-imc.c
index 490bb72..58a0794 100644
--- a/arch/powerpc/platforms/powernv/opal-imc.c
+++ b/arch/powerpc/platforms/powernv/opal-imc.c
@@ -255,6 +255,7 @@ static int opal_imc_counters_probe(struct platform_device 
*pdev)
 {
        struct device_node *imc_dev = pdev->dev.of_node;
        int pmu_count = 0, domain;
+       bool core_imc_reg = false, thread_imc_reg = false;
        u32 type;
 
        /*
@@ -292,6 +293,10 @@ static int opal_imc_counters_probe(struct platform_device 
*pdev)
                if (!imc_pmu_create(imc_dev, pmu_count, domain)) {
                        if (domain == IMC_DOMAIN_NEST)
                                pmu_count++;
+                       if (domain == IMC_DOMAIN_CORE)
+                               core_imc_reg = true;
+                       if (domain == IMC_DOMAIN_THREAD)
+                               thread_imc_reg = true;
                }
        }
 
@@ -299,6 +304,10 @@ static int opal_imc_counters_probe(struct platform_device 
*pdev)
        if (pmu_count == 0)
                debugfs_remove_recursive(imc_debugfs_parent);
 
+       /* If core imc is not registered, unregister thread-imc */
+       if (!core_imc_reg && thread_imc_reg)
+               unregister_thread_imc();
+
        return 0;
 }
 
-- 
2.7.4

Reply via email to