#else
        unsigned int    *tsk_pinned;
 #endif
-       /* Number of non-pinned cpu/task breakpoints in a cpu */
-       unsigned int    flexible; /* XXX: placeholder, see fetch_this_slot() */
 };
 
 static DEFINE_PER_CPU(struct bp_cpuinfo, bp_cpuinfo[TYPE_MAX]);
 
 static bool constraints_initialized __ro_after_init;
 
-/* Gather the number of total pinned and un-pinned bp in a cpuset */
-struct bp_busy_slots {
-       unsigned int pinned;
-       unsigned int flexible;
-};
-
 /* Serialize accesses to the above constraints */
 static DEFINE_MUTEX(nr_bp_mutex);
 
 }
 
 /*
- * Report the number of pinned/un-pinned breakpoints we have in
- * a given cpu (cpu > -1) or in all of them (cpu = -1).
+ * Returns the max pinned breakpoint slots in a given
+ * CPU (cpu > -1) or across all of them (cpu = -1).
  */
-static void
-fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
-                   enum bp_type_idx type)
+static int
+max_bp_pinned_slots(struct perf_event *bp, enum bp_type_idx type)
 {
        const struct cpumask *cpumask = cpumask_of_bp(bp);
+       int pinned_slots = 0;
        int cpu;
 
        for_each_cpu(cpu, cpumask) {
                else
                        nr += task_bp_pinned(cpu, bp, type);
 
-               if (nr > slots->pinned)
-                       slots->pinned = nr;
-
-               nr = info->flexible;
-               if (nr > slots->flexible)
-                       slots->flexible = nr;
+               pinned_slots = max(nr, pinned_slots);
        }
-}
 
-/*
- * For now, continue to consider flexible as pinned, until we can
- * ensure no flexible event can ever be scheduled before a pinned event
- * in a same cpu.
- */
-static void
-fetch_this_slot(struct bp_busy_slots *slots, int weight)
-{
-       slots->pinned += weight;
+       return pinned_slots;
 }
 
 /*
 }
 
 /*
- * Constraints to check before allowing this new breakpoint counter:
+ * Constraints to check before allowing this new breakpoint counter.
+ *
+ * Note: Flexible breakpoints are currently unimplemented, but outlined in the
+ * below algorithm for completeness.  The implementation treats flexible as
+ * pinned due to no guarantee that we currently always schedule flexible events
+ * before a pinned event in a same CPU.
  *
  *  == Non-pinned counter == (Considered as pinned for now)
  *
  */
 static int __reserve_bp_slot(struct perf_event *bp, u64 bp_type)
 {
-       struct bp_busy_slots slots = {0};
        enum bp_type_idx type;
+       int max_pinned_slots;
        int weight;
        int ret;
 
        type = find_slot_idx(bp_type);
        weight = hw_breakpoint_weight(bp);
 
-       fetch_bp_busy_slots(&slots, bp, type);
-       /*
-        * Simulate the addition of this breakpoint to the constraints
-        * and see the result.
-        */
-       fetch_this_slot(&slots, weight);
-
-       /* Flexible counters need to keep at least one slot */
-       if (slots.pinned + (!!slots.flexible) > hw_breakpoint_slots_cached(type))
+       /* Check if this new breakpoint can be satisfied across all CPUs. */
+       max_pinned_slots = max_bp_pinned_slots(bp, type) + weight;
+       if (max_pinned_slots > hw_breakpoint_slots_cached(type))
                return -ENOSPC;
 
        ret = arch_reserve_bp_slot(bp);