@@ -649,6 +649,10 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
props->num_mbwu_mon = FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumonidr);
if (props->num_mbwu_mon)
mpam_set_feature(mpam_feat_msmon_mbwu, props);
+
+ msc->mbwu_has_capture = FIELD_GET(MPAMF_MBWUMON_IDR_HAS_CAPTURE, mbwumonidr);
+ msc->mbwu_has_long = FIELD_GET(MPAMF_MBWUMON_IDR_HAS_LONG, mbwumonidr);
+ msc->mbwu_lwd = FIELD_GET(MPAMF_MBWUMON_IDR_HAS_LWD, mbwumonidr);
}
}
@@ -811,7 +815,8 @@ static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val,
mpam_write_monsel_reg(msc, CFG_MBWU_FLT, flt_val);
mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val);
mpam_write_monsel_reg(msc, MBWU, 0);
- mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val|MSMON_CFG_x_CTL_EN);
+ mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val|MSMON_CFG_x_CTL_EN|
+ MSMON_CFG_x_CTL_CAPT_EVNT);
mbwu_state = &m->ris->mbwu_state[m->ctx->mon];
if (mbwu_state)
@@ -841,7 +846,7 @@ static void __ris_msmon_read(void *arg)
struct mpam_msc_ris *ris = m->ris;
struct mpam_msc *msc = m->ris->msc;
struct msmon_mbwu_state *mbwu_state;
- u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt;
+ u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt, now_low;
spin_lock_irqsave(&msc->mon_sel_lock, flags);
mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, ctx->mon) |
@@ -875,12 +880,47 @@ static void __ris_msmon_read(void *arg)
now = FIELD_GET(MSMON___VALUE, now);
break;
case mpam_feat_msmon_mbwu:
- now = mpam_read_monsel_reg(msc, MBWU);
- nrdy = now & MSMON___NRDY;
- now = FIELD_GET(MSMON___VALUE, now);
+ /* If the monitor is a counter monitor such as MBWU,
+ * implementation should clear the nrdy bit, either
+ * doing explicit software write to clear NRDY bit or
+ * a capture event that automatically clear the nrdy
+ * bit, let's use the latter one.
+ * MSMON_MBWU_CAPTURE/L_CAPTURE is written atomically by
+ * copying all bits from MSMON_MBWU_L when the capture
+ * event that is programmed into the configuration of this
+ * monitor instance occurs.
+ */
+ mpam_write_monsel_reg(msc, CAPT_EVNT, 0x1);
- if (nrdy)
- break;
+ if (msc->mbwu_has_long && msc->mbwu_has_capture &&
+ msc->mbwu_lwd) {
+ now = mpam_read_monsel_reg(msc, MBWU_L + 4);
+ nrdy = now & MSMON___NRDY;
+ if (nrdy)
+ break;
+
+ now = mpam_read_monsel_reg(msc, MBWU_CAPTURE_L + 4);
+ now_low = mpam_read_monsel_reg(msc, MBWU_CAPTURE_L);
+ now = MSMON_MBWU_L_VALUE & (now << 32 | now_low);
+ } else if (msc->mbwu_has_long && msc->mbwu_has_capture &&
+ !msc->mbwu_lwd) {
+ now = mpam_read_monsel_reg(msc, MBWU_L + 4);
+ nrdy = now & MSMON___NRDY;
+ if (nrdy)
+ break;
+
+ now = mpam_read_monsel_reg(msc, MBWU_CAPTURE_L + 4);
+ now_low = mpam_read_monsel_reg(msc, MBWU_CAPTURE_L);
+ now = MSMON_MBWU_L_VALUE_LWD & (now << 32 | now_low);
+ } else {
+ now = mpam_read_monsel_reg(msc, MBWU);
+ nrdy = now & MSMON___NRDY;
+ if (nrdy)
+ break;
+
+ now = mpam_read_monsel_reg(msc, MBWU_CAPTURE);
+ now = FIELD_GET(MSMON___VALUE, now);
+ }
if (!mbwu_state)
break;
@@ -35,6 +35,9 @@ struct mpam_msc
u32 nrdy_usec;
cpumask_t accessibility;
bool has_extd_esr;
+ bool mbwu_has_capture;
+ bool mbwu_has_long;
+ bool mbwu_lwd;
int reenable_error_ppi;
struct mpam_msc * __percpu *error_dev_id;
@@ -328,6 +331,8 @@ void mpam_resctrl_exit(void);
#define MSMON_CSU_CAPTURE 0x0848 /* last cache-usage value captured */
#define MSMON_MBWU 0x0860 /* current mem-bw usage value */
#define MSMON_MBWU_CAPTURE 0x0868 /* last mem-bw value captured */
+#define MSMON_MBWU_L 0x0880 /* current mem-bw usage value, LONG version*/
+#define MSMON_MBWU_CAPTURE_L 0x0890 /* last mem-bw value captured, LONG version */
#define MSMON_CAPT_EVNT 0x0808 /* signal a capture event */
#define MPAMF_ESR 0x00F8 /* error status register */
#define MPAMF_ECR 0x00F0 /* error control register */
@@ -384,6 +389,9 @@ void mpam_resctrl_exit(void);
/* MPAMF_MBWUMON_IDR - MPAM memory bandwidth usage monitor ID register */
#define MPAMF_MBWUMON_IDR_NUM_MON GENMASK(15, 0)
#define MPAMF_MBWUMON_IDR_HAS_CAPTURE BIT(31)
+#define MPAMF_MBWUMON_IDR_HAS_LWD BIT(29)
+#define MPAMF_MBWUMON_IDR_HAS_LONG BIT(30)
+
/* MPAMF_PARTID_NRW_IDR - MPAM PARTID narrowing ID register */
#define MPAMF_PARTID_NRW_IDR_INTPARTID_MAX GENMASK(15, 0)
@@ -525,9 +533,10 @@ void mpam_resctrl_exit(void);
* MSMON_MBWU_CAPTURE - Memory system performance monitor memory bandwidth usage
* capture register
*/
-#define MSMON___VALUE GENMASK(30, 0)
-#define MSMON___NRDY BIT(31)
-#define MSMON_MBWU_L_VALUE GENMASK(62, 0)
+#define MSMON___VALUE GENMASK(30, 0)
+#define MSMON___NRDY BIT(31)
+#define MSMON_MBWU_L_VALUE GENMASK(62, 0)
+#define MSMON_MBWU_L_VALUE_LWD GENMASK(43, 0)
/*
* MSMON_CAPT_EVNT - Memory system performance monitoring capture event
* generation register
In MPAM v0.1 and from MPAM v1.1, There is an optional long monitor register, MSMON_MBWU_L/CAPTURE, that contains a count of 44 bits or 63 bits Capture register MSMON_MBWU_CAPTURE that is loaded from the monitor register each time the selected capture event occurs. When a capture event occurs, the monitor register is copied to the capture register Signed-off-by: Amit Singh Tomar <amitsinght@marvell.com> Change-Id: I0c7bb8d57a2f77e45b06df0529a5bf1624f66f77 --- drivers/platform/mpam/mpam_devices.c | 54 +++++++++++++++++++++++---- drivers/platform/mpam/mpam_internal.h | 15 ++++++-- 2 files changed, 59 insertions(+), 10 deletions(-)