diff --git a/lact-daemon/src/server/gpu_controller/nvidia.rs b/lact-daemon/src/server/gpu_controller/nvidia.rs index 2d2f06fa..8b2d9968 100644 --- a/lact-daemon/src/server/gpu_controller/nvidia.rs +++ b/lact-daemon/src/server/gpu_controller/nvidia.rs @@ -66,7 +66,7 @@ pub struct NvidiaGpuController { nvapi: Option<(Rc, NvPhysicalGpuHandle)>, driver_handle: Option, - nvapi_thermals_mask: Option, + nvapi_therm_channel_mask: Option, last_util_timestamp: Cell>, // Store last applied offsets as a workaround when the driver doesn't tell us the current offset @@ -93,7 +93,7 @@ impl NvidiaGpuController { ) })?; - let (nvapi_handle, nvapi_thermals_mask) = match nvapi.as_ref() { + let (nvapi_handle, nvapi_therm_channel_mask) = match nvapi.as_ref() { Some(nvapi) => { let bus_id = common.get_slot_info()?.bus; let gpu_handle = nvapi @@ -102,19 +102,19 @@ impl NvidiaGpuController { .ok() .flatten(); - let thermals_mask = gpu_handle.and_then(|handle| unsafe { + let therm_channel_mask = gpu_handle.and_then(|handle| unsafe { nvapi - .calculate_thermals_mask(handle) + .calculate_therm_channel_mask(handle) .inspect(|mask| { - debug!("calculated NvAPI thermals mask {mask:x}"); + debug!("calculated NvAPI therm channel mask {mask:x}"); }) .inspect_err(|err| { - error!("could not calculate NvAPI thermal mask: {err:#}"); + error!("could not calculate NvAPI therm channel mask: {err:#}"); }) .ok() }); - (gpu_handle, thermals_mask) + (gpu_handle, therm_channel_mask) } None => (None, None), }; @@ -142,7 +142,7 @@ impl NvidiaGpuController { nvapi: nvapi.zip(nvapi_handle), common, driver_handle, - nvapi_thermals_mask, + nvapi_therm_channel_mask, initial_target_temp: target_temp, last_util_timestamp: Cell::new(None), fan_control_handle: RefCell::new(None), @@ -404,7 +404,7 @@ impl NvidiaGpuController { unsafe { info = nvapi.clock_client_clk_vf_points_get_info(*handle)?; status = nvapi.clock_client_clk_vf_points_get_status(*handle, info.vf_points_mask)?; - control = nvapi.clock_client_clk_vf_get_control(*handle, info.vf_points_mask)?; + control = nvapi.clock_client_clk_vf_points_get_control(*handle, info.vf_points_mask)?; } Ok(build_vf_curve(&info, &status, &control)) @@ -427,7 +427,7 @@ impl NvidiaGpuController { unsafe { info = nvapi.clock_client_clk_vf_points_get_info(*handle)?; status = nvapi.clock_client_clk_vf_points_get_status(*handle, info.vf_points_mask)?; - control = nvapi.clock_client_clk_vf_get_control(*handle, info.vf_points_mask)?; + control = nvapi.clock_client_clk_vf_points_get_control(*handle, info.vf_points_mask)?; } let control = build_curve_control( @@ -442,7 +442,7 @@ impl NvidiaGpuController { )?; unsafe { - nvapi.clock_client_clk_vf_set_control(*handle, control)?; + nvapi.clock_client_clk_vf_points_set_control(*handle, control)?; } self.vf_curve_written.set(true); @@ -455,7 +455,7 @@ impl NvidiaGpuController { let info = unsafe { nvapi.clock_client_clk_vf_points_get_info(*handle)? }; let mut curve_control = - unsafe { nvapi.clock_client_clk_vf_get_control(*handle, info.vf_points_mask)? }; + unsafe { nvapi.clock_client_clk_vf_points_get_control(*handle, info.vf_points_mask)? }; for i in 0..point_count_from_mask(info.vf_points_mask) { let point_info = info.vf_points[i]; @@ -465,7 +465,7 @@ impl NvidiaGpuController { } unsafe { - nvapi.clock_client_clk_vf_set_control(*handle, curve_control)?; + nvapi.clock_client_clk_vf_points_set_control(*handle, curve_control)?; } Ok(()) @@ -474,7 +474,7 @@ impl NvidiaGpuController { fn get_voltage_boost(&self) -> anyhow::Result { let (nvapi, handle) = self.nvapi.as_ref().context("NvAPI not available")?; - let current = unsafe { nvapi.get_voltage_boost(*handle)? }; + let current = unsafe { nvapi.client_volt_rails_get_control(*handle)? }; Ok(NvidiaVoltageBoost { current: current.into(), @@ -494,11 +494,11 @@ impl NvidiaGpuController { debug!("applying voltage boost {percent}%"); unsafe { - nvapi.set_voltage_boost(*handle, percent)?; + nvapi.client_volt_rails_set_control(*handle, percent)?; } self.voltage_boost_written.set(true); - let applied = unsafe { nvapi.get_voltage_boost(*handle) } + let applied = unsafe { nvapi.client_volt_rails_get_control(*handle) } .context("Could not verify voltage boost")?; ensure!( applied == percent, @@ -512,7 +512,7 @@ impl NvidiaGpuController { let (nvapi, handle) = self.nvapi.as_ref().context("NvAPI not available")?; unsafe { - nvapi.set_voltage_boost(*handle, 0)?; + nvapi.client_volt_rails_set_control(*handle, 0)?; } self.voltage_boost_written.set(false); @@ -911,8 +911,8 @@ impl GpuController for NvidiaGpuController { let arch = device.architecture().ok(); unsafe { - if let Some(mask) = self.nvapi_thermals_mask - && let Ok(thermals) = nvapi.get_thermals(*handle, mask) + if let Some(mask) = self.nvapi_therm_channel_mask + && let Ok(thermals) = nvapi.therm_channel_get_status(*handle, mask) { if let Some(hotspot) = nvapi.read_hotspot(&thermals, *handle, arch.as_ref()) { temps.insert( @@ -972,7 +972,7 @@ impl GpuController for NvidiaGpuController { } } - if let Ok(value) = nvapi.get_voltage(*handle) { + if let Ok(value) = nvapi.client_volt_rails_get_status(*handle) { voltage = Some(u64::from(value) / 1000); } diff --git a/lact-daemon/src/server/gpu_controller/nvidia/nvapi.rs b/lact-daemon/src/server/gpu_controller/nvidia/nvapi.rs index 9faa470a..2715e9e9 100644 --- a/lact-daemon/src/server/gpu_controller/nvidia/nvapi.rs +++ b/lact-daemon/src/server/gpu_controller/nvidia/nvapi.rs @@ -24,19 +24,19 @@ const QUERY_INTERFACE_FN: &[u8] = b"nvapi_QueryInterface\0"; const QUERY_NVAPI_INITIALIZE: u32 = 0x0150e828; const QUERY_NVAPI_UNLOAD: u32 = 0xd22bdd7e; const QUERY_NVAPI_ENUM_PHYSICAL_GPUS: u32 = 0xe5ac921f; -const QUERY_NVAPI_GET_BUS_ID: u32 = 0x1be0b8e5; +const QUERY_NVAPI_GPU_GET_BUS_ID: u32 = 0x1be0b8e5; const QUERY_NVAPI_GET_ERROR_MESSAGE: u32 = 0x6c2d048c; // Undocumented calls -const QUERY_NVAPI_THERMALS: u32 = 0x65fe3aad; -const QUERY_NVAPI_VOLTAGE: u32 = 0x465f9bcf; -const QUERY_NVAPI_VOLTAGE_BOOST_GET: u32 = 0x9df23ca1; -const QUERY_NVAPI_VOLTAGE_BOOST_SET: u32 = 0xb9306d9b; +const QUERY_NVAPI_GPU_THERM_CHANNEL_GET_STATUS: u32 = 0x65fe3aad; +const QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_GET_STATUS: u32 = 0x465f9bcf; +const QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_GET_CONTROL: u32 = 0x9df23ca1; +const QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_SET_CONTROL: u32 = 0xb9306d9b; const QUERY_NVAPI_GPU_CLOCK_CLIENT_CLK_VF_POINTS_GET_STATUS: u32 = 0x21537ad4; const QUERY_NVAPI_GPU_CLOCK_CLIENT_CLK_VF_POINTS_GET_INFO: u32 = 0x507b4b59; const QUERY_NVAPI_GPU_CLOCK_CLIENT_CLK_VF_POINTS_SET_CONTROL: u32 = 0x733e009; const QUERY_NVAPI_GPU_CLOCK_CLIENT_CLK_VF_POINTS_GET_CONTROL: u32 = 0x23f1b133; const QUERY_NVAPI_GPU_REGISTER_OP: u32 = 0x2eb3c140; -const QUERY_NVAPI_GPU_GET_ALL_CLOCKS: u32 = 0x1BD69F49; +const QUERY_NVAPI_GPU_GET_ALL_CLOCKS: u32 = 0x1bd69f49; const REG_OFFSET_BLACKWELL_HOTSPOT_AGGREGATED: u32 = 0xad0aa0; @@ -70,7 +70,7 @@ impl NvApi { unsafe { let handles = self.enum_physical_gpus()?; for handle in handles { - let f = self.query_interface(QUERY_NVAPI_GET_BUS_ID)?; + let f = self.query_interface(QUERY_NVAPI_GPU_GET_BUS_ID)?; let f: unsafe extern "C" fn( handle: NvPhysicalGpuHandle, id: &mut u32, @@ -89,12 +89,12 @@ impl NvApi { Ok(None) } - pub unsafe fn get_thermals( + pub unsafe fn therm_channel_get_status( &self, handle: NvPhysicalGpuHandle, mask: i32, ) -> anyhow::Result { - let f = self.query_interface(QUERY_NVAPI_THERMALS)?; + let f = self.query_interface(QUERY_NVAPI_GPU_THERM_CHANNEL_GET_STATUS)?; let f: unsafe extern "C" fn( handle: NvPhysicalGpuHandle, sensors: &mut NvApiThermals, @@ -113,18 +113,32 @@ impl NvApi { Ok(sensors) } - pub unsafe fn get_voltage(&self, handle: NvPhysicalGpuHandle) -> anyhow::Result { - let mut data = NvApiVoltage::default(); - self.physical_gpu_query(handle, &mut data, QUERY_NVAPI_VOLTAGE)?; + pub unsafe fn client_volt_rails_get_status( + &self, + handle: NvPhysicalGpuHandle, + ) -> anyhow::Result { + let mut data = ClientVoltRailsStatusV1::default(); + self.physical_gpu_query( + handle, + &mut data, + QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_GET_STATUS, + )?; Ok(data.rails[0].current_voltage_uv) } - pub unsafe fn get_voltage_boost(&self, handle: NvPhysicalGpuHandle) -> anyhow::Result { - let mut data = NvApiVoltageBoost::default(); - self.physical_gpu_query(handle, &mut data, QUERY_NVAPI_VOLTAGE_BOOST_GET)?; + pub unsafe fn client_volt_rails_get_control( + &self, + handle: NvPhysicalGpuHandle, + ) -> anyhow::Result { + let mut data = ClientVoltRailsControlV1::default(); + self.physical_gpu_query( + handle, + &mut data, + QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_GET_CONTROL, + )?; - Ok(data.percent) + Ok(data.percent_delta) } pub unsafe fn get_all_clocks( @@ -137,16 +151,20 @@ impl NvApi { Ok(data) } - pub unsafe fn set_voltage_boost( + pub unsafe fn client_volt_rails_set_control( &self, handle: NvPhysicalGpuHandle, percent: u8, ) -> anyhow::Result<()> { - let mut data = NvApiVoltageBoost { - percent, + let mut data = ClientVoltRailsControlV1 { + percent_delta: percent, ..Default::default() }; - self.physical_gpu_query(handle, &mut data, QUERY_NVAPI_VOLTAGE_BOOST_SET)?; + self.physical_gpu_query( + handle, + &mut data, + QUERY_NVAPI_GPU_CLIENT_VOLT_RAILS_SET_CONTROL, + )?; Ok(()) } @@ -185,7 +203,7 @@ impl NvApi { Ok(data) } - pub unsafe fn clock_client_clk_vf_get_control( + pub unsafe fn clock_client_clk_vf_points_get_control( &self, handle: NvPhysicalGpuHandle, vf_points_mask: [NvU32; 8], @@ -204,7 +222,7 @@ impl NvApi { Ok(data) } - pub unsafe fn clock_client_clk_vf_set_control( + pub unsafe fn clock_client_clk_vf_points_set_control( &self, handle: NvPhysicalGpuHandle, mut control: ClockClientClkVfPointsControlV1, @@ -218,11 +236,11 @@ impl NvApi { Ok(()) } - pub unsafe fn calculate_thermals_mask( + pub unsafe fn calculate_therm_channel_mask( &self, handle: NvPhysicalGpuHandle, ) -> anyhow::Result { - let f = self.query_interface(QUERY_NVAPI_THERMALS)?; + let f = self.query_interface(QUERY_NVAPI_GPU_THERM_CHANNEL_GET_STATUS)?; let f: unsafe extern "C" fn( handle: NvPhysicalGpuHandle, sensors: &mut NvApiThermals, @@ -516,25 +534,25 @@ impl NvApiThermals { #[repr(C)] #[derive(Debug)] -struct NvApiVoltage { +struct ClientVoltRailsStatusV1 { version: NvU32, rsvd: [NvU8; 32], - rails: [NvApiVoltageRail; 1], + rails: [ClientVoltRailStatusV1; 1], } -impl Default for NvApiVoltage { +impl Default for ClientVoltRailsStatusV1 { fn default() -> Self { Self { version: make_version::(1), rsvd: [0; 32], - rails: [NvApiVoltageRail::default()], + rails: [ClientVoltRailStatusV1::default()], } } } #[repr(C)] #[derive(Debug, Default)] -struct NvApiVoltageRail { +struct ClientVoltRailStatusV1 { rail_id: NvU32, current_voltage_uv: NvU32, rsvd: [NvU8; 32], @@ -542,17 +560,17 @@ struct NvApiVoltageRail { #[repr(C)] #[derive(Debug, Copy, Clone)] -struct NvApiVoltageBoost { +struct ClientVoltRailsControlV1 { version: NvU32, - percent: NvU8, + percent_delta: NvU8, rsvd: [NvU8; 32], } -impl Default for NvApiVoltageBoost { +impl Default for ClientVoltRailsControlV1 { fn default() -> Self { Self { version: make_version::(1), - percent: 0, + percent_delta: 0, rsvd: [0; 32], } }