#include <asm/cputhreads.h>
 #include <asm/smp.h>
 #include <linux/string.h>
+#include <linux/spinlock.h>
 
 /* Nest IMC data structures and variables */
 
  * Used to avoid races in counting the nest-pmu units during hotplug
  * register and unregister
  */
-static DEFINE_MUTEX(nest_init_lock);
+static DEFINE_SPINLOCK(nest_init_lock);
 static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
 static struct imc_pmu **per_nest_pmu_arr;
 static cpumask_t nest_imc_cpumask;
  * core and trace-imc
  */
 static struct imc_pmu_ref imc_global_refc = {
-       .lock = __MUTEX_INITIALIZER(imc_global_refc.lock),
+       .lock = __SPIN_LOCK_INITIALIZER(imc_global_refc.lock),
        .id = 0,
        .refc = 0,
 };
                                       get_hard_smp_processor_id(cpu));
                /*
                 * If this is the last cpu in this chip then, skip the reference
-                * count mutex lock and make the reference count on this chip zero.
+                * count lock and make the reference count on this chip zero.
                 */
                ref = get_nest_pmu_ref(cpu);
                if (!ref)
        /*
         * See if we need to disable the nest PMU.
         * If no events are currently in use, then we have to take a
-        * mutex to ensure that we don't race with another task doing
+        * lock to ensure that we don't race with another task doing
         * enable or disable the nest counters.
         */
        ref = get_nest_pmu_ref(event->cpu);
        if (!ref)
                return;
 
-       /* Take the mutex lock for this node and then decrement the reference count */
-       mutex_lock(&ref->lock);
+       /* Take the lock for this node and then decrement the reference count */
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                /*
                 * The scenario where this is true is, when perf session is
                 * an OPAL call to disable the engine in that node.
                 *
                 */
-               mutex_unlock(&ref->lock);
+               spin_unlock(&ref->lock);
                return;
        }
        ref->refc--;
                rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
                                            get_hard_smp_processor_id(event->cpu));
                if (rc) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("nest-imc: Unable to stop the counters for core %d\n", node_id);
                        return;
                }
                WARN(1, "nest-imc: Invalid event reference count\n");
                ref->refc = 0;
        }
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 }
 
 static int nest_imc_event_init(struct perf_event *event)
 
        /*
         * Get the imc_pmu_ref struct for this node.
-        * Take the mutex lock and then increment the count of nest pmu events
-        * inited.
+        * Take the lock and then increment the count of nest pmu events inited.
         */
        ref = get_nest_pmu_ref(event->cpu);
        if (!ref)
                return -EINVAL;
 
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_NEST,
                                             get_hard_smp_processor_id(event->cpu));
                if (rc) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("nest-imc: Unable to start the counters for node %d\n",
                                                                        node_id);
                        return rc;
                }
        }
        ++ref->refc;
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 
        event->destroy = nest_imc_counters_release;
        return 0;
                return -ENOMEM;
        mem_info->vbase = page_address(page);
 
-       /* Init the mutex */
        core_imc_refc[core_id].id = core_id;
-       mutex_init(&core_imc_refc[core_id].lock);
+       spin_lock_init(&core_imc_refc[core_id].lock);
 
        rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_CORE,
                                __pa((void *)mem_info->vbase),
                perf_pmu_migrate_context(&core_imc_pmu->pmu, cpu, ncpu);
        } else {
                /*
-                * If this is the last cpu in this core then, skip taking refernce
-                * count mutex lock for this core and directly zero "refc" for
-                * this core.
+                * If this is the last cpu in this core then skip taking reference
+                * count lock for this core and directly zero "refc" for this core.
                 */
                opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
                                       get_hard_smp_processor_id(cpu));
                 * last cpu in this core and core-imc event running
                 * in this cpu.
                 */
-               mutex_lock(&imc_global_refc.lock);
+               spin_lock(&imc_global_refc.lock);
                if (imc_global_refc.id == IMC_DOMAIN_CORE)
                        imc_global_refc.refc--;
 
