summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/resctrl/mpam_devices.c2
-rw-r--r--drivers/resctrl/mpam_internal.h41
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 3d9b87a9727a..dcbc9cf5581d 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/printk.h>
#include <linux/srcu.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@@ -740,6 +741,7 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev)
if (err)
return ERR_PTR(err);
+ mpam_mon_sel_lock_init(msc);
msc->id = pdev->id;
msc->pdev = pdev;
INIT_LIST_HEAD_RCU(&msc->all_msc_list);
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index 768a58a3ab27..97f02cf92d7a 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -10,6 +10,7 @@
#include <linux/llist.h>
#include <linux/mutex.h>
#include <linux/srcu.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#define MPAM_MSC_MAX_NUM_RIS 16
@@ -65,12 +66,52 @@ struct mpam_msc {
*/
struct mutex part_sel_lock;
+ /*
+ * mon_sel_lock protects access to the MSC hardware registers that are
+ * affected by MPAMCFG_MON_SEL, and the mbwu_state.
+ * Access to mon_sel is needed from both process and interrupt contexts,
+ * but is complicated by firmware-backed platforms that can't make any
+ * access unless they can sleep.
+ * Always use the mpam_mon_sel_lock() helpers.
+ * Accesses to mon_sel need to be able to fail if they occur in the wrong
+ * context.
+ * If needed, take msc->probe_lock first.
+ */
+ raw_spinlock_t _mon_sel_lock;
+ unsigned long _mon_sel_flags;
+
void __iomem *mapped_hwpage;
size_t mapped_hwpage_sz;
struct mpam_garbage garbage;
};
+/* Returning false here means accesses to mon_sel must fail and report an error. */
+static inline bool __must_check mpam_mon_sel_lock(struct mpam_msc *msc)
+{
+ /* Locking will require updating to support a firmware backed interface */
+ if (WARN_ON_ONCE(msc->iface != MPAM_IFACE_MMIO))
+ return false;
+
+ raw_spin_lock_irqsave(&msc->_mon_sel_lock, msc->_mon_sel_flags);
+ return true;
+}
+
+static inline void mpam_mon_sel_unlock(struct mpam_msc *msc)
+{
+ raw_spin_unlock_irqrestore(&msc->_mon_sel_lock, msc->_mon_sel_flags);
+}
+
+static inline void mpam_mon_sel_lock_held(struct mpam_msc *msc)
+{
+ lockdep_assert_held_once(&msc->_mon_sel_lock);
+}
+
+static inline void mpam_mon_sel_lock_init(struct mpam_msc *msc)
+{
+ raw_spin_lock_init(&msc->_mon_sel_lock);
+}
+
struct mpam_class {
/* mpam_components in this class */
struct list_head components;