Repository navigation
fix(amdsmi): stop amdsmi_set_clk_freq() from falsely returning INVAL - #9536
Conversation
✅ All Policy Checks Passed
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
There was a problem hiding this comment.
Pull request overview
This PR adjusts AMD SMI / ROCm SMI clock-frequency setting behavior to avoid falsely rejecting supported clock masks (notably on Navi48), aligning mask handling more closely with the amdgpu driver by applying the in-range subset and only returning invalid-args when no settable levels are requested. It also updates tests and docs to reflect the more lenient contract and adds test infrastructure to prevent leaking forced performance-level state across tests.
Changes:
- Make
bitfield_to_freq_string()drop out-of-range DPM bits (and exclude deep-sleep from the settable range), rejecting only when the resulting set is empty. - Reorder/adjust
rsmi_dev_gpu_clk_freq_set()logic (clk-type lookup ordering, post-write read-only check) and expand debug logging. - Update functional tests and base test fixture to save/restore per-device performance levels and to tolerate
*_STATUS_INVALonly when no settable level exists.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| projects/amdsmi/tests/amd_smi_test/test_base.h | Adds perf-level save/restore APIs and state for test cleanup. |
| projects/amdsmi/tests/amd_smi_test/test_base.cc | Implements best-effort perf-level save/restore with verbose logging. |
| projects/amdsmi/tests/amd_smi_test/functional/gpu/power/power_read_write_test.cc | Saves/restores perf level around the test to avoid cross-test leakage. |
| projects/amdsmi/tests/amd_smi_test/functional/gpu/clock/frequencies_read_write_test.cc | Updates frequency write/reset expectations for the lenient mask contract; adds optional clock filter. |
| projects/amdsmi/rocm_smi/src/rocm_smi.cc | Implements lenient bitmask-to-string handling and adjusts clk freq set flow/logging. |
| projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h | Updates API docs to describe the new lenient behavior and deep-sleep handling. |
| projects/amdsmi/include/amd_smi/amdsmi.h | Updates API docs for the new lenient behavior and deep-sleep handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
9762d08 to
dcc8fbc
Compare
952b1b2 to
ca3dd73
Compare
amdsmi_set_clk_freq() from falsely returning INVAL
ca3dd73 to
bf8f58b
Compare
gabrpham
left a comment
There was a problem hiding this comment.
Looks good, but just need a few additional docs updates. Still need an update to the Python API docs since it still says "only lowest num_supported bits are relevant" and the example sets freq_bitmask = 0, which now returns AMDSMI_STATUS_INVAL.
|
This pull request has been inactive for 25 days and will be marked as stale. If you would like to keep this PR open, please:
This PR will be automatically closed in 5 days if no further activity occurs. |
|
This pull request has been automatically closed due to inactivity (30 days with no updates). If you'd like to continue working on this, feel free to reopen the PR or create a new one. |
|
@charis-poag-amd Please follow up with the comments and move this ticket along |
gabrpham
left a comment
There was a problem hiding this comment.
Previous comment has been answered. Potential follow up possible, but can go ahead and approve now.
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
3325b85 to
00ae9f6
Compare
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
00ae9f6 to
729cf64
Compare
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
729cf64 to
b4f2d4b
Compare
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
b4f2d4b to
351bdcc
Compare
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
351bdcc to
08549ff
Compare
The deep-sleep bitmask validation added in ROCM-9294 (#4707) rejected a clock-set with AMDSMI_STATUS_INVAL whenever the requested mask had any bit outside a settable range computed from a prior get_clk_freq read. Together with a pre-write read-only sysfs probe, this check-then-write sequence had a TOCTOU window that falsely failed on Navi48 (gfx1201) even though the set is supported (Navi31 runs the same flow and passes), surfacing as a TestFrequenciesReadWrite failure. Drop the strict up-front validation in favor of driver-like behavior: bitfield_to_freq_string() now discards bits above the highest settable level and applies the in-range subset, raising INVALID_ARGS only when no settable level remains. Deep-sleep ('S') is counted in num_supported but is not a writable pp_dpm_* label, so it is excluded from the settable range. The read-only check moves to the post-write PERMISSION path (removing the TOCTOU), and the clk-type lookup runs before the perf-level change so an invalid clock type no longer forces MANUAL. Tests: TestFrequenciesReadWrite accepts AMDSMI_STATUS_INVAL only when no level is settable, and TestBase::SavePerfLevels()/RestorePerfLevels() restore the device perf level so a forced MANUAL state cannot leak between tests. ROCM-28256
- rocm_smi.cc: only upgrade PERMISSION -> NOT_SUPPORTED when the read-only
sysfs probe succeeds; otherwise keep the real write result.
- amdsmi.h: fix doc grammar ("will restricts" -> "restricts").
ROCM-28256
The clock-set fix makes GpuFunctionalReadWrite.TestFrequenciesReadWrite pass on gfx90a / MI210, so remove it from FILTER[aldebaran] in amdsmitst.exclude (originally excluded under SWDEV-306889). Validated by CI on MI210. ROCM-28256
Record the lenient amdsmi_set_clk_freq behavior (drop out-of-range bits, INVAL only when nothing is settable, post-write read-only check) and the TestFrequenciesReadWrite re-enable on Aldebaran under the ROCm 7.15.0 Fixed section. ROCM-28256
…etvals - frequencies_read_write_test.cc: replace predict-before validation with a reactive post-hoc check (refresh f after an unexpected INVAL, assert the level is now out of the shrunk settable range) to close a TOCTOU race on live power-state changes (DF/FCLK flakiness). Extract refresh_f(), gpu_tag_str(), and to_bit_string() helpers to DRY up repeated patterns; derive the positive-case mask dynamically from settable_level_count(f) instead of a hardcoded 0b01100; add phase overview comments. - amdsmi.h / rocm_smi.h: document the deep-sleep pseudo-level's exclusion from the settable DPM level count, AMDSMI/RSMI_STATUS_UNEXPECTED_DATA for zero settable levels, and RSMI_STATUS_UNEXPECTED_SIZE for num_supported exceeding AMDSMI/RSMI_MAX_NUM_FREQUENCIES. Addresses review comments from bill-shuzhou-liu and gabrpham on PR #9536.
08549ff to
956ce8c
Compare
TheRock Submodule Bump ActivityNewest first
|
## Motivation `GpuFunctionalReadWrite.TestPciReadWrite` fails on GPUs with a single PCIe bandwidth level, such as MI100. Since #9536, `amdsmi_set_gpu_pci_bandwidth()` returns `AMDSMI_STATUS_INVAL` for a mask that selects no level, and the test's "every level except the current one" mask is empty on those GPUs. ## Technical Details - `pci_read_write_test.cc`: when that mask is empty, expect `AMDSMI_STATUS_INVAL` (or `NOT_SUPPORTED` / `NO_PERM`, as elsewhere in the test) and skip the rest of the set test for that GPU. The API rejects the mask before it changes anything, so there is nothing to restore. ## Issue Tracking JIRA ID: AILITOOLS-357 ## Test Plan - Build the changed file with the project's flags; run the amd-smi pre-commit hooks. - The Zuul AddressSanitizer job on MI100, which runs `amdsmitst` as root. ## Test Result - The file builds and pre-commit passes. - Before the fix, on develop with #9536, MI100 fails with `AMDSMI_STATUS_INVAL` for mask `0b0`. The test passed there before #9536 merged. Signed-off-by: Adam360x <Adam.pryor@amd.com>
#13460) ## Motivation Two `amdsmitst` read-write tests fail when they run as root in the Zuul AddressSanitizer jobs: `TestPerfCntrReadWrite` on Vega 20 and `TestFrequenciesReadWrite` on Navi 10. The regular Zuul jobs run `amdsmitst` without root, so they skip both tests. ## Technical Details - `perf_cntr_read_write_test.cc`: `CountEvents` no longer checks the result of freeing a counter whose event cannot start (added in #13307). - Stopping a counter that never started fails with `AMDSMI_STATUS_FILE_ERROR`, but the library frees the counter anyway. - The failed check returned instead of throwing, so the test went on into the simultaneous-events case. That case fails to start the same events and returns without freeing the counters it created. Before #13307 the throw skipped that case. - `frequencies_read_write_test.cc`: the out-of-range check now sets level `AMDSMI_MAX_NUM_FREQUENCIES`, which no device can have, instead of the first level above the levels the test read (added in #9536). - A clock with fine-grained DPM, like the Navi 10 data fabric clock, lists only its minimum and maximum, plus its current frequency while that is in between, so it shows 2 or 3 levels. - `amdsmi_set_clk_freq()` reads the levels again before the write. If the clock shows a third level by then, the mask selects a real level and the write succeeds. - `to_bit_string()` prints one more bit than the level count (`AMDSMI_MAX_NUM_FREQUENCIES + 1`), so the out-of-range bit shows in the log instead of `0b0`. ## Issue Tracking JIRA ID: AILITOOLS-357 ## Test Plan - Build both files with the project's flags; run the amd-smi pre-commit hooks. - The Zuul ASAN jobs on Vega 20 and Navi 10 (`test-baremetal-fedora-amdsmi-asan-ubuntu-26.04-vg20`, `-nv10`), which found both failures. ## Test Result - Both files build and pre-commit passes. - Before the fix, on Vega 20, the free check fails 24 times with `AMDSMI_STATUS_FILE_ERROR`, the simultaneous-events case fails to start an event, and LeakSanitizer reports 1268 bytes in 10 allocations, all from the simultaneous-events case. No leak comes from `CountEvents`, so the library did free those counters. - Before the fix, on Navi 10, the test read 2 data fabric levels (506 and 1266 MHz), and the mask `0b100` returned `AMDSMI_STATUS_SUCCESS`. In an earlier run the clock showed 3 levels, the mask `0b1000` got `AMDSMI_STATUS_INVAL`, and the test passed. - Zuul cannot test an unmerged GitHub PR, so the next ASAN run on Zuul confirms the fix after merge. --------- Signed-off-by: Adam360x <Adam.pryor@amd.com>
Summary
amdsmi_set_clk_freq()/rsmi_dev_gpu_clk_freq_set()could returnAMDSMI_STATUS_INVALfor a clock-set that the hardware actually supports. OnNavi48 (gfx1201) this fails
TestFrequenciesReadWrite, even though Navi31(gfx1100) runs the identical flow and passes.
Root cause
The deep-sleep-aware bitmask validation added in ROCM-9294 (#4707) rejects the
entire request with
INVALas soon as the caller's mask has any bit outside a"settable" range computed from a prior
get_clk_freqread. Because thatacceptable range is derived from a separate read and then acted on
(check-then-use), it doesn't always agree with what the driver will actually
accept, so a supported clock-set is falsely rejected on Navi48.
Fix
bitfield_to_freq_string()now mirrors the amdgpu driver: it silently dropsbits above the highest settable DPM level and applies the in-range subset,
raising
INVALID_ARGSonly when the requested mask has no settable level.Building the write payload this way — instead of validating the mask against a
separately-read range and then writing — removes the check-then-use mismatch
that produced the false
INVAL.'S') is counted innum_supportedbut is not a writablepp_dpm_*label, so it is excluded from the settable range (centralized inbitfield_to_freq_string()).PERMISSION, instead of probing before the write. A genuinely read-only nodestill returns
NOT_SUPPORTED; the result just comes from the actual writeoutcome rather than a separate pre-check.
no longer forces
MANUAL.amdsmi_set_clk_freq/rsmi_dev_gpu_clk_freq_setupdated todescribe the lenient contract.
Tests
TestFrequenciesReadWriteacceptsAMDSMI_STATUS_INVALonly when no level issettable, and exercises both the in-range-subset apply and the "enable all"
(
0xFFFFFFFF) reset paths.TestBase::SavePerfLevels()/RestorePerfLevels()restore the per-deviceperformance level in
Close()so a forcedMANUALstate cannot leak betweentests (wired into the frequencies and power read/write tests).
Validation
TestFrequenciesReadWritenow passesNotes
behavior supersedes the strict up-front check.
GpuFunctionalReadWrite.TestFrequenciesReadWriteon Aldebaran(gfx90a / MI210) by removing it from
FILTER[aldebaran]inamdsmitst.exclude(was excluded under SWDEV-306889); the fix makes it pass,validated by CI. Other Aldebaran exclusions are unchanged.
gfx1201mapping indetect_asic_filter.sh/amdsmitst.exclude) is intentionally not addressed here — fixing theunderlying behavior makes the set succeed, so no Navi48 test exclusion is
needed.
Fixes ROCM-28256