-               mutex_unlock(&imc_global_refc.lock);
+               spin_unlock(&imc_global_refc.lock);
        }
        return 0;
 }
 
 static void reset_global_refc(struct perf_event *event)
 {
-               mutex_lock(&imc_global_refc.lock);
+               spin_lock(&imc_global_refc.lock);
                imc_global_refc.refc--;
 
                /*
                        imc_global_refc.refc = 0;
                        imc_global_refc.id = 0;
                }
-               mutex_unlock(&imc_global_refc.lock);
+               spin_unlock(&imc_global_refc.lock);
 }
 
 static void core_imc_counters_release(struct perf_event *event)
        /*
         * See if we need to disable the IMC PMU.
         * If no events are currently in use, then we have to take a
-        * mutex to ensure that we don't race with another task doing
+        * lock to ensure that we don't race with another task doing
         * enable or disable the core counters.
         */
        core_id = event->cpu / threads_per_core;
 
-       /* Take the mutex lock and decrement the refernce count for this core */
+       /* Take the lock and decrement the refernce count for this core */
        ref = &core_imc_refc[core_id];
        if (!ref)
                return;
 
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                /*
                 * The scenario where this is true is, when perf session is
                 * an OPAL call to disable the engine in that core.
                 *
                 */
-               mutex_unlock(&ref->lock);
+               spin_unlock(&ref->lock);
                return;
        }
        ref->refc--;
                rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
                                            get_hard_smp_processor_id(event->cpu));
                if (rc) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("IMC: Unable to stop the counters for core %d\n", core_id);
                        return;
                }
                WARN(1, "core-imc: Invalid event reference count\n");
                ref->refc = 0;
        }
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 
        reset_global_refc(event);
 }
        if ((!pcmi->vbase))
                return -ENODEV;
 
-       /* Get the core_imc mutex for this core */
        ref = &core_imc_refc[core_id];
        if (!ref)
                return -EINVAL;
        /*
         * Core pmu units are enabled only when it is used.
         * See if this is triggered for the first time.
-        * If yes, take the mutex lock and enable the core counters.
+        * If yes, take the lock and enable the core counters.
         * If not, just increment the count in core_imc_refc struct.
         */
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
                                             get_hard_smp_processor_id(event->cpu));
                if (rc) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("core-imc: Unable to start the counters for core %d\n",
                                                                        core_id);
                        return rc;
                }
        }
        ++ref->refc;
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 
        /*
         * Since the system can run either in accumulation or trace-mode
         * to know whether any other trace/thread imc
         * events are running.
         */
-       mutex_lock(&imc_global_refc.lock);
+       spin_lock(&imc_global_refc.lock);
        if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_CORE) {
                /*
                 * No other trace/thread imc events are running in
                imc_global_refc.id = IMC_DOMAIN_CORE;
                imc_global_refc.refc++;
        } else {
-               mutex_unlock(&imc_global_refc.lock);
+               spin_unlock(&imc_global_refc.lock);
                return -EBUSY;
        }
-       mutex_unlock(&imc_global_refc.lock);
+       spin_unlock(&imc_global_refc.lock);
 
        event->hw.event_base = (u64)pcmi->vbase + (config & IMC_EVENT_OFFSET_MASK);
        event->destroy = core_imc_counters_release;
        mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
 
        /* Reduce the refc if thread-imc event running on this cpu */
-       mutex_lock(&imc_global_refc.lock);
+       spin_lock(&imc_global_refc.lock);
        if (imc_global_refc.id == IMC_DOMAIN_THREAD)
                imc_global_refc.refc--;
-       mutex_unlock(&imc_global_refc.lock);
+       spin_unlock(&imc_global_refc.lock);
 
        return 0;
 }
        if (!target)
                return -EINVAL;
 
-       mutex_lock(&imc_global_refc.lock);
+       spin_lock(&imc_global_refc.lock);
        /*
         * Check if any other trace/core imc events are running in the
         * system, if not set the global id to thread-imc.
                imc_global_refc.id = IMC_DOMAIN_THREAD;
                imc_global_refc.refc++;
        } else {
-               mutex_unlock(&imc_global_refc.lock);
+               spin_unlock(&imc_global_refc.lock);
                return -EBUSY;
        }
-       mutex_unlock(&imc_global_refc.lock);
+       spin_unlock(&imc_global_refc.lock);
 
        event->pmu->task_ctx_nr = perf_sw_context;
        event->destroy = reset_global_refc;
        /*
         * imc pmus are enabled only when it is used.
         * See if this is triggered for the first time.
-        * If yes, take the mutex lock and enable the counters.
+        * If yes, take the lock and enable the counters.
         * If not, just increment the count in ref count struct.
         */
        ref = &core_imc_refc[core_id];
        if (!ref)
                return -EINVAL;
 
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                if (opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
                    get_hard_smp_processor_id(smp_processor_id()))) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("thread-imc: Unable to start the counter\
                                for core %d\n", core_id);
                        return -EINVAL;
                }
        }
        ++ref->refc;
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
        return 0;
 }
 
                return;
        }
 
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        ref->refc--;
        if (ref->refc == 0) {
                if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
                    get_hard_smp_processor_id(smp_processor_id()))) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("thread-imc: Unable to stop the counters\
                                for core %d\n", core_id);
                        return;
        } else if (ref->refc < 0) {
                ref->refc = 0;
        }
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 
        /* Set bit 0 of LDBAR to zero, to stop posting updates to memory */
        mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
                }
        }
 
