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

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
993 struct mon_read *m = arg;993 struct mon_read *m = arg;
994 struct mon_cfg *ctx = m->ctx;994 struct mon_cfg *ctx = m->ctx;
995 struct mpam_msc_ris *ris = m->ris;995 struct mpam_msc_ris *ris = m->ris;
996 struct msmon_mbwu_state *mbwu_state;
996 struct mpam_props *rprops = &ris->props;997 struct mpam_props *rprops = &ris->props;
997 struct mpam_msc *msc = m->ris->vmsc->msc;998 struct mpam_msc *msc = m->ris->vmsc->msc;
998 u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt;999 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
1023 now = mpam_read_monsel_reg(msc, CSU);1024 now = mpam_read_monsel_reg(msc, CSU);
1024 if (mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, rprops))1025 if (mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, rprops))
1025 nrdy = now & MSMON___NRDY;1026 nrdy = now & MSMON___NRDY;
1027 now = FIELD_GET(MSMON___VALUE, now);
1026 break;1028 break;
1027 case mpam_feat_msmon_mbwu:1029 case mpam_feat_msmon_mbwu:
1028 now = mpam_read_monsel_reg(msc, MBWU);1030 now = mpam_read_monsel_reg(msc, MBWU);
1029 if (mpam_has_feature(mpam_feat_msmon_mbwu_hw_nrdy, rprops))1031 if (mpam_has_feature(mpam_feat_msmon_mbwu_hw_nrdy, rprops))
1030 nrdy = now & MSMON___NRDY;1032 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;
1031 break;1042 break;
1032 default:1043 default:
1033 m->err = -EINVAL;1044 m->err = -EINVAL;
@@ -1039,7 +1050,6 @@ static void __ris_msmon_read(void *arg) · 5 unmodified lines
1039 return;1050 return;
1040 }1051 }
1041 1052
1042 now = FIELD_GET(MSMON___VALUE, now);
1043 *m->val += now;1053 *m->val += now;
1044}1054}
1045 1055
@@ -1235,6 +1245,67 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, · 189 unmodified lines
1235 mutex_unlock(&msc->part_sel_lock);1245 mutex_unlock(&msc->part_sel_lock);
1236}1246}
1237 1247
1248/* Call with msc cfg_lock held */
1249static 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 */
1269static 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
1238static void mpam_init_reset_cfg(struct mpam_config *reset_cfg)1309static void mpam_init_reset_cfg(struct mpam_config *reset_cfg)
1239{1310{
1240 *reset_cfg = (struct mpam_config) {1311 *reset_cfg = (struct mpam_config) {
@@ -1343,6 +1414,9 @@ static void mpam_reprogram_msc(struct mpam_msc *msc) · 102 unmodified lines
1343 mpam_touch_msc(msc, __write_config, &arg);1414 mpam_touch_msc(msc, __write_config, &arg);
1344 }1415 }
1345 ris->in_reset_state = reset;1416 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);
1346 }1420 }
1347 mutex_unlock(&msc->cfg_lock);1421 mutex_unlock(&msc->cfg_lock);
1348}1422}
@@ -1436,6 +1510,9 @@ static int mpam_cpu_offline(unsigned int cpu) · 87 unmodified lines
1436 * lost while the CPUs are offline.1510 * lost while the CPUs are offline.
1437 */1511 */
1438 ris->in_reset_state = false;1512 ris->in_reset_state = false;
1513
1514 if (mpam_is_enabled())
1515 mpam_touch_msc(msc, &mpam_save_mbwu_state, ris);
1439 }1516 }
1440 mutex_unlock(&msc->cfg_lock);1517 mutex_unlock(&msc->cfg_lock);
1441 }1518 }
@@ -2109,7 +2186,22 @@ static void mpam_unregister_irqs(void) · 667 unmodified lines
2109 2186
2110static void __destroy_component_cfg(struct mpam_component *comp)2187static void __destroy_component_cfg(struct mpam_component *comp)
2111{2188{
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
2112 add_to_garbage(comp->cfg);2195 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 }
2113}2205}
2114 2206
2115static void mpam_reset_component_cfg(struct mpam_component *comp)2207static 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
2135 2227
2136static int __allocate_component_cfg(struct mpam_component *comp)2228static int __allocate_component_cfg(struct mpam_component *comp)
2137{2229{
2230 struct mpam_vmsc *vmsc;
2231
2138 mpam_assert_partid_sizes_fixed();2232 mpam_assert_partid_sizes_fixed();
2139 2233
2140 if (comp->cfg)2234 if (comp->cfg)
@@ -2152,6 +2246,36 @@ static int __allocate_component_cfg(struct mpam_component *comp) · 11 unmodified lines
2152 2246
2153 mpam_reset_component_cfg(comp);2247 mpam_reset_component_cfg(comp);
2154 2248
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
2155 return 0;2279 return 0;
2156}2280}
2157 2281
drivers/resctrl/mpam_internal.h+20−1
@@ -91,7 +91,10 @@ struct mpam_msc { · 90 unmodified lines
91 */91 */
92 struct mutex part_sel_lock;92 struct mutex part_sel_lock;
93 93
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 */
95 struct mutex cfg_lock;98 struct mutex cfg_lock;
96 99
97 /*100 /*
@@ -202,6 +205,19 @@ struct mon_cfg { · 104 unmodified lines
202 enum mon_filter_options opts;205 enum mon_filter_options opts;
203};206};
204 207
208/* Changes to msmon_mbwu_state are protected by the msc's mon_sel_lock. */
209struct 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
205struct mpam_class {221struct mpam_class {
206 /* mpam_components in this class */222 /* mpam_components in this class */
207 struct list_head components;223 struct list_head components;
@@ -295,6 +311,9 @@ struct mpam_msc_ris { · 87 unmodified lines
295 /* parent: */311 /* parent: */
296 struct mpam_vmsc *vmsc;312 struct mpam_vmsc *vmsc;
297 313
314 /* msmon mbwu configuration is preserved over reset */
315 struct msmon_mbwu_state *mbwu_state;
316
298 struct mpam_garbage garbage;317 struct mpam_garbage garbage;
299};318};
300 319

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