Skip to main content

decode_gpu_metrics_throttle

Function decode_gpu_metrics_throttle 

Source
pub fn decode_gpu_metrics_throttle(buf: &[u8]) -> Option<ThrottleReasons>
Expand description

Decode AMD throttle status from a raw gpu_metrics sysfs blob.

Offsets are derived from the in-tree kernel headers (drivers/gpu/drm/amd/include/kgd_pp_interface.h for the struct layouts and drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h for the SMU_THROTTLER_*_BIT values). The structs are naturally aligned, little-endian.

The contract is honest absence on any doubt: a buffer too short for the header, a structure_size that disagrees with the version’s known length (or is shorter than the fields we read), an unknown (format, content) revision, or an out-of-bounds field all yield None. Some is returned only off a successfully decoded struct, because under §5.4 an all-false ThrottleReasons is an observation of quiet — emitting it from a blob we could not decode would fabricate a fact-grade “not throttling” forever on any kernel shipping a revision newer than this table. Garbage content is a broken interface, which is unobservable too — refusing beats guessing. We never wrap, never panic, and never narrate a byte we are not certain of.

Mapping precedence: prefer indep_throttle_status (ASIC-independent bits) and split it into thermal / power_cap / hw_slowdown / other. For older revisions that expose only the legacy ASIC-specific throttle_status, the per-bit meaning varies by ASIC and is not safe to map; a nonzero value reliably means “some throttler is active”, so it surfaces as other alone rather than as a fabricated specific cause.

0xFF sentinel: the SMU memsets the whole metrics table to 0xFF before writing the fields this ASIC’s firmware supports (smu_cmn.h), so an all-ones word — u64::MAX indep / u32::MAX legacy — is the firmware’s “never wrote this” marker, NOT 64 simultaneous throttlers. A sentinel word is unobservable: decoding falls through indep → legacy → None as each word in turn proves unwritten. Cyan Skillfish (BC-250 class) is the known shipper: it emits v2_2 without ever writing indep_throttle_status, and without this guard every sample would narrate thermal+power+hw_slowdown+other, permanently.

v3_0 is recognised but its per-sample throttle decode is deliberately None — see the (3, 0) branch below.