-       /* Init the mutex, if not already */
        trace_imc_refc[core_id].id = core_id;
-       mutex_init(&trace_imc_refc[core_id].lock);
+       spin_lock_init(&trace_imc_refc[core_id].lock);
 
        mtspr(SPRN_LDBAR, 0);
        return 0;
         * Reduce the refc if any trace-imc event running
         * on this cpu.
         */
-       mutex_lock(&imc_global_refc.lock);
+       spin_lock(&imc_global_refc.lock);
        if (imc_global_refc.id == IMC_DOMAIN_TRACE)
                imc_global_refc.refc--;
-       mutex_unlock(&imc_global_refc.lock);
+       spin_unlock(&imc_global_refc.lock);
 
        return 0;
 }
        }
 
        mtspr(SPRN_LDBAR, ldbar_value);
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        if (ref->refc == 0) {
                if (opal_imc_counters_start(OPAL_IMC_COUNTERS_TRACE,
                                get_hard_smp_processor_id(smp_processor_id()))) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("trace-imc: Unable to start the counters for core %d\n", core_id);
                        return -EINVAL;
                }
        }
        ++ref->refc;
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
        return 0;
 }
 
                return;
        }
 
-       mutex_lock(&ref->lock);
+       spin_lock(&ref->lock);
        ref->refc--;
        if (ref->refc == 0) {
                if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_TRACE,
                                get_hard_smp_processor_id(smp_processor_id()))) {
-                       mutex_unlock(&ref->lock);
+                       spin_unlock(&ref->lock);
                        pr_err("trace-imc: Unable to stop the counters for core %d\n", core_id);
                        return;
                }
        } else if (ref->refc < 0) {
                ref->refc = 0;
        }
-       mutex_unlock(&ref->lock);
+       spin_unlock(&ref->lock);
 
        trace_imc_event_stop(event, flags);
 }
         * no other thread is running any core/thread imc
         * events
         */
-       mutex_lock(&imc_global_refc.lock);
+       spin_lock(&imc_global_refc.lock);
        if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_TRACE) {
                /*
                 * No core/thread imc events are running in the
                imc_global_refc.id = IMC_DOMAIN_TRACE;
                imc_global_refc.refc++;
        } else {
-               mutex_unlock(&imc_global_refc.lock);
+               spin_unlock(&imc_global_refc.lock);
                return -EBUSY;
        }
-       mutex_unlock(&imc_global_refc.lock);
+       spin_unlock(&imc_global_refc.lock);
 
        event->hw.idx = -1;
 
        i = 0;
        for_each_node(nid) {
                /*
-                * Mutex lock to avoid races while tracking the number of
+                * Take the lock to avoid races while tracking the number of
                 * sessions using the chip's nest pmu units.
                 */
-               mutex_init(&nest_imc_refc[i].lock);
+               spin_lock_init(&nest_imc_refc[i].lock);
 
                /*
                 * Loop to init the "id" with the node_id. Variable "i" initialized to
 static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
 {
        if (pmu_ptr->domain == IMC_DOMAIN_NEST) {
-               mutex_lock(&nest_init_lock);
+               spin_lock(&nest_init_lock);
                if (nest_pmus == 1) {
                        cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
                        kfree(nest_imc_refc);
 
                if (nest_pmus > 0)
                        nest_pmus--;
-               mutex_unlock(&nest_init_lock);
+               spin_unlock(&nest_init_lock);
        }
 
        /* Free core_imc memory */
                * rest. To handle the cpuhotplug callback unregister, we track
                * the number of nest pmus in "nest_pmus".
                */
-               mutex_lock(&nest_init_lock);
+               spin_lock(&nest_init_lock);
                if (nest_pmus == 0) {
                        ret = init_nest_pmu_ref();
                        if (ret) {
-                               mutex_unlock(&nest_init_lock);
+                               spin_unlock(&nest_init_lock);
                                kfree(per_nest_pmu_arr);
                                per_nest_pmu_arr = NULL;
                                goto err_free_mem;
                        /* Register for cpu hotplug notification. */
                        ret = nest_pmu_cpumask_init();
                        if (ret) {
-                               mutex_unlock(&nest_init_lock);
+                               spin_unlock(&nest_init_lock);
                                kfree(nest_imc_refc);
                                kfree(per_nest_pmu_arr);
                                per_nest_pmu_arr = NULL;
                        }
                }
                nest_pmus++;
-               mutex_unlock(&nest_init_lock);
+               spin_unlock(&nest_init_lock);
                break;
        case IMC_DOMAIN_CORE:
                ret = core_imc_pmu_cpumask_init();