Skip to content

Commit 41e8a14

Browse files
James Morsectmarinas
authored andcommitted
arm_mpam: Track bandwidth counter state for power management
Bandwidth counters need to run continuously to correctly reflect the bandwidth. Save the counter state when the hardware is reset due to CPU hotplug. Add struct mbwu_state to track the bandwidth counter. Support for tracking overflow with the same structure will be added in a subsequent commit. Cc: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Reviewed-by: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Reviewed-by: Fenghua Yu <fenghuay@nvidia.com> Tested-by: Carl Worth <carl@os.amperecomputing.com> Tested-by: Gavin Shan <gshan@redhat.com> Tested-by: Zeng Heng <zengheng4@huawei.com> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Tested-by: Hanjun Guo <guohanjun@huawei.com> Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 823e7c3 commit 41e8a14

2 files changed

Lines changed: 145 additions & 2 deletions

File tree

drivers/resctrl/mpam_devices.c

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ static void __ris_msmon_read(void *arg)
993993
struct mon_read *m = arg;
994994
struct mon_cfg *ctx = m->ctx;
995995
struct mpam_msc_ris *ris = m->ris;
996+
struct msmon_mbwu_state *mbwu_state;
996997
struct mpam_props *rprops = &ris->props;
997998
struct mpam_msc *msc = m->ris->vmsc->msc;
998999
u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt;
@@ -1023,11 +1024,21 @@ static void __ris_msmon_read(void *arg)
10231024
now = mpam_read_monsel_reg(msc, CSU);
10241025
if (mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, rprops))
10251026
nrdy = now & MSMON___NRDY;
1027+
now = FIELD_GET(MSMON___VALUE, now);
10261028
break;
10271029
case mpam_feat_msmon_mbwu:
10281030
now = mpam_read_monsel_reg(msc, MBWU);
10291031
if (mpam_has_feature(mpam_feat_msmon_mbwu_hw_nrdy, rprops))
10301032
nrdy = now & MSMON___NRDY;
1033+
now = FIELD_GET(MSMON___VALUE, now);
1034+
1035+
if (nrdy)
1036+
break;
1037+
1038+
mbwu_state = &ris->mbwu_state[ctx->mon];
1039+
1040+
/* Include bandwidth consumed before the last hardware reset */
1041+
now += mbwu_state->correction;
10311042
break;
10321043
default:
10331044
m->err = -EINVAL;
@@ -1039,7 +1050,6 @@ static void __ris_msmon_read(void *arg)
10391050
return;
10401051
}
10411052

1042-
now = FIELD_GET(MSMON___VALUE, now);
10431053
*m->val += now;
10441054
}
10451055

@@ -1235,6 +1245,67 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
12351245
mutex_unlock(&msc->part_sel_lock);
12361246
}
12371247

1248+
/* Call with msc cfg_lock held */
1249+
static int mpam_restore_mbwu_state(void *_ris)
1250+
{
1251+
int i;
1252+
struct mon_read mwbu_arg;
1253+
struct mpam_msc_ris *ris = _ris;
1254+
1255+
for (i = 0; i < ris->props.num_mbwu_mon; i++) {
1256+
if (ris->mbwu_state[i].enabled) {
1257+
mwbu_arg.ris = ris;
1258+
mwbu_arg.ctx = &ris->mbwu_state[i].cfg;
1259+
mwbu_arg.type = mpam_feat_msmon_mbwu;
1260+
1261+
__ris_msmon_read(&mwbu_arg);
1262+
}
1263+
}
1264+
1265+
return 0;
1266+
}
1267+
1268+
/* Call with MSC cfg_lock held */
1269+
static int mpam_save_mbwu_state(void *arg)
1270+
{
1271+
int i;
1272+
u64 val;
1273+
struct mon_cfg *cfg;
1274+
u32 cur_flt, cur_ctl, mon_sel;
1275+
struct mpam_msc_ris *ris = arg;
1276+
struct msmon_mbwu_state *mbwu_state;
1277+
struct mpam_msc *msc = ris->vmsc->msc;
1278+
1279+
for (i = 0; i < ris->props.num_mbwu_mon; i++) {
1280+
mbwu_state = &ris->mbwu_state[i];
1281+
cfg = &mbwu_state->cfg;
1282+
1283+
if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc)))
1284+
return -EIO;
1285+
1286+
mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, i) |
1287+
FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx);
1288+
mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel);
1289+
1290+
cur_flt = mpam_read_monsel_reg(msc, CFG_MBWU_FLT);
1291+
cur_ctl = mpam_read_monsel_reg(msc, CFG_MBWU_CTL);
1292+
mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0);
1293+
1294+
val = mpam_read_monsel_reg(msc, MBWU);
1295+
mpam_write_monsel_reg(msc, MBWU, 0);
1296+
1297+
cfg->mon = i;
1298+
cfg->pmg = FIELD_GET(MSMON_CFG_x_FLT_PMG, cur_flt);
1299+
cfg->match_pmg = FIELD_GET(MSMON_CFG_x_CTL_MATCH_PMG, cur_ctl);
1300+
cfg->partid = FIELD_GET(MSMON_CFG_x_FLT_PARTID, cur_flt);
1301+
mbwu_state->correction += val;
1302+
mbwu_state->enabled = FIELD_GET(MSMON_CFG_x_CTL_EN, cur_ctl);
1303+
mpam_mon_sel_unlock(msc);
1304+
}
1305+
1306+
return 0;
1307+
}
1308+
12381309
static void mpam_init_reset_cfg(struct mpam_config *reset_cfg)
12391310
{
12401311
*reset_cfg = (struct mpam_config) {
@@ -1343,6 +1414,9 @@ static void mpam_reprogram_msc(struct mpam_msc *msc)
13431414
mpam_touch_msc(msc, __write_config, &arg);
13441415
}
13451416
ris->in_reset_state = reset;
1417+
1418+
if (mpam_has_feature(mpam_feat_msmon_mbwu, &ris->props))
1419+
mpam_touch_msc(msc, &mpam_restore_mbwu_state, ris);
13461420
}
13471421
mutex_unlock(&msc->cfg_lock);
13481422
}
@@ -1436,6 +1510,9 @@ static int mpam_cpu_offline(unsigned int cpu)
14361510
* lost while the CPUs are offline.
14371511
*/
14381512
ris->in_reset_state = false;
1513+
1514+
if (mpam_is_enabled())
1515+
mpam_touch_msc(msc, &mpam_save_mbwu_state, ris);
14391516
}
14401517
mutex_unlock(&msc->cfg_lock);
14411518
}
@@ -2109,7 +2186,22 @@ static void mpam_unregister_irqs(void)
21092186

