x86/resctrl: Allow RMID allocation to be scoped by CLOSID
[linux-2.6-microblaze.git] / arch / x86 / kernel / cpu / resctrl / monitor.c
index bc5ceef..c49f2e8 100644 (file)
@@ -344,24 +344,49 @@ bool has_busy_rmid(struct rdt_domain *d)
        return find_first_bit(d->rmid_busy_llc, idx_limit) != idx_limit;
 }
 
+static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
+{
+       struct rmid_entry *itr;
+       u32 itr_idx, cmp_idx;
+
+       if (list_empty(&rmid_free_lru))
+               return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
+
+       list_for_each_entry(itr, &rmid_free_lru, list) {
+               /*
+                * Get the index of this free RMID, and the index it would need
+                * to be if it were used with this CLOSID.
+                * If the CLOSID is irrelevant on this architecture, the two
+                * index values are always the same on every entry and thus the
+                * very first entry will be returned.
+                */
+               itr_idx = resctrl_arch_rmid_idx_encode(itr->closid, itr->rmid);
+               cmp_idx = resctrl_arch_rmid_idx_encode(closid, itr->rmid);
+
+               if (itr_idx == cmp_idx)
+                       return itr;
+       }
+
+       return ERR_PTR(-ENOSPC);
+}
+
 /*
- * As of now the RMIDs allocation is global.
- * However we keep track of which packages the RMIDs
- * are used to optimize the limbo list management.
+ * For MPAM the RMID value is not unique, and has to be considered with
+ * the CLOSID. The (CLOSID, RMID) pair is allocated on all domains, which
+ * allows all domains to be managed by a single free list.
+ * Each domain also has a rmid_busy_llc to reduce the work of the limbo handler.
  */
-int alloc_rmid(void)
+int alloc_rmid(u32 closid)
 {
        struct rmid_entry *entry;
 
        lockdep_assert_held(&rdtgroup_mutex);
 
-       if (list_empty(&rmid_free_lru))
-               return rmid_limbo_count ? -EBUSY : -ENOSPC;
+       entry = resctrl_find_free_rmid(closid);
+       if (IS_ERR(entry))
+               return PTR_ERR(entry);
 
-       entry = list_first_entry(&rmid_free_lru,
-                                struct rmid_entry, list);
        list_del(&entry->list);
-
        return entry->rmid;
 }