#include "coresight-etm-perf.h"
 #include "coresight-priv.h"
 #include "coresight-syscfg.h"
+#include "coresight-trace-id.h"
 
 static struct pmu etm_pmu;
 static bool etm_perf_up;
                if (!(IS_ERR_OR_NULL(*ppath)))
                        coresight_release_path(*ppath);
                *ppath = NULL;
+               coresight_trace_id_put_cpu_id(cpu);
        }
 
+       /* mark perf event as done for trace id allocator */
+       coresight_trace_id_perf_stop();
+
        free_percpu(event_data->path);
        kfree(event_data);
 }
 {
        u32 id, cfg_hash;
        int cpu = event->cpu;
+       int trace_id;
        cpumask_t *mask;
        struct coresight_device *sink = NULL;
        struct coresight_device *user_sink = NULL, *last_sink = NULL;
                sink = user_sink = coresight_get_sink_by_id(id);
        }
 
+       /* tell the trace ID allocator that a perf event is starting up */
+       coresight_trace_id_perf_start();
+
        /* check if user wants a coresight configuration selected */
        cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
        if (cfg_hash) {
                        continue;
                }
 
+               /* ensure we can allocate a trace ID for this CPU */
+               trace_id = coresight_trace_id_get_cpu_id(cpu);
+               if (!IS_VALID_CS_TRACE_ID(trace_id)) {
+                       cpumask_clear_cpu(cpu, mask);
+                       continue;
+               }
+
                *etm_event_cpu_path_ptr(event_data, cpu) = path;
        }