21102187
static void __destroy_component_cfg(struct mpam_component *comp)
21112188
{
2189+
struct mpam_msc *msc;
2190+
struct mpam_vmsc *vmsc;
2191+
struct mpam_msc_ris *ris;
2192+
2193+
lockdep_assert_held(&mpam_list_lock);
2194+
21122195
add_to_garbage(comp->cfg);
2196+
list_for_each_entry(vmsc, &comp->vmsc, comp_list) {
2197+
msc = vmsc->msc;
2198+
2199+
if (mpam_mon_sel_lock(msc)) {
2200+
list_for_each_entry(ris, &vmsc->ris, vmsc_list)
2201+
add_to_garbage(ris->mbwu_state);
2202+
mpam_mon_sel_unlock(msc);
2203+
}
2204+
}
21132205
}
21142206

21152207
static void mpam_reset_component_cfg(struct mpam_component *comp)
@@ -2135,6 +2227,8 @@ static void mpam_reset_component_cfg(struct mpam_component *comp)
21352227

21362228
static int __allocate_component_cfg(struct mpam_component *comp)
21372229
{
2230+
struct mpam_vmsc *vmsc;
2231+
21382232
mpam_assert_partid_sizes_fixed();
21392233

21402234
if (comp->cfg)
@@ -2152,6 +2246,36 @@ static int __allocate_component_cfg(struct mpam_component *comp)
21522246

21532247
mpam_reset_component_cfg(comp);
21542248

2249+
list_for_each_entry(vmsc, &comp->vmsc, comp_list) {
2250+
struct mpam_msc *msc;
2251+
struct mpam_msc_ris *ris;
2252+
struct msmon_mbwu_state *mbwu_state;
2253+
2254+
if (!vmsc->props.num_mbwu_mon)
2255+
continue;
2256+
2257+
msc = vmsc->msc;
2258+
list_for_each_entry(ris, &vmsc->ris, vmsc_list) {
2259+
if (!ris->props.num_mbwu_mon)
2260+
continue;
2261+
2262+
mbwu_state = kcalloc(ris->props.num_mbwu_mon,
2263+
sizeof(*ris->mbwu_state),
2264+
GFP_KERNEL);
2265+
if (!mbwu_state) {
2266+
__destroy_component_cfg(comp);
2267+
return -ENOMEM;
2268+
}
2269+
2270+
init_garbage(&mbwu_state[0].garbage);
2271+
2272+
if (mpam_mon_sel_lock(msc)) {
2273+
ris->mbwu_state = mbwu_state;
2274+
mpam_mon_sel_unlock(msc);
2275+
}
2276+
}
2277+
}
2278+
21552279
return 0;
21562280
}
21572281

drivers/resctrl/mpam_internal.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ struct mpam_msc {
9191
*/
9292
struct mutex part_sel_lock;
9393

94-
/* cfg_lock protects the msc configuration. */
94+
/*
95+
* cfg_lock protects the msc configuration and guards against mbwu_state
96+
* save and restore racing.
97+
*/
9598
struct mutex cfg_lock;
9699

97100
/*
@@ -202,6 +205,19 @@ struct mon_cfg {
202205
enum mon_filter_options opts;
203206
};
204207

208+
/* Changes to msmon_mbwu_state are protected by the msc's mon_sel_lock. */
209+
struct msmon_mbwu_state {
210+
bool enabled;
211+
struct mon_cfg cfg;
212+
213+
/*
214+
* The value to add to the new reading to account for power management.
215+
*/
216+
u64 correction;
217+
218+
struct mpam_garbage garbage;
219+
};
220+
205221
struct mpam_class {
206222
/* mpam_components in this class */
207223
struct list_head components;
@@ -295,6 +311,9 @@ struct mpam_msc_ris {
295311
/* parent: */
296312
struct mpam_vmsc *vmsc;
297313

314+
/* msmon mbwu configuration is preserved over reset */
315+
struct msmon_mbwu_state *mbwu_state;
316+
298317
struct mpam_garbage garbage;
299318
};
300319

0 commit comments

Comments
 (0)