History

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.

James Morse committed 12 months ago

Commit 41e8a141 parent 823e7c32 files · +145 −2Browse files

Showing the changes to drivers/resctrl (2 of 2 files). Show all

Unified · Split

2 files
  1. drivers/resctrl/mpam_devices.c +125 −1
  2. drivers/resctrl/mpam_internal.h +20 −1
drivers/resctrl/mpam_devices.c+125−1
@@ -993,6 +993,7 @@ static void __ris_msmon_read(void *arg) · 992 unmodified lines
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) · 24 unmodified lines
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) · 5 unmodified lines
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, · 189 unmodified lines
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) · 102 unmodified lines
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) · 87 unmodified lines
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) · 667 unmodified lines
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) · 19 unmodified lines
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) · 11 unmodified lines
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+20−1
@@ -91,7 +91,10 @@ struct mpam_msc { · 90 unmodified lines
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 { · 104 unmodified lines
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 { · 87 unmodified lines
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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t