@@ -57,6 +57,7 @@ static struct rdt_resource *resctrl_event_get_resource(u16 event_num)
switch (event_id) {
case QOS_L3_OCCUP_EVENT_ID:
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ return resctrl_arch_get_resource(RDT_RESOURCE_MBA);
case QOS_L3_MBM_LOCAL_EVENT_ID:
return resctrl_arch_get_resource(RDT_RESOURCE_L3);
}
@@ -30,7 +30,7 @@ static struct mpam_resctrl_res mpam_resctrl_exports[RDT_NUM_RESOURCES];
static bool exposed_alloc_capable;
static bool exposed_mon_capable;
-static struct mpam_class *mbm_local_class;
+static struct mpam_class *mbm_local_class, *mbm_total_class;
/*
* MPAM emulates CDP by setting different PARTID in the I/D fields of MPAM1_EL1.
@@ -38,6 +38,11 @@ static struct mpam_class *mbm_local_class;
*/
static bool cdp_enabled;
+bool resctrl_arch_is_mbm_total_enabled(void)
+{
+ return mbm_total_class;
+}
+
/*
* If resctrl_init() succeeded, resctrl_exit() can be used to remove support
* for the filesystem in the event of an error.
@@ -300,6 +305,11 @@ int resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, int evtid)
return mpam_alloc_mbwu_mon(res->class);
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ if (mpam_monitors_free_runing)
+ return USE_RMID_IDX;
+ res = container_of(r, struct mpam_resctrl_res, resctrl_res);
+
+ return mpam_alloc_mbwu_mon(res->class);
default:
return -EOPNOTSUPP;
}
@@ -325,6 +335,13 @@ void resctrl_arch_mon_ctx_free(struct rdt_resource *r, int evtid, int ctx)
wake_up(&resctrl_mon_ctx_waiters);
return;
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ if (mpam_monitors_free_runing)
+ return;
+ res = container_of(r, struct mpam_resctrl_res, resctrl_res);
+
+ mpam_free_mbwu_mon(res->class, ctx);
+ wake_up(&resctrl_mon_ctx_waiters);
+ return;
default:
return;
}
@@ -350,6 +367,9 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d,
type = mpam_feat_msmon_mbwu;
break;
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ type = mpam_feat_msmon_mbwu;
+ break;
+ default:
return -EOPNOTSUPP;
}
@@ -726,6 +746,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
}
} else if (res->resctrl_res.rid == RDT_RESOURCE_MBA) {
struct mpam_props *cprops = &class->props;
+ bool has_mbwu = class_has_usable_mbwu(class);
/* TODO: kill these properties off as they are derivatives */
r->format_str = "%d=%0*u";
@@ -750,7 +771,17 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
r->alloc_capable = true;
exposed_alloc_capable = true;
}
- }
+
+ if (has_mbwu) {
+ r->mon_capable = true;
+ exposed_mon_capable = true;
+ }
+
+ r->num_rmid = 1;
+
+ if (class_has_usable_mbwu(class))
+ mbm_total_class = class;
+ }
return 0;
}
@@ -448,7 +448,8 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
struct list_head *head;
struct rdtgroup *entry;
- if (!resctrl_arch_is_mbm_local_enabled())
+ if (!resctrl_arch_is_mbm_local_enabled() ||
+ !resctrl_arch_is_mbm_total_enabled())
return;
r_mba = resctrl_arch_get_resource(RDT_RESOURCE_MBA);
@@ -721,29 +722,34 @@ static struct mon_evt mbm_local_event = {
* because as per the SDM the total and local memory bandwidth
* are enumerated as part of L3 monitoring.
*/
-static void l3_mon_evt_init(struct rdt_resource *r)
+static void resource_mon_evt_init(struct rdt_resource *r)
{
INIT_LIST_HEAD(&r->evt_list);
- if (resctrl_arch_is_llc_occupancy_enabled())
+ if (resctrl_arch_is_llc_occupancy_enabled() && !strcmp(r->name, "L3"))
list_add_tail(&llc_occupancy_event.list, &r->evt_list);
- if (resctrl_arch_is_mbm_total_enabled())
+ if (resctrl_arch_is_mbm_total_enabled() && !strcmp(r->name, "MB"))
list_add_tail(&mbm_total_event.list, &r->evt_list);
- if (resctrl_arch_is_mbm_local_enabled())
+ if (resctrl_arch_is_mbm_local_enabled() && !strcmp(r->name, "L3"))
list_add_tail(&mbm_local_event.list, &r->evt_list);
}
int resctrl_mon_resource_init(void)
{
- struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+ enum resctrl_res_level i;
+ struct rdt_resource *r;
int ret;
- ret = dom_data_init(r);
- if (ret)
- return ret;
+ for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+ r = resctrl_arch_get_resource(i);
- if (r->mon_capable)
- l3_mon_evt_init(r);
+ ret = dom_data_init(r);
+ if (ret)
+ return ret;
+
+ if (r->mon_capable)
+ resource_mon_evt_init(r);
+ }
return 0;
}
@@ -47,6 +47,7 @@ static inline bool resctrl_arch_event_is_free_running(enum resctrl_event_id evt)
case QOS_L3_OCCUP_EVENT_ID:
return true;
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ return mpam_monitors_free_runing;
case QOS_L3_MBM_LOCAL_EVENT_ID:
return mpam_monitors_free_runing;
}
@@ -65,11 +66,7 @@ bool resctrl_arch_alloc_capable(void);
bool resctrl_arch_mon_capable(void);
bool resctrl_arch_is_llc_occupancy_enabled(void);
bool resctrl_arch_is_mbm_local_enabled(void);
-
-static inline bool resctrl_arch_is_mbm_total_enabled(void)
-{
- return false;
-}
+bool resctrl_arch_is_mbm_total_enabled(void);
/* reset cached configurations, then all devices */
void resctrl_arch_reset_resources(void);
Currently, the driver enables "mbm_local" if mpam class that is picked to be "L3" resource control, and bandwidth counter is enumerated as part of "L3" resource control. But this will be a problem when bandwidth counter is hosted by DDR MSC, and is enumerated as part of "MB" mpam class. To support this configuration, lets enable mbm_total if the mpam class picked to be "MB" resource control. mbm_local is still used for the bandwidth counter enumerated as part of "L3" resource control. Signed-off-by: Amit Singh Tomar <amitsinght@marvell.com> Change-Id: Ida7c0367465ba9f1343af3226f475b862d0fa214 --- drivers/perf/resctrl_pmu.c | 1 + drivers/platform/mpam/mpam_resctrl.c | 35 ++++++++++++++++++++++++++-- fs/resctrl/monitor.c | 28 +++++++++++++--------- include/linux/arm_mpam.h | 7 ++---- 4 files changed, 53 insertions(+), 18 deletions(-)