cpuhp callbacks aren't the only time the MSC configuration may need to be reset. Resctrl has an API call to reset a class. If an MPAM error interrupt arrives it indicates the driver has misprogrammed an MSC. The safest thing to do is reset all the MSCs and disable MPAM. Add a helper to reset RIS via their class. Call this from mpam_disable(), which can be scheduled from the error interrupt handler.
Unified · Split
| @@ -808,15 +808,13 @@ static void mpam_reset_ris_partid(struct mpam_msc_ris *ris, u16 partid) · 807 unmodified lines | |||
| 808 | 808 | ||
| 809 | /* | 809 | /* |
| 810 | * Called via smp_call_on_cpu() to prevent migration, while still being | 810 | * Called via smp_call_on_cpu() to prevent migration, while still being |
| 811 | * pre-emptible. | 811 | * pre-emptible. Caller must hold mpam_srcu. |
| 812 | */ | 812 | */ |
| 813 | static int mpam_reset_ris(void *arg) | 813 | static int mpam_reset_ris(void *arg) |
| 814 | { | 814 | { |
| 815 | u16 partid, partid_max; | 815 | u16 partid, partid_max; |
| 816 | struct mpam_msc_ris *ris = arg; | 816 | struct mpam_msc_ris *ris = arg; |
| 817 | 817 | ||
| 818 | WARN_ON_ONCE(!srcu_read_lock_held((&mpam_srcu))); | ||
| 819 | |||
| 820 | if (ris->in_reset_state) | 818 | if (ris->in_reset_state) |
| 821 | return 0; | 819 | return 0; |
| 822 | 820 | ||
| @@ -1337,8 +1335,55 @@ static void mpam_enable_once(void) · 514 unmodified lines | |||
| 1337 | mpam_partid_max + 1, mpam_pmg_max + 1); | 1335 | mpam_partid_max + 1, mpam_pmg_max + 1); |
| 1338 | } | 1336 | } |
| 1339 | 1337 | ||
| 1338 | static void mpam_reset_component_locked(struct mpam_component *comp) | ||
| 1339 | { | ||
| 1340 | struct mpam_vmsc *vmsc; | ||
| 1341 | |||
| 1342 | lockdep_assert_cpus_held(); | ||
| 1343 | |||
| 1344 | guard(srcu)(&mpam_srcu); | ||
| 1345 | list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list, | ||
| 1346 | srcu_read_lock_held(&mpam_srcu)) { | ||
| 1347 | struct mpam_msc *msc = vmsc->msc; | ||
| 1348 | struct mpam_msc_ris *ris; | ||
| 1349 | |||
| 1350 | list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, | ||
| 1351 | srcu_read_lock_held(&mpam_srcu)) { | ||
| 1352 | if (!ris->in_reset_state) | ||
| 1353 | mpam_touch_msc(msc, mpam_reset_ris, ris); | ||
| 1354 | ris->in_reset_state = true; | ||
| 1355 | } | ||
| 1356 | } | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | static void mpam_reset_class_locked(struct mpam_class *class) | ||
| 1360 | { | ||
| 1361 | struct mpam_component *comp; | ||
| 1362 | |||
| 1363 | lockdep_assert_cpus_held(); | ||
| 1364 | |||
| 1365 | guard(srcu)(&mpam_srcu); | ||
| 1366 | list_for_each_entry_srcu(comp, &class->components, class_list, | ||
| 1367 | srcu_read_lock_held(&mpam_srcu)) | ||
| 1368 | mpam_reset_component_locked(comp); | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static void mpam_reset_class(struct mpam_class *class) | ||
| 1372 | { | ||
| 1373 | cpus_read_lock(); | ||
| 1374 | mpam_reset_class_locked(class); | ||
| 1375 | cpus_read_unlock(); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* | ||
| 1379 | * Called in response to an error IRQ. | ||
| 1380 | * All of MPAMs errors indicate a software bug, restore any modified | ||
| 1381 | * controls to their reset values. | ||
| 1382 | */ | ||
| 1340 | void mpam_disable(struct work_struct *ignored) | 1383 | void mpam_disable(struct work_struct *ignored) |
| 1341 | { | 1384 | { |
| 1385 | int idx; | ||
| 1386 | struct mpam_class *class; | ||
| 1342 | struct mpam_msc *msc, *tmp; | 1387 | struct mpam_msc *msc, *tmp; |
| 1343 | 1388 | ||
| 1344 | mutex_lock(&mpam_cpuhp_state_lock); | 1389 | mutex_lock(&mpam_cpuhp_state_lock); |
| @@ -1348,6 +1393,12 @@ void mpam_disable(struct work_struct *ignored) · 3 unmodified lines | |||
| 1348 | } | 1393 | } |
| 1349 | mutex_unlock(&mpam_cpuhp_state_lock); | 1394 | mutex_unlock(&mpam_cpuhp_state_lock); |
| 1350 | 1395 | ||
| 1396 | idx = srcu_read_lock(&mpam_srcu); | ||
| 1397 | list_for_each_entry_srcu(class, &mpam_classes, classes_list, | ||
| 1398 | srcu_read_lock_held(&mpam_srcu)) | ||
| 1399 | mpam_reset_class(class); | ||
| 1400 | srcu_read_unlock(&mpam_srcu, idx); | ||
| 1401 | |||
| 1351 | mutex_lock(&mpam_list_lock); | 1402 | mutex_lock(&mpam_list_lock); |
| 1352 | list_for_each_entry_safe(msc, tmp, &mpam_all_msc, all_msc_list) | 1403 | list_for_each_entry_safe(msc, tmp, &mpam_all_msc, all_msc_list) |
| 1353 | mpam_msc_destroy(msc); | 1404 | mpam_msc_destroy(msc); |