diff --git a/projects/amdsmi/CMakeLists.txt b/projects/amdsmi/CMakeLists.txt index 9136b016be..5534406493 100644 --- a/projects/amdsmi/CMakeLists.txt +++ b/projects/amdsmi/CMakeLists.txt @@ -76,6 +76,7 @@ include(CMakeDependentOption) # these options don't work without BUILD_SHARED_LIBS cmake_dependent_option(BUILD_WRAPPER "Rebuild AMDSMI-wrapper" OFF "BUILD_SHARED_LIBS" OFF) cmake_dependent_option(BUILD_CLI "Build AMDSMI-CLI and install" ON "BUILD_SHARED_LIBS" OFF) +cmake_dependent_option(BUILD_RUST_WRAPPER "Build rust wrapper and install" OFF "BUILD_SHARED_LIBS" OFF) cmake_dependent_option(ENABLE_LDCONFIG "Set library links and caches using ldconfig." ON "BUILD_SHARED_LIBS" OFF) # Set share path here because project name != amd_smi @@ -193,6 +194,9 @@ if(BUILD_SHARED_LIBS) if(BUILD_CLI) add_subdirectory("amdsmi_cli") endif() + if(BUILD_RUST_WRAPPER) + add_subdirectory("rust-interface") + endif() endif() include(CMakePackageConfigHelpers) diff --git a/projects/amdsmi/rust-interface/.gitignore b/projects/amdsmi/rust-interface/.gitignore new file mode 100644 index 0000000000..6385672312 --- /dev/null +++ b/projects/amdsmi/rust-interface/.gitignore @@ -0,0 +1,4 @@ +# Auto generated by Carge +target +build +*.lock diff --git a/projects/amdsmi/rust-interface/CMakeLists.txt b/projects/amdsmi/rust-interface/CMakeLists.txt new file mode 100644 index 0000000000..3e87612c09 --- /dev/null +++ b/projects/amdsmi/rust-interface/CMakeLists.txt @@ -0,0 +1,124 @@ +# Generate rust-wrapper and package targets + +# This string is the installation directory containing all rust files +set(RUST_WRAPPER_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/rust-wrapper" CACHE STRING "Rust wrapper installation directory") + +# Optional to build examples +option(BUILD_RUST_EXAMPLES "Build rust-interface examples" OFF) + +# Optional to regenerate the Rust wrapper amdsmi_wrapper.rs +option(REGENERATE_RUST_WRAPPER "Re-generate AMD SMI Rust wrapper file" OFF) + +# Determine the Cargo build type based on the CMake build type +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CARGO_BUILD_TYPE debug) + set(CARGO_BUILD_TYPE_ARG) # Default is debug for Cargo, no argument "--debug" +else() + set(CARGO_BUILD_TYPE release) + set(CARGO_BUILD_TYPE_ARG --release) +endif() + +set(RUST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/target) +set(RUST_PACKAGE_SROUCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/source) +set(RUST_OUTPUT_DIR ${RUST_BUILD_DIR}/${CARGO_BUILD_TYPE}) + +if(REGENERATE_RUST_WRAPPER) + set(AMDSMI_GENERATE_RUST_WRAPPER "AMDSMI_GENERATE_RUST_WRAPPER=1") +else() + set(AMDSMI_GENERATE_RUST_WRAPPER "") +endif() + +# Create source tar.gz archive +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/source.tar.gz + COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_PACKAGE_SROUCE_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_PACKAGE_SROUCE_DIR}/include/amd_smi + COMMAND ${CMAKE_COMMAND} -E make_directory ${RUST_PACKAGE_SROUCE_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h ${RUST_PACKAGE_SROUCE_DIR}/include/amd_smi/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/src/libamd_smi.so ${RUST_PACKAGE_SROUCE_DIR}/lib/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/build.rs ${RUST_PACKAGE_SROUCE_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/callbacks.rs ${RUST_PACKAGE_SROUCE_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml ${RUST_PACKAGE_SROUCE_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${RUST_PACKAGE_SROUCE_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/src ${RUST_PACKAGE_SROUCE_DIR}/src + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/examples ${RUST_PACKAGE_SROUCE_DIR}/examples + COMMAND ${CMAKE_COMMAND} -E tar cfz ${CMAKE_CURRENT_BINARY_DIR}/source.tar.gz --format=gnutar ${RUST_PACKAGE_SROUCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${AMD_SMI} + ${CMAKE_CURRENT_SOURCE_DIR}/build.rs + ${CMAKE_CURRENT_SOURCE_DIR}/callbacks.rs + ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml + ${CMAKE_CURRENT_SOURCE_DIR}/README.md + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/examples + COMMENT "Creating AMD SMI Rust wrapper source tar.gz archive" +) + +add_custom_target(amdsmi_rust_source ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/source.tar.gz +) + +find_program(CARGO_EXECUTABLE NAMES cargo) + +if(NOT CARGO_EXECUTABLE) + message(STATUS "Cargo not found. Installing Rust and Cargo...") + execute_process( + COMMAND /bin/sh -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" + RESULT_VARIABLE result + ) + + if(result) + message(FATAL_ERROR "Failed to install Rust and Cargo.") + endif() + + # Add Cargo to the PATH + set(CARGO_EXECUTABLE "$ENV{HOME}/.cargo/bin/cargo") +endif() + +# Determine the Cargo build command +set(CARGO_BUILD_COMMAND ${CARGO_EXECUTABLE} build ${CARGO_BUILD_TYPE_ARG} --target-dir ${RUST_BUILD_DIR}) + +# Use make amdsmi_rust to build the library +add_custom_target(amdsmi_rust + COMMAND ${CMAKE_COMMAND} -E env ${AMDSMI_GENERATE_RUST_WRAPPER} AMDSMI_LIB_DIR=${PROJECT_BINARY_DIR}/src ${CARGO_BUILD_COMMAND} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${AMD_SMI} + COMMENT "Build the AMD SMI Rust library" +) + +if(BUILD_RUST_EXAMPLES) + # Determine the build command for examples if enabled + set(CARGO_BUILD_EXAMPLES_COMMAND ${CARGO_EXECUTABLE} build ${CARGO_BUILD_TYPE_ARG} --target-dir ${RUST_BUILD_DIR} --examples) + + # Define the build command for the Rust examples + add_custom_command( + OUTPUT ${RUST_OUTPUT_DIR}/examples/amdsmi_get_gpu_info + ${RUST_OUTPUT_DIR}/examples/amdsmi_exporter + COMMAND ${CMAKE_COMMAND} -E env AMDSMI_LIB_DIR=${PROJECT_BINARY_DIR}/src ${CARGO_BUILD_COMMAND} + COMMAND ${CMAKE_COMMAND} -E env AMDSMI_LIB_DIR=${PROJECT_BINARY_DIR}/src ${CARGO_BUILD_EXAMPLES_COMMAND} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Building AMD SMI Rust examples" + ) + add_custom_target(rust_examples ALL + DEPENDS ${RUST_BUILD_DIR}/${CARGO_BUILD_TYPE}/examples/amdsmi_get_gpu_info + ${RUST_OUTPUT_DIR}/examples/amdsmi_exporter + ) +endif() + +# Deploy the Rust interface with source code only, as using static or dynamic library binaries is not recommended by the Rust ecosystem. +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/source.tar.gz + DESTINATION ${RUST_WRAPPER_INSTALL_DIR} + COMPONENT dev) + +# Deploy rust-interface examples +if(BUILD_RUST_EXAMPLES) + install(DIRECTORY DESTINATION ${RUST_WRAPPER_INSTALL_DIR}/examples COMPONENT dev) + install( + FILES ${RUST_OUTPUT_DIR}/examples/amdsmi_get_gpu_info + ${RUST_OUTPUT_DIR}/examples/amdsmi_exporter + DESTINATION ${RUST_WRAPPER_INSTALL_DIR}/examples + PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + COMPONENT dev) +endif() \ No newline at end of file diff --git a/projects/amdsmi/rust-interface/Cargo.toml b/projects/amdsmi/rust-interface/Cargo.toml new file mode 100644 index 0000000000..185b0d0e99 --- /dev/null +++ b/projects/amdsmi/rust-interface/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "amdsmi" +version = "0.1.1" +edition = "2021" +description = "A rust binding for the AMD System Management Interface (AMD-SMI) library" +repository = "https://github.com/ROCm/amdsmi/rust-interface" +readme = "README.md" +keywords = ["amdsmi", "rust binding"] +license = "Copyright (c) 2019-2024 Advanced Micro Devices, Inc" + +[build-dependencies] +bindgen = "0.70.1" + +[lib] +name = "amdsmi" +path = "src/lib.rs" + +[[example]] +name = "amdsmi_get_gpu_info" +crate-type = ["bin"] + +[[example]] +name = "amdsmi_exporter" +crate-type = ["bin"] + +[dev-dependencies] +prometheus-client = "0.22.3" +axum = "0.5" +hyper = "0.14" +clap = "3.0" +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/projects/amdsmi/rust-interface/README.md b/projects/amdsmi/rust-interface/README.md new file mode 100644 index 0000000000..913706d8a6 --- /dev/null +++ b/projects/amdsmi/rust-interface/README.md @@ -0,0 +1,246 @@ +# AMD SMI Rust Binding + +This rust crate provides Rust bindings for the AMD System Management Interface (AMD-SMI) library. It allows you to interact with AMD GPUs and retrieve various information using Rust. + +## Table of Contents + +- [Overview](#overview) +- [Hello World Example](#hello-world-example) +- [Directory Structure](#directory-structure) +- [Building](#building) +- [Running Tests](#running-tests) +- [Running Examples](#running-examples) +- [Generating Documentation](#generating-documentation) +- [Adding New API and Tests](#adding-new-api-and-tests) + +## Overview + +The AMD SMI Rust binding crate automates the generation of bindings and ensures safety, maintainability, and ease of use. The implementation consists of two main steps: + +1. **Generating Bindings with `bindgen`**: + - The `build.rs` script uses `bindgen` to automatically generate Rust FFI (Foreign Function Interface) bindings for the AMD SMI C library. This step exports all enums, structs, unions, and unsafe functions from the C library into Rust, providing a comprehensive low-level interface to the AMD SMI library. + +2. **Implementing Safe Rust Wrappers**: + - The generated bindings are then wrapped in safe Rust functions. These safe wrappers handle error checking, resource management, and provide a more idiomatic Rust interface. This ensures that users of the library can interact with the AMD SMI functions without dealing with unsafe code directly. + +## Hello World Example +Here is a simple "Hello World" example to get you started with the AMD SMI Rust bindings. This example initializes the AMD SMI library, retrieves the GPU information, and prints it to the console. +``` +use amdsmi::*; + +fn main() { + // Initialize the AMD SMI library + if let Err(e) = amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus) { + eprintln!("Failed to initialize AMD SMI: {}", e); + return; + } + + // Get socket handles + let socket_handles = match amdsmi_get_socket_handles() { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get socket handles: {}", e); + amdsmi_shut_down().expect("Failed to shutdown AMD SMI"); + return; + } + }; + + for socket_handle in socket_handles { + // Get processor handles for each socket handle + let processor_handles = match amdsmi_get_processor_handles(socket_handle) { + Ok(handles) => handles, + Err(e) => { + eprintln!( + "Failed to get processor handles for socket {:?}: {}", + socket_handle, e + ); + continue; + } + }; + + for processor_handle in processor_handles { + // Get GPU ID using the processor handle + match amdsmi_get_gpu_id(processor_handle) { + Ok(gpu_id) => println!("GPU ID: {}", gpu_id), + Err(e) => eprintln!("Failed to get GPU ID: {}", e), + } + + // Get GPU revision using the processor handle + match amdsmi_get_gpu_revision(processor_handle) { + Ok(gpu_revision) => println!("GPU Revision: {}", gpu_revision), + Err(e) => eprintln!("Failed to get GPU revision: {}", e), + } + + // Get GPU vendor name using the processor handle + match amdsmi_get_gpu_vendor_name(processor_handle) { + Ok(gpu_vendor_name) => println!("GPU Vendor Name: {}", gpu_vendor_name), + Err(e) => eprintln!("Failed to get GPU vendor name: {}", e), + } + + // Get GPU VRAM vendor using the processor handle + match amdsmi_get_gpu_vram_vendor(processor_handle) { + Ok(gpu_vram_vendor) => println!("GPU VRAM Vendor: {}", gpu_vram_vendor), + Err(e) => eprintln!("Failed to get GPU VRAM vendor: {}", e), + } + + // Get GPU BDF using the processor handle + match amdsmi_get_gpu_device_bdf(processor_handle) { + Ok(gpu_bdf) => println!("GPU BDF: {}", gpu_bdf), + Err(e) => eprintln!("Failed to get GPU BDF: {}", e), + } + + println!(); + } + } + + // Shutdown the AMD SMI library + if let Err(e) = amdsmi_shut_down() { + eprintln!("Failed to shutdown AMD SMI: {}", e); + } +} +``` + +## Directory Structure + +``` +amd-smi/rust-interface +├── Cargo.toml # Cargo configuration file +├── CMakeLists.txt # CMake configuration file for building the AMD SMI library +├── build.rs # Build script for generating bindings +├── src/ +│ ├── lib.rs # Library entry point +│ ├── amdsmi.rs # Main module for AMD SMI bindings +│ ├── utils.rs # Utility functions and helpers +│ └── amdsmi_wrapper.rs # Automatically generate FFI bindings by `bindgen` +└── examples # Example programs demonstrating usage +``` + +## Building + +To build this Rust binding, you need to have Rust and Cargo installed. + +### Option 1: Using CMake + +Navigate to the project's root directory and use the project's CMake build system. You need to define the `BUILD_RUST_WRAPPER` option. This will build this Rust interface and integrate it with the rest of the project. + +```sh +mkdir build +cd build +cmake -DBUILD_RUST_WRAPPER=ON .. +make +sudo make install +``` + +### Option 2: Using Cargo + +Alternatively, you can navigate to the `rust-interface` folder and build the project using Cargo. + +```sh +cd rust-interface +cargo build +``` + +## Running Tests + +To run the tests, use the following command: + +```sh +cargo test --doc -- --show-output --test-threads=1 +``` + +This command will execute all the unit tests that are defined in the API's example code within the API's documentation comments. + +## Running Examples + +To run the examples, use the following command: + +```sh +cargo run --example example_name +``` + +Replace `example_name` with the name of the example you want to run. For example, if you have an example named `get_gpu_info`, you can run it as follows: + +```sh +cargo run --example get_gpu_info +``` + +## Generating Documentation + +To generate the documentation for the project, use the following command: + +```sh +cargo doc --open +``` + +This will generate the documentation and open it in your default web browser. + +## Adding New API and Tests + +### Adding New API + +1. **Update Bindings**: + - Rebuilding this Rust library will automatically generate the bindings using `bindgen` according to the latest `amdsmi.h`. + +2. **Define the API**: + - Add the new API function in the appropriate Rust file, e.g., `src/amdsmi.rs`. + - Implement the function to use the `call_unsafe!` macro to call the `bindgen` generated unsafe rust FFI function in `amdsmi_wrapper.rs`. + +3. **Document the API**: + - Use Rust doc comments `///` to document the new API function. Include a description, parameters, return values, and examples. + +### Adding Tests + +Include examples in the documentation comments of your functions. These examples will be compiled and run as tests when you run `cargo test`. + + +### Example of New API + +Here is an example of adding a new API function and documenting it with a doc test: + +```rust +/// Retrieves the GPU ID for a given processor handle. +/// +/// This function returns the GPU ID associated with the specified processor handle. +/// The GPU ID is a unique identifier for the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU ID is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU ID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU ID +/// match amdsmi_get_gpu_id(processor_handle) { +/// Ok(gpu_id) => println!("GPU ID: {}", gpu_id), +/// Err(e) => panic!("Failed to get GPU ID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_id` call fails. +pub fn amdsmi_get_gpu_id(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut id: u16 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_id(processor_handle, &mut id)); + Ok(id) +} +``` + diff --git a/projects/amdsmi/rust-interface/build.rs b/projects/amdsmi/rust-interface/build.rs new file mode 100644 index 0000000000..f1fd4478c5 --- /dev/null +++ b/projects/amdsmi/rust-interface/build.rs @@ -0,0 +1,188 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +extern crate bindgen; +use std::env; +use std::fs; +use std::io::Result; +use std::path::{Path, PathBuf}; +mod callbacks; + +fn get_rocm_dir() -> Option { + // Look for the latest folder in /opt that begins with "rocm" + let opt_path = Path::new("/opt"); + if let Ok(entries) = fs::read_dir(opt_path) { + let mut rocm_dirs: Vec = entries + .filter_map(|entry| entry.ok()) + .map(|entry| entry.path()) + .filter(|path| { + path.is_dir() + && path + .file_name() + .unwrap_or_default() + .to_string_lossy() + .starts_with("rocm") + }) + .collect(); + + // Sort the directories by name and get the latest one + rocm_dirs.sort(); + if let Some(latest_rocm_dir) = rocm_dirs.last() { + return Some(latest_rocm_dir.clone()); + } + } + None +} + +fn get_amdsmi_lib_dir() -> Result { + let amdsmi_file = "libamd_smi.so"; + + // Check the environment variable AMDSMI_LIB_DIR to get the library directory + if let Ok(lib_dir) = env::var("AMDSMI_LIB_DIR") { + if PathBuf::from(lib_dir.clone()).join(amdsmi_file).exists() { + return Ok(lib_dir); + } + } + + // Check the current directory + if let Ok(current_dir) = env::current_dir() { + let current_lib_dir = current_dir.join("lib"); + if current_lib_dir.join(amdsmi_file).exists() { + return Ok(current_lib_dir.to_string_lossy().into_owned()); + } + } + + // Check the ROCm directory + if let Some(lib_dir) = get_rocm_dir() { + if lib_dir.join("lib").join(amdsmi_file).exists() { + return Ok(lib_dir.join("lib").to_string_lossy().into_owned()); + } + } + + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "The libamd_smi.so library was not found. Please set the AMDSMI_LIB_DIR environment variable to the directory containing the library.", + )) +} + +fn get_amdsmi_header_file() -> Result { + let amdsmi_header_path = "include/amd_smi/amdsmi.h"; + // Use the project's header as the first priority + let default_path = PathBuf::from("../").join(amdsmi_header_path); + if default_path.exists() { + return Ok(default_path.to_string_lossy().into_owned()); + } + + // Check the current directory + if let Ok(current_dir) = env::current_dir() { + let fallback_path = current_dir.join(amdsmi_header_path); + if fallback_path.exists() { + return Ok(fallback_path.to_string_lossy().into_owned()); + } + } + + // Check the ROCm directory + if let Some(rocm_dir) = get_rocm_dir() { + let fallback_path = rocm_dir.join(amdsmi_header_path); + if fallback_path.exists() { + return Ok(fallback_path.to_string_lossy().into_owned()); + } + } + + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "The amdsmi.h header file was not found", + )) +} + +fn generate_amdsmi_wrapper(amdsmi_header_file: &str) { + let bindings = bindgen::Builder::default() + .header(amdsmi_header_file) + .generate_comments(false) + .prepend_enum_name(false) + .rustified_enum("^(.*)$") + .allowlist_type("^(amdsmi.*)$") + .allowlist_function("^(amdsmi.*)$") + .allowlist_var("^(AMDSMI.*)$") + .parse_callbacks(Box::new(callbacks::UpperCamelCaseCallbacks)) + .raw_line("// Copyright (C) 2024 Advanced Micro Devices. All rights reserved.") + .raw_line("//") + .raw_line( + "// Permission is hereby granted, free of charge, to any person obtaining a copy of", + ) + .raw_line( + "// this software and associated documentation files (the \"Software\"), to deal in", + ) + .raw_line("// the Software without restriction, including without limitation the rights to") + .raw_line( + "// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of", + ) + .raw_line( + "// the Software, and to permit persons to whom the Software is furnished to do so,", + ) + .raw_line("// subject to the following conditions:") + .raw_line("//") + .raw_line( + "// The above copyright notice and this permission notice shall be included in all", + ) + .raw_line("// copies or substantial portions of the Software.") + .raw_line("//") + .raw_line("// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR") + .raw_line( + "// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS", + ) + .raw_line( + "// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR", + ) + .raw_line( + "// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER", + ) + .raw_line("// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN") + .raw_line("// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.") + .raw_line("") + .raw_line("#![allow(non_upper_case_globals)]") + .generate() + .expect("Unable to binding wrapper for amdsmi C interface!"); + + let bindings_path = PathBuf::from("./src/amdsmi_wrapper.rs"); + bindings + .write_to_file(&bindings_path) + .expect("Couldn't write binding wrapper for amdsmi C interface!"); + println!("Wrapper generated at: {:?}", bindings_path); + +} + +fn main() { + // Get the amd_smi library directory + let amdsmi_lib_dir = get_amdsmi_lib_dir().expect("Failed to get the amd_smi library path"); + + // Tell cargo to tell rustc to link the AMD-SMI library + println!("cargo:rustc-link-lib=amd_smi"); + println!("cargo:rustc-link-search=native={}", amdsmi_lib_dir); + + let generate_wrapper = env::var("AMDSMI_GENERATE_RUST_WRAPPER").is_ok(); + if generate_wrapper { + // Get the amdsmi.h header file path + let amdsmi_header_file = get_amdsmi_header_file().expect("Failed to get the amd_smi header file"); + + // Generate the amdsmi wrapper + generate_amdsmi_wrapper(&amdsmi_header_file); + } +} diff --git a/projects/amdsmi/rust-interface/callbacks.rs b/projects/amdsmi/rust-interface/callbacks.rs new file mode 100644 index 0000000000..8362202dd4 --- /dev/null +++ b/projects/amdsmi/rust-interface/callbacks.rs @@ -0,0 +1,71 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use bindgen::callbacks::EnumVariantValue; + +#[derive(Debug)] +pub struct UpperCamelCaseCallbacks; + +impl bindgen::callbacks::ParseCallbacks for UpperCamelCaseCallbacks { + fn item_name(&self, original_item_name: &str) -> Option { + if original_item_name.starts_with("amdsmi") + && (original_item_name.ends_with("_t") || original_item_name.contains("_t_")) + { + Some(convert_to_upper_camel_case(original_item_name)) + } else { + match original_item_name { + "amdsmi_processor_handle" + | "amdsmi_socket_handle" + | "processor_type_t" + | "amd_metrics_table_header_t" => { + Some(convert_to_upper_camel_case(original_item_name)) + } + _ => None, + } + } + } + + fn enum_variant_name( + &self, + _enum_name: Option<&str>, + original_variant_name: &str, + _variant_value: EnumVariantValue, + ) -> Option { + Some(convert_to_upper_camel_case(original_variant_name)) + } +} + +fn convert_to_upper_camel_case(s: &str) -> String { + let mut result = String::new(); + let mut capitalize_next = true; + + for c in s.chars() { + if c == '_' { + capitalize_next = true; + } else if capitalize_next { + result.push(c.to_ascii_uppercase()); + capitalize_next = false; + } else { + result.push(c.to_ascii_lowercase()); + } + } + + result +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/README.md b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/README.md new file mode 100644 index 0000000000..1f720c6b84 --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/README.md @@ -0,0 +1,96 @@ +# AMDSMI Exporter + +The `AMDSMI Exporter` is a tool that exports AMD SMI metrics and runs an HTTP server to serve these metrics. It provides options to list supported GPUs and metrics' information, as well as to export metrics with optional filtering using whitelist and blacklist. This enables fine-grained control over which metrics are included or excluded. + +## Features + +- List supported GPUs and detailed metrics information. +- Export AMD SMI metrics and serve them via an HTTP server. +- Filter metrics using whitelist and blacklist. +- Filter metrics by GPU BDF or ID. + +## Usage + +### List Supported GPUs and Metrics + +To list the supported GPUs and metrics' information, use the `list` subcommand: + +```sh +amdsmi_exporter list +``` + +### Export Metrics and Run HTTP Server + +To export AMD SMI metrics and run the HTTP server, use the `metric` subcommand: + +```sh +amdsmi_exporter metric [OPTIONS] +``` + +#### Options + +- `-p, --port `: Sets the port to listen on (default: 9898). +- `-g, --gpu `: Sets the GPU BDF or the zero-based index of the socket ID and processor ID for export. + Example: + - `--gpu 0000:03:00.0` + - `--gpu 0.0` +- `-w, --whitelist `: Comma-separated list of metric field names to include. +- `-b, --blacklist `: Comma-separated list of metric field names to exclude. + +### Examples + +#### List Supported GPUs and Metrics + +```sh +amdsmi_exporter list +``` + +#### Export Metrics and Run HTTP Server on Port 8080 for a Specific GPU + +```sh +amdsmi_exporter metric --port 8080 --gpu 0000:03:00.0 +``` + +#### Export Metrics with Whitelist Filter + +```sh +amdsmi_exporter metric --whitelist AMDSMI_FI_GFX_ACTIVITY,AMDSMI_FI_UMC_ACTIVITY +``` + +#### Export Metrics with Blacklist Filter + +```sh +amdsmi_exporter metric --blacklist AMDSMI_FI_GFX_VOLTAGE,AMDSMI_FI_SOC_VOLTAGE +``` + +### Set Up Prometheus Docker Server to Connect to This Client Exporter + +To set up a Prometheus Docker server to connect to this client exporter, follow these steps: + +1. **Create a Prometheus Configuration File** + + Create a file named prometheus.yml with the following content: + + ```yaml + global: + scrape_interval: 15s + + scrape_configs: + - job_name: 'amdsmi_exporter' + static_configs: + - targets: ['localhost:9898'] + ``` + + Replace `localhost:9898` with the appropriate address and port if you are running the exporter on a different host or port. + +2. **Run Prometheus Docker Container** + + Run the Prometheus Docker container with the configuration file: + + ```sh + docker run -d --name=prometheus -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus + ``` + +3. **Access Prometheus Web Interface** + + Open your web browser and go to `http://localhost:9090` to access the Prometheus web interface. You should see the `amdsmi_exporter` job listed under the "Targets" section. diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_collectors.rs b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_collectors.rs new file mode 100644 index 0000000000..a6420ada05 --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_collectors.rs @@ -0,0 +1,527 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use crate::amdsmi_metric::*; +use crate::collectors::collectors_create; +use amdsmi::*; +use prometheus_client::metrics::family::Family; +use prometheus_client::metrics::gauge::Gauge; +use prometheus_client::registry::Registry; +use std::collections::HashMap; +use std::fmt::Debug; +use std::fmt::Display; + +pub struct AmdsmiCollectors { + pub collectors: HashMap<&'static str, AmdsmiCollector>, + pub gpu_filter: Option>, + pub whitelist: Option>, + pub blacklist: Option>, +} + +impl Default for AmdsmiCollectors { + fn default() -> Self { + AmdsmiCollectors::new() + } +} + +impl AmdsmiCollectors { + pub fn new() -> Self { + let mut instance = AmdsmiCollectors { + collectors: HashMap::new(), + gpu_filter: None, + whitelist: None, + blacklist: None, + }; + collectors_create(&mut instance); + instance + } + + pub fn set_gpu_filter(&mut self, filters: Option>) -> &mut Self { + self.gpu_filter = filters; + self + } + + pub fn set_field_filter( + &mut self, + whitelist: Option>, + blacklist: Option>, + ) -> &mut Self { + self.whitelist = whitelist; + self.blacklist = blacklist; + // Re-generate the collectors after setting the field filters + self.collectors.clear(); + collectors_create(self); + self + } + + pub fn add_metric(&mut self, collector: AmdsmiGauge) -> &mut Self + where + T: 'static + Into + Display + Copy, + F: 'static + Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync, + { + let name = collector.info.name; + let description = collector.info.description; + let unit = collector.info.unit; + let func = collector.func; + + // Apply whitelist and blacklist filters before inserting the collector + if let Some(ref whitelist) = self.whitelist { + if !whitelist.contains(&name.to_string()) { + return self; + } + } + if let Some(ref blacklist) = self.blacklist { + if blacklist.contains(&name.to_string()) { + return self; + } + } + self.collectors.insert( + name, + Box::new(move |processor_handle| match func(processor_handle) { + Ok(value) => vec![AmdsmiMetric { + info: AmdsmiInfo { + name, + description, + unit: unit.clone(), + }, + value: value.into(), + status: AmdsmiStatusT::AmdsmiStatusSuccess, + }], + Err(e) => vec![AmdsmiMetric { + info: AmdsmiInfo { + name, + description, + unit: unit.clone(), + }, + value: 0, + status: e, + }], + }), + ); + self + } + + pub fn add_metric_group(&mut self, collector: &AmdsmiGaugeGroup) -> &mut Self + where + T: 'static + Debug, + F: 'static + Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync + Clone, + { + let name = collector.name; + let func = collector.func.clone(); + + // Apply whitelist and blacklist filters before the Box::new + let filtered_info_list: Vec<_> = collector + .info_list + .iter() + .filter(|(info, _)| { + if let Some(ref whitelist) = self.whitelist { + if !whitelist.contains(&info.name.to_string()) { + return false; + } + } + if let Some(ref blacklist) = self.blacklist { + if blacklist.contains(&info.name.to_string()) { + return false; + } + } + true + }) + .cloned() + .collect(); + + // If the filtered_info_list is empty, return early + if filtered_info_list.is_empty() { + return self; + } + + self.collectors.insert( + name, + Box::new(move |processor_handle| { + let mut results = Vec::new(); + + match func(processor_handle) { + Ok(value) => { + for (info, accessor) in &filtered_info_list { + results.push(AmdsmiMetric { + info: AmdsmiInfo { + name: info.name, + description: info.description, + unit: info.unit.clone(), + }, + value: accessor(&value), + status: AmdsmiStatusT::AmdsmiStatusSuccess, + }); + } + } + Err(e) => { + for (info, _) in &filtered_info_list { + results.push(AmdsmiMetric { + info: AmdsmiInfo { + name: info.name, + description: info.description, + unit: info.unit.clone(), + }, + value: 0, + status: e, + }); + } + } + } + results + }), + ); + self + } + + pub fn print_supported(&self) { + // Initialize the AMD SMI library + if let Err(e) = amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus) { + eprintln!("Failed to initialize AMD SMI: {}", e); + return; + } + + // Get socket handles + let socket_handles = match amdsmi_get_socket_handles() { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get socket handles: {}", e); + return; + } + }; + + for (socket_index, socket_handle) in socket_handles.iter().enumerate() { + let socket_id = socket_index.to_string(); + + // Get processor handles for each socket handle + let processor_handles = match amdsmi_get_processor_handles(*socket_handle) { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get processor handles: {}", e); + continue; + } + }; + + for (processor_index, processor_handle) in processor_handles.iter().enumerate() { + let processor_id = processor_index.to_string(); + + let bdf = match amdsmi_get_gpu_device_bdf(*processor_handle) { + Ok(bdf) => bdf.to_string(), + Err(e) => { + eprintln!("Failed to get GPU device BDF: {}", e); + continue; + } + }; + + println!("========================================"); + println!("GPU Information:"); + println!(" Socket ID: {}", socket_id); + println!(" Processor ID: {}", processor_id); + println!(" BDF: {}", bdf); + println!("----------------------------------------"); + println!("Supported Metrics:"); + println!( + "{:<30} | {:<10} | {:<10} | {:<50}", + "Metric ID", "Value", "Unit", "Help" + ); + println!("{:-<30}-+-{:-<10}-+-{:-<10}-+-{:-<50}", "", "", "", ""); + + // Collect metrics + for (_, collector) in &self.collectors { + let results = collector(*processor_handle); + for metric in results { + let value_str = if metric.status == AmdsmiStatusT::AmdsmiStatusSuccess { + metric.value.to_string() + } else { + "NA".to_string() + }; + + println!( + "{:<30} | {:<10} | {:<10} | {:<50}", + metric.info.name, + value_str, + metric.info.unit.as_str(), + metric.info.description + ); + } + } + println!("========================================\n"); + } + } + + // Shutdown the AMD SMI library + if let Err(e) = amdsmi_shut_down() { + eprintln!("Failed to shutdown AMD SMI: {}", e); + } + } + + pub fn run_collect(&mut self) -> Registry { + // Initialize the AMD SMI library + if let Err(e) = amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus) { + eprintln!("Failed to initialize AMD SMI: {}", e); + return Registry::default(); + } + + let mut registry = Registry::default(); + + // Get socket handles + let socket_handles = match amdsmi_get_socket_handles() { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get socket handles: {}", e); + return registry; + } + }; + + for (socket_index, socket_handle) in socket_handles.iter().enumerate() { + let socket_id = socket_index.to_string(); + + // Get processor handles for each socket handle + let processor_handles = match amdsmi_get_processor_handles(*socket_handle) { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get processor handles: {}", e); + continue; + } + }; + + for (processor_index, processor_handle) in processor_handles.iter().enumerate() { + let processor_id = processor_index.to_string(); + + let bdf = match amdsmi_get_gpu_device_bdf(*processor_handle) { + Ok(bdf) => bdf.to_string(), + Err(e) => { + eprintln!("Failed to get GPU device BDF: {}", e); + continue; + } + }; + + let labels = AmdsmiLabels { + socket_id: socket_id.clone(), + processor_id: processor_id.clone(), + bdf, + }; + + // Only for GPUs which match the provided gpu filter argument + if let Some(ref filters) = self.gpu_filter { + if !filters.iter().any(|filter| { + filter == &labels.bdf + || filter == &format!("{}.{}", socket_id, processor_id) + }) { + continue; + } + } + + // Collect metrics + for (_, collector) in &self.collectors { + let results = collector(*processor_handle); + for metric in results { + if metric.status == AmdsmiStatusT::AmdsmiStatusSuccess { + let metric_family = + Family::::new_with_constructor(Gauge::default); + if metric.info.unit.as_str().is_empty() { + registry.register( + metric.info.name, + metric.info.description, + metric_family.clone(), + ); + } else { + registry.register_with_unit( + metric.info.name, + metric.info.description, + metric.info.unit.clone(), + metric_family.clone(), + ); + } + metric_family.get_or_create(&labels).set(metric.value); + } else { + #[cfg(debug_assertions)] + eprintln!( + "Failed to collect metric {}: {} for socket {} processor {}", + metric.info.name, + metric.status, + labels.socket_id, + labels.processor_id + ); + } + } + } + } + } + + // Shutdown the AMD SMI library + if let Err(e) = amdsmi_shut_down() { + eprintln!("Failed to shutdown AMD SMI: {}", e); + } + + registry + } +} + +/// A macro to add a metric collector. +/// +/// This macro creates an `AmdsmiGauge` instance and adds it to the collectors. +/// +/// # Parameters +/// - `$collectors`: The collectors to add the metric to. +/// - `$name`: The name of the metric. +/// - `$description`: The description of the metric. +/// - `$unit`: The unit of the metric. +/// - `$func`: The function to collect the metric. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # use amdsmi_collectors::*; +/// +/// # fn main() { +/// let mut collectors = AmdsmiCollectors::default(); +/// add_metric!( +/// collectors, +/// "AMDSMI_FI_TEMPERATURE_EDGE", +/// "Currnt edge temperature", +/// Unit::Celsius, +/// amdsmi_func!(amdsmi_get_temp_metric, AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeEdge, AmdsmiTemperatureMetricT::AmdsmiTempCurrent) +/// ); +/// # } +/// ``` +macro_rules! add_metric { + ($collectors:expr, $name:expr, $description:expr, $unit:expr, $func:expr) => { + let collector = AmdsmiGauge::new($name, $description, $unit, $func); + $collectors.add_metric(collector); + }; +} + +/// A macro to add a single metric from a struct to the collectors. +/// +/// This macro creates an `AmdsmiGauge` instance from a field of struct and adds it to the collectors. +/// +/// # Parameters +/// - `$collectors`: The collectors to add the metric to. +/// - `$name`: The name of the metric. +/// - `$description`: The description of the metric. +/// - `$unit`: The unit of the metric. +/// - `$func`: The function to collect the metric. +/// - `$field`: The struct field from which the metric is collected. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # use amdsmi_collectors::*; +/// +/// # fn main() { +/// let mut collectors = AmdsmiCollectors::default(); +/// add_metric_field!( +/// collectors, +/// "AMDSMI_FI_CURRENT_SOCKET_POWER", +/// "Current Socket Power", +/// Unit::Watts, +/// amdsmi_get_power_info, +/// current_socket_power +/// ); +/// # } +/// ``` +#[allow(unused_macros)] +macro_rules! add_metric_field { + ($collectors:expr, $name:expr, $description:expr, $unit:expr, $func:expr, $field:ident) => { + let collector = AmdsmiGauge::new($name, $description, $unit, |handle| { + $func(handle).map(|info| info.$field.into()) + }); + $collectors.add_metric(collector); + }; +} +/// A macro to add a group of metrics within a single struct. +/// +/// This macro creates an `AmdsmiGaugeGroup` instance and adds it to the collectors. +/// +/// # Parameters +/// - `$collectors`: The collectors to add the metric group to. +/// - `$group_name`: The name of the metric group. +/// - `$func`: The function to collect the metrics. +/// - `$t`: The type of the struct containing the metrics. +/// - `$name`: The name of each metric. +/// - `$description`: The description of each metric. +/// - `$unit`: The unit of each metric. +/// - `$field`: The struct field from which each metric is collected. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # use amdsmi_collectors::*; +/// +/// # fn main() { +/// let mut collectors = AmdsmiCollectors::default(); +/// add_metric_group!( +/// collectors, +/// "AmdsmiPowerInfoMetrics", +/// amdsmi_get_power_info, +/// AmdsmiPowerInfoT, +/// ("AMDSMI_FI_CURRENT_SOCKET_POWER", "Current Socket Power", Unit::Watts, current_socket_power), +/// ("AMDSMI_FI_AVERAGE_SOCKET_POWER", "Average Socket Power", Unit::Watts, average_socket_power), +/// ("AMDSMI_FI_GFX_VOLTAGE", "GFX Voltage", Unit::Volts, gfx_voltage), +/// ("AMDSMI_FI_SOC_VOLTAGE", "SOC Voltage", Unit::Volts, soc_voltage), +/// ("AMDSMI_FI_MEM_VOLTAGE", "Memory Voltage", Unit::Volts, mem_voltage), +/// ("AMDSMI_FI_POWER_LIMIT", "Power Limit", Unit::Watts, power_limit) +/// ); +/// # } +/// ``` +#[allow(unused_macros)] +macro_rules! add_metric_group { + ($collectors:expr, $group_name:expr, $func:expr, $t:ty, $(($name:expr, $description:expr, $unit:expr, $field:ident)),+ $(,)?) => { + let info_list = vec![ + $( + ( + $name, + $description, + $unit, + Arc::new(|info: &$t| info.$field as i64) as Arc i64 + Send + Sync>, + ), + )+ + ]; + let mut collector = AmdsmiGaugeGroup::new($group_name, info_list, $func); + $collectors.add_metric_group(&mut collector); + }; +} +/// A macro to create a closure for an AMD SMI function with dynamic arguments. +/// +/// This macro generates a closure that calls the specified function with the provided arguments. +/// +/// # Parameters +/// - `$func`: The function to create the closure for. +/// - `$arg`: The arguments to pass to the function. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # use amdsmi_collectors::*; +/// +/// # fn main() { +/// let func = amdsmi_func!(amdsmi_get_temp_metric, AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeEdge, AmdsmiTemperatureMetricT::AmdsmiTempCurrent); +/// # } +/// `` +#[allow(unused_macros)] +macro_rules! amdsmi_func { + ($func:expr, $($arg:expr),*) => { + move |handle| $func(handle, $($arg),*) + }; +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_metric.rs b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_metric.rs new file mode 100644 index 0000000000..ef78a184aa --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/amdsmi_metric.rs @@ -0,0 +1,138 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use amdsmi::{AmdsmiProcessorHandle, AmdsmiResult, AmdsmiStatusT}; +use prometheus_client::encoding::EncodeLabelSet; +use prometheus_client::registry::Unit; +use std::fmt::Debug; +use std::sync::Arc; + +#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] +pub struct AmdsmiLabels { + pub socket_id: String, + pub processor_id: String, + pub bdf: String, +} +#[derive(Clone)] +pub struct AmdsmiInfo { + pub name: &'static str, + pub description: &'static str, + pub unit: Unit, +} +#[derive(Clone)] +pub struct AmdsmiMetric { + pub info: AmdsmiInfo, + pub value: i64, + pub status: AmdsmiStatusT, +} + +pub type AmdsmiCollector = Box Vec + Send + Sync>; + +pub struct AmdsmiGauge +where + F: Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync, +{ + pub info: AmdsmiInfo, + pub func: F, +} + +impl AmdsmiGauge +where + F: Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync, +{ + pub fn new(name: &'static str, description: &'static str, unit: Unit, func: F) -> Self { + Self { + info: AmdsmiInfo { + name, + description, + unit, + }, + func, + } + } +} + +pub struct AmdsmiGaugeGroup +where + F: Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync + Clone, +{ + pub name: &'static str, /* name of the group */ + pub info_list: Vec<( + AmdsmiInfo, + Arc i64 + Send + Sync>, /* field accessor */ + )>, + pub func: F, +} + +impl AmdsmiGaugeGroup +where + F: Fn(AmdsmiProcessorHandle) -> AmdsmiResult + Send + Sync + Clone, +{ + pub fn new( + name: &'static str, /* name of the group */ + info_list: Vec<( + &'static str, /* name */ + &'static str, /* description */ + Unit, /* unit */ + Arc i64 + Send + Sync>, /* field accessor */ + )>, + func: F, + ) -> Self { + Self { + name, + info_list: info_list + .into_iter() + .map(|(name, description, unit, accessor)| { + ( + AmdsmiInfo { + name, + description, + unit, + }, + accessor, + ) + }) + .collect(), + func, + } + } +} + +/// A macro to define a unit as `Unit::Other`. +/// +/// This macro takes a unit string as an argument and generates the appropriate `Unit` value. +/// +/// # Parameters +/// - `$unit_str`: The unit string to define the unit. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # use amdsmi_metric::*; +/// +/// let unit = metric_unit_other!("W"); +/// assert_eq!(unit, Unit::Other("W".to_string())); +/// ``` +macro_rules! metric_unit_other { + ($unit_str:expr) => { + Unit::Other($unit_str.to_string()) + }; +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/collectors.rs b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/collectors.rs new file mode 100644 index 0000000000..b5b0eefc64 --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/collectors.rs @@ -0,0 +1,191 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use crate::amdsmi_collectors::AmdsmiCollectors; +use crate::amdsmi_metric::*; +use amdsmi::*; +use prometheus_client::registry::Unit; +use std::sync::Arc; +pub fn collectors_create(collectors: &mut AmdsmiCollectors) { + add_metric_group!( + collectors, + "AmdsmiEngineUsageMetrics", + amdsmi_get_gpu_activity, + AmdsmiEngineUsageT, + ( + "AMDSMI_FI_GFX_ACTIVITY", + "GFX Activity", + Unit::Ratios, + gfx_activity + ), + ( + "AMDSMI_FI_UMC_ACTIVITY", + "UMC Activity", + Unit::Ratios, + umc_activity + ), + ( + "AMDSMI_FI_MM_ACTIVITY", + "MM Activity", + Unit::Ratios, + mm_activity + ) + ); + + add_metric_group!( + collectors, + "AmdsmiPowerInfoMetrics", + amdsmi_get_power_info, + AmdsmiPowerInfoT, + ( + "AMDSMI_FI_CURRENT_SOCKET_POWER", + "Current Socket Power", + metric_unit_other!("W"), + current_socket_power + ), + ( + "AMDSMI_FI_AVERAGE_SOCKET_POWER", + "Average Socket Power", + metric_unit_other!("W"), + average_socket_power + ), + ( + "AMDSMI_FI_GFX_VOLTAGE", + "GFX Voltage", + metric_unit_other!("mV"), + gfx_voltage + ), + ( + "AMDSMI_FI_SOC_VOLTAGE", + "SOC Voltage", + metric_unit_other!("mV"), + soc_voltage + ), + ( + "AMDSMI_FI_MEM_VOLTAGE", + "Memory Voltage", + metric_unit_other!("mV"), + mem_voltage + ), + ); + + add_metric_group!( + collectors, + "AmdsmiGfxClockMetrics", + amdsmi_func!(amdsmi_get_clock_info, AmdsmiClkTypeT::AmdsmiClkTypeGfx), + AmdsmiClkInfoT, + ( + "AMDSMI_FI_GFX_CLK", + "GFX Clock", + metric_unit_other!("MHz"), + clk + ), + ( + "AMDSMI_FI_GFX_MIN_CLK", + "GFX Min Clock", + metric_unit_other!("MHz"), + min_clk + ), + ( + "AMDSMI_FI_GFX_MAX_CLK", + "GFX Max Clock", + metric_unit_other!("MHz"), + max_clk + ) + ); + + add_metric_group!( + collectors, + "AmdsmiVRAMUsageMetrics", + amdsmi_get_gpu_vram_usage, + AmdsmiVramUsageT, + ( + "AMDSMI_FI_VRAM_TOTAL", + "VRAM total", + metric_unit_other!("MB"), + vram_total + ), + ( + "AMDSMI_FI_VRAM_USED", + "VRAM used", + metric_unit_other!("MB"), + vram_used + ), + ); + + add_metric_group!( + collectors, + "AmdsmiMemClockMetrics", + amdsmi_func!(amdsmi_get_clock_info, AmdsmiClkTypeT::AmdsmiClkTypeMem), + AmdsmiClkInfoT, + ( + "AMDSMI_FI_MEM_CLK", + "Memory Clock", + metric_unit_other!("MHz"), + clk + ), + ( + "AMDSMI_FI_MEM_MIN_CLK", + "Memory Min Clock", + metric_unit_other!("MHz"), + min_clk + ), + ( + "AMDSMI_FI_MEM_MAX_CLK", + "Memory Max Clock", + metric_unit_other!("MHz"), + max_clk + ) + ); + + add_metric!( + collectors, + "AMDSMI_FI_TEMPERATURE_EDGE", + "Current edge temperature", + Unit::Celsius, + amdsmi_func!( + amdsmi_get_temp_metric, + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeEdge, + AmdsmiTemperatureMetricT::AmdsmiTempCurrent + ) + ); + add_metric!( + collectors, + "AMDSMI_FI_TEMPERATURE_HOTSPOT", + "Current Hotspot temperature", + Unit::Celsius, + amdsmi_func!( + amdsmi_get_temp_metric, + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeHotspot, + AmdsmiTemperatureMetricT::AmdsmiTempCurrent + ) + ); + add_metric!( + collectors, + "AMDSMI_FI_TEMPERATURE_MEM", + "Current VRAM temperature", + Unit::Celsius, + amdsmi_func!( + amdsmi_get_temp_metric, + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeVram, + AmdsmiTemperatureMetricT::AmdsmiTempCurrent + ) + ); +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/http_server.rs b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/http_server.rs new file mode 100644 index 0000000000..301060f180 --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/http_server.rs @@ -0,0 +1,63 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use crate::amdsmi_collectors::AmdsmiCollectors; +use axum::response::{IntoResponse, Response}; +use axum::{routing::get, Router}; +use hyper::Server; +use prometheus_client::encoding::text::encode; +use prometheus_client::registry::Registry; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::sync::Mutex; + +async fn serve_req(registry: Arc>) -> impl IntoResponse { + let mut buffer = String::new(); + let registry = registry.lock().await; + encode(&mut buffer, &*registry).unwrap(); + Response::builder() + .header("Content-Type", "text/plain; version=0.0.4") + .body(buffer) + .unwrap() +} + +pub async fn run_http_server(collectors: &Arc>, addr: SocketAddr) { + let app = Router::new().route( + "/metrics", + get({ + let collectors = Arc::clone(&collectors); + move || { + let collectors = Arc::clone(&collectors); + async move { + let mut collectors = collectors.lock().await; + let registry = Arc::new(Mutex::new(collectors.run_collect())); + serve_req(registry).await + } + } + }), + ); + + println!("Listening on http://{}", addr); + + Server::bind(&addr) + .serve(app.into_make_service()) + .await + .unwrap(); +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/main.rs b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/main.rs new file mode 100644 index 0000000000..5a2849d788 --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/main.rs @@ -0,0 +1,133 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#[macro_use] +mod amdsmi_collectors; +#[macro_use] +mod amdsmi_metric; +mod collectors; +mod http_server; + +use crate::amdsmi_collectors::*; +use clap::{App, Arg, SubCommand}; +use http_server::run_http_server; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::sync::Mutex; + +const APP_VERSION_STR: &str = "1.0"; + +#[tokio::main] +async fn main() { + // Parse command line arguments + let cli_matches = App::new("AMDSMI Exporter") + .version(APP_VERSION_STR) + .author("AMD ") + .about("Exports AMD SMI metrics") + .subcommand( + SubCommand::with_name("list") + .about("Lists the supported GPUs and metrics' information") + ) + .subcommand( + SubCommand::with_name("metric") + .about("Exports AMD SMI metrics and runs the HTTP server") + .arg( + Arg::new("port") + .short('p') + .long("port") + .value_name("PORT") + .help("Sets the port to listen on") + .takes_value(true), + ) + .arg( + Arg::new("gpu") + .short('g') + .long("gpu") + .value_name("GPU") + .help("Sets the GPU BDF or the zero-based index of the socket ID and processor ID for export. Example: --gpu 0000:03:00.0 or --gpu 0.0. You can specify multiple GPUs separated by commas") + .takes_value(true) + ) + .arg( + Arg::new("whitelist") + .short('w') + .long("whitelist") + .value_name("METRIC") + .help("Comma-separated list of metric field names to include") + .takes_value(true), + ) + .arg( + Arg::new("blacklist") + .short('b') + .long("blacklist") + .value_name("METRIC") + .help("Comma-separated list of metric field names to exclude") + .takes_value(true), + ) + ) + .get_matches(); + + let collectors = Arc::new(Mutex::new(AmdsmiCollectors::default())); + + match cli_matches.subcommand() { + Some(("list", _)) => { + collectors.lock().await.print_supported(); + } + Some(("metric", arg_options)) => { + export_metrics(arg_options, &collectors).await; + } + _ => { + eprintln!("Invalid command. Please use 'list' to list supported GPUs and metrics, or 'metric' to export metrics and run the HTTP server. Use --help for more information."); + } + } +} + +async fn export_metrics(arg_options: &clap::ArgMatches, collectors: &Arc>) { + let port: u16 = arg_options + .get_one::("port") + .unwrap_or(&"9898".to_string()) + .parse::() + .unwrap_or_else(|_| { + eprintln!("Invalid port number provided. Using default port 9898."); + 9898 + }); + + let gpu_filters: Option> = arg_options + .get_one::("gpu") + .map(|s| s.split(',').map(|s| s.trim().to_string()).collect()); + + let whitelist: Option> = arg_options + .get_one::("whitelist") + .map(|s| s.split(',').map(|s| s.trim().to_string()).collect()); + + let blacklist: Option> = arg_options + .get_one::("blacklist") + .map(|s| s.split(',').map(|s| s.trim().to_string()).collect()); + + collectors + .lock() + .await + .set_gpu_filter(gpu_filters) + .set_field_filter(whitelist, blacklist); + + let addr = SocketAddr::from(([0, 0, 0, 0], port)); + + // Run the HTTP server + run_http_server(&collectors, addr).await; +} diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_exporter/prometheus.yml b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/prometheus.yml new file mode 100644 index 0000000000..76f9417f2f --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_exporter/prometheus.yml @@ -0,0 +1,7 @@ + global: + scrape_interval: 15s + + scrape_configs: + - job_name: 'amdsmi_exporter' + static_configs: + - targets: ['localhost:9898'] \ No newline at end of file diff --git a/projects/amdsmi/rust-interface/examples/amdsmi_get_gpu_info.rs b/projects/amdsmi/rust-interface/examples/amdsmi_get_gpu_info.rs new file mode 100644 index 0000000000..9a8cf9552c --- /dev/null +++ b/projects/amdsmi/rust-interface/examples/amdsmi_get_gpu_info.rs @@ -0,0 +1,110 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use amdsmi::*; + +fn main() { + // Initialize the AMD SMI library + if let Err(e) = amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus) { + eprintln!("Failed to initialize AMD SMI: {}", e); + return; + } + + // Get socket handles + let socket_handles = match amdsmi_get_socket_handles() { + Ok(handles) => handles, + Err(e) => { + eprintln!("Failed to get socket handles: {}", e); + amdsmi_shut_down().expect("Failed to shutdown AMD SMI"); + return; + } + }; + + for socket_handle in socket_handles { + // Get processor handles for each socket handle + let processor_handles = match amdsmi_get_processor_handles(socket_handle) { + Ok(handles) => handles, + Err(e) => { + eprintln!( + "Failed to get processor handles for socket {:?}: {}", + socket_handle, e + ); + continue; + } + }; + + for processor_handle in processor_handles { + // Get GPU ID using the processor handle + match amdsmi_get_gpu_id(processor_handle) { + Ok(gpu_id) => println!("GPU ID: {}", gpu_id), + Err(e) => eprintln!("Failed to get GPU ID: {}", e), + } + + // Get GPU revision using the processor handle + match amdsmi_get_gpu_revision(processor_handle) { + Ok(gpu_revision) => println!("GPU Revision: {}", gpu_revision), + Err(e) => eprintln!("Failed to get GPU revision: {}", e), + } + + // Get GPU vendor name using the processor handle + match amdsmi_get_gpu_vendor_name(processor_handle) { + Ok(gpu_vendor_name) => println!("GPU Vendor Name: {}", gpu_vendor_name), + Err(e) => eprintln!("Failed to get GPU vendor name: {}", e), + } + + // Get GPU VRAM vendor using the processor handle + match amdsmi_get_gpu_vram_vendor(processor_handle) { + Ok(gpu_vram_vendor) => println!("GPU VRAM Vendor: {}", gpu_vram_vendor), + Err(e) => eprintln!("Failed to get GPU VRAM vendor: {}", e), + } + + // Get GPU subsystem ID using the processor handle + match amdsmi_get_gpu_subsystem_id(processor_handle) { + Ok(gpu_subsystem_id) => println!("GPU Subsystem ID: {}", gpu_subsystem_id), + Err(e) => eprintln!("Failed to get GPU subsystem ID: {}", e), + } + + // Get GPU subsystem name using the processor handle + match amdsmi_get_gpu_subsystem_name(processor_handle) { + Ok(gpu_subsystem_name) => println!("GPU Subsystem Name: {}", gpu_subsystem_name), + Err(e) => eprintln!("Failed to get GPU subsystem name: {}", e), + } + + // Get GPU BDF using the processor handle + match amdsmi_get_gpu_device_bdf(processor_handle) { + Ok(gpu_bdf) => println!("GPU BDF: {}", gpu_bdf), + Err(e) => eprintln!("Failed to get GPU BDF: {}", e), + } + + // Get GPU BDF ID using the processor handle + match amdsmi_get_gpu_bdf_id(processor_handle) { + Ok(gpu_bdf_id) => println!("GPU BDF ID: {}", gpu_bdf_id), + Err(e) => eprintln!("Failed to get GPU BDF ID: {}", e), + } + + println!(); + } + } + + // Shutdown the AMD SMI library + if let Err(e) = amdsmi_shut_down() { + eprintln!("Failed to shutdown AMD SMI: {}", e); + } +} diff --git a/projects/amdsmi/rust-interface/src/amdsmi.rs b/projects/amdsmi/rust-interface/src/amdsmi.rs new file mode 100644 index 0000000000..7f88844478 --- /dev/null +++ b/projects/amdsmi/rust-interface/src/amdsmi.rs @@ -0,0 +1,6324 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +use crate::amdsmi_wrapper; +use crate::utils::*; +use std::mem::MaybeUninit; +use std::os::raw::c_void; +use std::ptr::null_mut; + +/// Initializes the AMD SMI library. +/// +/// This function must be called before any other AMD SMI functions are used. +/// It initializes the library with the specified flags. +/// +/// # Arguments +/// +/// * `init_flags` - Use a [`ProcessorTypeT`] for initialization flags. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if the initialization is successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// match amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus) { +/// Ok(_) => println!("AMD SMI initialized successfully"), +/// Err(e) => panic!("Failed to initialize AMD SMI: {}", e), +/// } +/// //Perform various tasks by invoking additional AMD SMI functions +/// //... +/// +/// // Shut down the AMD SMI library +/// amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_init` call fails. +pub fn amdsmi_init(init_flags: AmdsmiInitFlagsT) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_init(init_flags as u64)); + Ok(()) +} + +/// Shuts down the AMD SMI library. +/// +/// This function should be called when the AMD SMI library is no longer needed. +/// It performs any necessary cleanup and releases resources allocated by the library. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if the shutdown is successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// // Initialize the AMD SMI library +/// amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// +/// // Perform operations with the AMD SMI library +/// // ... +/// # +/// # // Shut down the AMD SMI library +/// match amdsmi_shut_down() { +/// Ok(_) => println!("AMD SMI shut down successfully"), +/// Err(e) => panic!("Failed to shut down AMD SMI: {}", e), +/// } +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_shut_down` call fails. +pub fn amdsmi_shut_down() -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_shut_down()); + Ok(()) +} + +/// Retrieves the socket handles for the AMD SMI library. +/// +/// This function returns a list of socket handles available in the system. +/// Each handle can be used to query further information about the corresponding socket. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing the list of [`AmdsmiSocketHandle`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Retrieve the socket handles +/// match amdsmi_get_socket_handles() { +/// Ok(handles) => { +/// for handle in handles { +/// // Perform operations with the AMD SMI library +/// // ... +/// } +/// } +/// Err(e) => panic!("Failed to get socket handles: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_socket_handles` call fails. +pub fn amdsmi_get_socket_handles() -> AmdsmiResult> { + let mut socket_count: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_socket_handles( + &mut socket_count, + std::ptr::null_mut() + )); + + let mut socket_handles = Vec::with_capacity(socket_count as usize); + call_unsafe!(amdsmi_wrapper::amdsmi_get_socket_handles( + &mut socket_count, + socket_handles.as_mut_ptr() + )); + + unsafe { socket_handles.set_len(socket_count as usize) }; + Ok(socket_handles) +} + +/// Retrieves information about a specific socket. +/// +/// This function returns a string containing information about the specified socket handle. +/// +/// # Arguments +/// +/// * `socket_handle` - A handle to the socket for which information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the socket information if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example socket handle, Get socket handle from amdsmi_get_socket_handles() function +/// let socket_handle = amdsmi_get_socket_handles().unwrap()[0]; +/// +/// // Retrieve the socket information +/// match amdsmi_get_socket_info(socket_handle) { +/// Ok(info) => println!("Socket info: {}", info), +/// Err(e) => panic!("Failed to get socket info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_socket_info` call fails. +pub fn amdsmi_get_socket_info(socket_handle: AmdsmiSocketHandle) -> AmdsmiResult { + let (mut info, len) = define_cstr!(amdsmi_wrapper::AMDSMI_256_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_socket_info( + socket_handle, + len, + info.as_mut_ptr(), + )); + Ok(cstr_to_string!(info)) +} + +/// Retrieves the processor handles for a given socket. +/// +/// This function returns a list of processor handles associated with the specified socket handle. +/// Each handle can be used to query further information about the corresponding processor. +/// +/// # Arguments +/// +/// * `socket_handle` - A handle to the socket for which processor handles are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing the list of [`AmdsmiProcessorHandle`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example socket handle, can get from amdsmi_get_socket_handles() function +/// let socket_handle = amdsmi_get_socket_handles().unwrap()[0]; +/// +/// // Retrieve the processor handles +/// match amdsmi_get_processor_handles(socket_handle) { +/// Ok(handles) => { +/// for handle in handles { +/// // Perform operations with the AMD SMI library +/// // ... +/// } +/// } +/// Err(e) => panic!("Failed to get processor handles: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_processor_handles` call fails. +pub fn amdsmi_get_processor_handles( + socket_handle: AmdsmiSocketHandle, +) -> AmdsmiResult> { + let mut processor_count: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_processor_handles( + socket_handle, + &mut processor_count, + std::ptr::null_mut() + )); + + let mut processor_handles = Vec::with_capacity(processor_count as usize); + call_unsafe!(amdsmi_wrapper::amdsmi_get_processor_handles( + socket_handle, + &mut processor_count, + processor_handles.as_mut_ptr() + )); + + unsafe { + processor_handles.set_len(processor_count as usize); + } + Ok(processor_handles) +} + +/// Retrieves the type of a specific processor. +/// +/// This function returns the processor type of the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the type is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(ProcessorTypeT)` containing the [`ProcessorTypeT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the processor type +/// match amdsmi_get_processor_type(processor_handle) { +/// Ok(processor_type) => println!("Processor type: {:?}", processor_type), +/// Err(e) => panic!("Failed to get processor type: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_processor_type` call fails. +pub fn amdsmi_get_processor_type( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut processor_type = ProcessorTypeT::AmdsmiProcessorTypeUnknown; + call_unsafe!(amdsmi_wrapper::amdsmi_get_processor_type( + processor_handle, + &mut processor_type + )); + Ok(processor_type) +} + +///Retrieves the processor handle for a given Bus-Device-Function (BDF) address. +/// +/// This function returns a handle to the processor associated with the specified BDF address. +/// The BDF address is a unique identifier for a device on the PCI bus. +/// +/// # Arguments +/// +/// * `bdf` - A [`AmdsmiBdfT`] representing the Bus-Device-Function (BDF) address. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiProcessorHandle)` containing the [`AmdsmiProcessorHandle`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Get a processor_handle from the amdsmi_get_processor_handles() function +/// let processor_handle_example = amdsmi_get_processor_handles!()[0]; +/// // Example BDF +/// let bdf = amdsmi_get_gpu_device_bdf(processor_handle_example).expect("Failed to get BDF"); +/// +/// // Retrieve the processor handle +/// let processor_handle = amdsmi_get_processor_handle_from_bdf(bdf).expect("Failed to get processor handle"); +/// +/// assert_eq!(processor_handle, processor_handle_example); +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_processor_handle_from_bdf` call fails. +pub fn amdsmi_get_processor_handle_from_bdf( + bdf: AmdsmiBdfT, +) -> AmdsmiResult { + let mut processor_handle = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_processor_handle_from_bdf( + bdf, + processor_handle.as_mut_ptr() + )); + Ok(unsafe { processor_handle.assume_init() }) +} + +/// Retrieves the GPU ID for a given processor handle. +/// +/// This function returns the GPU ID associated with the specified processor handle. +/// The GPU ID is a unique identifier for the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU ID is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU ID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU ID +/// match amdsmi_get_gpu_id(processor_handle) { +/// Ok(gpu_id) => println!("GPU ID: {}", gpu_id), +/// Err(e) => panic!("Failed to get GPU ID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_id` call fails. +pub fn amdsmi_get_gpu_id(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut id: u16 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_id(processor_handle, &mut id)); + Ok(id) +} + +/// Retrieves the GPU revision for a given processor handle. +/// +/// This function returns the GPU revision associated with the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU revision is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU revision if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU revision +/// match amdsmi_get_gpu_revision(processor_handle) { +/// Ok(gpu_revision) => println!("GPU Revision: {}", gpu_revision), +/// Err(e) => panic!("Failed to get GPU revision: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_revision` call fails. +pub fn amdsmi_get_gpu_revision(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut revision: u16 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_revision( + processor_handle, + &mut revision + )); + Ok(revision) +} + +/// Retrieves the GPU vendor name for a given processor handle. +/// +/// This function returns the GPU vendor name associated with the specified processor handle. +/// The vendor name provides information about the manufacturer of the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU vendor name is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the GPU vendor name if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU vendor name +/// match amdsmi_get_gpu_vendor_name(processor_handle) { +/// Ok(vendor_name) => println!("GPU Vendor Name: {}", vendor_name), +/// Err(e) => panic!("Failed to get GPU vendor name: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_vendor_name` call fails. +pub fn amdsmi_get_gpu_vendor_name(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let (mut name, len) = define_cstr!(amdsmi_wrapper::AMDSMI_MAX_STRING_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_vendor_name( + processor_handle, + name.as_mut_ptr(), + len + )); + Ok(cstr_to_string!(name)) +} + +/// Retrieves the GPU VRAM vendor name for a given processor handle. +/// +/// This function returns the GPU VRAM vendor name associated with the specified processor handle. +/// The VRAM vendor name provides information about the manufacturer of the GPU's VRAM. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU VRAM vendor name is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the GPU VRAM vendor name if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU VRAM vendor name +/// match amdsmi_get_gpu_vram_vendor(processor_handle) { +/// Ok(vram_vendor_name) => println!("GPU VRAM Vendor Name: {}", vram_vendor_name), +/// Err(e) => panic!("Failed to get GPU VRAM vendor name: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_vram_vendor` call fails. +pub fn amdsmi_get_gpu_vram_vendor(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let (mut brand, len) = define_cstr!(amdsmi_wrapper::AMDSMI_MAX_STRING_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_vram_vendor( + processor_handle, + brand.as_mut_ptr(), + len as u32, + )); + Ok(cstr_to_string!(brand)) +} + +/// Retrieves the GPU subsystem ID for a given processor handle. +/// +/// This function returns the GPU subsystem ID associated with the specified processor handle. +/// The subsystem ID provides information about the specific subsystem of the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU subsystem ID is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU subsystem ID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU subsystem ID +/// match amdsmi_get_gpu_subsystem_id(processor_handle) { +/// Ok(subsystem_id) => println!("GPU Subsystem ID: {}", subsystem_id), +/// Err(e) => panic!("Failed to get GPU subsystem ID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_subsystem_id` call fails. +pub fn amdsmi_get_gpu_subsystem_id(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut id: u16 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_subsystem_id( + processor_handle, + &mut id + )); + Ok(id) +} + +/// Retrieves the GPU subsystem name for a given processor handle. +/// +/// This function returns the GPU subsystem name associated with the specified processor handle. +/// The subsystem name provides information about the specific subsystem of the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU subsystem name is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the GPU subsystem name if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU subsystem name +/// match amdsmi_get_gpu_subsystem_name(processor_handle) { +/// Ok(subsystem_name) => println!("GPU Subsystem Name: {}", subsystem_name), +/// Err(e) => panic!("Failed to get GPU subsystem name: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_subsystem_name` call fails. +pub fn amdsmi_get_gpu_subsystem_name( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let (mut name, len) = define_cstr!(amdsmi_wrapper::AMDSMI_MAX_STRING_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_subsystem_name( + processor_handle, + name.as_mut_ptr(), + len + )); + Ok(cstr_to_string!(name)) +} + +/// Retrieves the PCI bandwidth for a given GPU processor handle. +/// +/// This function returns the PCI bandwidth associated with the specified processor handle. +/// The PCI bandwidth provides information about the data transfer rate of the GPU over the PCI bus. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the PCI bandwidth is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the PCI bandwidth if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the PCI bandwidth +/// match amdsmi_get_gpu_pci_bandwidth(processor_handle) { +/// Ok(pci_bandwidth) => println!("PCI Bandwidth: {:?}", pci_bandwidth), +/// Err(e) => panic!("Failed to get PCI bandwidth: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_pci_bandwidth` call fails. +pub fn amdsmi_get_gpu_pci_bandwidth( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut bandwidth = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_pci_bandwidth( + processor_handle, + bandwidth.as_mut_ptr() + )); + let bandwidth = unsafe { bandwidth.assume_init() }; + Ok(bandwidth) +} + +/// Retrieves the Bus-Device-Function (BDF) ID for a given GPU processor handle. +/// +/// This function returns the BDF ID associated with the specified processor handle. +/// The BDF ID is a unique identifier for a device on the PCI bus, which includes the bus number, device number, and function number. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the BDF ID is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the BDF ID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the BDF ID +/// match amdsmi_get_gpu_bdf_id(processor_handle) { +/// Ok(bdf_id) => println!("BDF ID: {:#010x}", bdf_id), +/// Err(e) => panic!("Failed to get BDF ID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_bdf_id` call fails. +pub fn amdsmi_get_gpu_bdf_id(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut bdfid: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_bdf_id( + processor_handle, + &mut bdfid + )); + Ok(bdfid) +} + +/// Retrieves the NUMA (Non-Uniform Memory Access) node for a given GPU processor handle. +/// +/// This function returns the NUMA node associated with the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the NUMA node is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the NUMA node value if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the NUMA node +/// match amdsmi_get_gpu_topo_numa_affinity(processor_handle) { +/// Ok(numa_node) => println!("NUMA Node ID: {}", numa_node), +/// Err(e) => panic!("Failed to get NUMA affinity: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_topo_numa_affinity` call fails. +pub fn amdsmi_get_gpu_topo_numa_affinity( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut numa_node: i32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_topo_numa_affinity( + processor_handle, + &mut numa_node + )); + Ok(numa_node) +} + +/// Retrieves the PCI throughput for a given GPU processor handle. +/// +/// This function returns the PCI throughput associated with the specified processor handle. +/// The PCI throughput provides information about the data transfer rate of the GPU over the PCI bus. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the PCI throughput is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult<(u64, u64, u64)>` - Returns `Ok((u64, u64, u64))` containing the PCI throughput as below: +/// - The first value is the number of bytes sent will be written in 1 second. +/// - The second value is the number of bytes received will be written. +/// - The third value is the maximum packet size will be written. +/// If successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the PCI throughput +/// match amdsmi_get_gpu_pci_throughput(processor_handle) { +/// Ok((sent, received, max_pkt_sz)) => { +/// println!("PCI Throughput - Sent: {} B/s, Received: {} B/s, Max package size: {} B/s", sent, received, max_pkt_sz); +/// } +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_pci_throughput() not supported on this device"), +/// Err(e) => panic!("Failed to get PCI throughput: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_pci_throughput` call fails. +pub fn amdsmi_get_gpu_pci_throughput( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult<(u64, u64, u64)> { + let mut sent: u64 = 0; + let mut received: u64 = 0; + let mut max_pkt_sz: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_pci_throughput( + processor_handle, + &mut sent, + &mut received, + &mut max_pkt_sz + )); + Ok((sent, received, max_pkt_sz)) +} + +/// Retrieves the PCI replay counter for a given GPU processor handle. +/// +/// This function returns the PCI replay counter associated with the specified processor handle. +/// The PCI replay counter provides information about the sum of the NAK's received and generated by the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the PCI replay counter is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the PCI replay counter if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the PCI replay counter +/// match amdsmi_get_gpu_pci_replay_counter(processor_handle) { +/// Ok(counter) => println!("PCI Replay Counter: {}", counter), +/// Err(e) => panic!("Failed to get PCI replay counter: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_pci_replay_counter` call fails. +pub fn amdsmi_get_gpu_pci_replay_counter( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut counter: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_pci_replay_counter( + processor_handle, + &mut counter + )); + Ok(counter) +} + +/// Control the set of allowed PCIe bandwidths that can be used for a given GPU processor handle. +/// +/// This function Control the set of allowed PCIe bandwidths that can be used with the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the PCI bandwidth is being set. +/// * `bw_bitmask` - The allowed PCI bandwidth bitmask. A bitmask indicating the indices of the +/// bandwidths that are to be enabled (1) and disabled (0). Only the lowest AmdsmiFrequenciesT.num_supported bits of this mask are relevant. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if the PCI bandwidth is successfully set, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Set the PCI bandwidth +/// match amdsmi_set_gpu_pci_bandwidth(processor_handle, 0) { +/// Ok(_) => println!("PCI Bandwidth set successfully"), +/// Err(e) => panic!("Failed to set PCI bandwidth: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_pci_bandwidth` call fails. +pub fn amdsmi_set_gpu_pci_bandwidth( + processor_handle: AmdsmiProcessorHandle, + bw_bitmask: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_pci_bandwidth( + processor_handle, + bw_bitmask + )); + Ok(()) +} + +/// Retrieves the energy accumulator counter information for the specified processor handle. +/// +/// This function retrieves energy accumulator counter information for the specified processor handle, +/// returning the energy accumulator, counter resolution, and timestamp. +/// energy_accumulator * counter_resolution = total_energy_consumption in micro-Joules. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the energy count is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult<(u64, f32, u64)>` - Returns a tuple containing the energy accumulator, counter resolution, and timestamp if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the energy count +/// match amdsmi_get_energy_count(processor_handle) { +/// Ok((energy_accumulator, counter_resolution, timestamp)) => { +/// println!("Energy Accumulator: {}", energy_accumulator); +/// println!("Counter Resolution: {}", counter_resolution); +/// println!("Timestamp: {}", timestamp); +/// }, +/// Err(e) => panic!("Failed to get energy count: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_energy_count` call fails. +pub fn amdsmi_get_energy_count( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult<(u64, f32, u64)> { + let mut energy_accumulator: u64 = 0; + let mut counter_resolution: f32 = 0.0; + let mut timestamp: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_energy_count( + processor_handle, + &mut energy_accumulator, + &mut counter_resolution, + &mut timestamp + )); + Ok((energy_accumulator, counter_resolution, timestamp)) +} + +/// Sets the power cap for a given GPU processor handle. +/// +/// This function sets the power cap associated with the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the power cap is being set. +/// * `power_cap` - The desired power cap in milliwatts (mW). +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if the power cap is successfully set, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// let sensor_ind : u32 = 0; +/// +/// let cap_info = match amdsmi_get_power_cap_info(processor_handle, sensor_ind) { +/// Ok(info) => info, +/// Err(e) => panic!("Failed to get power cap information: {}", e), +/// }; +/// +/// let power_cap = (cap_info.min_power_cap + cap_info.max_power_cap) / 2; +/// +/// // Set the power cap +/// match amdsmi_set_power_cap(processor_handle, sensor_ind, power_cap) { +/// Ok(_) => println!("Power cap {} set successfully", power_cap), +/// Err(e) => panic!("Failed to set power cap: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_power_cap` call fails. +pub fn amdsmi_set_power_cap( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + cap: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_power_cap( + processor_handle, + sensor_ind, + cap + )); + Ok(()) +} + +/// Sets the power profile for a given GPU processor handle. +/// +/// This function sets the power profile associated with the specified processor handle. +/// The power profile determines the power consumption and performance characteristics of the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the power profile is being set. +/// * `profile` - A [`AmdsmiPowerProfilePresetMasksT`] type that hold the mask of the desired new power profile. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if the power profile is successfully set, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Set the power profile +/// match amdsmi_set_gpu_power_profile(processor_handle, AmdsmiPowerProfilePresetMasksT::AmdsmiPwrProfPrstCustomMask) { +/// Ok(_) => println!("Power profile set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_power_profile() not supported on this device"), +/// Err(e) => panic!("Failed to set power profile: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_power_profile` call fails. +pub fn amdsmi_set_gpu_power_profile( + processor_handle: AmdsmiProcessorHandle, + profile: AmdsmiPowerProfilePresetMasksT, +) -> AmdsmiResult<()> { + let reserved: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_power_profile( + processor_handle, + reserved, + profile + )); + Ok(()) +} + +/// Retrieves the total memory for a given GPU processor handle. +/// +/// This function returns the total memory associated with the specified processor handle. +/// The total memory provides information about the total amount of memory that exist. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the total memory is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the total memory in bytes if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the total memory +/// match amdsmi_get_gpu_memory_total(processor_handle, AmdsmiMemoryTypeT::AmdsmiMemTypeVram) { +/// Ok(total_memory) => println!("Total GPU Memory: {} bytes", total_memory), +/// Err(e) => panic!("Failed to get total GPU memory: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_memory_total` call fails. +pub fn amdsmi_get_gpu_memory_total( + processor_handle: AmdsmiProcessorHandle, + memory_type: AmdsmiMemoryTypeT, +) -> AmdsmiResult { + let mut memory_total: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_memory_total( + processor_handle, + memory_type, + &mut memory_total + )); + Ok(memory_total) +} + +/// Retrieves the memory usage for a given GPU processor handle. +/// +/// This function returns the memory usage associated with the specified processor handle. +/// The memory usage provides information about the amount of memory currently being used on the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the memory usage is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the memory usage in bytes if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the memory usage +/// match amdsmi_get_gpu_memory_usage(processor_handle, AmdsmiMemoryTypeT::AmdsmiMemTypeVram) { +/// Ok(memory_usage) => println!("GPU Memory Usage: {} bytes", memory_usage), +/// Err(e) => panic!("Failed to get GPU memory usage: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_memory_usage` call fails. +pub fn amdsmi_get_gpu_memory_usage( + processor_handle: AmdsmiProcessorHandle, + memory_type: AmdsmiMemoryTypeT, +) -> AmdsmiResult { + let mut memory_used: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_memory_usage( + processor_handle, + memory_type, + &mut memory_used + )); + Ok(memory_used) +} + +/// Retrieves the bad page information for a given GPU processor handle. +/// +/// This function returns the bad page information associated with the specified processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the bad page information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing a list of [`AmdsmiRetiredPageRecordT`] structs if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the bad page information +/// match amdsmi_get_gpu_bad_page_info(processor_handle) { +/// Ok(bad_page_info) => { +/// for page in bad_page_info { +/// println!("Bad Page: {:?}", page); +/// } +/// } +/// Err(e) => panic!("Failed to get bad page information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_bad_page_info` call fails. +pub fn amdsmi_get_gpu_bad_page_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult> { + // First call to get the number of bad pages + let mut num_pages: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_bad_page_info( + processor_handle, + &mut num_pages, + std::ptr::null_mut() + )); + + // Allocate a vector with the capacity of num_pages + let mut bad_pages: Vec = Vec::with_capacity(num_pages as usize); + + // Second call to get the bad page information + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_bad_page_info( + processor_handle, + &mut num_pages, + bad_pages.as_mut_ptr() + )); + + // Set the length of the vector to num_pages + unsafe { bad_pages.set_len(num_pages as usize) }; + + Ok(bad_pages) +} + +/// Retrieves the RAS (Reliability, Availability, and Serviceability) feature information for a given GPU handle. +/// +/// This function returns the RAS feature information for the specified GPU handle. The RAS feature +/// information includes the RAS version and schema information. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the RAS feature information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiRasFeatureT)` containing the [`AmdsmiRasFeatureT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the RAS feature information +/// match amdsmi_get_gpu_ras_feature_info(processor_handle) { +/// Ok(ras_info) => println!("GPU RAS Feature Info: {:?}", ras_info), +/// Err(e) => panic!("Failed to get GPU RAS Feature Info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_ras_feature_info` call fails. +pub fn amdsmi_get_gpu_ras_feature_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut ras_info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_ras_feature_info( + processor_handle, + ras_info.as_mut_ptr() + )); + let ras_info = unsafe { ras_info.assume_init() }; + Ok(ras_info) +} + +/// Retrieves the RAS (Reliability, Availability, and Serviceability) block status for a given GPU handle. +/// +/// This function returns if RAS features are enabled or disabled for given block. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the RAS block features are being queried. +/// * `block` - The specific GPU block for which the RAS features are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiRasErrStateT)` containing the [`AmdsmiRasErrStateT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example GPU block +/// let block = AmdsmiGpuBlockT::AmdsmiGpuBlockGfx; +/// +/// // Retrieve the enabled RAS block features +/// match amdsmi_get_gpu_ras_block_features_enabled(processor_handle, block) { +/// Ok(ras_features) => println!("Enabled RAS Block Features: {:?}", ras_features), +/// Err(e) => panic!("Failed to get enabled RAS block features: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_ras_block_features_enabled` call fails. +pub fn amdsmi_get_gpu_ras_block_features_enabled( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, +) -> AmdsmiResult { + let mut ras_features = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_ras_block_features_enabled( + processor_handle, + block, + ras_features.as_mut_ptr() + )); + let ras_features = unsafe { ras_features.assume_init() }; + Ok(ras_features) +} + +/// Retrieves the reserved memory pages information for a given GPU handle. +/// +/// This function returns the reserved memory pages information for the specified GPU handle. The reserved memory pages +/// include details about the memory pages that are reserved by the GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the reserved memory pages are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing the reserved memory pages if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the reserved memory pages +/// match amdsmi_get_gpu_memory_reserved_pages(processor_handle) { +/// Ok(pages) => println!("Reserved Memory Pages: {:?}", pages), +/// Err(e) => panic!("Failed to get reserved memory pages: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_memory_reserved_pages` call fails. +pub fn amdsmi_get_gpu_memory_reserved_pages( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult> { + let mut num_pages = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_memory_reserved_pages( + processor_handle, + &mut num_pages, + std::ptr::null_mut() + )); + + let mut pages = Vec::with_capacity(num_pages as usize); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_memory_reserved_pages( + processor_handle, + &mut num_pages, + pages.as_mut_ptr() + )); + + unsafe { + pages.set_len(num_pages as usize); + } + + Ok(pages) +} + +/// Retrieves the fan speed for a given GPU handle and sensor index. +/// +/// This function returns the fan speed for the specified GPU handle and sensor index. The fan speed +/// provides information as a value relative to AMDSMI_MAX_FAN_SPEED. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the fan speed is being queried. +/// * `sensor_index` - The index of the fan sensor to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(i64)` containing the fan speed relative to MAX if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_index = 0; +/// +/// // Retrieve the fan speed +/// match amdsmi_get_gpu_fan_speed(processor_handle, sensor_index) { +/// Ok(speed) => println!("GPU Fan Speed: {}", speed), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_fan_speed() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU fan speed: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_fan_speed` call fails. +pub fn amdsmi_get_gpu_fan_speed( + processor_handle: AmdsmiProcessorHandle, + sensor_index: u32, +) -> AmdsmiResult { + let mut speed = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_fan_speed( + processor_handle, + sensor_index, + &mut speed + )); + Ok(speed) +} + +/// Get the maximum fan speed of the device with the specified processor handle and sensor index. +/// +/// Given a processor handle `processor_handle` and a sensor index `sensor_ind`, this function returns +/// the maximum fan speed for the specified GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the maximum fan speed is being queried. +/// * `sensor_ind` - The index of the fan sensor to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the maximum fan speed if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_ind = 0; +/// +/// // Retrieve the maximum fan speed +/// match amdsmi_get_gpu_fan_speed_max(processor_handle, sensor_ind) { +/// Ok(speed) => println!("GPU Maximum Fan Speed: {}", speed), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_fan_speed_max() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU maximum fan speed: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_fan_speed_max` call fails. +pub fn amdsmi_get_gpu_fan_speed_max( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, +) -> AmdsmiResult { + let mut speed = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_fan_speed_max( + processor_handle, + sensor_ind, + &mut speed + )); + Ok(speed) +} + +/// Get the temperature metric of the device with the specified processor handle, sensor type, and metric. +/// +/// Given a processor handle `processor_handle`, a sensor type `sensor_type`, and a temperature metric `metric`, +/// this function returns the temperature metric for the specified GPU. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the temperature metric is being queried. +/// * `sensor_type` - The type of the temperature sensor [`AmdsmiTemperatureTypeT`] to query. +/// * `metric` - The temperature metric [`AmdsmiTemperatureMetricT`] to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(i64)` containing the temperature metric value if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor type and metric +/// let sensor_type = AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeEdge; +/// let metric = AmdsmiTemperatureMetricT::AmdsmiTempCurrent; +/// +/// // Retrieve the temperature metric +/// match amdsmi_get_temp_metric(processor_handle, sensor_type, metric) { +/// Ok(temp_metric) => println!("GPU Temperature Metric: {}", temp_metric), +/// Err(e) => panic!("Failed to get GPU temperature metric: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_temp_metric` call fails. +pub fn amdsmi_get_temp_metric( + processor_handle: AmdsmiProcessorHandle, + sensor_type: AmdsmiTemperatureTypeT, + metric: AmdsmiTemperatureMetricT, +) -> AmdsmiResult { + let mut temperature = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_temp_metric( + processor_handle, + sensor_type, + metric, + &mut temperature + )); + Ok(temperature) +} + +/// Get the GPU cache information of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU cache information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the cache information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiGpuCacheInfoT)` containing the [`AmdsmiGpuCacheInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU cache information +/// match amdsmi_get_gpu_cache_info(processor_handle) { +/// Ok(cache_info) => println!("GPU Cache Info: {:?}", cache_info), +/// Err(e) => panic!("Failed to get GPU cache info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_cache_info` call fails. +pub fn amdsmi_get_gpu_cache_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_cache_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the voltage metric of the device with the specified processor handle, sensor type, and metric. +/// +/// Given a processor handle `processor_handle`, a sensor type `sensor_type`, and a voltage metric type `metric`, +/// this function returns the voltage metric for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the voltage metric is being queried. +/// * `sensor_type` - The type of the voltage sensor [`AmdsmiVoltageTypeT`] to query. +/// * `metric` - The voltage metric [`amdsmi_get_gpu_volt_metric`] to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(i64)` containing the voltage metric if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor type and metric +/// let sensor_type = AmdsmiVoltageTypeT::AmdsmiVoltTypeVddgfx; +/// let metric = AmdsmiVoltageMetricT::AmdsmiVoltCurrent; +/// +/// // Retrieve the voltage metric +/// match amdsmi_get_gpu_volt_metric(processor_handle, sensor_type, metric) { +/// Ok(voltage_metric) => println!("GPU Voltage Metric: {}", voltage_metric), +/// Err(e) => panic!("Failed to get GPU voltage metric: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_volt_metric` call fails. +pub fn amdsmi_get_gpu_volt_metric( + processor_handle: AmdsmiProcessorHandle, + sensor_type: AmdsmiVoltageTypeT, + metric: AmdsmiVoltageMetricT, +) -> AmdsmiResult { + let mut voltage = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_volt_metric( + processor_handle, + sensor_type, + metric, + &mut voltage + )); + Ok(voltage) +} + +/// Reset the GPU fan of the device with the specified processor handle and sensor index. +/// +/// Given a processor handle `processor_handle` and a sensor index `sensor_ind`, this function resets the GPU fan +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU fan is being reset. +/// * `sensor_ind` - The 0-based sensor index of the fan sensor to reset. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_ind = 0; +/// +/// // Reset the GPU fan +/// match amdsmi_reset_gpu_fan(processor_handle, sensor_ind) { +/// Ok(()) => println!("GPU fan reset successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_reset_gpu_fan() not supported on this device"), +/// Err(e) => panic!("Failed to reset GPU fan: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_reset_gpu_fan` call fails. +pub fn amdsmi_reset_gpu_fan( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_reset_gpu_fan( + processor_handle, + sensor_ind + )); + Ok(()) +} + +/// Get the fan speed in RPM for the GPU device with the specified processor handle and sensor index. +/// +/// Given a processor handle `processor_handle` and a sensor index `sensor_ind`, this function retrieves the fan speed in RPM +/// for the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the fan speed is being queried. +/// * `sensor_ind` - The index of the sensor for which the fan speed is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(i64)` containing the fan speed in RPM if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_ind: u32 = 0; +/// +/// // Retrieve the fan speed in RPM +/// match amdsmi_get_gpu_fan_rpms(processor_handle, sensor_ind) { +/// Ok(speed) => println!("Fan speed: {} RPM", speed), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_fan_rpms() not supported on this device"), +/// Err(e) => panic!("Failed to get fan speed: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_fan_rpms` call fails. +pub fn amdsmi_get_gpu_fan_rpms( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, +) -> AmdsmiResult { + let mut speed: i64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_fan_rpms( + processor_handle, + sensor_ind, + &mut speed as *mut i64 + )); + Ok(speed) +} + +/// Set the GPU fan speed of the device with the specified processor handle, sensor index, and speed. +/// +/// Given a processor handle `processor_handle`, a sensor index `sensor_ind`, and a fan speed `speed`, +/// this function sets the GPU fan speed for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU fan speed is being set. +/// * `sensor_ind` - The index of the fan sensor to set the speed for. +/// * `speed` - The speed to set the fan to, in RPM. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index and speed +/// let sensor_ind = 0; +/// let speed = 1333; +/// +/// // Set the GPU fan speed +/// match amdsmi_set_gpu_fan_speed(processor_handle, sensor_ind, speed) { +/// Ok(()) => println!("GPU fan speed set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_fan_speed() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU fan speed: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_fan_speed` call fails. +pub fn amdsmi_set_gpu_fan_speed( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + speed: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_fan_speed( + processor_handle, + sensor_ind, + speed + )); + Ok(()) +} + +/// +/// Retrieves the utilization count for the specified processor handle and counter types. +/// +/// This function retrieves the utilization count for the specified processor handle and counter types, +/// returning a list of utilization counters and a timestamp. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the utilization count is being retrieved. +/// * `counter_types` - A list of counter types [`AmdsmiUtilizationCounterTypeT`] for which the utilization count is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult<(Vec, u64)>` - Returns a tuple containing a list of [`AmdsmiUtilizationCounterT`] and a timestamp if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Define the counter types +/// let counter_types = vec![ +/// AmdsmiUtilizationCounterTypeT::AmdsmiFineGrainGfxActivity, +/// AmdsmiUtilizationCounterTypeT::AmdsmiFineGrainMemActivity, +/// ]; +/// +/// // Get the utilization count +/// match amdsmi_get_utilization_count(processor_handle, counter_types) { +/// Ok((utilization_counters, timestamp)) => { +/// println!("Timestamp: {}", timestamp); +/// for counter in utilization_counters { +/// println!("Counter Type: {:?}, Value: {}", counter.type_, counter.value); +/// } +/// }, +/// Err(e) => panic!("Failed to get utilization count: {}", e), +/// } +/// +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_utilization_count` call fails. +pub fn amdsmi_get_utilization_count( + processor_handle: AmdsmiProcessorHandle, + counter_types: Vec, +) -> AmdsmiResult<(Vec, u64)> { + let count = counter_types.len() as u32; + let mut utilization_counters: Vec = + Vec::with_capacity(count as usize); + let mut timestamp = 0; + + // Initialize the utilization_counters with the appropriate types + for counter_type in counter_types { + let utilization_counter = AmdsmiUtilizationCounterT { + type_: counter_type, + value: 0, + fine_value: [0; 4], + fine_value_count: 0, + }; + utilization_counters.push(utilization_counter); + } + + call_unsafe!(amdsmi_wrapper::amdsmi_get_utilization_count( + processor_handle, + utilization_counters.as_mut_ptr(), + count, + &mut timestamp + )); + Ok((utilization_counters, timestamp)) +} + +/// Get the GPU performance level of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU performance level +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU performance level is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiDevPerfLevelT)` containing the [`AmdsmiDevPerfLevelT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU performance level +/// match amdsmi_get_gpu_perf_level(processor_handle) { +/// Ok(perf_level) => println!("GPU Performance Level: {:?}", perf_level), +/// Err(e) => panic!("Failed to get GPU performance level: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_perf_level` call fails. +pub fn amdsmi_get_gpu_perf_level( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut perf = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_perf_level( + processor_handle, + perf.as_mut_ptr() + )); + let perf = unsafe { perf.assume_init() }; + Ok(perf) +} + +/// Enter performance determinism mode with provided processor handle. +/// +/// Given a processor handle `processor_handle` and a clock value `clkvalue`, this function will enable the GPU performance +/// determinism mode which enforces a GFXCLK frequency SoftMax limit per GPU for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU performance determinism mode is being set. +/// * `clkvalue` - The clock value to set for the performance determinism mode. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock value +/// let clkvalue = 1000; +/// +/// // Set the GPU performance determinism mode +/// match amdsmi_set_gpu_perf_determinism_mode(processor_handle, clkvalue) { +/// Ok(()) => println!("GPU performance determinism mode set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_perf_determinism_mode() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU performance determinism mode: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_perf_determinism_mode` call fails. +pub fn amdsmi_set_gpu_perf_determinism_mode( + processor_handle: AmdsmiProcessorHandle, + clkvalue: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_perf_determinism_mode( + processor_handle, + clkvalue + )); + Ok(()) +} + +/// Get the GPU overdrive level of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU overdrive level +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive level is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU overdrive level if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU overdrive level +/// match amdsmi_get_gpu_overdrive_level(processor_handle) { +/// Ok(overdrive_level) => println!("GPU Overdrive Level: {}", overdrive_level), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_overdrive_level() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU overdrive level: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_overdrive_level` call fails. +pub fn amdsmi_get_gpu_overdrive_level( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut od = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_overdrive_level( + processor_handle, + &mut od + )); + Ok(od) +} + +/// Get the memory overdrive percent for the GPU device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the memory overdrive level +/// for the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the memory overdrive level is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the memory overdrive level if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the memory overdrive level +/// match amdsmi_get_gpu_mem_overdrive_level(processor_handle) { +/// Ok(overdrive_level) => println!("Memory overdrive level: {}", overdrive_level), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_mem_overdrive_level() not supported on this device"), +/// Err(e) => panic!("Failed to get memory overdrive level: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_mem_overdrive_level` call fails. +pub fn amdsmi_get_gpu_mem_overdrive_level( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut od: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_mem_overdrive_level( + processor_handle, + &mut od as *mut u32 + )); + Ok(od) +} + +/// Get the clock frequencies of the device with the specified processor handle and clock type. +/// +/// Given a processor handle `processor_handle` and a clock type `clk_type`, this function returns the clock frequencies +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the clock frequencies are being queried. +/// * `clk_type` - The type of the clock to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiFrequenciesT)` containing the [`AmdsmiFrequenciesT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock type +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeGfx; +/// +/// // Retrieve the clock frequencies +/// match amdsmi_get_clk_freq(processor_handle, clk_type) { +/// Ok(frequencies) => println!("Clock Frequencies: {:?}", frequencies), +/// Err(e) => panic!("Failed to get clock frequencies: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_clk_freq` call fails. +pub fn amdsmi_get_clk_freq( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, +) -> AmdsmiResult { + let mut frequencies = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_clk_freq( + processor_handle, + clk_type, + frequencies.as_mut_ptr() + )); + let frequencies = unsafe { frequencies.assume_init() }; + Ok(frequencies) +} + +/// Reset the GPU of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function resets the GPU +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU is being reset. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Reset the GPU +/// match amdsmi_reset_gpu(processor_handle) { +/// Ok(()) => println!("GPU reset successfully"), +/// Err(e) => panic!("Failed to reset GPU: {}", e), +/// } +/// // Wait for some time +/// std::thread::sleep(std::time::Duration::from_secs(5)); +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_reset_gpu` call fails. +pub fn amdsmi_reset_gpu(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_reset_gpu(processor_handle)); + Ok(()) +} + +/// Get the GPU overdrive voltage and frequency information of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU overdrive voltage and frequency information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive voltage and frequency information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiOdVoltFreqDataT)` containing the [`AmdsmiOdVoltFreqDataT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU overdrive voltage and frequency information +/// match amdsmi_get_gpu_od_volt_info(processor_handle) { +/// Ok(od_volt_info) => println!("GPU Overdrive Voltage and Frequency Info: {:?}", od_volt_info), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_od_volt_info() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU overdrive voltage and frequency info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_od_volt_info` call fails. +pub fn amdsmi_get_gpu_od_volt_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut odv = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_od_volt_info( + processor_handle, + odv.as_mut_ptr() + )); + let odv = unsafe { odv.assume_init() }; + Ok(odv) +} + +/// Get the GPU metrics header information of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU metrics header information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU metrics header information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdMetricsTableHeaderT)` containing the [`AmdMetricsTableHeaderT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU metrics header information +/// match amdsmi_get_gpu_metrics_header_info(processor_handle) { +/// Ok(header_info) => println!("GPU Metrics Header Info: {:?}", header_info), +/// Err(e) => panic!("Failed to get GPU metrics header info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_metrics_header_info` call fails. +pub fn amdsmi_get_gpu_metrics_header_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut header_value = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_metrics_header_info( + processor_handle, + header_value.as_mut_ptr() + )); + let header_value = unsafe { header_value.assume_init() }; + Ok(header_value) +} + +/// Get the GPU metrics information of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU metrics information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU metrics information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiGpuMetricsT)` containing the [`AmdsmiGpuMetricsT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU metrics information +/// match amdsmi_get_gpu_metrics_info(processor_handle) { +/// Ok(gpu_metrics) => println!("GPU Metrics Info: {:?}", gpu_metrics), +/// Err(e) => panic!("Failed to get GPU metrics info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_metrics_info` call fails. +pub fn amdsmi_get_gpu_metrics_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut pgpu_metrics = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_metrics_info( + processor_handle, + pgpu_metrics.as_mut_ptr() + )); + let pgpu_metrics = unsafe { pgpu_metrics.assume_init() }; + Ok(pgpu_metrics) +} + +/// Get the GPU power management metrics information of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU power management metrics information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU power management metrics information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing a list of [`AmdsmiNameValueT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU power management metrics information +/// match amdsmi_get_gpu_pm_metrics_info(processor_handle) { +/// Ok(pm_metrics) => { +/// println!("Number of Metrics: {}", pm_metrics.len()); +/// for metric in pm_metrics { +/// println!("Metric: {:?}", metric); +/// } +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_pm_metrics_info() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU power management metrics info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_pm_metrics_info` call fails. +pub fn amdsmi_get_gpu_pm_metrics_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult> { + let mut pm_metrics_ptr: *mut AmdsmiNameValueT = null_mut(); + let mut num_of_metrics = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_pm_metrics_info( + processor_handle, + &mut pm_metrics_ptr, + &mut num_of_metrics + )); + + let pm_metrics_slice = + unsafe { std::slice::from_raw_parts(pm_metrics_ptr, num_of_metrics as usize) }; + let pm_metrics = pm_metrics_slice.to_vec(); + + unsafe { amdsmi_wrapper::amdsmi_free_name_value_pairs(pm_metrics_ptr as *mut c_void) }; + + Ok(pm_metrics) +} + +/// Get the GPU register table information of the device with the specified processor handle and register type. +/// +/// Given a processor handle `processor_handle` and a register type `reg_type`, this function returns the GPU register table information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU register table information is being queried. +/// * `reg_type` - The [`AmdsmiRegTypeT`] type of the register to query. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing a list of [`AmdsmiNameValueT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example register type +/// let reg_type = AmdsmiRegTypeT::AmdsmiRegPcie; +/// +/// // Retrieve the GPU register table information +/// match amdsmi_get_gpu_reg_table_info(processor_handle, reg_type) { +/// Ok(reg_metrics) => { +/// println!("Number of Metrics: {}", reg_metrics.len()); +/// for metric in reg_metrics { +/// println!("Metric: {:?}", metric); +/// } +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_reg_table_info() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU register table info: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_reg_table_info` call fails. +pub fn amdsmi_get_gpu_reg_table_info( + processor_handle: AmdsmiProcessorHandle, + reg_type: AmdsmiRegTypeT, +) -> AmdsmiResult> { + let mut reg_metrics_ptr: *mut AmdsmiNameValueT = null_mut(); + let mut num_of_metrics = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_reg_table_info( + processor_handle, + reg_type, + &mut reg_metrics_ptr, + &mut num_of_metrics + )); + + let reg_metrics_slice = + unsafe { std::slice::from_raw_parts(reg_metrics_ptr, num_of_metrics as usize) }; + let reg_metrics = reg_metrics_slice.to_vec(); + + unsafe { amdsmi_wrapper::amdsmi_free_name_value_pairs(reg_metrics_ptr as *mut c_void) }; + + Ok(reg_metrics) +} + +/// Set the GPU clock range of the device with the specified processor handle, minimum clock value, maximum clock value, and clock type. +/// +/// Given a processor handle `processor_handle`, a minimum clock value `minclkvalue`, a maximum clock value `maxclkvalue`, and a clock type `clk_type`, +/// this function sets the GPU clock range for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU clock range is being set. +/// * `minclkvalue` - The minimum clock value to set. +/// * `maxclkvalue` - The maximum clock value to set. +/// * `clk_type` - The type of the clock to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock values and clock type +/// let minclkvalue = 500; // Set minimum clock value to 500 MHz +/// let maxclkvalue = 1500; // Set maximum clock value to 1500 MHz +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeGfx; +/// +/// // Set the GPU clock range +/// match amdsmi_set_gpu_clk_range(processor_handle, minclkvalue, maxclkvalue, clk_type) { +/// Ok(()) => println!("GPU clock range set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_clk_range() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU clock range: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_clk_range` call fails. +pub fn amdsmi_set_gpu_clk_range( + processor_handle: AmdsmiProcessorHandle, + minclkvalue: u64, + maxclkvalue: u64, + clk_type: AmdsmiClkTypeT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_clk_range( + processor_handle, + minclkvalue, + maxclkvalue, + clk_type + )); + Ok(()) +} + +/// Set the GPU clock limit of the device with the specified processor handle, clock type, limit type, and clock value. +/// +/// Given a processor handle `processor_handle`, a clock type `clk_type`, a limit type `limit_type`, and a clock value `clk_value`, +/// this function sets the GPU clock limit for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU clock limit is being set. +/// * `clk_type` - The type of the clock to set. +/// * `limit_type` - The type of the clock limit to set. +/// * `clk_value` - The clock value to set. Frequency values are in MHz. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock type, limit type, and clock value +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeGfx; +/// let limit_type = AmdsmiClkLimitTypeT::ClkLimitMin; +/// let clk_value = 1500; // Set clock value to 1500 MHz +/// +/// // Set the GPU clock limit +/// match amdsmi_set_gpu_clk_limit(processor_handle, clk_type, limit_type, clk_value) { +/// Ok(()) => println!("GPU clock limit set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_clk_limit() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU clock limit: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_clk_limit` call fails. +pub fn amdsmi_set_gpu_clk_limit( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + limit_type: AmdsmiClkLimitTypeT, + clk_value: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_clk_limit( + processor_handle, + clk_type, + limit_type, + clk_value + )); + Ok(()) +} + +/// Set the GPU overdrive clock information of the device with the specified processor handle, level, clock value, and clock type. +/// +/// Given a processor handle `processor_handle`, a frequency index `level`, a clock value `clkvalue`, and a clock type `clk_type`, +/// this function sets the GPU overdrive clock information for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive clock information is being set. +/// * `level` - The frequency index level [`AmdsmiFreqIndT`] to set. +/// * `clkvalue` - The clock value to set. +/// * `clk_type` - The type of the clock [`AmdsmiClkTypeT`] to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example frequency index level, clock value, and clock type +/// let level = AmdsmiFreqIndT::AmdsmiFreqIndMin; +/// let clkvalue = 1500; // Set clock value to 1500 MHz +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeGfx; +/// +/// // Set the GPU overdrive clock information +/// match amdsmi_set_gpu_od_clk_info(processor_handle, level, clkvalue, clk_type) { +/// Ok(()) => println!("GPU overdrive clock information set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_od_clk_info() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU overdrive clock information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_od_clk_info` call fails. +pub fn amdsmi_set_gpu_od_clk_info( + processor_handle: AmdsmiProcessorHandle, + level: AmdsmiFreqIndT, + clkvalue: u64, + clk_type: AmdsmiClkTypeT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_od_clk_info( + processor_handle, + level, + clkvalue, + clk_type + )); + Ok(()) +} + +/// Set the GPU overdrive voltage information of the device with the specified processor handle, voltage point, clock value, and voltage value. +/// +/// Given a processor handle `processor_handle`, a voltage point `vpoint`, a clock value `clkvalue`, and a voltage value `voltvalue`, +/// this function sets the GPU overdrive voltage information for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive voltage information is being set. +/// * `vpoint` - The voltage point [0|1|2] on the voltage curve to set. +/// * `clkvalue` - The clock value component of voltage curve point to set. +/// * `voltvalue` - The voltage value component of voltage curve point to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example voltage point, clock value, and voltage value +/// let vpoint = 1; +/// let clkvalue = 1000; +/// let voltvalue = 980; +/// +/// // Set the GPU overdrive voltage information +/// match amdsmi_set_gpu_od_volt_info(processor_handle, vpoint, clkvalue, voltvalue) { +/// Ok(()) => println!("GPU overdrive voltage information set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_od_volt_info() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU overdrive voltage information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_od_volt_info` call fails. +pub fn amdsmi_set_gpu_od_volt_info( + processor_handle: AmdsmiProcessorHandle, + vpoint: u32, + clkvalue: u64, + voltvalue: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_od_volt_info( + processor_handle, + vpoint, + clkvalue, + voltvalue + )); + Ok(()) +} + +/// Get the GPU overdrive voltage curve regions of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the GPU current valid overdrive voltage +/// curve regions for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive voltage curve regions are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing a list of [`AmdsmiFreqVoltRegionT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU overdrive voltage curve regions +/// match amdsmi_get_gpu_od_volt_curve_regions(processor_handle) { +/// Ok(regions) => { +/// println!("Number of Regions: {}", regions.len()); +/// for region in regions { +/// println!("Region: {:?}", region); +/// } +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_od_volt_curve_regions() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU overdrive voltage curve regions: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_od_volt_curve_regions` call fails. +pub fn amdsmi_get_gpu_od_volt_curve_regions( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult> { + let mut num_regions = MaybeUninit::::uninit(); + let buffer_ptr: *mut AmdsmiFreqVoltRegionT = std::ptr::null_mut(); + + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_od_volt_curve_regions( + processor_handle, + num_regions.as_mut_ptr(), + buffer_ptr + )); + + let num_regions = unsafe { num_regions.assume_init() }; + let buffer_slice = unsafe { std::slice::from_raw_parts(buffer_ptr, num_regions as usize) }; + let buffer = buffer_slice.to_vec(); + + Ok(buffer) +} + +/// Get the GPU power profile presets of the device with the specified processor handle and sensor index. +/// +/// Given a processor handle `processor_handle` and a sensor index `sensor_ind`, this function returns the GPU power profile presets +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU power profile presets are being queried. +/// * `sensor_ind` - The sensor index to query. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiPowerProfileStatusT)` containing the [`AmdsmiPowerProfileStatusT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_ind = 0; // Sensor index 0 +/// +/// // Retrieve the GPU power profile presets +/// match amdsmi_get_gpu_power_profile_presets(processor_handle, sensor_ind) { +/// Ok(status) => println!("GPU Power Profile Status: {:?}", status), +/// Err(e) => panic!("Failed to get GPU power profile presets: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_power_profile_presets` call fails. +pub fn amdsmi_get_gpu_power_profile_presets( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, +) -> AmdsmiResult { + let mut status = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_power_profile_presets( + processor_handle, + sensor_ind, + status.as_mut_ptr() + )); + let status = unsafe { status.assume_init() }; + Ok(status) +} + +/// Set the GPU performance level of the device with the specified processor handle and performance level. +/// +/// Given a processor handle `processor_handle` and a performance level `perf_lvl`, this function sets the GPU performance level +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU performance level is being set. +/// * `perf_lvl` - The performance level [`AmdsmiDevPerfLevelT`] to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example performance level +/// let perf_lvl = AmdsmiDevPerfLevelT::AmdsmiDevPerfLevelHigh; +/// +/// // Set the GPU performance level +/// match amdsmi_set_gpu_perf_level(processor_handle, perf_lvl) { +/// Ok(()) => println!("GPU performance level set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_perf_level() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU performance level: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_perf_level` call fails. +pub fn amdsmi_set_gpu_perf_level( + processor_handle: AmdsmiProcessorHandle, + perf_lvl: AmdsmiDevPerfLevelT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_perf_level( + processor_handle, + perf_lvl + )); + Ok(()) +} + +/// Set the GPU overdrive percent of the device with the specified processor handle and overdrive level. +/// +/// Given a processor handle `processor_handle` and an overdrive level `od`, this function sets the GPU overdrive level +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU overdrive level is being set. +/// * `od` - The overdrive level to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example overdrive level +/// let od = 0; // Set overdrive level to 0 +/// +/// // Set the GPU overdrive level +/// match amdsmi_set_gpu_overdrive_level(processor_handle, od) { +/// Ok(()) => println!("GPU overdrive level set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_overdrive_level() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU overdrive level: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_overdrive_level` call fails. +pub fn amdsmi_set_gpu_overdrive_level( + processor_handle: AmdsmiProcessorHandle, + od: u32, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_overdrive_level( + processor_handle, + od + )); + Ok(()) +} + +/// Set the clock frequency of the device with the specified processor handle, clock type, and frequency bitmask. +/// +/// Given a processor handle `processor_handle`, a clock type `clk_type`, and a frequency bitmask `freq_bitmask`, +/// this function sets the clock frequency for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the clock frequency is being set. +/// * `clk_type` - The type of the clock to set. +/// * `freq_bitmask` - The frequency bitmask to set. A bitmask indicating the indices of the frequencies +/// that are to be enabled (1) and disabled (0). Only the lowest `AmdsmiFrequenciesT.num_supported` +/// bits of this mask are relevant. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock type and frequency bitmask +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeGfx; +/// let freq_bitmask = 0; // Example frequency bitmask +/// +/// // Set the clock frequency +/// match amdsmi_set_clk_freq(processor_handle, clk_type, freq_bitmask) { +/// Ok(()) => println!("Clock frequency set successfully"), +/// Err(e) => panic!("Failed to set clock frequency: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_clk_freq` call fails. +pub fn amdsmi_set_clk_freq( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + freq_bitmask: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_clk_freq( + processor_handle, + clk_type, + freq_bitmask + )); + Ok(()) +} + +/// Get the SoC P-state of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the SoC P-state +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the SoC P-state is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiDpmPolicyT)` containing the [`AmdsmiDpmPolicyT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the SoC P-state +/// match amdsmi_get_soc_pstate(processor_handle) { +/// Ok(policy) => println!("SoC P-state: {:?}", policy), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_soc_pstate() not supported on this device"), +/// Err(e) => panic!("Failed to get SoC P-state: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_soc_pstate` call fails. +pub fn amdsmi_get_soc_pstate( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut policy = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_soc_pstate( + processor_handle, + policy.as_mut_ptr() + )); + let policy = unsafe { policy.assume_init() }; + Ok(policy) +} + +/// Set the SoC P-state of the device with the specified processor handle and policy ID. +/// +/// Given a processor handle `processor_handle` and a policy ID `policy_id`, this function sets the SoC P-state +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the SoC P-state is being set. +/// * `policy_id` - The policy ID to set. The id is the id in [`AmdsmiDpmPolicyEntryT`], which can be obtained by calling amdsmi_get_soc_pstate(). +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example policy ID +/// let policy_id = 0; +/// +/// // Set the SoC P-state +/// match amdsmi_set_soc_pstate(processor_handle, policy_id) { +/// Ok(()) => println!("SoC P-state set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_soc_pstate() not supported on this device"), +/// Err(e) => panic!("Failed to set SoC P-state: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_soc_pstate` call fails. +pub fn amdsmi_set_soc_pstate( + processor_handle: AmdsmiProcessorHandle, + policy_id: u32, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_soc_pstate( + processor_handle, + policy_id + )); + Ok(()) +} + +/// Get the XGMI per-link power down (PLPD) policy of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the XGMI PLPD policy +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the XGMI PLPD policy is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiDpmPolicyT)` containing the [`AmdsmiDpmPolicyT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the XGMI PLPD policy +/// match amdsmi_get_xgmi_plpd(processor_handle) { +/// Ok(xgmi_plpd) => println!("XGMI PLPD policy: {:?}", xgmi_plpd), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_xgmi_plpd() not supported on this device"), +/// Err(e) => panic!("Failed to get XGMI PLPD policy: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_xgmi_plpd` call fails. +pub fn amdsmi_get_xgmi_plpd( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut xgmi_plpd = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_xgmi_plpd( + processor_handle, + xgmi_plpd.as_mut_ptr() + )); + let xgmi_plpd = unsafe { xgmi_plpd.assume_init() }; + Ok(xgmi_plpd) +} + +/// Set the XGMI per-link power down (PLPD) policy of the device with the specified processor handle and PLPD ID. +/// +/// Given a processor handle `processor_handle` and a PLPD ID `plpd_id`, this function sets the XGMI PLPD policy +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the XGMI PLPD policy is being set. +/// * `plpd_id` - The PLPD ID to set. The id is the id in [`AmdsmiDpmPolicyEntryT`], which can be obtained by calling amdsmi_get_xgmi_plpd(). +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example PLPD ID +/// let plpd_id = 0; +/// +/// // Set the XGMI PLPD policy +/// match amdsmi_set_xgmi_plpd(processor_handle, plpd_id) { +/// Ok(()) => println!("XGMI PLPD policy set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_xgmi_plpd() not supported on this device"), +/// Err(e) => panic!("Failed to set XGMI PLPD policy: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_xgmi_plpd` call fails. +pub fn amdsmi_set_xgmi_plpd( + processor_handle: AmdsmiProcessorHandle, + plpd_id: u32, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_xgmi_plpd( + processor_handle, + plpd_id + )); + Ok(()) +} + +/// Get the GPU process isolation status of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function returns the integer GPU process isolation status: +/// 0 - disabled, 1 - enabled. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU process isolation status is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the GPU process isolation status if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU process isolation status +/// match amdsmi_get_gpu_process_isolation(processor_handle) { +/// Ok(pisolate) => println!("GPU process isolation status: {}", pisolate), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_process_isolation() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU process isolation status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_process_isolation` call fails. +pub fn amdsmi_get_gpu_process_isolation( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut pisolate = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_process_isolation( + processor_handle, + pisolate.as_mut_ptr() + )); + let pisolate = unsafe { pisolate.assume_init() }; + Ok(pisolate) +} + +/// Enable/disable the system Process Isolation for the given device handle. +/// +/// Given a processor handle `processor_handle` and an isolation value `pisolate`, this function sets the GPU process isolation status +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU process isolation status is being set. +/// * `pisolate` - The isolation value to set. 0 is the process isolation disabled, and 1 is the process isolation enabled. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example isolation value +/// let pisolate = 1; // Set isolation to enabled +/// +/// // Set the GPU process isolation status +/// match amdsmi_set_gpu_process_isolation(processor_handle, pisolate) { +/// Ok(()) => println!("GPU process isolation status set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_process_isolation() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU process isolation status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_process_isolation` call fails. +pub fn amdsmi_set_gpu_process_isolation( + processor_handle: AmdsmiProcessorHandle, + pisolate: u32, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_process_isolation( + processor_handle, + pisolate + )); + Ok(()) +} + +/// Clean the GPU local data of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function cleans the GPU local data +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU local data is being cleaned. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Clean the GPU local data +/// match amdsmi_clean_gpu_local_data(processor_handle) { +/// Ok(()) => println!("GPU local data cleaned successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_clean_gpu_local_data() not supported on this device"), +/// Err(e) => panic!("Failed to clean GPU local data: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_clean_gpu_local_data` call fails. +pub fn amdsmi_clean_gpu_local_data(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_clean_gpu_local_data( + processor_handle + )); + Ok(()) +} + +/// Get the GPU ECC error count for a specific block of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and a GPU block `block`, this function returns the ECC error count +/// for the specified block of the processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the ECC error count is being queried. +/// * `block` - The GPU block for which the ECC error count is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiErrorCountT)` containing the [`AmdsmiErrorCountT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example GPU block +/// let block = AmdsmiGpuBlockT::AmdsmiGpuBlockGfx; +/// +/// // Retrieve the GPU ECC error count +/// match amdsmi_get_gpu_ecc_count(processor_handle, block) { +/// Ok(ec) => println!("GPU ECC error count: {:?}", ec), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_ecc_count() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU ECC error count: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_ecc_count` call fails. +pub fn amdsmi_get_gpu_ecc_count( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, +) -> AmdsmiResult { + let mut ec = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_ecc_count( + processor_handle, + block, + ec.as_mut_ptr() + )); + let ec = unsafe { ec.assume_init() }; + Ok(ec) +} + +/// Retrieve the enabled ECC bit-mask. +/// +/// Given a processor handle `processor_handle`, this function returns the ECC enabled +/// ECC bit-mask for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the ECC enabled bit-mask are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the ECC enabled bit-mask if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU ECC enabled bit-mask +/// match amdsmi_get_gpu_ecc_enabled(processor_handle) { +/// Ok(enabled_mask) => println!("GPU ECC enabled: {}", enabled_mask), +/// Err(e) => panic!("Failed to get GPU ECC enabled: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_ecc_enabled` call fails. +pub fn amdsmi_get_gpu_ecc_enabled(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut enabled_mask = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_ecc_enabled( + processor_handle, + enabled_mask.as_mut_ptr() + )); + let enabled_mask = unsafe { enabled_mask.assume_init() }; + Ok(enabled_mask) +} + +/// Get the GPU ECC status for a specific block of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and a GPU block `block`, this function returns the ECC status +/// for the specified block of the processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the ECC status is being queried. +/// * `block` - The GPU block for which the ECC status is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiRasErrStateT)` containing the [`AmdsmiRasErrStateT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example GPU block +/// let block = AmdsmiGpuBlockT::AmdsmiGpuBlockGfx; +/// +/// // Retrieve the GPU ECC status +/// match amdsmi_get_gpu_ecc_status(processor_handle, block) { +/// Ok(state) => println!("GPU ECC status: {:?}", state), +/// Err(e) => panic!("Failed to get GPU ECC status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_ecc_status` call fails. +pub fn amdsmi_get_gpu_ecc_status( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, +) -> AmdsmiResult { + let mut state = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_ecc_status( + processor_handle, + block, + state.as_mut_ptr() + )); + let state = unsafe { state.assume_init() }; + Ok(state) +} + +/// Convert an AMD SMI status code to a string representation. +/// +/// Given a status code `status`, this function returns the string representation of the status code. +/// +/// # Arguments +/// +/// * `status` - The AMD SMI status code to convert. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the string representation of the status code if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// // Example status code +/// let status = AmdsmiStatusT::AmdsmiStatusNotSupported; +/// +/// // Convert the status code to a string +/// match amdsmi_status_code_to_string(status) { +/// Ok(status_str) => println!("Status string: {}", status_str), +/// Err(e) => panic!("Failed to convert status code to string: {}", e), +/// } +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_status_code_to_string` call fails. +pub fn amdsmi_status_code_to_string(status: AmdsmiStatusT) -> AmdsmiResult { + let mut status_string: *const ::std::os::raw::c_char = null_mut(); + call_unsafe!(amdsmi_wrapper::amdsmi_status_code_to_string( + status, + &mut status_string + )); + + let c_str = unsafe { std::ffi::CStr::from_ptr(status_string) }; + let string = c_str.to_string_lossy().into_owned(); + + Ok(string) +} + +/// Check if a GPU counter group is supported for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and an event group `group`, this function checks if the specified GPU counter group +/// is supported for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU counter group support is being queried. +/// * `group` - The event group to check for support. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(bool)` indicating whether the GPU counter group is supported if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example event group +/// let group = AmdsmiEventGroupT::AmdsmiEvntGrpXgmi; +/// +/// // Check if the GPU counter group is supported +/// match amdsmi_gpu_counter_group_supported(processor_handle, group) { +/// Ok(supported) => println!("GPU counter group supported: {}", supported), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_gpu_counter_group_supported() not supported on this device"), +/// Err(e) => panic!("Failed to check GPU counter group support: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_counter_group_supported` call fails. +pub fn amdsmi_gpu_counter_group_supported( + processor_handle: AmdsmiProcessorHandle, + group: AmdsmiEventGroupT, +) -> AmdsmiResult { + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_counter_group_supported( + processor_handle, + group + )); + // Here amdsmi_wrapper::amdsmi_gpu_counter_group_supported return successfull means supported. + Ok(true) +} + +/// Creates a GPU counter for the specified event type on the device with the specified processor handle. +/// +/// This function creates a GPU counter for the specified event type on the specified processor handle, +/// allowing the user to monitor specific GPU events. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU counter is being created. +/// * `event_type` - The type of event for which the GPU counter is being created. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiEventHandleT)` containing the [`AmdsmiEventHandleT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Check if the event group is supported +/// let event_group = AmdsmiEventGroupT::AmdsmiEvntGrpXgmi; +/// match amdsmi_gpu_counter_group_supported(processor_handle, event_group) { +/// Ok(_) => println!("Event group supported."), +/// Err(e) => { +/// assert!( e == AmdsmiStatusT::AmdsmiStatusNotSupported, "Event group not supported: {}", e); +/// } +/// } +/// +/// // Check available GPU counters +/// let available_counters = match amdsmi_get_gpu_available_counters(processor_handle, event_group) { +/// Ok(available_counters) => available_counters, +/// Err(e) => { +/// assert!( e == AmdsmiStatusT::AmdsmiStatusNotSupported, "Failed to get available GPU counters: {}", e); +/// 0 +/// } +/// }; +/// +/// if available_counters == 0 { +/// println!("No available GPU counters or event group not supported."); +/// amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// return; +/// } +/// +/// // Example event type +/// let event_type = AmdsmiEventTypeT::AmdsmiEvntXgmi0RequestTx; +/// +/// // Create a GPU counter +/// match amdsmi_gpu_create_counter(processor_handle, event_type) { +/// Ok(event_handle) => { +/// println!("GPU counter created with handle: {:?}", event_handle); +/// +/// // Start the GPU counter +/// let cmd_start = AmdsmiCounterCommandT::AmdsmiCntrCmdStart; +/// amdsmi_gpu_control_counter(event_handle, cmd_start).expect("Failed to start GPU counter"); +/// +/// // Wait for some time +/// std::thread::sleep(std::time::Duration::from_secs(1)); +/// +/// // Read the GPU counter value +/// let value = amdsmi_gpu_read_counter(event_handle).expect("Failed to read GPU counter"); +/// println!("GPU counter value: {:?}", value); +/// +/// // Stop the GPU counter +/// let cmd_stop = AmdsmiCounterCommandT::AmdsmiCntrCmdStop; +/// amdsmi_gpu_control_counter(event_handle, cmd_stop).expect("Failed to stop GPU counter"); +/// +/// // Destroy the GPU counter +/// amdsmi_gpu_destroy_counter(event_handle).expect("Failed to destroy GPU counter"); +/// }, +/// Err(e) => eprintln!("Failed to create GPU counter: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_create_counter` call fails. +pub fn amdsmi_gpu_create_counter( + processor_handle: AmdsmiProcessorHandle, + event_type: AmdsmiEventTypeT, +) -> AmdsmiResult { + let mut evnt_handle = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_create_counter( + processor_handle, + event_type, + evnt_handle.as_mut_ptr() + )); + let evnt_handle = unsafe { evnt_handle.assume_init() }; + Ok(evnt_handle) +} + +/// Destroy a GPU counter with the specified event handle. +/// +/// Given an event handle `evnt_handle`, this function destroys the GPU counter. +/// +/// # Arguments +/// +/// * `evnt_handle` - The event handle of the GPU counter to be destroyed. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_gpu_create_counter`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_destroy_counter` call fails. +pub fn amdsmi_gpu_destroy_counter(evnt_handle: AmdsmiEventHandleT) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_destroy_counter(evnt_handle)); + Ok(()) +} + +/// Control a GPU counter with the specified event handle and command. +/// +/// Given an event handle `evt_handle`, a command `cmd`, this function controls the GPU counter. +/// +/// # Arguments +/// +/// * `evt_handle` - The event handle of the GPU counter to be controlled. +/// * `cmd` - The command to be executed on the GPU counter. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_gpu_create_counter`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_control_counter` call fails. +pub fn amdsmi_gpu_control_counter( + evt_handle: AmdsmiEventHandleT, + cmd: AmdsmiCounterCommandT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_control_counter( + evt_handle, + cmd, + std::ptr::null_mut() + )); + Ok(()) +} + +/// Read the value of a GPU counter with the specified event handle. +/// +/// Given an event handle `evt_handle`, this function reads the value of the GPU counter. +/// +/// # Arguments +/// +/// * `evt_handle` - The event handle of the GPU counter to be read. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiCounterValueT)` containing the [`AmdsmiCounterValueT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_gpu_create_counter`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_read_counter` call fails. +pub fn amdsmi_gpu_read_counter( + evt_handle: AmdsmiEventHandleT, +) -> AmdsmiResult { + let mut value = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_read_counter( + evt_handle, + value.as_mut_ptr() + )); + let value = unsafe { value.assume_init() }; + Ok(value) +} + +/// Get the number of available GPU counters for the device with the specified processor handle and event group. +/// +/// Given a processor handle `processor_handle` and an event group `grp`, this function retrieves the number of available GPU counters +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the available GPU counters are being queried. +/// * `grp` - The event group for which the available GPU counters are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the number of available GPU counters if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_gpu_create_counter`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_available_counters` call fails. +pub fn amdsmi_get_gpu_available_counters( + processor_handle: AmdsmiProcessorHandle, + grp: AmdsmiEventGroupT, +) -> AmdsmiResult { + let mut available: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_available_counters( + processor_handle, + grp, + &mut available as *mut u32 + )); + Ok(available) +} + +/// Get the GPU compute process information. +/// +/// This function retrieves information about GPU compute processes. +/// +/// # Arguments +/// +/// * `procs` - A mutable pointer to an array of `AmdsmiProcessInfoT` where the process information will be stored. +/// * `num_items` - A mutable pointer to a `u32` where the number of items will be stored. +/// +/// # Returns +/// +/// * `AmdsmiResult<(Vec, u32)>` - Returns `Ok((Vec, u32))` containing a list of [`AmdsmiProcessInfoT`] and the number of items if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Get the GPU compute process information +/// match amdsmi_get_gpu_compute_process_info() { +/// Ok((procs, num_items)) => { +/// println!("Number of GPU compute processes: {}", num_items); +/// for proc in procs { +/// println!("{:?}", proc); +/// } +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_compute_process_info() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU compute process information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_compute_process_info` call fails. +pub fn amdsmi_get_gpu_compute_process_info() -> AmdsmiResult<(Vec, u32)> { + let mut num_items = MaybeUninit::::uninit(); + + // First call to get the number of items + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_process_info( + std::ptr::null_mut(), + num_items.as_mut_ptr() + )); + + let num_items = unsafe { num_items.assume_init() }; + let mut procs: Vec = Vec::with_capacity(num_items as usize); + + // Second call to get the actual process information + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_process_info( + procs.as_mut_ptr(), + &mut (num_items as u32) + )); + + unsafe { procs.set_len(num_items as usize) }; + + Ok((procs, num_items)) +} + +/// Get the GPU compute process information by PID. +/// +/// This function retrieves information about a specific GPU compute process identified by its PID. +/// +/// # Arguments +/// +/// * `pid` - The process ID of the GPU compute process. +/// * `proc_` - A mutable pointer to an `AmdsmiProcessInfoT` where the process information will be stored. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiProcessInfoT)` containing the [`AmdsmiProcessInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust, should_panic +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example PID, +/// let pid = 12345; +/// +/// // Get the process information by PID +/// match amdsmi_get_gpu_compute_process_info_by_pid(pid) { +/// Ok(proc_info) => println!("{:?}", proc_info), +/// Err(e) => panic!("Failed to get GPU compute process information by PID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_compute_process_info_by_pid` call fails. +pub fn amdsmi_get_gpu_compute_process_info_by_pid(pid: u32) -> AmdsmiResult { + let mut proc_info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_process_info_by_pid( + pid, + proc_info.as_mut_ptr() + )); + let proc_info = unsafe { proc_info.assume_init() }; + Ok(proc_info) +} + +/// Get the device indices currently being used by a process. +/// +/// This function retrieves the GPU indices for a specific GPU compute process identified by its PID. +/// +/// # Arguments +/// +/// * `pid` - The process ID of the GPU compute process. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns a vector containing the GPU indices if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust,should_panic +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example PID, assuming a valid PID for a GPU compute process +/// let pid = 12345; +/// +/// // Retrieve the GPU indices for the process +/// match amdsmi_get_gpu_compute_process_gpus(pid) { +/// Ok(gpu_indices) => { +/// for index in gpu_indices { +/// println!("GPU Index: {}", index); +/// } +/// }, +/// Err(e) => panic!("Failed to get GPU compute process devices: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_compute_process_gpus` call fails. +pub fn amdsmi_get_gpu_compute_process_gpus(pid: u32) -> AmdsmiResult> { + let mut num_devices: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_process_gpus( + pid, + std::ptr::null_mut(), + &mut num_devices + )); + + let mut devices: Vec = Vec::with_capacity(num_devices as usize); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_process_gpus( + pid, + devices.as_mut_ptr(), + &mut num_devices + )); + unsafe { devices.set_len(num_devices as usize) }; + + Ok(devices) +} + +/// Get the XGMI error status of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the XGMI error status +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the XGMI error status is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiXgmiStatusT)` containing the [`AmdsmiXgmiStatusT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the XGMI error status +/// match amdsmi_gpu_xgmi_error_status(processor_handle) { +/// Ok(status) => println!("XGMI error status: {:?}", status), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_gpu_xgmi_error_status() not supported on this device"), +/// Err(e) => panic!("Failed to get XGMI error status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_gpu_xgmi_error_status` call fails. +pub fn amdsmi_gpu_xgmi_error_status( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut status = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_gpu_xgmi_error_status( + processor_handle, + status.as_mut_ptr() + )); + let status = unsafe { status.assume_init() }; + Ok(status) +} + +/// Reset the XGMI error status of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function resets the XGMI error status +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the XGMI error status is being reset. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Reset the XGMI error status +/// match amdsmi_reset_gpu_xgmi_error(processor_handle) { +/// Ok(()) => println!("XGMI error status reset successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_reset_gpu_xgmi_error() not supported on this device"), +/// Err(e) => panic!("Failed to reset XGMI error status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_reset_gpu_xgmi_error` call fails. +pub fn amdsmi_reset_gpu_xgmi_error(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_reset_gpu_xgmi_error( + processor_handle + )); + Ok(()) +} + +/// Get the link metrics of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the link metrics +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the link metrics are being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiLinkMetricsT)` containing the [`AmdsmiLinkMetricsT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the link metrics +/// match amdsmi_get_link_metrics(processor_handle) { +/// Ok(link_metrics) => println!("Link metrics number: {}", link_metrics.num_links), +/// Err(e) => panic!("Failed to get link metrics: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_link_metrics` call fails. +pub fn amdsmi_get_link_metrics( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut link_metrics = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_link_metrics( + processor_handle, + link_metrics.as_mut_ptr() + )); + let link_metrics = unsafe { link_metrics.assume_init() }; + Ok(link_metrics) +} + +/// Get the NUMA node number of the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the NUMA node number +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the NUMA node number is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u32)` containing the NUMA node number if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the NUMA node number +/// match amdsmi_topo_get_numa_node_number(processor_handle) { +/// Ok(numa_node) => println!("NUMA node number: {}", numa_node), +/// Err(e) => panic!("Failed to get NUMA node number: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_topo_get_numa_node_number` call fails. +pub fn amdsmi_topo_get_numa_node_number( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut numa_node: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_topo_get_numa_node_number( + processor_handle, + &mut numa_node + )); + Ok(numa_node) +} + +/// Get the link weight between two processors with the specified processor handles. +/// +/// Given source and destination processor handles `processor_handle_src` and `processor_handle_dst`, +/// this function retrieves the link weight between the two processors. +/// +/// # Arguments +/// +/// * `processor_handle_src` - A handle to the source processor. +/// * `processor_handle_dst` - A handle to the destination processor. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(u64)` containing the link weight if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor handles, assuming the number of processors is greater than one +/// let processor_handle_src = amdsmi_get_processor_handles!()[0]; +/// let processor_handle_dst = amdsmi_get_processor_handles!()[1]; +/// +/// // Retrieve the link weight +/// match amdsmi_topo_get_link_weight(processor_handle_src, processor_handle_dst) { +/// Ok(weight) => println!("Link weight: {}", weight), +/// Err(e) => panic!("Failed to get link weight: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_topo_get_link_weight` call fails. +pub fn amdsmi_topo_get_link_weight( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut weight: u64 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_topo_get_link_weight( + processor_handle_src, + processor_handle_dst, + &mut weight + )); + Ok(weight) +} + +/// Get the minimum and maximum bandwidth between two processors with the specified processor handles. +/// +/// Given source and destination processor handles `processor_handle_src` and `processor_handle_dst`, +/// this function retrieves the minimum and maximum bandwidth between the two processors. +/// +/// # Arguments +/// +/// * `processor_handle_src` - A handle to the source processor. +/// * `processor_handle_dst` - A handle to the destination processor. +/// +/// # Returns +/// +/// * `AmdsmiResult<(u64, u64)>` - Returns `Ok((u64, u64))` containing the minimum and maximum bandwidth if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor handles, assuming the number of processors is greater than one +/// let processor_handle_src = amdsmi_get_processor_handles!()[0]; +/// let processor_handle_dst = amdsmi_get_processor_handles!()[1]; +/// +/// // Retrieve the minimum and maximum bandwidth +/// match amdsmi_get_minmax_bandwidth_between_processors(processor_handle_src, processor_handle_dst) { +/// Ok((min_bandwidth, max_bandwidth)) => { +/// println!("Minimum bandwidth: {}", min_bandwidth); +/// println!("Maximum bandwidth: {}", max_bandwidth); +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_minmax_bandwidth_between_processors() not supported on this device"), +/// Err(e) => panic!("Failed to get bandwidth: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_minmax_bandwidth_between_processors` call fails. +pub fn amdsmi_get_minmax_bandwidth_between_processors( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, +) -> AmdsmiResult<(u64, u64)> { + let mut min_bandwidth: u64 = 0; + let mut max_bandwidth: u64 = 0; + call_unsafe!( + amdsmi_wrapper::amdsmi_get_minmax_bandwidth_between_processors( + processor_handle_src, + processor_handle_dst, + &mut min_bandwidth, + &mut max_bandwidth + ) + ); + Ok((min_bandwidth, max_bandwidth)) +} + +/// Check if P2P access is possible between two processors with the specified processor handles. +/// +/// Given source and destination processor handles `processor_handle_src` and `processor_handle_dst`, +/// this function checks if P2P (peer-to-peer) access is possible between the two processors. +/// +/// # Arguments +/// +/// * `processor_handle_src` - A handle to the source processor. +/// * `processor_handle_dst` - A handle to the destination processor. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(bool)` indicating whether P2P access is possible if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor handles, assuming the number of processors is greater than one +/// let processor_handle_src = amdsmi_get_processor_handles!()[0]; +/// let processor_handle_dst = amdsmi_get_processor_handles!()[1]; +/// +/// // Check if P2P access is possible +/// match amdsmi_is_p2p_accessible(processor_handle_src, processor_handle_dst) { +/// Ok(accessible) => println!("P2P access is possible: {}", accessible), +/// Err(e) => panic!("Failed to check P2P access: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_is_P2P_accessible` call fails. +pub fn amdsmi_is_p2p_accessible( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut accessible: bool = false; + call_unsafe!(amdsmi_wrapper::amdsmi_is_P2P_accessible( + processor_handle_src, + processor_handle_dst, + &mut accessible + )); + Ok(accessible) +} + +/// Retrieves the link type and number of hops between two processors. +/// +/// This function retrieves the link type and number of hops between two processors, +/// returning the results in a tuple. +/// +/// # Arguments +/// +/// * `processor_handle_src` - A handle to the source processor. +/// * `processor_handle_dst` - A handle to the destination processor. +/// +/// # Returns +/// +/// * `AmdsmiResult<(u64, AmdsmiIoLinkTypeT)>` - Returns a tuple containing the number of hops and the link type if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor handles, assuming the number of processors is greater than one +/// let processor_handle_src = amdsmi_get_processor_handles!()[0]; +/// let processor_handle_dst = amdsmi_get_processor_handles!()[1]; +/// +/// // Get the link type and number of hops +/// match amdsmi_topo_get_link_type(processor_handle_src, processor_handle_dst) { +/// Ok((hops, link_type)) => println!("Hops: {}, Link Type: {:?}", hops, link_type), +/// Err(e) => panic!("Failed to get link type: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_topo_get_link_type` call fails. +pub fn amdsmi_topo_get_link_type( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, +) -> AmdsmiResult<(u64, AmdsmiIoLinkTypeT)> { + let mut hops: u64 = 0; + let mut link_type: AmdsmiIoLinkTypeT = AmdsmiIoLinkTypeT::AmdsmiIolinkTypeUndefined; + + call_unsafe!(amdsmi_wrapper::amdsmi_topo_get_link_type( + processor_handle_src, + processor_handle_dst, + &mut hops, + &mut link_type + )); + + Ok((hops, link_type)) +} + +/// Retrieves the P2P status between two processors. +/// +/// This function retrieves the P2P status between two processors, returning the link type and P2P capability. +/// +/// # Arguments +/// +/// * `processor_handle_src` - A handle to the source processor. +/// * `processor_handle_dst` - A handle to the destination processor. +/// +/// # Returns +/// +/// * `AmdsmiResult<(AmdsmiIoLinkTypeT, AmdsmiP2pCapabilityT)>` - Returns a tuple containing the link type and P2P capability if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor handles, assuming the number of processors is greater than one +/// let processor_handle_src = amdsmi_get_processor_handles!()[0]; +/// let processor_handle_dst = amdsmi_get_processor_handles!()[1]; +/// +/// // Get the P2P status +/// match amdsmi_topo_get_p2p_status(processor_handle_src, processor_handle_dst) { +/// Ok((link_type, p2p_capability)) => println!("Link Type: {:?}, P2P Capability: {:?}", link_type, p2p_capability), +/// Err(e) => panic!("Failed to get P2P status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_topo_get_p2p_status` call fails. +pub fn amdsmi_topo_get_p2p_status( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, +) -> AmdsmiResult<(AmdsmiIoLinkTypeT, AmdsmiP2pCapabilityT)> { + let mut link_type: AmdsmiIoLinkTypeT = AmdsmiIoLinkTypeT::AmdsmiIolinkTypeUndefined; + let mut p2p_capability = MaybeUninit::::uninit(); + + call_unsafe!(amdsmi_wrapper::amdsmi_topo_get_p2p_status( + processor_handle_src, + processor_handle_dst, + &mut link_type, + p2p_capability.as_mut_ptr() + )); + + let p2p_capability = unsafe { p2p_capability.assume_init() }; + + Ok((link_type, p2p_capability)) +} + +/// Retrieves the GPU compute partition for the device with the specified processor handle. +/// +/// This function retrieves the GPU compute partition for the specified processor handle, +/// returning the compute partition as a string. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU compute partition is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns the compute partition as a string if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU compute partition +/// match amdsmi_get_gpu_compute_partition(processor_handle) { +/// Ok(compute_partition) => println!("Compute Partition: {}", compute_partition), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_compute_partition() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU compute partition: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_compute_partition` call fails. +pub fn amdsmi_get_gpu_compute_partition( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let (mut compute_partition, len) = define_cstr!(amdsmi_wrapper::AMDSMI_256_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_compute_partition( + processor_handle, + compute_partition.as_mut_ptr(), + len as u32 + )); + + Ok(cstr_to_string!(compute_partition)) +} + +/// Set the GPU compute partition for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and a compute partition type `compute_partition`, +/// this function sets the GPU compute partition for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU compute partition is being set. +/// * `compute_partition` - The compute partition type [`AmdsmiComputePartitionTypeT`] to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example compute partition type +/// let compute_partition = AmdsmiComputePartitionTypeT::AmdsmiComputePartitionSpx; +/// +/// // Set the GPU compute partition +/// match amdsmi_set_gpu_compute_partition(processor_handle, compute_partition) { +/// Ok(()) => println!("GPU compute partition set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_compute_partition() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU compute partition: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_compute_partition` call fails. +pub fn amdsmi_set_gpu_compute_partition( + processor_handle: AmdsmiProcessorHandle, + compute_partition: AmdsmiComputePartitionTypeT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_compute_partition( + processor_handle, + compute_partition + )); + Ok(()) +} + +/// Retrieves the GPU memory partition for the device with the specified processor handle. +/// +/// This function retrieves the GPU memory partition for the specified processor handle, +/// returning the memory partition as a string. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU memory partition is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns the memory partition as a string if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU memory partition +/// match amdsmi_get_gpu_memory_partition(processor_handle) { +/// Ok(memory_partition) => println!("Memory Partition: {}", memory_partition), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_gpu_memory_partition() not supported on this device"), +/// Err(e) => panic!("Failed to get GPU memory partition: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_memory_partition` call fails. +pub fn amdsmi_get_gpu_memory_partition( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let (mut memory_partition, len) = define_cstr!(amdsmi_wrapper::AMDSMI_256_LENGTH); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_memory_partition( + processor_handle, + memory_partition.as_mut_ptr(), + len as u32 + )); + + Ok(cstr_to_string!(memory_partition)) +} + +/// Set the GPU memory partition for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and a memory partition type `memory_partition`, +/// this function sets the GPU memory partition for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU memory partition is being set. +/// * `memory_partition` - The memory partition type [`AmdsmiMemoryPartitionTypeT`] to set. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example memory partition type +/// let memory_partition = AmdsmiMemoryPartitionTypeT::AmdsmiMemoryPartitionNps1; +/// +/// // Set the GPU memory partition +/// match amdsmi_set_gpu_memory_partition(processor_handle, memory_partition) { +/// Ok(()) => println!("GPU memory partition set successfully"), +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_set_gpu_memory_partition() not supported on this device"), +/// Err(e) => panic!("Failed to set GPU memory partition: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_memory_partition` call fails. +pub fn amdsmi_set_gpu_memory_partition( + processor_handle: AmdsmiProcessorHandle, + memory_partition: AmdsmiMemoryPartitionTypeT, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_memory_partition( + processor_handle, + memory_partition + )); + Ok(()) +} + +/// Initialize GPU event notification for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function initializes GPU event notification +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU event notification is being initialized. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Initialize GPU event notification +/// match amdsmi_init_gpu_event_notification(processor_handle) { +/// Ok(_) => println!("GPU event notification initialized successfully."), +/// Err(e) => { +/// panic!("Failed to initialize GPU event notification: {}", e); +/// } +/// } +/// +/// // Set GPU event notification mask +/// let event_mask: u64 = 0x0000000000000003; // AmdsmiEvtNotifVmfault | AmdsmiEvtNotifThermalThrottle +/// match amdsmi_set_gpu_event_notification_mask(processor_handle, event_mask) { +/// Ok(_) => println!("GPU event notification mask set successfully."), +/// Err(e) => { +/// panic!("Failed to set GPU event notification mask: {}", e); +/// } +/// } +/// +/// // Example timeout in milliseconds +/// let timeout_ms: i32 = 10000; +/// let mut num_elem : u32 = 10; +/// +/// // Get the GPU event notification data +/// match amdsmi_get_gpu_event_notification(timeout_ms, num_elem) { +/// Ok(data) => { +/// for event in data { +/// println!("Event: {:?}", event); +/// } +/// }, +/// Err(e) => assert!(e == AmdsmiStatusT::AmdsmiStatusNoData, "Failed to get GPU event notification data: {}", e), +/// } +/// +/// // Stop GPU event notification +/// match amdsmi_stop_gpu_event_notification(processor_handle) { +/// Ok(_) => println!("GPU event notification stopped successfully."), +/// Err(e) => { +/// panic!("Failed to stop GPU event notification: {}", e); +/// } +/// } +/// +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_socket_handles` call fails. +pub fn amdsmi_init_gpu_event_notification( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_init_gpu_event_notification( + processor_handle + )); + Ok(()) +} + +/// Set the GPU event notification mask for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle` and a mask `mask`, this function sets the GPU event notification mask +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU event notification mask is being set. +/// * `mask` - The event notification mask to set. Bitmask generated by OR'ing 1 or more elements of +/// [`AmdsmiEvtNotificationTypeT`] indicating which event types to listen for. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_init_gpu_event_notification`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_set_gpu_event_notification_mask` call fails. +pub fn amdsmi_set_gpu_event_notification_mask( + processor_handle: AmdsmiProcessorHandle, + mask: u64, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_set_gpu_event_notification_mask( + processor_handle, + mask + )); + Ok(()) +} + +/// Get the GPU event notification data. +/// +/// Given a timeout in milliseconds `timeout_ms`, this function retrieves the GPU event notification data. +/// +/// # Arguments +/// +/// * `timeout_ms` - The timeout in milliseconds to wait for the event notification. +/// * `num_elem` - The number of elements to retrieve. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns `Ok(Vec)` containing the [`Vec`] if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_init_gpu_event_notification`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_event_notification` call fails. +pub fn amdsmi_get_gpu_event_notification( + timeout_ms: i32, + mut num_elem: u32, +) -> AmdsmiResult> { + let mut data: Vec = Vec::with_capacity(num_elem as usize); + + // Call to get the actual event notification data + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_event_notification( + timeout_ms, + &mut num_elem, + data.as_mut_ptr() + )); + + unsafe { data.set_len(num_elem as usize) }; + + Ok(data) +} + +/// Stop GPU event notification for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function stops GPU event notification +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU event notification is being stopped. +/// +/// # Returns +/// +/// * `AmdsmiResult<()>` - Returns `Ok(())` if successful, or an error if it fails. +/// +/// # Example +/// +/// Refer to the example in the documentation for [`amdsmi_init_gpu_event_notification`]. +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_stop_gpu_event_notification` call fails. +pub fn amdsmi_stop_gpu_event_notification( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult<()> { + call_unsafe!(amdsmi_wrapper::amdsmi_stop_gpu_event_notification( + processor_handle + )); + Ok(()) +} + +/// Get the BDF (Bus-Device-Function) information for the GPU device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the BDF information +/// for the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the BDF information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiBdfT)` containing the [`AmdsmiBdfT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the BDF information +/// match amdsmi_get_gpu_device_bdf(processor_handle) { +/// Ok(bdf) => println!("BDF information: {}", bdf), +/// Err(e) => panic!("Failed to get BDF information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_device_bdf` call fails. +pub fn amdsmi_get_gpu_device_bdf( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut bdf = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_device_bdf( + processor_handle, + bdf.as_mut_ptr() + )); + let bdf = unsafe { bdf.assume_init() }; + Ok(bdf) +} + +/// Get the UUID of the GPU device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the UUID of the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the UUID is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(String)` containing the UUID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the UUID +/// match amdsmi_get_gpu_device_uuid(processor_handle) { +/// Ok(uuid) => println!("GPU device UUID: {}", uuid), +/// Err(e) => panic!("Failed to get GPU device UUID: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_device_uuid` call fails. +pub fn amdsmi_get_gpu_device_uuid(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let (mut uuid, uuid_len) = define_cstr!(amdsmi_wrapper::AMDSMI_GPU_UUID_SIZE); + let mut uuid_len = uuid_len as std::os::raw::c_uint; + + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_device_uuid( + processor_handle, + &mut uuid_len, + uuid.as_mut_ptr() + )); + + Ok(cstr_to_string!(uuid)) +} + +/// Get the GPU driver information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the GPU driver information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU driver information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiDriverInfoT)` containing the [`AmdsmiDriverInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU driver information +/// match amdsmi_get_gpu_driver_info(processor_handle) { +/// Ok(info) => println!("GPU driver information: {:?}", info), +/// Err(e) => panic!("Failed to get GPU driver information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_driver_info` call fails. +pub fn amdsmi_get_gpu_driver_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_driver_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the GPU ASIC information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the GPU ASIC information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU ASIC information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiAsicInfoT)` containing the [`AmdsmiAsicInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU ASIC information +/// match amdsmi_get_gpu_asic_info(processor_handle) { +/// Ok(info) => println!("GPU ASIC information: {:?}", info), +/// Err(e) => panic!("Failed to get GPU ASIC information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_asic_info` call fails. +pub fn amdsmi_get_gpu_asic_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_asic_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the GPU VRAM information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the GPU VRAM information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU VRAM information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiVramInfoT)` containing the [`AmdsmiVramInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU VRAM information +/// match amdsmi_get_gpu_vram_info(processor_handle) { +/// Ok(info) => println!("GPU VRAM information: {:?}", info), +/// Err(e) => panic!("Failed to get GPU VRAM information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_vram_info` call fails. +pub fn amdsmi_get_gpu_vram_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_vram_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the GPU board information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the GPU board information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU board information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiBoardInfoT)` containing the [`AmdsmiBoardInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the GPU board information +/// match amdsmi_get_gpu_board_info(processor_handle) { +/// Ok(info) => println!("GPU board information: {:?}", info), +/// Err(e) => panic!("Failed to get GPU board information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_board_info` call fails. +pub fn amdsmi_get_gpu_board_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_board_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the power cap information for the device with the specified processor handle and sensor index. +/// +/// Given a processor handle `processor_handle` and a sensor index `sensor_ind`, this function retrieves the power cap information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the power cap information is being queried. +/// * `sensor_ind` - The index of the sensor for which the power cap information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiPowerCapInfoT)` containing the [`AmdsmiPowerCapInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example sensor index +/// let sensor_ind: u32 = 0; +/// +/// // Retrieve the power cap information +/// match amdsmi_get_power_cap_info(processor_handle, sensor_ind) { +/// Ok(info) => println!("Power cap information: {:?}", info), +/// Err(e) => panic!("Failed to get power cap information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_power_cap_info` call fails. +pub fn amdsmi_get_power_cap_info( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_power_cap_info( + processor_handle, + sensor_ind, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the PCIe information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the PCIe information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the PCIe information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiPcieInfoT)` containing the [`AmdsmiPcieInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the PCIe information +/// match amdsmi_get_pcie_info(processor_handle) { +/// Ok(info) => println!("PCIe information: {:?}", info), +/// Err(e) => panic!("Failed to get PCIe information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_pcie_info` call fails. +pub fn amdsmi_get_pcie_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_pcie_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the XGMI information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the XGMI information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the XGMI information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiXgmiInfoT)` containing the [`AmdsmiXgmiInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the XGMI information +/// match amdsmi_get_xgmi_info(processor_handle) { +/// Ok(info) => println!("XGMI information: {:?}", info), +/// Err(e) => panic!("Failed to get XGMI information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_xgmi_info` call fails. +pub fn amdsmi_get_xgmi_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_xgmi_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the firmware information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the firmware information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the firmware information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiFwInfoT)` containing the [`AmdsmiFwInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the firmware information +/// let info = amdsmi_get_fw_info(processor_handle).expect("Failed to get firmware info"); +/// +/// assert!(0 < info.num_fw_info && +/// info.num_fw_info < AmdsmiFwBlockT::AmdsmiFwIdMax as u8); +/// +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_fw_info` call fails. +pub fn amdsmi_get_fw_info(processor_handle: AmdsmiProcessorHandle) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_fw_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the VBIOS information for the GPU device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the VBIOS information +/// for the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the VBIOS information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiVbiosInfoT)` containing the [`AmdsmiVbiosInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the VBIOS information +/// match amdsmi_get_gpu_vbios_info(processor_handle) { +/// Ok(info) => println!("VBIOS information: {:?}", info), +/// Err(e) => panic!("Failed to get VBIOS information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_vbios_info` call fails. +pub fn amdsmi_get_gpu_vbios_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_vbios_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the GPU activity information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the GPU activity information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU activity information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiEngineUsageT)` containing the [`AmdsmiEngineUsageT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!().first().expect("No processor handles found").clone(); +/// +/// // Retrieve the GPU activity information +/// match amdsmi_get_gpu_activity(processor_handle) { +/// Ok(info) => println!("GPU activity information: {:?}", info), +/// Err(e) => panic!("Failed to get GPU activity information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_activity` call fails. +pub fn amdsmi_get_gpu_activity( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_activity( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the power information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the power information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the power information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiPowerInfoT)` containing the [`AmdsmiPowerInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the power information +/// match amdsmi_get_power_info(processor_handle) { +/// Ok(info) => println!("Power information: {:?}", info), +/// Err(e) => panic!("Failed to get power information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_power_info` call fails. +pub fn amdsmi_get_power_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_power_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Check if GPU power management is enabled for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function checks if GPU power management is enabled +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the power management status is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(bool)` indicating whether power management is enabled if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Check if GPU power management is enabled +/// match amdsmi_is_gpu_power_management_enabled(processor_handle) { +/// Ok(enabled) => println!("GPU power management enabled: {}", enabled), +/// Err(e) => panic!("Failed to check GPU power management status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_is_gpu_power_management_enabled` call fails. +pub fn amdsmi_is_gpu_power_management_enabled( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut enabled: bool = false; + call_unsafe!(amdsmi_wrapper::amdsmi_is_gpu_power_management_enabled( + processor_handle, + &mut enabled as *mut bool + )); + Ok(enabled) +} + +/// Get the clock information for the device with the specified processor handle and clock type. +/// +/// Given a processor handle `processor_handle` and a clock type `clk_type`, this function retrieves the clock information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the clock information is being queried. +/// * `clk_type` - The type of clock for which the information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiClkInfoT)` containing the [`AmdsmiClkInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Example clock type +/// let clk_type = AmdsmiClkTypeT::AmdsmiClkTypeSys; +/// +/// // Retrieve the clock information +/// match amdsmi_get_clock_info(processor_handle, clk_type) { +/// Ok(info) => println!("Clock information: {:?}", info), +/// Err(e) => panic!("Failed to get clock information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_clock_info` call fails. +pub fn amdsmi_get_clock_info( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_clock_info( + processor_handle, + clk_type, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the VRAM usage information for the device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the VRAM usage information +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the VRAM usage information is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiVramUsageT)` containing the [`AmdsmiVramUsageT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the VRAM usage information +/// match amdsmi_get_gpu_vram_usage(processor_handle) { +/// Ok(info) => println!("VRAM usage information: {:?}", info), +/// Err(e) => panic!("Failed to get VRAM usage information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_vram_usage` call fails. +pub fn amdsmi_get_gpu_vram_usage( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_vram_usage( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Get the total ECC error count for the GPU device with the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the total ECC error count +/// for the specified GPU device. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the ECC error count is being queried. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiErrorCountT)` containing the [`AmdsmiErrorCountT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the total ECC error count +/// match amdsmi_get_gpu_total_ecc_count(processor_handle) { +/// Ok(error_count) => println!("Total ECC error count: {:?}", error_count), +/// Err(e) => panic!("Failed to get total ECC error count: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_total_ecc_count` call fails. +pub fn amdsmi_get_gpu_total_ecc_count( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut ec = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_total_ecc_count( + processor_handle, + ec.as_mut_ptr() + )); + let ec = unsafe { ec.assume_init() }; + Ok(ec) +} + +/// Retrieves the list of GPU processes for the specified processor handle. +/// +/// Given a processor handle `processor_handle`, this function retrieves the list of GPU processes +/// for the specified processor. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU process list is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult>` - Returns a vector containing the [`AmdsmiProcInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// // Retrieve the list of GPU processes +/// match amdsmi_get_gpu_process_list(processor_handle) { +/// Ok(process_list) => { +/// for process in process_list { +/// println!("Process Info: {:?}", process); +/// } +/// }, +/// Err(e) => panic!("Failed to get GPU process list: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_process_list` call fails. +pub fn amdsmi_get_gpu_process_list( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult> { + let mut num_processes: u32 = 0; + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_process_list( + processor_handle, + &mut num_processes, + std::ptr::null_mut() + )); + + let mut processes: Vec = Vec::with_capacity(num_processes as usize); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_process_list( + processor_handle, + &mut num_processes, + processes.as_mut_ptr() + )); + unsafe { processes.set_len(num_processes as usize) }; + + Ok(processes) +} + +/// Get the library version information. +/// +/// This function retrieves the version information of the AMD SMI library. +/// +/// # Arguments +/// +/// * `version` - A mutable pointer to an `AmdsmiVersionT` structure where the version information will be stored. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiVersionT)` containing the [`AmdsmiVersionT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Retrieve the library version information +/// match amdsmi_get_lib_version() { +/// Ok(version) => println!("Library version: {:?}", version), +/// Err(e) => panic!("Failed to get library version: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_lib_version` call fails. +pub fn amdsmi_get_lib_version() -> AmdsmiResult { + let mut version = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_lib_version(version.as_mut_ptr())); + let version = unsafe { version.assume_init() }; + Ok(version) +} + +/// Retrieve the GPU accelerator partition profile. +/// +/// This function retrieves the GPU accelerator partition profile for a given processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU accelerator partition profile is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult<(AmdsmiAcceleratorPartitionProfileT, u32)>` - Returns `Ok((AmdsmiAcceleratorPartitionProfileT, u32))` containing the [`AmdsmiAcceleratorPartitionProfileT`] and partition ID if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// match amdsmi_get_gpu_accelerator_partition_profile(processor_handle) { +/// Ok((profile, partition_id)) => { +/// println!("Profile: {:?}", profile.profile_type); +/// println!("Partition ID: {}", partition_id); +/// }, +/// Err(e) => println!("Failed to retrieve GPU accelerator partition profile: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_accelerator_partition_profile` call fails. +pub fn amdsmi_get_gpu_accelerator_partition_profile( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult<(AmdsmiAcceleratorPartitionProfileT, u32)> { + let mut profile = MaybeUninit::::uninit(); + let mut partition_id = MaybeUninit::::uninit(); + call_unsafe!( + amdsmi_wrapper::amdsmi_get_gpu_accelerator_partition_profile( + processor_handle, + profile.as_mut_ptr(), + partition_id.as_mut_ptr() + ) + ); + let profile = unsafe { profile.assume_init() }; + let partition_id = unsafe { partition_id.assume_init() }; + Ok((profile, partition_id)) +} + +/// Retrieve the GPU KFD information. +/// +/// This function retrieves the GPU KFD information for a given processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the GPU KFD information is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiKfdInfoT)` containing the [`AmdsmiKfdInfoT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// match amdsmi_get_gpu_kfd_info(processor_handle) { +/// Ok(info) => { +/// println!("KFD Info: {:?}", info); +/// }, +/// Err(e) => println!("Failed to retrieve GPU KFD information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_gpu_kfd_info` call fails. +pub fn amdsmi_get_gpu_kfd_info( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_gpu_kfd_info( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Retrieve the GPU violation status. +/// +/// This function retrieves the violation status for a given processor handle. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the violation status is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiViolationStatusT)` containing the [`AmdsmiViolationStatusT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// +/// match amdsmi_get_violation_status(processor_handle) { +/// Ok(info) => { +/// println!("Violation Status: {:?}", info); +/// }, +/// Err(AmdsmiStatusT::AmdsmiStatusNotSupported) => println!("amdsmi_get_violation_status() not supported on this device"), +/// Err(e) => println!("Failed to retrieve violation status: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_violation_status` call fails. +pub fn amdsmi_get_violation_status( + processor_handle: AmdsmiProcessorHandle, +) -> AmdsmiResult { + let mut info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_violation_status( + processor_handle, + info.as_mut_ptr() + )); + let info = unsafe { info.assume_init() }; + Ok(info) +} + +/// Retrieve the nearest link topology information. +/// +/// This function retrieves the nearest link topology information for a given processor handle and link type. +/// +/// # Arguments +/// +/// * `processor_handle` - A handle to the processor for which the link topology information is being retrieved. +/// * `link_type` - The type of [`AmdsmiLinkTypeT`] for which the topology information is being retrieved. +/// +/// # Returns +/// +/// * `AmdsmiResult` - Returns `Ok(AmdsmiTopologyNearestT)` containing the [`AmdsmiTopologyNearestT`] if successful, or an error if it fails. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// # +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// // Example processor_handle, assuming the number of processors is greater than zero +/// let processor_handle = amdsmi_get_processor_handles!()[0]; +/// let link_type = AmdsmiLinkTypeT::AmdsmiLinkTypePcie; +/// +/// match amdsmi_get_link_topology_nearest(processor_handle, link_type) { +/// Ok(info) => { +/// println!("Topology Nearest Info: {:?}", info); +/// }, +/// Err(e) => println!("Failed to retrieve link topology nearest information: {}", e), +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return the error in [`AmdsmiStatusT`] if the underlying `amdsmi_wrapper::amdsmi_get_link_topology_nearest` call fails. +pub fn amdsmi_get_link_topology_nearest( + processor_handle: AmdsmiProcessorHandle, + link_type: AmdsmiLinkTypeT, +) -> AmdsmiResult { + let mut topology_nearest_info = MaybeUninit::::uninit(); + call_unsafe!(amdsmi_wrapper::amdsmi_get_link_topology_nearest( + processor_handle, + link_type, + topology_nearest_info.as_mut_ptr() + )); + let topology_nearest_info = unsafe { topology_nearest_info.assume_init() }; + Ok(topology_nearest_info) +} + +/// A macro to get all the GPU processor handles directly. +/// +/// This macro retrieves all the GPU processor handles by first getting the socket handles +/// and then getting the processor handles for each socket. +/// +/// # Example +/// +/// ```rust +/// # use amdsmi::*; +/// +/// # fn main() { +/// # // Initialize the AMD SMI library +/// # amdsmi_init(AmdsmiInitFlagsT::AmdsmiInitAmdGpus).expect("Failed to initialize AMD SMI"); +/// # +/// let processor_handles = amdsmi_get_processor_handles!(); +/// for handle in processor_handles { +/// // Perform operations with each processor handle +/// // ... +/// } +/// # +/// # // Shut down the AMD SMI library +/// # amdsmi_shut_down().expect("Failed to shut down AMD SMI"); +/// # } +/// ``` +#[macro_export] +macro_rules! amdsmi_get_processor_handles { + () => {{ + // Get the socket handles + let socket_handles = amdsmi_get_socket_handles().expect("Failed to get socket handles"); + + let mut processor_handles = Vec::new(); + + // Iterate over each socket handle to get the processor handles + for socket_handle in socket_handles { + // Call the amdsmi_get_processor_handles function directly + let mut processors = amdsmi_get_processor_handles(socket_handle) + .expect("Failed to get processor handles for socket"); + + // Append the processor handles to the main vector + processor_handles.append(&mut processors); + } + + processor_handles + }}; +} diff --git a/projects/amdsmi/rust-interface/src/amdsmi_wrapper.rs b/projects/amdsmi/rust-interface/src/amdsmi_wrapper.rs new file mode 100644 index 0000000000..72077f4834 --- /dev/null +++ b/projects/amdsmi/rust-interface/src/amdsmi_wrapper.rs @@ -0,0 +1,3072 @@ +/* automatically generated by rust-bindgen 0.70.1 */ + +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#![allow(non_upper_case_globals)] + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { + *byte |= mask; + } else { + *byte &= !mask; + } + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } +} +pub const AMDSMI_MAX_MM_IP_COUNT: u32 = 8; +pub const AMDSMI_MAX_DATE_LENGTH: u32 = 32; +pub const AMDSMI_MAX_STRING_LENGTH: u32 = 256; +pub const AMDSMI_NORMAL_STRING_LENGTH: u32 = 256; +pub const AMDSMI_256_LENGTH: u32 = 256; +pub const AMDSMI_MAX_DEVICES: u32 = 32; +pub const AMDSMI_MAX_NAME: u32 = 32; +pub const AMDSMI_MAX_DRIVER_VERSION_LENGTH: u32 = 80; +pub const AMDSMI_MAX_CONTAINER_TYPE: u32 = 2; +pub const AMDSMI_MAX_CACHE_TYPES: u32 = 10; +pub const AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK: u32 = 64; +pub const AMDSMI_MAX_ACCELERATOR_PROFILE: u32 = 32; +pub const AMDSMI_MAX_CP_PROFILE_RESOURCES: u32 = 32; +pub const AMDSMI_MAX_ACCELERATOR_PARTITIONS: u32 = 8; +pub const AMDSMI_GPU_UUID_SIZE: u32 = 38; +pub const AMDSMI_NUM_HBM_INSTANCES: u32 = 4; +pub const AMDSMI_MAX_NUM_VCN: u32 = 4; +pub const AMDSMI_MAX_NUM_CLKS: u32 = 4; +pub const AMDSMI_MAX_NUM_XGMI_LINKS: u32 = 8; +pub const AMDSMI_MAX_NUM_GFX_CLKS: u32 = 8; +pub const AMDSMI_MAX_AID: u32 = 4; +pub const AMDSMI_MAX_ENGINES: u32 = 8; +pub const AMDSMI_MAX_NUM_JPEG: u32 = 32; +pub const AMDSMI_MAX_NUM_XCC: u32 = 8; +pub const AMDSMI_MAX_NUM_XCP: u32 = 8; +pub const AMDSMI_TIME_FORMAT: &[u8; 20] = b"%02d:%02d:%02d.%03d\0"; +pub const AMDSMI_DATE_FORMAT: &[u8; 35] = b"%04d-%02d-%02d:%02d:%02d:%02d.%03d\0"; +pub const AMDSMI_LIB_VERSION_YEAR: u32 = 24; +pub const AMDSMI_LIB_VERSION_MAJOR: u32 = 7; +pub const AMDSMI_LIB_VERSION_MINOR: u32 = 1; +pub const AMDSMI_LIB_VERSION_RELEASE: u32 = 0; +pub const AMDSMI_MAX_NUM_FREQUENCIES: u32 = 33; +pub const AMDSMI_MAX_FAN_SPEED: u32 = 255; +pub const AMDSMI_NUM_VOLTAGE_CURVE_POINTS: u32 = 3; +pub const AMDSMI_MAX_UTILIZATION_VALUES: u32 = 4; +pub const AMDSMI_MAX_NUM_PM_POLICIES: u32 = 32; +pub const AMDSMI_DEFAULT_VARIANT: i32 = -1; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiInitFlagsT { + AmdsmiInitAllProcessors = 4294967295, + AmdsmiInitAmdCpus = 1, + AmdsmiInitAmdGpus = 2, + AmdsmiInitNonAmdCpus = 4, + AmdsmiInitNonAmdGpus = 8, + AmdsmiInitAmdApus = 3, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiMmIpT { + AmdsmiMmUvd = 0, + AmdsmiMmVce = 1, + AmdsmiMmVcn = 2, + AmdsmiMmMax = 3, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiContainerTypesT { + AmdsmiContainerLxc = 0, + AmdsmiContainerDocker = 1, +} +pub type AmdsmiProcessorHandle = *mut ::std::os::raw::c_void; +pub type AmdsmiSocketHandle = *mut ::std::os::raw::c_void; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum ProcessorTypeT { + AmdsmiProcessorTypeUnknown = 0, + AmdsmiProcessorTypeAmdGpu = 1, + AmdsmiProcessorTypeAmdCpu = 2, + AmdsmiProcessorTypeNonAmdGpu = 3, + AmdsmiProcessorTypeNonAmdCpu = 4, + AmdsmiProcessorTypeAmdCpuCore = 5, + AmdsmiProcessorTypeAmdApu = 6, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiStatusT { + AmdsmiStatusSuccess = 0, + AmdsmiStatusInval = 1, + AmdsmiStatusNotSupported = 2, + AmdsmiStatusNotYetImplemented = 3, + AmdsmiStatusFailLoadModule = 4, + AmdsmiStatusFailLoadSymbol = 5, + AmdsmiStatusDrmError = 6, + AmdsmiStatusApiFailed = 7, + AmdsmiStatusTimeout = 8, + AmdsmiStatusRetry = 9, + AmdsmiStatusNoPerm = 10, + AmdsmiStatusInterrupt = 11, + AmdsmiStatusIo = 12, + AmdsmiStatusAddressFault = 13, + AmdsmiStatusFileError = 14, + AmdsmiStatusOutOfResources = 15, + AmdsmiStatusInternalException = 16, + AmdsmiStatusInputOutOfBounds = 17, + AmdsmiStatusInitError = 18, + AmdsmiStatusRefcountOverflow = 19, + AmdsmiStatusBusy = 30, + AmdsmiStatusNotFound = 31, + AmdsmiStatusNotInit = 32, + AmdsmiStatusNoSlot = 33, + AmdsmiStatusDriverNotLoaded = 34, + AmdsmiStatusNoData = 40, + AmdsmiStatusInsufficientSize = 41, + AmdsmiStatusUnexpectedSize = 42, + AmdsmiStatusUnexpectedData = 43, + AmdsmiStatusNonAmdCpu = 44, + AmdsmiStatusNoEnergyDrv = 45, + AmdsmiStatusNoMsrDrv = 46, + AmdsmiStatusNoHsmpDrv = 47, + AmdsmiStatusNoHsmpSup = 48, + AmdsmiStatusNoHsmpMsgSup = 49, + AmdsmiStatusHsmpTimeout = 50, + AmdsmiStatusNoDrv = 51, + AmdsmiStatusFileNotFound = 52, + AmdsmiStatusArgPtrNull = 53, + AmdsmiStatusAmdgpuRestartErr = 54, + AmdsmiStatusSettingUnavailable = 55, + AmdsmiStatusMapError = 4294967294, + AmdsmiStatusUnknownError = 4294967295, +} +impl AmdsmiClkTypeT { + pub const AmdsmiClkTypeFirst: AmdsmiClkTypeT = AmdsmiClkTypeT::AmdsmiClkTypeSys; +} +impl AmdsmiClkTypeT { + pub const AmdsmiClkTypeGfx: AmdsmiClkTypeT = AmdsmiClkTypeT::AmdsmiClkTypeSys; +} +impl AmdsmiClkTypeT { + pub const AmdsmiClkTypeMax: AmdsmiClkTypeT = AmdsmiClkTypeT::AmdsmiClkTypeDclk1; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiClkTypeT { + AmdsmiClkTypeSys = 0, + AmdsmiClkTypeDf = 1, + AmdsmiClkTypeDcef = 2, + AmdsmiClkTypeSoc = 3, + AmdsmiClkTypeMem = 4, + AmdsmiClkTypePcie = 5, + AmdsmiClkTypeVclk0 = 6, + AmdsmiClkTypeVclk1 = 7, + AmdsmiClkTypeDclk0 = 8, + AmdsmiClkTypeDclk1 = 9, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiAcceleratorPartitionTypeT { + AmdsmiAcceleratorPartitionInvalid = 0, + AmdsmiAcceleratorPartitionSpx = 1, + AmdsmiAcceleratorPartitionDpx = 2, + AmdsmiAcceleratorPartitionTpx = 3, + AmdsmiAcceleratorPartitionQpx = 4, + AmdsmiAcceleratorPartitionCpx = 5, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiComputePartitionTypeT { + AmdsmiComputePartitionInvalid = 0, + AmdsmiComputePartitionSpx = 1, + AmdsmiComputePartitionDpx = 2, + AmdsmiComputePartitionTpx = 3, + AmdsmiComputePartitionQpx = 4, + AmdsmiComputePartitionCpx = 5, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiMemoryPartitionTypeT { + AmdsmiMemoryPartitionUnknown = 0, + AmdsmiMemoryPartitionNps1 = 1, + AmdsmiMemoryPartitionNps2 = 2, + AmdsmiMemoryPartitionNps4 = 3, + AmdsmiMemoryPartitionNps8 = 4, +} +impl AmdsmiTemperatureTypeT { + pub const AmdsmiTemperatureTypeFirst: AmdsmiTemperatureTypeT = + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeEdge; +} +impl AmdsmiTemperatureTypeT { + pub const AmdsmiTemperatureTypeJunction: AmdsmiTemperatureTypeT = + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypeHotspot; +} +impl AmdsmiTemperatureTypeT { + pub const AmdsmiTemperatureTypeMax: AmdsmiTemperatureTypeT = + AmdsmiTemperatureTypeT::AmdsmiTemperatureTypePlx; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiTemperatureTypeT { + AmdsmiTemperatureTypeEdge = 0, + AmdsmiTemperatureTypeHotspot = 1, + AmdsmiTemperatureTypeVram = 2, + AmdsmiTemperatureTypeHbm0 = 3, + AmdsmiTemperatureTypeHbm1 = 4, + AmdsmiTemperatureTypeHbm2 = 5, + AmdsmiTemperatureTypeHbm3 = 6, + AmdsmiTemperatureTypePlx = 7, +} +impl AmdsmiFwBlockT { + pub const AmdsmiFwIdFirst: AmdsmiFwBlockT = AmdsmiFwBlockT::AmdsmiFwIdSmu; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiFwBlockT { + AmdsmiFwIdSmu = 1, + AmdsmiFwIdCpCe = 2, + AmdsmiFwIdCpPfp = 3, + AmdsmiFwIdCpMe = 4, + AmdsmiFwIdCpMecJt1 = 5, + AmdsmiFwIdCpMecJt2 = 6, + AmdsmiFwIdCpMec1 = 7, + AmdsmiFwIdCpMec2 = 8, + AmdsmiFwIdRlc = 9, + AmdsmiFwIdSdma0 = 10, + AmdsmiFwIdSdma1 = 11, + AmdsmiFwIdSdma2 = 12, + AmdsmiFwIdSdma3 = 13, + AmdsmiFwIdSdma4 = 14, + AmdsmiFwIdSdma5 = 15, + AmdsmiFwIdSdma6 = 16, + AmdsmiFwIdSdma7 = 17, + AmdsmiFwIdVcn = 18, + AmdsmiFwIdUvd = 19, + AmdsmiFwIdVce = 20, + AmdsmiFwIdIsp = 21, + AmdsmiFwIdDmcuEram = 22, + AmdsmiFwIdDmcuIsr = 23, + AmdsmiFwIdRlcRestoreListGpmMem = 24, + AmdsmiFwIdRlcRestoreListSrmMem = 25, + AmdsmiFwIdRlcRestoreListCntl = 26, + AmdsmiFwIdRlcV = 27, + AmdsmiFwIdMmsch = 28, + AmdsmiFwIdPspSysdrv = 29, + AmdsmiFwIdPspSosdrv = 30, + AmdsmiFwIdPspToc = 31, + AmdsmiFwIdPspKeydb = 32, + AmdsmiFwIdDfc = 33, + AmdsmiFwIdPspSpl = 34, + AmdsmiFwIdDrvCap = 35, + AmdsmiFwIdMc = 36, + AmdsmiFwIdPspBl = 37, + AmdsmiFwIdCpPm4 = 38, + AmdsmiFwIdRlcP = 39, + AmdsmiFwIdSecPolicyStage2 = 40, + AmdsmiFwIdRegAccessWhitelist = 41, + AmdsmiFwIdImuDram = 42, + AmdsmiFwIdImuIram = 43, + AmdsmiFwIdSdmaTh0 = 44, + AmdsmiFwIdSdmaTh1 = 45, + AmdsmiFwIdCpMes = 46, + AmdsmiFwIdMesKiq = 47, + AmdsmiFwIdMesStack = 48, + AmdsmiFwIdMesThread1 = 49, + AmdsmiFwIdMesThread1Stack = 50, + AmdsmiFwIdRlx6 = 51, + AmdsmiFwIdRlx6DramBoot = 52, + AmdsmiFwIdRs64Me = 53, + AmdsmiFwIdRs64MeP0Data = 54, + AmdsmiFwIdRs64MeP1Data = 55, + AmdsmiFwIdRs64Pfp = 56, + AmdsmiFwIdRs64PfpP0Data = 57, + AmdsmiFwIdRs64PfpP1Data = 58, + AmdsmiFwIdRs64Mec = 59, + AmdsmiFwIdRs64MecP0Data = 60, + AmdsmiFwIdRs64MecP1Data = 61, + AmdsmiFwIdRs64MecP2Data = 62, + AmdsmiFwIdRs64MecP3Data = 63, + AmdsmiFwIdPptable = 64, + AmdsmiFwIdPspSoc = 65, + AmdsmiFwIdPspDbg = 66, + AmdsmiFwIdPspIntf = 67, + AmdsmiFwIdRlx6Core1 = 68, + AmdsmiFwIdRlx6DramBootCore1 = 69, + AmdsmiFwIdRlcvLx7 = 70, + AmdsmiFwIdRlcSaveRestoreList = 71, + AmdsmiFwIdAsd = 72, + AmdsmiFwIdTaRas = 73, + AmdsmiFwIdTaXgmi = 74, + AmdsmiFwIdRlcSrlg = 75, + AmdsmiFwIdRlcSrls = 76, + AmdsmiFwIdPm = 77, + AmdsmiFwIdDmcu = 78, + AmdsmiFwIdMax = 79, +} +impl AmdsmiVramTypeT { + pub const AmdsmiVramTypeMax: AmdsmiVramTypeT = AmdsmiVramTypeT::AmdsmiVramTypeGddr7; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiVramTypeT { + AmdsmiVramTypeUnknown = 0, + AmdsmiVramTypeHbm = 1, + AmdsmiVramTypeHbm2 = 2, + AmdsmiVramTypeHbm2e = 3, + AmdsmiVramTypeHbm3 = 4, + AmdsmiVramTypeDdr2 = 10, + AmdsmiVramTypeDdr3 = 11, + AmdsmiVramTypeDdr4 = 12, + AmdsmiVramTypeGddr1 = 17, + AmdsmiVramTypeGddr2 = 18, + AmdsmiVramTypeGddr3 = 19, + AmdsmiVramTypeGddr4 = 20, + AmdsmiVramTypeGddr5 = 21, + AmdsmiVramTypeGddr6 = 22, + AmdsmiVramTypeGddr7 = 23, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiVramVendorTypeT { + AmdsmiVramVendorPlaceholder0 = 0, + AmdsmiVramVendorSamsung = 1, + AmdsmiVramVendorInfineon = 2, + AmdsmiVramVendorElpida = 3, + AmdsmiVramVendorEtron = 4, + AmdsmiVramVendorNanya = 5, + AmdsmiVramVendorHynix = 6, + AmdsmiVramVendorMosel = 7, + AmdsmiVramVendorWinbond = 8, + AmdsmiVramVendorEsmt = 9, + AmdsmiVramVendorPlaceholder1 = 10, + AmdsmiVramVendorPlaceholder2 = 11, + AmdsmiVramVendorPlaceholder3 = 12, + AmdsmiVramVendorPlaceholder4 = 13, + AmdsmiVramVendorPlaceholder5 = 14, + AmdsmiVramVendorMicron = 15, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiRangeT { + pub lower_bound: u64, + pub upper_bound: u64, + pub reserved: [u64; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiRangeT"][::std::mem::size_of::() - 32usize]; + ["Alignment of AmdsmiRangeT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiRangeT::lower_bound"] + [::std::mem::offset_of!(AmdsmiRangeT, lower_bound) - 0usize]; + ["Offset of field: AmdsmiRangeT::upper_bound"] + [::std::mem::offset_of!(AmdsmiRangeT, upper_bound) - 8usize]; + ["Offset of field: AmdsmiRangeT::reserved"] + [::std::mem::offset_of!(AmdsmiRangeT, reserved) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiXgmiInfoT { + pub xgmi_lanes: u8, + pub xgmi_hive_id: u64, + pub xgmi_node_id: u64, + pub index: u32, + pub reserved: [u32; 9usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiXgmiInfoT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiXgmiInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiXgmiInfoT::xgmi_lanes"] + [::std::mem::offset_of!(AmdsmiXgmiInfoT, xgmi_lanes) - 0usize]; + ["Offset of field: AmdsmiXgmiInfoT::xgmi_hive_id"] + [::std::mem::offset_of!(AmdsmiXgmiInfoT, xgmi_hive_id) - 8usize]; + ["Offset of field: AmdsmiXgmiInfoT::xgmi_node_id"] + [::std::mem::offset_of!(AmdsmiXgmiInfoT, xgmi_node_id) - 16usize]; + ["Offset of field: AmdsmiXgmiInfoT::index"] + [::std::mem::offset_of!(AmdsmiXgmiInfoT, index) - 24usize]; + ["Offset of field: AmdsmiXgmiInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiXgmiInfoT, reserved) - 28usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiVramUsageT { + pub vram_total: u32, + pub vram_used: u32, + pub reserved: [u32; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiVramUsageT"][::std::mem::size_of::() - 16usize]; + ["Alignment of AmdsmiVramUsageT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiVramUsageT::vram_total"] + [::std::mem::offset_of!(AmdsmiVramUsageT, vram_total) - 0usize]; + ["Offset of field: AmdsmiVramUsageT::vram_used"] + [::std::mem::offset_of!(AmdsmiVramUsageT, vram_used) - 4usize]; + ["Offset of field: AmdsmiVramUsageT::reserved"] + [::std::mem::offset_of!(AmdsmiVramUsageT, reserved) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiViolationStatusT { + pub reference_timestamp: u64, + pub violation_timestamp: u64, + pub acc_counter: u64, + pub acc_prochot_thrm: u64, + pub acc_ppt_pwr: u64, + pub acc_socket_thrm: u64, + pub acc_vr_thrm: u64, + pub acc_hbm_thrm: u64, + pub per_prochot_thrm: u64, + pub per_ppt_pwr: u64, + pub per_socket_thrm: u64, + pub per_vr_thrm: u64, + pub per_hbm_thrm: u64, + pub active_prochot_thrm: u8, + pub active_ppt_pwr: u8, + pub active_socket_thrm: u8, + pub active_vr_thrm: u8, + pub active_hbm_thrm: u8, + pub reserved: [u64; 30usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiViolationStatusT"][::std::mem::size_of::() - 352usize]; + ["Alignment of AmdsmiViolationStatusT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiViolationStatusT::reference_timestamp"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, reference_timestamp) - 0usize]; + ["Offset of field: AmdsmiViolationStatusT::violation_timestamp"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, violation_timestamp) - 8usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_counter"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_counter) - 16usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_prochot_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_prochot_thrm) - 24usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_ppt_pwr"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_ppt_pwr) - 32usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_socket_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_socket_thrm) - 40usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_vr_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_vr_thrm) - 48usize]; + ["Offset of field: AmdsmiViolationStatusT::acc_hbm_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, acc_hbm_thrm) - 56usize]; + ["Offset of field: AmdsmiViolationStatusT::per_prochot_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, per_prochot_thrm) - 64usize]; + ["Offset of field: AmdsmiViolationStatusT::per_ppt_pwr"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, per_ppt_pwr) - 72usize]; + ["Offset of field: AmdsmiViolationStatusT::per_socket_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, per_socket_thrm) - 80usize]; + ["Offset of field: AmdsmiViolationStatusT::per_vr_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, per_vr_thrm) - 88usize]; + ["Offset of field: AmdsmiViolationStatusT::per_hbm_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, per_hbm_thrm) - 96usize]; + ["Offset of field: AmdsmiViolationStatusT::active_prochot_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, active_prochot_thrm) - 104usize]; + ["Offset of field: AmdsmiViolationStatusT::active_ppt_pwr"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, active_ppt_pwr) - 105usize]; + ["Offset of field: AmdsmiViolationStatusT::active_socket_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, active_socket_thrm) - 106usize]; + ["Offset of field: AmdsmiViolationStatusT::active_vr_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, active_vr_thrm) - 107usize]; + ["Offset of field: AmdsmiViolationStatusT::active_hbm_thrm"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, active_hbm_thrm) - 108usize]; + ["Offset of field: AmdsmiViolationStatusT::reserved"] + [::std::mem::offset_of!(AmdsmiViolationStatusT, reserved) - 112usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiFrequencyRangeT { + pub supported_freq_range: AmdsmiRangeT, + pub current_freq_range: AmdsmiRangeT, + pub reserved: [u32; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiFrequencyRangeT"][::std::mem::size_of::() - 96usize]; + ["Alignment of AmdsmiFrequencyRangeT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiFrequencyRangeT::supported_freq_range"] + [::std::mem::offset_of!(AmdsmiFrequencyRangeT, supported_freq_range) - 0usize]; + ["Offset of field: AmdsmiFrequencyRangeT::current_freq_range"] + [::std::mem::offset_of!(AmdsmiFrequencyRangeT, current_freq_range) - 32usize]; + ["Offset of field: AmdsmiFrequencyRangeT::reserved"] + [::std::mem::offset_of!(AmdsmiFrequencyRangeT, reserved) - 64usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub union AmdsmiBdfT { + pub __bindgen_anon_1: AmdsmiBdfTBindgenTy1, + pub as_uint: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiBdfTBindgenTy1 { + pub _bitfield_align_1: [u64; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiBdfTBindgenTy1"][::std::mem::size_of::() - 8usize]; + ["Alignment of AmdsmiBdfTBindgenTy1"][::std::mem::align_of::() - 8usize]; +}; +impl AmdsmiBdfTBindgenTy1 { + #[inline] + pub fn function_number(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 3u8) as u64) } + } + #[inline] + pub fn set_function_number(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 3u8, val as u64) + } + } + #[inline] + pub fn device_number(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 5u8) as u64) } + } + #[inline] + pub fn set_device_number(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 5u8, val as u64) + } + } + #[inline] + pub fn bus_number(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u64) } + } + #[inline] + pub fn set_bus_number(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 8u8, val as u64) + } + } + #[inline] + pub fn domain_number(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 48u8) as u64) } + } + #[inline] + pub fn set_domain_number(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(16usize, 48u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + function_number: u64, + device_number: u64, + bus_number: u64, + domain_number: u64, + ) -> __BindgenBitfieldUnit<[u8; 8usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 3u8, { + let function_number: u64 = unsafe { ::std::mem::transmute(function_number) }; + function_number as u64 + }); + __bindgen_bitfield_unit.set(3usize, 5u8, { + let device_number: u64 = unsafe { ::std::mem::transmute(device_number) }; + device_number as u64 + }); + __bindgen_bitfield_unit.set(8usize, 8u8, { + let bus_number: u64 = unsafe { ::std::mem::transmute(bus_number) }; + bus_number as u64 + }); + __bindgen_bitfield_unit.set(16usize, 48u8, { + let domain_number: u64 = unsafe { ::std::mem::transmute(domain_number) }; + domain_number as u64 + }); + __bindgen_bitfield_unit + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiBdfT"][::std::mem::size_of::() - 8usize]; + ["Alignment of AmdsmiBdfT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiBdfT::as_uint"][::std::mem::offset_of!(AmdsmiBdfT, as_uint) - 0usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiCardFormFactorT { + AmdsmiCardFormFactorPcie = 0, + AmdsmiCardFormFactorOam = 1, + AmdsmiCardFormFactorCem = 2, + AmdsmiCardFormFactorUnknown = 3, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPcieInfoT { + pub pcie_static: AmdsmiPcieInfoTPcieStatic, + pub pcie_metric: AmdsmiPcieInfoTPcieMetric, + pub reserved: [u64; 32usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPcieInfoTPcieStatic { + pub max_pcie_width: u16, + pub max_pcie_speed: u32, + pub pcie_interface_version: u32, + pub slot_type: AmdsmiCardFormFactorT, + pub reserved: [u64; 10usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPcieInfoTPcieStatic"] + [::std::mem::size_of::() - 96usize]; + ["Alignment of AmdsmiPcieInfoTPcieStatic"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPcieInfoTPcieStatic::max_pcie_width"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieStatic, max_pcie_width) - 0usize]; + ["Offset of field: AmdsmiPcieInfoTPcieStatic::max_pcie_speed"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieStatic, max_pcie_speed) - 4usize]; + ["Offset of field: AmdsmiPcieInfoTPcieStatic::pcie_interface_version"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieStatic, pcie_interface_version) - 8usize]; + ["Offset of field: AmdsmiPcieInfoTPcieStatic::slot_type"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieStatic, slot_type) - 12usize]; + ["Offset of field: AmdsmiPcieInfoTPcieStatic::reserved"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieStatic, reserved) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPcieInfoTPcieMetric { + pub pcie_width: u16, + pub pcie_speed: u32, + pub pcie_bandwidth: u32, + pub pcie_replay_count: u64, + pub pcie_l0_to_recovery_count: u64, + pub pcie_replay_roll_over_count: u64, + pub pcie_nak_sent_count: u64, + pub pcie_nak_received_count: u64, + pub pcie_lc_perf_other_end_recovery_count: u32, + pub reserved: [u64; 12usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPcieInfoTPcieMetric"] + [::std::mem::size_of::() - 160usize]; + ["Alignment of AmdsmiPcieInfoTPcieMetric"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_width"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_width) - 0usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_speed"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_speed) - 4usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_bandwidth"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_bandwidth) - 8usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_replay_count"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_replay_count) - 16usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_l0_to_recovery_count"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_l0_to_recovery_count) - 24usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_replay_roll_over_count"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_replay_roll_over_count) - 32usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_nak_sent_count"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_nak_sent_count) - 40usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_nak_received_count"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, pcie_nak_received_count) - 48usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::pcie_lc_perf_other_end_recovery_count"][::std::mem::offset_of!( + AmdsmiPcieInfoTPcieMetric, + pcie_lc_perf_other_end_recovery_count + ) + - 56usize]; + ["Offset of field: AmdsmiPcieInfoTPcieMetric::reserved"] + [::std::mem::offset_of!(AmdsmiPcieInfoTPcieMetric, reserved) - 64usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPcieInfoT"][::std::mem::size_of::() - 512usize]; + ["Alignment of AmdsmiPcieInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPcieInfoT::pcie_static"] + [::std::mem::offset_of!(AmdsmiPcieInfoT, pcie_static) - 0usize]; + ["Offset of field: AmdsmiPcieInfoT::pcie_metric"] + [::std::mem::offset_of!(AmdsmiPcieInfoT, pcie_metric) - 96usize]; + ["Offset of field: AmdsmiPcieInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiPcieInfoT, reserved) - 256usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPowerCapInfoT { + pub power_cap: u64, + pub default_power_cap: u64, + pub dpm_cap: u64, + pub min_power_cap: u64, + pub max_power_cap: u64, + pub reserved: [u64; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPowerCapInfoT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiPowerCapInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPowerCapInfoT::power_cap"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, power_cap) - 0usize]; + ["Offset of field: AmdsmiPowerCapInfoT::default_power_cap"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, default_power_cap) - 8usize]; + ["Offset of field: AmdsmiPowerCapInfoT::dpm_cap"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, dpm_cap) - 16usize]; + ["Offset of field: AmdsmiPowerCapInfoT::min_power_cap"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, min_power_cap) - 24usize]; + ["Offset of field: AmdsmiPowerCapInfoT::max_power_cap"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, max_power_cap) - 32usize]; + ["Offset of field: AmdsmiPowerCapInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiPowerCapInfoT, reserved) - 40usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiVbiosInfoT { + pub name: [::std::os::raw::c_char; 256usize], + pub build_date: [::std::os::raw::c_char; 32usize], + pub part_number: [::std::os::raw::c_char; 256usize], + pub version: [::std::os::raw::c_char; 256usize], + pub reserved: [u64; 32usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiVbiosInfoT"][::std::mem::size_of::() - 1056usize]; + ["Alignment of AmdsmiVbiosInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiVbiosInfoT::name"] + [::std::mem::offset_of!(AmdsmiVbiosInfoT, name) - 0usize]; + ["Offset of field: AmdsmiVbiosInfoT::build_date"] + [::std::mem::offset_of!(AmdsmiVbiosInfoT, build_date) - 256usize]; + ["Offset of field: AmdsmiVbiosInfoT::part_number"] + [::std::mem::offset_of!(AmdsmiVbiosInfoT, part_number) - 288usize]; + ["Offset of field: AmdsmiVbiosInfoT::version"] + [::std::mem::offset_of!(AmdsmiVbiosInfoT, version) - 544usize]; + ["Offset of field: AmdsmiVbiosInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiVbiosInfoT, reserved) - 800usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiCachePropertyTypeT { + AmdsmiCachePropertyEnabled = 1, + AmdsmiCachePropertyDataCache = 2, + AmdsmiCachePropertyInstCache = 4, + AmdsmiCachePropertyCpuCache = 8, + AmdsmiCachePropertySimdCache = 16, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiGpuCacheInfoT { + pub num_cache_types: u32, + pub cache: [AmdsmiGpuCacheInfoTCache; 10usize], + pub reserved: [u32; 15usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiGpuCacheInfoTCache { + pub cache_properties: u32, + pub cache_size: u32, + pub cache_level: u32, + pub max_num_cu_shared: u32, + pub num_cache_instance: u32, + pub reserved: [u32; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiGpuCacheInfoTCache"] + [::std::mem::size_of::() - 32usize]; + ["Alignment of AmdsmiGpuCacheInfoTCache"] + [::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::cache_properties"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, cache_properties) - 0usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::cache_size"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, cache_size) - 4usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::cache_level"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, cache_level) - 8usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::max_num_cu_shared"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, max_num_cu_shared) - 12usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::num_cache_instance"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, num_cache_instance) - 16usize]; + ["Offset of field: AmdsmiGpuCacheInfoTCache::reserved"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoTCache, reserved) - 20usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiGpuCacheInfoT"][::std::mem::size_of::() - 384usize]; + ["Alignment of AmdsmiGpuCacheInfoT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiGpuCacheInfoT::num_cache_types"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoT, num_cache_types) - 0usize]; + ["Offset of field: AmdsmiGpuCacheInfoT::cache"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoT, cache) - 4usize]; + ["Offset of field: AmdsmiGpuCacheInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiGpuCacheInfoT, reserved) - 324usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiFwInfoT { + pub num_fw_info: u8, + pub fw_info_list: [AmdsmiFwInfoTFwInfoList; 79usize], + pub reserved: [u32; 7usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiFwInfoTFwInfoList { + pub fw_id: AmdsmiFwBlockT, + pub fw_version: u64, + pub reserved: [u64; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiFwInfoTFwInfoList"][::std::mem::size_of::() - 32usize]; + ["Alignment of AmdsmiFwInfoTFwInfoList"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiFwInfoTFwInfoList::fw_id"] + [::std::mem::offset_of!(AmdsmiFwInfoTFwInfoList, fw_id) - 0usize]; + ["Offset of field: AmdsmiFwInfoTFwInfoList::fw_version"] + [::std::mem::offset_of!(AmdsmiFwInfoTFwInfoList, fw_version) - 8usize]; + ["Offset of field: AmdsmiFwInfoTFwInfoList::reserved"] + [::std::mem::offset_of!(AmdsmiFwInfoTFwInfoList, reserved) - 16usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiFwInfoT"][::std::mem::size_of::() - 2568usize]; + ["Alignment of AmdsmiFwInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiFwInfoT::num_fw_info"] + [::std::mem::offset_of!(AmdsmiFwInfoT, num_fw_info) - 0usize]; + ["Offset of field: AmdsmiFwInfoT::fw_info_list"] + [::std::mem::offset_of!(AmdsmiFwInfoT, fw_info_list) - 8usize]; + ["Offset of field: AmdsmiFwInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiFwInfoT, reserved) - 2536usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiAsicInfoT { + pub market_name: [::std::os::raw::c_char; 256usize], + pub vendor_id: u32, + pub vendor_name: [::std::os::raw::c_char; 256usize], + pub subvendor_id: u32, + pub device_id: u64, + pub rev_id: u32, + pub asic_serial: [::std::os::raw::c_char; 256usize], + pub oam_id: u32, + pub num_of_compute_units: u32, + pub target_graphics_version: u64, + pub reserved: [u32; 22usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiAsicInfoT"][::std::mem::size_of::() - 896usize]; + ["Alignment of AmdsmiAsicInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiAsicInfoT::market_name"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, market_name) - 0usize]; + ["Offset of field: AmdsmiAsicInfoT::vendor_id"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, vendor_id) - 256usize]; + ["Offset of field: AmdsmiAsicInfoT::vendor_name"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, vendor_name) - 260usize]; + ["Offset of field: AmdsmiAsicInfoT::subvendor_id"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, subvendor_id) - 516usize]; + ["Offset of field: AmdsmiAsicInfoT::device_id"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, device_id) - 520usize]; + ["Offset of field: AmdsmiAsicInfoT::rev_id"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, rev_id) - 528usize]; + ["Offset of field: AmdsmiAsicInfoT::asic_serial"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, asic_serial) - 532usize]; + ["Offset of field: AmdsmiAsicInfoT::oam_id"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, oam_id) - 788usize]; + ["Offset of field: AmdsmiAsicInfoT::num_of_compute_units"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, num_of_compute_units) - 792usize]; + ["Offset of field: AmdsmiAsicInfoT::target_graphics_version"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, target_graphics_version) - 800usize]; + ["Offset of field: AmdsmiAsicInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiAsicInfoT, reserved) - 808usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiKfdInfoT { + pub kfd_id: u64, + pub node_id: u32, + pub current_partition_id: u32, + pub reserved: [u32; 12usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiKfdInfoT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiKfdInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiKfdInfoT::kfd_id"] + [::std::mem::offset_of!(AmdsmiKfdInfoT, kfd_id) - 0usize]; + ["Offset of field: AmdsmiKfdInfoT::node_id"] + [::std::mem::offset_of!(AmdsmiKfdInfoT, node_id) - 8usize]; + ["Offset of field: AmdsmiKfdInfoT::current_partition_id"] + [::std::mem::offset_of!(AmdsmiKfdInfoT, current_partition_id) - 12usize]; + ["Offset of field: AmdsmiKfdInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiKfdInfoT, reserved) - 16usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub union AmdsmiNpsCapsT { + pub amdsmi_nps_flags_t: AmdsmiNpsCapsTNpsFlags, + pub nps_cap_mask: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiNpsCapsTNpsFlags { + pub _bitfield_align_1: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiNpsCapsTNpsFlags"][::std::mem::size_of::() - 4usize]; + ["Alignment of AmdsmiNpsCapsTNpsFlags"] + [::std::mem::align_of::() - 4usize]; +}; +impl AmdsmiNpsCapsTNpsFlags { + #[inline] + pub fn nps1_cap(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_nps1_cap(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn nps2_cap(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_nps2_cap(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn nps4_cap(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } + } + #[inline] + pub fn set_nps4_cap(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn nps8_cap(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } + } + #[inline] + pub fn set_nps8_cap(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(3usize, 1u8, val as u64) + } + } + #[inline] + pub fn reserved(&self) -> u32 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 28u8) as u32) } + } + #[inline] + pub fn set_reserved(&mut self, val: u32) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 28u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + nps1_cap: u32, + nps2_cap: u32, + nps4_cap: u32, + nps8_cap: u32, + reserved: u32, + ) -> __BindgenBitfieldUnit<[u8; 4usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let nps1_cap: u32 = unsafe { ::std::mem::transmute(nps1_cap) }; + nps1_cap as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let nps2_cap: u32 = unsafe { ::std::mem::transmute(nps2_cap) }; + nps2_cap as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let nps4_cap: u32 = unsafe { ::std::mem::transmute(nps4_cap) }; + nps4_cap as u64 + }); + __bindgen_bitfield_unit.set(3usize, 1u8, { + let nps8_cap: u32 = unsafe { ::std::mem::transmute(nps8_cap) }; + nps8_cap as u64 + }); + __bindgen_bitfield_unit.set(4usize, 28u8, { + let reserved: u32 = unsafe { ::std::mem::transmute(reserved) }; + reserved as u64 + }); + __bindgen_bitfield_unit + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiNpsCapsT"][::std::mem::size_of::() - 4usize]; + ["Alignment of AmdsmiNpsCapsT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiNpsCapsT::amdsmi_nps_flags_t"] + [::std::mem::offset_of!(AmdsmiNpsCapsT, amdsmi_nps_flags_t) - 0usize]; + ["Offset of field: AmdsmiNpsCapsT::nps_cap_mask"] + [::std::mem::offset_of!(AmdsmiNpsCapsT, nps_cap_mask) - 0usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AmdsmiAcceleratorPartitionProfileT { + pub profile_type: AmdsmiAcceleratorPartitionTypeT, + pub num_partitions: u32, + pub memory_caps: AmdsmiNpsCapsT, + pub profile_index: u32, + pub num_resources: u32, + pub resources: [[u32; 32usize]; 8usize], + pub reserved: [u64; 13usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiAcceleratorPartitionProfileT"] + [::std::mem::size_of::() - 1152usize]; + ["Alignment of AmdsmiAcceleratorPartitionProfileT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::profile_type"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, profile_type) - 0usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::num_partitions"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, num_partitions) - 4usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::memory_caps"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, memory_caps) - 8usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::profile_index"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, profile_index) - 12usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::num_resources"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, num_resources) - 16usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::resources"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, resources) - 20usize]; + ["Offset of field: AmdsmiAcceleratorPartitionProfileT::reserved"] + [::std::mem::offset_of!(AmdsmiAcceleratorPartitionProfileT, reserved) - 1048usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiLinkTypeT { + AmdsmiLinkTypeInternal = 0, + AmdsmiLinkTypeXgmi = 1, + AmdsmiLinkTypePcie = 2, + AmdsmiLinkTypeNotApplicable = 3, + AmdsmiLinkTypeUnknown = 4, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AmdsmiLinkMetricsT { + pub num_links: u32, + pub links: [AmdsmiLinkMetricsTLinks; 64usize], + pub reserved: [u64; 7usize], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct AmdsmiLinkMetricsTLinks { + pub bdf: AmdsmiBdfT, + pub bit_rate: u32, + pub max_bandwidth: u32, + pub link_type: AmdsmiLinkTypeT, + pub read: u64, + pub write: u64, + pub reserved: [u64; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiLinkMetricsTLinks"][::std::mem::size_of::() - 56usize]; + ["Alignment of AmdsmiLinkMetricsTLinks"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::bdf"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, bdf) - 0usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::bit_rate"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, bit_rate) - 8usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::max_bandwidth"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, max_bandwidth) - 12usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::link_type"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, link_type) - 16usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::read"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, read) - 24usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::write"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, write) - 32usize]; + ["Offset of field: AmdsmiLinkMetricsTLinks::reserved"] + [::std::mem::offset_of!(AmdsmiLinkMetricsTLinks, reserved) - 40usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiLinkMetricsT"][::std::mem::size_of::() - 3648usize]; + ["Alignment of AmdsmiLinkMetricsT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiLinkMetricsT::num_links"] + [::std::mem::offset_of!(AmdsmiLinkMetricsT, num_links) - 0usize]; + ["Offset of field: AmdsmiLinkMetricsT::links"] + [::std::mem::offset_of!(AmdsmiLinkMetricsT, links) - 8usize]; + ["Offset of field: AmdsmiLinkMetricsT::reserved"] + [::std::mem::offset_of!(AmdsmiLinkMetricsT, reserved) - 3592usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiVramInfoT { + pub vram_type: AmdsmiVramTypeT, + pub vram_vendor: AmdsmiVramVendorTypeT, + pub vram_size: u64, + pub vram_bit_width: u32, + pub reserved: [u64; 5usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiVramInfoT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiVramInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiVramInfoT::vram_type"] + [::std::mem::offset_of!(AmdsmiVramInfoT, vram_type) - 0usize]; + ["Offset of field: AmdsmiVramInfoT::vram_vendor"] + [::std::mem::offset_of!(AmdsmiVramInfoT, vram_vendor) - 4usize]; + ["Offset of field: AmdsmiVramInfoT::vram_size"] + [::std::mem::offset_of!(AmdsmiVramInfoT, vram_size) - 8usize]; + ["Offset of field: AmdsmiVramInfoT::vram_bit_width"] + [::std::mem::offset_of!(AmdsmiVramInfoT, vram_bit_width) - 16usize]; + ["Offset of field: AmdsmiVramInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiVramInfoT, reserved) - 24usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiDriverInfoT { + pub driver_version: [::std::os::raw::c_char; 256usize], + pub driver_date: [::std::os::raw::c_char; 256usize], + pub driver_name: [::std::os::raw::c_char; 256usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiDriverInfoT"][::std::mem::size_of::() - 768usize]; + ["Alignment of AmdsmiDriverInfoT"][::std::mem::align_of::() - 1usize]; + ["Offset of field: AmdsmiDriverInfoT::driver_version"] + [::std::mem::offset_of!(AmdsmiDriverInfoT, driver_version) - 0usize]; + ["Offset of field: AmdsmiDriverInfoT::driver_date"] + [::std::mem::offset_of!(AmdsmiDriverInfoT, driver_date) - 256usize]; + ["Offset of field: AmdsmiDriverInfoT::driver_name"] + [::std::mem::offset_of!(AmdsmiDriverInfoT, driver_name) - 512usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiBoardInfoT { + pub model_number: [::std::os::raw::c_char; 256usize], + pub product_serial: [::std::os::raw::c_char; 256usize], + pub fru_id: [::std::os::raw::c_char; 256usize], + pub product_name: [::std::os::raw::c_char; 256usize], + pub manufacturer_name: [::std::os::raw::c_char; 256usize], + pub reserved: [u64; 32usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiBoardInfoT"][::std::mem::size_of::() - 1536usize]; + ["Alignment of AmdsmiBoardInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiBoardInfoT::model_number"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, model_number) - 0usize]; + ["Offset of field: AmdsmiBoardInfoT::product_serial"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, product_serial) - 256usize]; + ["Offset of field: AmdsmiBoardInfoT::fru_id"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, fru_id) - 512usize]; + ["Offset of field: AmdsmiBoardInfoT::product_name"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, product_name) - 768usize]; + ["Offset of field: AmdsmiBoardInfoT::manufacturer_name"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, manufacturer_name) - 1024usize]; + ["Offset of field: AmdsmiBoardInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiBoardInfoT, reserved) - 1280usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPowerInfoT { + pub current_socket_power: u32, + pub average_socket_power: u32, + pub gfx_voltage: u32, + pub soc_voltage: u32, + pub mem_voltage: u32, + pub power_limit: u32, + pub reserved: [u32; 11usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPowerInfoT"][::std::mem::size_of::() - 68usize]; + ["Alignment of AmdsmiPowerInfoT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiPowerInfoT::current_socket_power"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, current_socket_power) - 0usize]; + ["Offset of field: AmdsmiPowerInfoT::average_socket_power"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, average_socket_power) - 4usize]; + ["Offset of field: AmdsmiPowerInfoT::gfx_voltage"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, gfx_voltage) - 8usize]; + ["Offset of field: AmdsmiPowerInfoT::soc_voltage"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, soc_voltage) - 12usize]; + ["Offset of field: AmdsmiPowerInfoT::mem_voltage"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, mem_voltage) - 16usize]; + ["Offset of field: AmdsmiPowerInfoT::power_limit"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, power_limit) - 20usize]; + ["Offset of field: AmdsmiPowerInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiPowerInfoT, reserved) - 24usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiClkInfoT { + pub clk: u32, + pub min_clk: u32, + pub max_clk: u32, + pub clk_locked: u8, + pub clk_deep_sleep: u8, + pub reserved: [u32; 4usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiClkInfoT"][::std::mem::size_of::() - 32usize]; + ["Alignment of AmdsmiClkInfoT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiClkInfoT::clk"][::std::mem::offset_of!(AmdsmiClkInfoT, clk) - 0usize]; + ["Offset of field: AmdsmiClkInfoT::min_clk"] + [::std::mem::offset_of!(AmdsmiClkInfoT, min_clk) - 4usize]; + ["Offset of field: AmdsmiClkInfoT::max_clk"] + [::std::mem::offset_of!(AmdsmiClkInfoT, max_clk) - 8usize]; + ["Offset of field: AmdsmiClkInfoT::clk_locked"] + [::std::mem::offset_of!(AmdsmiClkInfoT, clk_locked) - 12usize]; + ["Offset of field: AmdsmiClkInfoT::clk_deep_sleep"] + [::std::mem::offset_of!(AmdsmiClkInfoT, clk_deep_sleep) - 13usize]; + ["Offset of field: AmdsmiClkInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiClkInfoT, reserved) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiEngineUsageT { + pub gfx_activity: u32, + pub umc_activity: u32, + pub mm_activity: u32, + pub reserved: [u32; 13usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiEngineUsageT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiEngineUsageT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiEngineUsageT::gfx_activity"] + [::std::mem::offset_of!(AmdsmiEngineUsageT, gfx_activity) - 0usize]; + ["Offset of field: AmdsmiEngineUsageT::umc_activity"] + [::std::mem::offset_of!(AmdsmiEngineUsageT, umc_activity) - 4usize]; + ["Offset of field: AmdsmiEngineUsageT::mm_activity"] + [::std::mem::offset_of!(AmdsmiEngineUsageT, mm_activity) - 8usize]; + ["Offset of field: AmdsmiEngineUsageT::reserved"] + [::std::mem::offset_of!(AmdsmiEngineUsageT, reserved) - 12usize]; +}; +pub type AmdsmiProcessHandleT = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiProcInfoT { + pub name: [::std::os::raw::c_char; 256usize], + pub pid: AmdsmiProcessHandleT, + pub mem: u64, + pub engine_usage: AmdsmiProcInfoTEngineUsage, + pub memory_usage: AmdsmiProcInfoTMemoryUsage, + pub container_name: [::std::os::raw::c_char; 256usize], + pub reserved: [u32; 12usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiProcInfoTEngineUsage { + pub gfx: u64, + pub enc: u64, + pub reserved: [u32; 12usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiProcInfoTEngineUsage"] + [::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiProcInfoTEngineUsage"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiProcInfoTEngineUsage::gfx"] + [::std::mem::offset_of!(AmdsmiProcInfoTEngineUsage, gfx) - 0usize]; + ["Offset of field: AmdsmiProcInfoTEngineUsage::enc"] + [::std::mem::offset_of!(AmdsmiProcInfoTEngineUsage, enc) - 8usize]; + ["Offset of field: AmdsmiProcInfoTEngineUsage::reserved"] + [::std::mem::offset_of!(AmdsmiProcInfoTEngineUsage, reserved) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiProcInfoTMemoryUsage { + pub gtt_mem: u64, + pub cpu_mem: u64, + pub vram_mem: u64, + pub reserved: [u32; 10usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiProcInfoTMemoryUsage"] + [::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiProcInfoTMemoryUsage"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiProcInfoTMemoryUsage::gtt_mem"] + [::std::mem::offset_of!(AmdsmiProcInfoTMemoryUsage, gtt_mem) - 0usize]; + ["Offset of field: AmdsmiProcInfoTMemoryUsage::cpu_mem"] + [::std::mem::offset_of!(AmdsmiProcInfoTMemoryUsage, cpu_mem) - 8usize]; + ["Offset of field: AmdsmiProcInfoTMemoryUsage::vram_mem"] + [::std::mem::offset_of!(AmdsmiProcInfoTMemoryUsage, vram_mem) - 16usize]; + ["Offset of field: AmdsmiProcInfoTMemoryUsage::reserved"] + [::std::mem::offset_of!(AmdsmiProcInfoTMemoryUsage, reserved) - 24usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiProcInfoT"][::std::mem::size_of::() - 704usize]; + ["Alignment of AmdsmiProcInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiProcInfoT::name"] + [::std::mem::offset_of!(AmdsmiProcInfoT, name) - 0usize]; + ["Offset of field: AmdsmiProcInfoT::pid"] + [::std::mem::offset_of!(AmdsmiProcInfoT, pid) - 256usize]; + ["Offset of field: AmdsmiProcInfoT::mem"] + [::std::mem::offset_of!(AmdsmiProcInfoT, mem) - 264usize]; + ["Offset of field: AmdsmiProcInfoT::engine_usage"] + [::std::mem::offset_of!(AmdsmiProcInfoT, engine_usage) - 272usize]; + ["Offset of field: AmdsmiProcInfoT::memory_usage"] + [::std::mem::offset_of!(AmdsmiProcInfoT, memory_usage) - 336usize]; + ["Offset of field: AmdsmiProcInfoT::container_name"] + [::std::mem::offset_of!(AmdsmiProcInfoT, container_name) - 400usize]; + ["Offset of field: AmdsmiProcInfoT::reserved"] + [::std::mem::offset_of!(AmdsmiProcInfoT, reserved) - 656usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiP2pCapabilityT { + pub is_iolink_coherent: u8, + pub is_iolink_atomics_32bit: u8, + pub is_iolink_atomics_64bit: u8, + pub is_iolink_dma: u8, + pub is_iolink_bi_directional: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiP2pCapabilityT"][::std::mem::size_of::() - 5usize]; + ["Alignment of AmdsmiP2pCapabilityT"][::std::mem::align_of::() - 1usize]; + ["Offset of field: AmdsmiP2pCapabilityT::is_iolink_coherent"] + [::std::mem::offset_of!(AmdsmiP2pCapabilityT, is_iolink_coherent) - 0usize]; + ["Offset of field: AmdsmiP2pCapabilityT::is_iolink_atomics_32bit"] + [::std::mem::offset_of!(AmdsmiP2pCapabilityT, is_iolink_atomics_32bit) - 1usize]; + ["Offset of field: AmdsmiP2pCapabilityT::is_iolink_atomics_64bit"] + [::std::mem::offset_of!(AmdsmiP2pCapabilityT, is_iolink_atomics_64bit) - 2usize]; + ["Offset of field: AmdsmiP2pCapabilityT::is_iolink_dma"] + [::std::mem::offset_of!(AmdsmiP2pCapabilityT, is_iolink_dma) - 3usize]; + ["Offset of field: AmdsmiP2pCapabilityT::is_iolink_bi_directional"] + [::std::mem::offset_of!(AmdsmiP2pCapabilityT, is_iolink_bi_directional) - 4usize]; +}; +impl AmdsmiDevPerfLevelT { + pub const AmdsmiDevPerfLevelFirst: AmdsmiDevPerfLevelT = + AmdsmiDevPerfLevelT::AmdsmiDevPerfLevelAuto; +} +impl AmdsmiDevPerfLevelT { + pub const AmdsmiDevPerfLevelLast: AmdsmiDevPerfLevelT = + AmdsmiDevPerfLevelT::AmdsmiDevPerfLevelDeterminism; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiDevPerfLevelT { + AmdsmiDevPerfLevelAuto = 0, + AmdsmiDevPerfLevelLow = 1, + AmdsmiDevPerfLevelHigh = 2, + AmdsmiDevPerfLevelManual = 3, + AmdsmiDevPerfLevelStableStd = 4, + AmdsmiDevPerfLevelStablePeak = 5, + AmdsmiDevPerfLevelStableMinMclk = 6, + AmdsmiDevPerfLevelStableMinSclk = 7, + AmdsmiDevPerfLevelDeterminism = 8, + AmdsmiDevPerfLevelUnknown = 256, +} +pub type AmdsmiEventHandleT = usize; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiEventGroupT { + AmdsmiEvntGrpXgmi = 0, + AmdsmiEvntGrpXgmiDataOut = 10, + AmdsmiEvntGrpInvalid = 4294967295, +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntXgmiFirst: AmdsmiEventTypeT = AmdsmiEventTypeT::AmdsmiEvntFirst; +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntXgmi0NopTx: AmdsmiEventTypeT = AmdsmiEventTypeT::AmdsmiEvntFirst; +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntXgmiLast: AmdsmiEventTypeT = AmdsmiEventTypeT::AmdsmiEvntXgmi1BeatsTx; +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntXgmiDataOut0: AmdsmiEventTypeT = + AmdsmiEventTypeT::AmdsmiEvntXgmiDataOutFirst; +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntXgmiDataOutLast: AmdsmiEventTypeT = + AmdsmiEventTypeT::AmdsmiEvntXgmiDataOut5; +} +impl AmdsmiEventTypeT { + pub const AmdsmiEvntLast: AmdsmiEventTypeT = AmdsmiEventTypeT::AmdsmiEvntXgmiDataOut5; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiEventTypeT { + AmdsmiEvntFirst = 0, + AmdsmiEvntXgmi0RequestTx = 1, + AmdsmiEvntXgmi0ResponseTx = 2, + AmdsmiEvntXgmi0BeatsTx = 3, + AmdsmiEvntXgmi1NopTx = 4, + AmdsmiEvntXgmi1RequestTx = 5, + AmdsmiEvntXgmi1ResponseTx = 6, + AmdsmiEvntXgmi1BeatsTx = 7, + AmdsmiEvntXgmiDataOutFirst = 10, + AmdsmiEvntXgmiDataOut1 = 11, + AmdsmiEvntXgmiDataOut2 = 12, + AmdsmiEvntXgmiDataOut3 = 13, + AmdsmiEvntXgmiDataOut4 = 14, + AmdsmiEvntXgmiDataOut5 = 15, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiCounterCommandT { + AmdsmiCntrCmdStart = 0, + AmdsmiCntrCmdStop = 1, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiCounterValueT { + pub value: u64, + pub time_enabled: u64, + pub time_running: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiCounterValueT"][::std::mem::size_of::() - 24usize]; + ["Alignment of AmdsmiCounterValueT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiCounterValueT::value"] + [::std::mem::offset_of!(AmdsmiCounterValueT, value) - 0usize]; + ["Offset of field: AmdsmiCounterValueT::time_enabled"] + [::std::mem::offset_of!(AmdsmiCounterValueT, time_enabled) - 8usize]; + ["Offset of field: AmdsmiCounterValueT::time_running"] + [::std::mem::offset_of!(AmdsmiCounterValueT, time_running) - 16usize]; +}; +impl AmdsmiEvtNotificationTypeT { + pub const AmdsmiEvtNotifFirst: AmdsmiEvtNotificationTypeT = + AmdsmiEvtNotificationTypeT::AmdsmiEvtNotifVmfault; +} +impl AmdsmiEvtNotificationTypeT { + pub const AmdsmiEvtNotifLast: AmdsmiEvtNotificationTypeT = + AmdsmiEvtNotificationTypeT::AmdsmiEvtNotifRingHang; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiEvtNotificationTypeT { + AmdsmiEvtNotifNone = 0, + AmdsmiEvtNotifVmfault = 1, + AmdsmiEvtNotifThermalThrottle = 2, + AmdsmiEvtNotifGpuPreReset = 3, + AmdsmiEvtNotifGpuPostReset = 4, + AmdsmiEvtNotifRingHang = 5, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiEvtNotificationDataT { + pub processor_handle: AmdsmiProcessorHandle, + pub event: AmdsmiEvtNotificationTypeT, + pub message: [::std::os::raw::c_char; 64usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiEvtNotificationDataT"] + [::std::mem::size_of::() - 80usize]; + ["Alignment of AmdsmiEvtNotificationDataT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiEvtNotificationDataT::processor_handle"] + [::std::mem::offset_of!(AmdsmiEvtNotificationDataT, processor_handle) - 0usize]; + ["Offset of field: AmdsmiEvtNotificationDataT::event"] + [::std::mem::offset_of!(AmdsmiEvtNotificationDataT, event) - 8usize]; + ["Offset of field: AmdsmiEvtNotificationDataT::message"] + [::std::mem::offset_of!(AmdsmiEvtNotificationDataT, message) - 12usize]; +}; +impl AmdsmiTemperatureMetricT { + pub const AmdsmiTempFirst: AmdsmiTemperatureMetricT = + AmdsmiTemperatureMetricT::AmdsmiTempCurrent; +} +impl AmdsmiTemperatureMetricT { + pub const AmdsmiTempLast: AmdsmiTemperatureMetricT = + AmdsmiTemperatureMetricT::AmdsmiTempHighest; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiTemperatureMetricT { + AmdsmiTempCurrent = 0, + AmdsmiTempMax = 1, + AmdsmiTempMin = 2, + AmdsmiTempMaxHyst = 3, + AmdsmiTempMinHyst = 4, + AmdsmiTempCritical = 5, + AmdsmiTempCriticalHyst = 6, + AmdsmiTempEmergency = 7, + AmdsmiTempEmergencyHyst = 8, + AmdsmiTempCritMin = 9, + AmdsmiTempCritMinHyst = 10, + AmdsmiTempOffset = 11, + AmdsmiTempLowest = 12, + AmdsmiTempHighest = 13, +} +impl AmdsmiVoltageMetricT { + pub const AmdsmiVoltFirst: AmdsmiVoltageMetricT = AmdsmiVoltageMetricT::AmdsmiVoltCurrent; +} +impl AmdsmiVoltageMetricT { + pub const AmdsmiVoltLast: AmdsmiVoltageMetricT = AmdsmiVoltageMetricT::AmdsmiVoltHighest; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiVoltageMetricT { + AmdsmiVoltCurrent = 0, + AmdsmiVoltMax = 1, + AmdsmiVoltMinCrit = 2, + AmdsmiVoltMin = 3, + AmdsmiVoltMaxCrit = 4, + AmdsmiVoltAverage = 5, + AmdsmiVoltLowest = 6, + AmdsmiVoltHighest = 7, +} +impl AmdsmiVoltageTypeT { + pub const AmdsmiVoltTypeVddgfx: AmdsmiVoltageTypeT = AmdsmiVoltageTypeT::AmdsmiVoltTypeFirst; +} +impl AmdsmiVoltageTypeT { + pub const AmdsmiVoltTypeLast: AmdsmiVoltageTypeT = AmdsmiVoltageTypeT::AmdsmiVoltTypeFirst; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiVoltageTypeT { + AmdsmiVoltTypeFirst = 0, + AmdsmiVoltTypeInvalid = 4294967295, +} +impl AmdsmiPowerProfilePresetMasksT { + pub const AmdsmiPwrProfPrstLast: AmdsmiPowerProfilePresetMasksT = + AmdsmiPowerProfilePresetMasksT::AmdsmiPwrProfPrstBootupDefault; +} +#[repr(u64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiPowerProfilePresetMasksT { + AmdsmiPwrProfPrstCustomMask = 1, + AmdsmiPwrProfPrstVideoMask = 2, + AmdsmiPwrProfPrstPowerSavingMask = 4, + AmdsmiPwrProfPrstComputeMask = 8, + AmdsmiPwrProfPrstVrMask = 16, + AmdsmiPwrProfPrst3dFullScrMask = 32, + AmdsmiPwrProfPrstBootupDefault = 64, + AmdsmiPwrProfPrstInvalid = 18446744073709551615, +} +impl AmdsmiGpuBlockT { + pub const AmdsmiGpuBlockUmc: AmdsmiGpuBlockT = AmdsmiGpuBlockT::AmdsmiGpuBlockFirst; +} +impl AmdsmiGpuBlockT { + pub const AmdsmiGpuBlockLast: AmdsmiGpuBlockT = AmdsmiGpuBlockT::AmdsmiGpuBlockMpio; +} +#[repr(u64)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiGpuBlockT { + AmdsmiGpuBlockInvalid = 0, + AmdsmiGpuBlockFirst = 1, + AmdsmiGpuBlockSdma = 2, + AmdsmiGpuBlockGfx = 4, + AmdsmiGpuBlockMmhub = 8, + AmdsmiGpuBlockAthub = 16, + AmdsmiGpuBlockPcieBif = 32, + AmdsmiGpuBlockHdp = 64, + AmdsmiGpuBlockXgmiWafl = 128, + AmdsmiGpuBlockDf = 256, + AmdsmiGpuBlockSmn = 512, + AmdsmiGpuBlockSem = 1024, + AmdsmiGpuBlockMp0 = 2048, + AmdsmiGpuBlockMp1 = 4096, + AmdsmiGpuBlockFuse = 8192, + AmdsmiGpuBlockMca = 16384, + AmdsmiGpuBlockVcn = 32768, + AmdsmiGpuBlockJpeg = 65536, + AmdsmiGpuBlockIh = 131072, + AmdsmiGpuBlockMpio = 262144, + AmdsmiGpuBlockReserved = 9223372036854775808, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiClkLimitTypeT { + ClkLimitMin = 0, + ClkLimitMax = 1, +} +impl AmdsmiRasErrStateT { + pub const AmdsmiRasErrStateLast: AmdsmiRasErrStateT = + AmdsmiRasErrStateT::AmdsmiRasErrStateEnabled; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiRasErrStateT { + AmdsmiRasErrStateNone = 0, + AmdsmiRasErrStateDisabled = 1, + AmdsmiRasErrStateParity = 2, + AmdsmiRasErrStateSingC = 3, + AmdsmiRasErrStateMultUc = 4, + AmdsmiRasErrStatePoison = 5, + AmdsmiRasErrStateEnabled = 6, + AmdsmiRasErrStateInvalid = 4294967295, +} +impl AmdsmiMemoryTypeT { + pub const AmdsmiMemTypeVram: AmdsmiMemoryTypeT = AmdsmiMemoryTypeT::AmdsmiMemTypeFirst; +} +impl AmdsmiMemoryTypeT { + pub const AmdsmiMemTypeLast: AmdsmiMemoryTypeT = AmdsmiMemoryTypeT::AmdsmiMemTypeGtt; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiMemoryTypeT { + AmdsmiMemTypeFirst = 0, + AmdsmiMemTypeVisVram = 1, + AmdsmiMemTypeGtt = 2, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiFreqIndT { + AmdsmiFreqIndMin = 0, + AmdsmiFreqIndMax = 1, + AmdsmiFreqIndInvalid = 4294967295, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiXgmiStatusT { + AmdsmiXgmiStatusNoErrors = 0, + AmdsmiXgmiStatusError = 1, + AmdsmiXgmiStatusMultipleErrors = 2, +} +pub type AmdsmiBitFieldT = u64; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiMemoryPageStatusT { + AmdsmiMemPageStatusReserved = 0, + AmdsmiMemPageStatusPending = 1, + AmdsmiMemPageStatusUnreservable = 2, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiIoLinkTypeT { + AmdsmiIolinkTypeUndefined = 0, + AmdsmiIolinkTypePciexpress = 1, + AmdsmiIolinkTypeXgmi = 2, + AmdsmiIolinkTypeNumiolinktypes = 3, + AmdsmiIolinkTypeSize = 4294967295, +} +impl AmdsmiUtilizationCounterTypeT { + pub const AmdsmiCoarseGrainGfxActivity: AmdsmiUtilizationCounterTypeT = + AmdsmiUtilizationCounterTypeT::AmdsmiUtilizationCounterFirst; +} +impl AmdsmiUtilizationCounterTypeT { + pub const AmdsmiUtilizationCounterLast: AmdsmiUtilizationCounterTypeT = + AmdsmiUtilizationCounterTypeT::AmdsmiFineDecoderActivity; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiUtilizationCounterTypeT { + AmdsmiUtilizationCounterFirst = 0, + AmdsmiCoarseGrainMemActivity = 1, + AmdsmiCoarseDecoderActivity = 2, + AmdsmiFineGrainGfxActivity = 100, + AmdsmiFineGrainMemActivity = 101, + AmdsmiFineDecoderActivity = 102, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiPowerTypeT { + AmdsmiAveragePower = 0, + AmdsmiCurrentPower = 1, + AmdsmiInvalidPower = 4294967295, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiUtilizationCounterT { + pub type_: AmdsmiUtilizationCounterTypeT, + pub value: u64, + pub fine_value: [u64; 4usize], + pub fine_value_count: u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiUtilizationCounterT"] + [::std::mem::size_of::() - 56usize]; + ["Alignment of AmdsmiUtilizationCounterT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiUtilizationCounterT::type_"] + [::std::mem::offset_of!(AmdsmiUtilizationCounterT, type_) - 0usize]; + ["Offset of field: AmdsmiUtilizationCounterT::value"] + [::std::mem::offset_of!(AmdsmiUtilizationCounterT, value) - 8usize]; + ["Offset of field: AmdsmiUtilizationCounterT::fine_value"] + [::std::mem::offset_of!(AmdsmiUtilizationCounterT, fine_value) - 16usize]; + ["Offset of field: AmdsmiUtilizationCounterT::fine_value_count"] + [::std::mem::offset_of!(AmdsmiUtilizationCounterT, fine_value_count) - 48usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiRetiredPageRecordT { + pub page_address: u64, + pub page_size: u64, + pub status: AmdsmiMemoryPageStatusT, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiRetiredPageRecordT"] + [::std::mem::size_of::() - 24usize]; + ["Alignment of AmdsmiRetiredPageRecordT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiRetiredPageRecordT::page_address"] + [::std::mem::offset_of!(AmdsmiRetiredPageRecordT, page_address) - 0usize]; + ["Offset of field: AmdsmiRetiredPageRecordT::page_size"] + [::std::mem::offset_of!(AmdsmiRetiredPageRecordT, page_size) - 8usize]; + ["Offset of field: AmdsmiRetiredPageRecordT::status"] + [::std::mem::offset_of!(AmdsmiRetiredPageRecordT, status) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPowerProfileStatusT { + pub available_profiles: AmdsmiBitFieldT, + pub current: AmdsmiPowerProfilePresetMasksT, + pub num_profiles: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPowerProfileStatusT"] + [::std::mem::size_of::() - 24usize]; + ["Alignment of AmdsmiPowerProfileStatusT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPowerProfileStatusT::available_profiles"] + [::std::mem::offset_of!(AmdsmiPowerProfileStatusT, available_profiles) - 0usize]; + ["Offset of field: AmdsmiPowerProfileStatusT::current"] + [::std::mem::offset_of!(AmdsmiPowerProfileStatusT, current) - 8usize]; + ["Offset of field: AmdsmiPowerProfileStatusT::num_profiles"] + [::std::mem::offset_of!(AmdsmiPowerProfileStatusT, num_profiles) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiFrequenciesT { + pub has_deep_sleep: bool, + pub num_supported: u32, + pub current: u32, + pub frequency: [u64; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiFrequenciesT"][::std::mem::size_of::() - 280usize]; + ["Alignment of AmdsmiFrequenciesT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiFrequenciesT::has_deep_sleep"] + [::std::mem::offset_of!(AmdsmiFrequenciesT, has_deep_sleep) - 0usize]; + ["Offset of field: AmdsmiFrequenciesT::num_supported"] + [::std::mem::offset_of!(AmdsmiFrequenciesT, num_supported) - 4usize]; + ["Offset of field: AmdsmiFrequenciesT::current"] + [::std::mem::offset_of!(AmdsmiFrequenciesT, current) - 8usize]; + ["Offset of field: AmdsmiFrequenciesT::frequency"] + [::std::mem::offset_of!(AmdsmiFrequenciesT, frequency) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiDpmPolicyEntryT { + pub policy_id: u32, + pub policy_description: [::std::os::raw::c_char; 32usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiDpmPolicyEntryT"][::std::mem::size_of::() - 36usize]; + ["Alignment of AmdsmiDpmPolicyEntryT"] + [::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiDpmPolicyEntryT::policy_id"] + [::std::mem::offset_of!(AmdsmiDpmPolicyEntryT, policy_id) - 0usize]; + ["Offset of field: AmdsmiDpmPolicyEntryT::policy_description"] + [::std::mem::offset_of!(AmdsmiDpmPolicyEntryT, policy_description) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiDpmPolicyT { + pub num_supported: u32, + pub current: u32, + pub policies: [AmdsmiDpmPolicyEntryT; 32usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiDpmPolicyT"][::std::mem::size_of::() - 1160usize]; + ["Alignment of AmdsmiDpmPolicyT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiDpmPolicyT::num_supported"] + [::std::mem::offset_of!(AmdsmiDpmPolicyT, num_supported) - 0usize]; + ["Offset of field: AmdsmiDpmPolicyT::current"] + [::std::mem::offset_of!(AmdsmiDpmPolicyT, current) - 4usize]; + ["Offset of field: AmdsmiDpmPolicyT::policies"] + [::std::mem::offset_of!(AmdsmiDpmPolicyT, policies) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiPcieBandwidthT { + pub transfer_rate: AmdsmiFrequenciesT, + pub lanes: [u32; 33usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiPcieBandwidthT"][::std::mem::size_of::() - 416usize]; + ["Alignment of AmdsmiPcieBandwidthT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiPcieBandwidthT::transfer_rate"] + [::std::mem::offset_of!(AmdsmiPcieBandwidthT, transfer_rate) - 0usize]; + ["Offset of field: AmdsmiPcieBandwidthT::lanes"] + [::std::mem::offset_of!(AmdsmiPcieBandwidthT, lanes) - 280usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiVersionT { + pub year: u32, + pub major: u32, + pub minor: u32, + pub release: u32, + pub build: *const ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiVersionT"][::std::mem::size_of::() - 24usize]; + ["Alignment of AmdsmiVersionT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiVersionT::year"] + [::std::mem::offset_of!(AmdsmiVersionT, year) - 0usize]; + ["Offset of field: AmdsmiVersionT::major"] + [::std::mem::offset_of!(AmdsmiVersionT, major) - 4usize]; + ["Offset of field: AmdsmiVersionT::minor"] + [::std::mem::offset_of!(AmdsmiVersionT, minor) - 8usize]; + ["Offset of field: AmdsmiVersionT::release"] + [::std::mem::offset_of!(AmdsmiVersionT, release) - 12usize]; + ["Offset of field: AmdsmiVersionT::build"] + [::std::mem::offset_of!(AmdsmiVersionT, build) - 16usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiOdVddcPointT { + pub frequency: u64, + pub voltage: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiOdVddcPointT"][::std::mem::size_of::() - 16usize]; + ["Alignment of AmdsmiOdVddcPointT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiOdVddcPointT::frequency"] + [::std::mem::offset_of!(AmdsmiOdVddcPointT, frequency) - 0usize]; + ["Offset of field: AmdsmiOdVddcPointT::voltage"] + [::std::mem::offset_of!(AmdsmiOdVddcPointT, voltage) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiFreqVoltRegionT { + pub freq_range: AmdsmiRangeT, + pub volt_range: AmdsmiRangeT, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiFreqVoltRegionT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiFreqVoltRegionT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiFreqVoltRegionT::freq_range"] + [::std::mem::offset_of!(AmdsmiFreqVoltRegionT, freq_range) - 0usize]; + ["Offset of field: AmdsmiFreqVoltRegionT::volt_range"] + [::std::mem::offset_of!(AmdsmiFreqVoltRegionT, volt_range) - 32usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiOdVoltCurveT { + pub vc_points: [AmdsmiOdVddcPointT; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiOdVoltCurveT"][::std::mem::size_of::() - 48usize]; + ["Alignment of AmdsmiOdVoltCurveT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiOdVoltCurveT::vc_points"] + [::std::mem::offset_of!(AmdsmiOdVoltCurveT, vc_points) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiOdVoltFreqDataT { + pub curr_sclk_range: AmdsmiRangeT, + pub curr_mclk_range: AmdsmiRangeT, + pub sclk_freq_limits: AmdsmiRangeT, + pub mclk_freq_limits: AmdsmiRangeT, + pub curve: AmdsmiOdVoltCurveT, + pub num_regions: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiOdVoltFreqDataT"][::std::mem::size_of::() - 184usize]; + ["Alignment of AmdsmiOdVoltFreqDataT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::curr_sclk_range"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, curr_sclk_range) - 0usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::curr_mclk_range"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, curr_mclk_range) - 32usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::sclk_freq_limits"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, sclk_freq_limits) - 64usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::mclk_freq_limits"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, mclk_freq_limits) - 96usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::curve"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, curve) - 128usize]; + ["Offset of field: AmdsmiOdVoltFreqDataT::num_regions"] + [::std::mem::offset_of!(AmdsmiOdVoltFreqDataT, num_regions) - 176usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdMetricsTableHeaderT { + pub structure_size: u16, + pub format_revision: u8, + pub content_revision: u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdMetricsTableHeaderT"][::std::mem::size_of::() - 4usize]; + ["Alignment of AmdMetricsTableHeaderT"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: AmdMetricsTableHeaderT::structure_size"] + [::std::mem::offset_of!(AmdMetricsTableHeaderT, structure_size) - 0usize]; + ["Offset of field: AmdMetricsTableHeaderT::format_revision"] + [::std::mem::offset_of!(AmdMetricsTableHeaderT, format_revision) - 2usize]; + ["Offset of field: AmdMetricsTableHeaderT::content_revision"] + [::std::mem::offset_of!(AmdMetricsTableHeaderT, content_revision) - 3usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiGpuXcpMetricsT { + pub gfx_busy_inst: [u32; 8usize], + pub jpeg_busy: [u16; 32usize], + pub vcn_busy: [u16; 4usize], + pub gfx_busy_acc: [u64; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiGpuXcpMetricsT"][::std::mem::size_of::() - 168usize]; + ["Alignment of AmdsmiGpuXcpMetricsT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiGpuXcpMetricsT::gfx_busy_inst"] + [::std::mem::offset_of!(AmdsmiGpuXcpMetricsT, gfx_busy_inst) - 0usize]; + ["Offset of field: AmdsmiGpuXcpMetricsT::jpeg_busy"] + [::std::mem::offset_of!(AmdsmiGpuXcpMetricsT, jpeg_busy) - 32usize]; + ["Offset of field: AmdsmiGpuXcpMetricsT::vcn_busy"] + [::std::mem::offset_of!(AmdsmiGpuXcpMetricsT, vcn_busy) - 96usize]; + ["Offset of field: AmdsmiGpuXcpMetricsT::gfx_busy_acc"] + [::std::mem::offset_of!(AmdsmiGpuXcpMetricsT, gfx_busy_acc) - 104usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiGpuMetricsT { + pub common_header: AmdMetricsTableHeaderT, + pub temperature_edge: u16, + pub temperature_hotspot: u16, + pub temperature_mem: u16, + pub temperature_vrgfx: u16, + pub temperature_vrsoc: u16, + pub temperature_vrmem: u16, + pub average_gfx_activity: u16, + pub average_umc_activity: u16, + pub average_mm_activity: u16, + pub average_socket_power: u16, + pub energy_accumulator: u64, + pub system_clock_counter: u64, + pub average_gfxclk_frequency: u16, + pub average_socclk_frequency: u16, + pub average_uclk_frequency: u16, + pub average_vclk0_frequency: u16, + pub average_dclk0_frequency: u16, + pub average_vclk1_frequency: u16, + pub average_dclk1_frequency: u16, + pub current_gfxclk: u16, + pub current_socclk: u16, + pub current_uclk: u16, + pub current_vclk0: u16, + pub current_dclk0: u16, + pub current_vclk1: u16, + pub current_dclk1: u16, + pub throttle_status: u32, + pub current_fan_speed: u16, + pub pcie_link_width: u16, + pub pcie_link_speed: u16, + pub gfx_activity_acc: u32, + pub mem_activity_acc: u32, + pub temperature_hbm: [u16; 4usize], + pub firmware_timestamp: u64, + pub voltage_soc: u16, + pub voltage_gfx: u16, + pub voltage_mem: u16, + pub indep_throttle_status: u64, + pub current_socket_power: u16, + pub vcn_activity: [u16; 4usize], + pub gfxclk_lock_status: u32, + pub xgmi_link_width: u16, + pub xgmi_link_speed: u16, + pub pcie_bandwidth_acc: u64, + pub pcie_bandwidth_inst: u64, + pub pcie_l0_to_recov_count_acc: u64, + pub pcie_replay_count_acc: u64, + pub pcie_replay_rover_count_acc: u64, + pub xgmi_read_data_acc: [u64; 8usize], + pub xgmi_write_data_acc: [u64; 8usize], + pub current_gfxclks: [u16; 8usize], + pub current_socclks: [u16; 4usize], + pub current_vclk0s: [u16; 4usize], + pub current_dclk0s: [u16; 4usize], + pub jpeg_activity: [u16; 32usize], + pub pcie_nak_sent_count_acc: u32, + pub pcie_nak_rcvd_count_acc: u32, + pub accumulation_counter: u64, + pub prochot_residency_acc: u64, + pub ppt_residency_acc: u64, + pub socket_thm_residency_acc: u64, + pub vr_thm_residency_acc: u64, + pub hbm_thm_residency_acc: u64, + pub num_partition: u16, + pub xcp_stats: [AmdsmiGpuXcpMetricsT; 8usize], + pub pcie_lc_perf_other_end_recovery: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiGpuMetricsT"][::std::mem::size_of::() - 1832usize]; + ["Alignment of AmdsmiGpuMetricsT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiGpuMetricsT::common_header"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, common_header) - 0usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_edge"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_edge) - 4usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_hotspot"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_hotspot) - 6usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_mem"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_mem) - 8usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_vrgfx"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_vrgfx) - 10usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_vrsoc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_vrsoc) - 12usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_vrmem"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_vrmem) - 14usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_gfx_activity"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_gfx_activity) - 16usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_umc_activity"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_umc_activity) - 18usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_mm_activity"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_mm_activity) - 20usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_socket_power"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_socket_power) - 22usize]; + ["Offset of field: AmdsmiGpuMetricsT::energy_accumulator"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, energy_accumulator) - 24usize]; + ["Offset of field: AmdsmiGpuMetricsT::system_clock_counter"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, system_clock_counter) - 32usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_gfxclk_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_gfxclk_frequency) - 40usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_socclk_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_socclk_frequency) - 42usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_uclk_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_uclk_frequency) - 44usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_vclk0_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_vclk0_frequency) - 46usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_dclk0_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_dclk0_frequency) - 48usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_vclk1_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_vclk1_frequency) - 50usize]; + ["Offset of field: AmdsmiGpuMetricsT::average_dclk1_frequency"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, average_dclk1_frequency) - 52usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_gfxclk"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_gfxclk) - 54usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_socclk"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_socclk) - 56usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_uclk"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_uclk) - 58usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_vclk0"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_vclk0) - 60usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_dclk0"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_dclk0) - 62usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_vclk1"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_vclk1) - 64usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_dclk1"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_dclk1) - 66usize]; + ["Offset of field: AmdsmiGpuMetricsT::throttle_status"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, throttle_status) - 68usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_fan_speed"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_fan_speed) - 72usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_link_width"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_link_width) - 74usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_link_speed"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_link_speed) - 76usize]; + ["Offset of field: AmdsmiGpuMetricsT::gfx_activity_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, gfx_activity_acc) - 80usize]; + ["Offset of field: AmdsmiGpuMetricsT::mem_activity_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, mem_activity_acc) - 84usize]; + ["Offset of field: AmdsmiGpuMetricsT::temperature_hbm"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, temperature_hbm) - 88usize]; + ["Offset of field: AmdsmiGpuMetricsT::firmware_timestamp"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, firmware_timestamp) - 96usize]; + ["Offset of field: AmdsmiGpuMetricsT::voltage_soc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, voltage_soc) - 104usize]; + ["Offset of field: AmdsmiGpuMetricsT::voltage_gfx"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, voltage_gfx) - 106usize]; + ["Offset of field: AmdsmiGpuMetricsT::voltage_mem"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, voltage_mem) - 108usize]; + ["Offset of field: AmdsmiGpuMetricsT::indep_throttle_status"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, indep_throttle_status) - 112usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_socket_power"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_socket_power) - 120usize]; + ["Offset of field: AmdsmiGpuMetricsT::vcn_activity"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, vcn_activity) - 122usize]; + ["Offset of field: AmdsmiGpuMetricsT::gfxclk_lock_status"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, gfxclk_lock_status) - 132usize]; + ["Offset of field: AmdsmiGpuMetricsT::xgmi_link_width"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, xgmi_link_width) - 136usize]; + ["Offset of field: AmdsmiGpuMetricsT::xgmi_link_speed"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, xgmi_link_speed) - 138usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_bandwidth_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_bandwidth_acc) - 144usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_bandwidth_inst"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_bandwidth_inst) - 152usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_l0_to_recov_count_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_l0_to_recov_count_acc) - 160usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_replay_count_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_replay_count_acc) - 168usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_replay_rover_count_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_replay_rover_count_acc) - 176usize]; + ["Offset of field: AmdsmiGpuMetricsT::xgmi_read_data_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, xgmi_read_data_acc) - 184usize]; + ["Offset of field: AmdsmiGpuMetricsT::xgmi_write_data_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, xgmi_write_data_acc) - 248usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_gfxclks"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_gfxclks) - 312usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_socclks"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_socclks) - 328usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_vclk0s"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_vclk0s) - 336usize]; + ["Offset of field: AmdsmiGpuMetricsT::current_dclk0s"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, current_dclk0s) - 344usize]; + ["Offset of field: AmdsmiGpuMetricsT::jpeg_activity"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, jpeg_activity) - 352usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_nak_sent_count_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_nak_sent_count_acc) - 416usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_nak_rcvd_count_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_nak_rcvd_count_acc) - 420usize]; + ["Offset of field: AmdsmiGpuMetricsT::accumulation_counter"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, accumulation_counter) - 424usize]; + ["Offset of field: AmdsmiGpuMetricsT::prochot_residency_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, prochot_residency_acc) - 432usize]; + ["Offset of field: AmdsmiGpuMetricsT::ppt_residency_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, ppt_residency_acc) - 440usize]; + ["Offset of field: AmdsmiGpuMetricsT::socket_thm_residency_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, socket_thm_residency_acc) - 448usize]; + ["Offset of field: AmdsmiGpuMetricsT::vr_thm_residency_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, vr_thm_residency_acc) - 456usize]; + ["Offset of field: AmdsmiGpuMetricsT::hbm_thm_residency_acc"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, hbm_thm_residency_acc) - 464usize]; + ["Offset of field: AmdsmiGpuMetricsT::num_partition"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, num_partition) - 472usize]; + ["Offset of field: AmdsmiGpuMetricsT::xcp_stats"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, xcp_stats) - 480usize]; + ["Offset of field: AmdsmiGpuMetricsT::pcie_lc_perf_other_end_recovery"] + [::std::mem::offset_of!(AmdsmiGpuMetricsT, pcie_lc_perf_other_end_recovery) - 1824usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiNameValueT { + pub name: [::std::os::raw::c_char; 64usize], + pub value: u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiNameValueT"][::std::mem::size_of::() - 72usize]; + ["Alignment of AmdsmiNameValueT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiNameValueT::name"] + [::std::mem::offset_of!(AmdsmiNameValueT, name) - 0usize]; + ["Offset of field: AmdsmiNameValueT::value"] + [::std::mem::offset_of!(AmdsmiNameValueT, value) - 64usize]; +}; +#[repr(u32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum AmdsmiRegTypeT { + AmdsmiRegXgmi = 0, + AmdsmiRegWafl = 1, + AmdsmiRegPcie = 2, + AmdsmiRegUsr = 3, + AmdsmiRegUsr1 = 4, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiRasFeatureT { + pub ras_eeprom_version: u32, + pub ecc_correction_schema_flag: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiRasFeatureT"][::std::mem::size_of::() - 8usize]; + ["Alignment of AmdsmiRasFeatureT"][::std::mem::align_of::() - 4usize]; + ["Offset of field: AmdsmiRasFeatureT::ras_eeprom_version"] + [::std::mem::offset_of!(AmdsmiRasFeatureT, ras_eeprom_version) - 0usize]; + ["Offset of field: AmdsmiRasFeatureT::ecc_correction_schema_flag"] + [::std::mem::offset_of!(AmdsmiRasFeatureT, ecc_correction_schema_flag) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiErrorCountT { + pub correctable_count: u64, + pub uncorrectable_count: u64, + pub deferred_count: u64, + pub reserved: [u64; 5usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiErrorCountT"][::std::mem::size_of::() - 64usize]; + ["Alignment of AmdsmiErrorCountT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiErrorCountT::correctable_count"] + [::std::mem::offset_of!(AmdsmiErrorCountT, correctable_count) - 0usize]; + ["Offset of field: AmdsmiErrorCountT::uncorrectable_count"] + [::std::mem::offset_of!(AmdsmiErrorCountT, uncorrectable_count) - 8usize]; + ["Offset of field: AmdsmiErrorCountT::deferred_count"] + [::std::mem::offset_of!(AmdsmiErrorCountT, deferred_count) - 16usize]; + ["Offset of field: AmdsmiErrorCountT::reserved"] + [::std::mem::offset_of!(AmdsmiErrorCountT, reserved) - 24usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiProcessInfoT { + pub process_id: u32, + pub pasid: u32, + pub vram_usage: u64, + pub sdma_usage: u64, + pub cu_occupancy: u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiProcessInfoT"][::std::mem::size_of::() - 32usize]; + ["Alignment of AmdsmiProcessInfoT"][::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiProcessInfoT::process_id"] + [::std::mem::offset_of!(AmdsmiProcessInfoT, process_id) - 0usize]; + ["Offset of field: AmdsmiProcessInfoT::pasid"] + [::std::mem::offset_of!(AmdsmiProcessInfoT, pasid) - 4usize]; + ["Offset of field: AmdsmiProcessInfoT::vram_usage"] + [::std::mem::offset_of!(AmdsmiProcessInfoT, vram_usage) - 8usize]; + ["Offset of field: AmdsmiProcessInfoT::sdma_usage"] + [::std::mem::offset_of!(AmdsmiProcessInfoT, sdma_usage) - 16usize]; + ["Offset of field: AmdsmiProcessInfoT::cu_occupancy"] + [::std::mem::offset_of!(AmdsmiProcessInfoT, cu_occupancy) - 24usize]; +}; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct AmdsmiTopologyNearestT { + pub count: u32, + pub processor_list: [AmdsmiProcessorHandle; 32usize], + pub reserved: [u64; 15usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of AmdsmiTopologyNearestT"][::std::mem::size_of::() - 384usize]; + ["Alignment of AmdsmiTopologyNearestT"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: AmdsmiTopologyNearestT::count"] + [::std::mem::offset_of!(AmdsmiTopologyNearestT, count) - 0usize]; + ["Offset of field: AmdsmiTopologyNearestT::processor_list"] + [::std::mem::offset_of!(AmdsmiTopologyNearestT, processor_list) - 8usize]; + ["Offset of field: AmdsmiTopologyNearestT::reserved"] + [::std::mem::offset_of!(AmdsmiTopologyNearestT, reserved) - 264usize]; +}; +extern "C" { + pub fn amdsmi_init(init_flags: u64) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_shut_down() -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_socket_handles( + socket_count: *mut u32, + socket_handles: *mut AmdsmiSocketHandle, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_socket_info( + socket_handle: AmdsmiSocketHandle, + len: usize, + name: *mut ::std::os::raw::c_char, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_processor_handles( + socket_handle: AmdsmiSocketHandle, + processor_count: *mut u32, + processor_handles: *mut AmdsmiProcessorHandle, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_processor_type( + processor_handle: AmdsmiProcessorHandle, + processor_type: *mut ProcessorTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_processor_handle_from_bdf( + bdf: AmdsmiBdfT, + processor_handle: *mut AmdsmiProcessorHandle, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_id( + processor_handle: AmdsmiProcessorHandle, + id: *mut u16, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_revision( + processor_handle: AmdsmiProcessorHandle, + revision: *mut u16, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_vendor_name( + processor_handle: AmdsmiProcessorHandle, + name: *mut ::std::os::raw::c_char, + len: usize, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_vram_vendor( + processor_handle: AmdsmiProcessorHandle, + brand: *mut ::std::os::raw::c_char, + len: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_subsystem_id( + processor_handle: AmdsmiProcessorHandle, + id: *mut u16, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_subsystem_name( + processor_handle: AmdsmiProcessorHandle, + name: *mut ::std::os::raw::c_char, + len: usize, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_pci_bandwidth( + processor_handle: AmdsmiProcessorHandle, + bandwidth: *mut AmdsmiPcieBandwidthT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_bdf_id( + processor_handle: AmdsmiProcessorHandle, + bdfid: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_topo_numa_affinity( + processor_handle: AmdsmiProcessorHandle, + numa_node: *mut i32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_pci_throughput( + processor_handle: AmdsmiProcessorHandle, + sent: *mut u64, + received: *mut u64, + max_pkt_sz: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_pci_replay_counter( + processor_handle: AmdsmiProcessorHandle, + counter: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_pci_bandwidth( + processor_handle: AmdsmiProcessorHandle, + bw_bitmask: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_energy_count( + processor_handle: AmdsmiProcessorHandle, + energy_accumulator: *mut u64, + counter_resolution: *mut f32, + timestamp: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_power_cap( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + cap: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_power_profile( + processor_handle: AmdsmiProcessorHandle, + reserved: u32, + profile: AmdsmiPowerProfilePresetMasksT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_memory_total( + processor_handle: AmdsmiProcessorHandle, + mem_type: AmdsmiMemoryTypeT, + total: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_memory_usage( + processor_handle: AmdsmiProcessorHandle, + mem_type: AmdsmiMemoryTypeT, + used: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_bad_page_info( + processor_handle: AmdsmiProcessorHandle, + num_pages: *mut u32, + info: *mut AmdsmiRetiredPageRecordT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_ras_feature_info( + processor_handle: AmdsmiProcessorHandle, + ras_feature: *mut AmdsmiRasFeatureT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_ras_block_features_enabled( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, + state: *mut AmdsmiRasErrStateT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_memory_reserved_pages( + processor_handle: AmdsmiProcessorHandle, + num_pages: *mut u32, + records: *mut AmdsmiRetiredPageRecordT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_fan_rpms( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + speed: *mut i64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_fan_speed( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + speed: *mut i64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_fan_speed_max( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + max_speed: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_temp_metric( + processor_handle: AmdsmiProcessorHandle, + sensor_type: AmdsmiTemperatureTypeT, + metric: AmdsmiTemperatureMetricT, + temperature: *mut i64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_cache_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiGpuCacheInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_volt_metric( + processor_handle: AmdsmiProcessorHandle, + sensor_type: AmdsmiVoltageTypeT, + metric: AmdsmiVoltageMetricT, + voltage: *mut i64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_reset_gpu_fan( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_fan_speed( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + speed: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_utilization_count( + processor_handle: AmdsmiProcessorHandle, + utilization_counters: *mut AmdsmiUtilizationCounterT, + count: u32, + timestamp: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_perf_level( + processor_handle: AmdsmiProcessorHandle, + perf: *mut AmdsmiDevPerfLevelT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_perf_determinism_mode( + processor_handle: AmdsmiProcessorHandle, + clkvalue: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_overdrive_level( + processor_handle: AmdsmiProcessorHandle, + od: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_mem_overdrive_level( + processor_handle: AmdsmiProcessorHandle, + od: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_clk_freq( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + f: *mut AmdsmiFrequenciesT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_reset_gpu(processor_handle: AmdsmiProcessorHandle) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_od_volt_info( + processor_handle: AmdsmiProcessorHandle, + odv: *mut AmdsmiOdVoltFreqDataT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_metrics_header_info( + processor_handle: AmdsmiProcessorHandle, + header_value: *mut AmdMetricsTableHeaderT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_metrics_info( + processor_handle: AmdsmiProcessorHandle, + pgpu_metrics: *mut AmdsmiGpuMetricsT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_pm_metrics_info( + processor_handle: AmdsmiProcessorHandle, + pm_metrics: *mut *mut AmdsmiNameValueT, + num_of_metrics: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_reg_table_info( + processor_handle: AmdsmiProcessorHandle, + reg_type: AmdsmiRegTypeT, + reg_metrics: *mut *mut AmdsmiNameValueT, + num_of_metrics: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_clk_range( + processor_handle: AmdsmiProcessorHandle, + minclkvalue: u64, + maxclkvalue: u64, + clkType: AmdsmiClkTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_clk_limit( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + limit_type: AmdsmiClkLimitTypeT, + clk_value: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_free_name_value_pairs(p: *mut ::std::os::raw::c_void); +} +extern "C" { + pub fn amdsmi_set_gpu_od_clk_info( + processor_handle: AmdsmiProcessorHandle, + level: AmdsmiFreqIndT, + clkvalue: u64, + clkType: AmdsmiClkTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_od_volt_info( + processor_handle: AmdsmiProcessorHandle, + vpoint: u32, + clkvalue: u64, + voltvalue: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_od_volt_curve_regions( + processor_handle: AmdsmiProcessorHandle, + num_regions: *mut u32, + buffer: *mut AmdsmiFreqVoltRegionT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_power_profile_presets( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + status: *mut AmdsmiPowerProfileStatusT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_perf_level( + processor_handle: AmdsmiProcessorHandle, + perf_lvl: AmdsmiDevPerfLevelT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_overdrive_level( + processor_handle: AmdsmiProcessorHandle, + od: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_clk_freq( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + freq_bitmask: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_soc_pstate( + processor_handle: AmdsmiProcessorHandle, + policy: *mut AmdsmiDpmPolicyT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_soc_pstate( + processor_handle: AmdsmiProcessorHandle, + policy_id: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_xgmi_plpd( + processor_handle: AmdsmiProcessorHandle, + xgmi_plpd: *mut AmdsmiDpmPolicyT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_xgmi_plpd( + processor_handle: AmdsmiProcessorHandle, + plpd_id: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_process_isolation( + processor_handle: AmdsmiProcessorHandle, + pisolate: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_process_isolation( + processor_handle: AmdsmiProcessorHandle, + pisolate: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_clean_gpu_local_data(processor_handle: AmdsmiProcessorHandle) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_lib_version(version: *mut AmdsmiVersionT) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_ecc_count( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, + ec: *mut AmdsmiErrorCountT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_ecc_enabled( + processor_handle: AmdsmiProcessorHandle, + enabled_blocks: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_ecc_status( + processor_handle: AmdsmiProcessorHandle, + block: AmdsmiGpuBlockT, + state: *mut AmdsmiRasErrStateT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_status_code_to_string( + status: AmdsmiStatusT, + status_string: *mut *const ::std::os::raw::c_char, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_counter_group_supported( + processor_handle: AmdsmiProcessorHandle, + group: AmdsmiEventGroupT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_create_counter( + processor_handle: AmdsmiProcessorHandle, + type_: AmdsmiEventTypeT, + evnt_handle: *mut AmdsmiEventHandleT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_destroy_counter(evnt_handle: AmdsmiEventHandleT) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_control_counter( + evt_handle: AmdsmiEventHandleT, + cmd: AmdsmiCounterCommandT, + cmd_args: *mut ::std::os::raw::c_void, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_read_counter( + evt_handle: AmdsmiEventHandleT, + value: *mut AmdsmiCounterValueT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_available_counters( + processor_handle: AmdsmiProcessorHandle, + grp: AmdsmiEventGroupT, + available: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_compute_process_info( + procs: *mut AmdsmiProcessInfoT, + num_items: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_compute_process_info_by_pid( + pid: u32, + proc_: *mut AmdsmiProcessInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_compute_process_gpus( + pid: u32, + dv_indices: *mut u32, + num_devices: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_gpu_xgmi_error_status( + processor_handle: AmdsmiProcessorHandle, + status: *mut AmdsmiXgmiStatusT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_reset_gpu_xgmi_error(processor_handle: AmdsmiProcessorHandle) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_link_metrics( + processor_handle: AmdsmiProcessorHandle, + link_metrics: *mut AmdsmiLinkMetricsT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_topo_get_numa_node_number( + processor_handle: AmdsmiProcessorHandle, + numa_node: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_topo_get_link_weight( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, + weight: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_minmax_bandwidth_between_processors( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, + min_bandwidth: *mut u64, + max_bandwidth: *mut u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_topo_get_link_type( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, + hops: *mut u64, + type_: *mut AmdsmiIoLinkTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_is_P2P_accessible( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, + accessible: *mut bool, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_topo_get_p2p_status( + processor_handle_src: AmdsmiProcessorHandle, + processor_handle_dst: AmdsmiProcessorHandle, + type_: *mut AmdsmiIoLinkTypeT, + cap: *mut AmdsmiP2pCapabilityT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_compute_partition( + processor_handle: AmdsmiProcessorHandle, + compute_partition: *mut ::std::os::raw::c_char, + len: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_compute_partition( + processor_handle: AmdsmiProcessorHandle, + compute_partition: AmdsmiComputePartitionTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_memory_partition( + processor_handle: AmdsmiProcessorHandle, + memory_partition: *mut ::std::os::raw::c_char, + len: u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_memory_partition( + processor_handle: AmdsmiProcessorHandle, + memory_partition: AmdsmiMemoryPartitionTypeT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_accelerator_partition_profile( + processor_handle: AmdsmiProcessorHandle, + profile: *mut AmdsmiAcceleratorPartitionProfileT, + partition_id: *mut u32, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_init_gpu_event_notification( + processor_handle: AmdsmiProcessorHandle, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_set_gpu_event_notification_mask( + processor_handle: AmdsmiProcessorHandle, + mask: u64, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_event_notification( + timeout_ms: ::std::os::raw::c_int, + num_elem: *mut u32, + data: *mut AmdsmiEvtNotificationDataT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_stop_gpu_event_notification( + processor_handle: AmdsmiProcessorHandle, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_device_bdf( + processor_handle: AmdsmiProcessorHandle, + bdf: *mut AmdsmiBdfT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_device_uuid( + processor_handle: AmdsmiProcessorHandle, + uuid_length: *mut ::std::os::raw::c_uint, + uuid: *mut ::std::os::raw::c_char, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_driver_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiDriverInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_asic_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiAsicInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_kfd_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiKfdInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_vram_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiVramInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_board_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiBoardInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_power_cap_info( + processor_handle: AmdsmiProcessorHandle, + sensor_ind: u32, + info: *mut AmdsmiPowerCapInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_pcie_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiPcieInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_xgmi_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiXgmiInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_fw_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiFwInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_vbios_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiVbiosInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_activity( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiEngineUsageT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_power_info( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiPowerInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_is_gpu_power_management_enabled( + processor_handle: AmdsmiProcessorHandle, + enabled: *mut bool, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_clock_info( + processor_handle: AmdsmiProcessorHandle, + clk_type: AmdsmiClkTypeT, + info: *mut AmdsmiClkInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_vram_usage( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiVramUsageT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_violation_status( + processor_handle: AmdsmiProcessorHandle, + info: *mut AmdsmiViolationStatusT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_process_list( + processor_handle: AmdsmiProcessorHandle, + max_processes: *mut u32, + list: *mut AmdsmiProcInfoT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_gpu_total_ecc_count( + processor_handle: AmdsmiProcessorHandle, + ec: *mut AmdsmiErrorCountT, + ) -> AmdsmiStatusT; +} +extern "C" { + pub fn amdsmi_get_link_topology_nearest( + processor_handle: AmdsmiProcessorHandle, + link_type: AmdsmiLinkTypeT, + topology_nearest_info: *mut AmdsmiTopologyNearestT, + ) -> AmdsmiStatusT; +} diff --git a/projects/amdsmi/rust-interface/src/lib.rs b/projects/amdsmi/rust-interface/src/lib.rs new file mode 100644 index 0000000000..87f30eb7c5 --- /dev/null +++ b/projects/amdsmi/rust-interface/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#![allow(dead_code)] +mod amdsmi_wrapper; + +#[macro_use] +mod utils; +mod amdsmi; + +pub use utils::*; +pub use amdsmi::*; diff --git a/projects/amdsmi/rust-interface/src/utils.rs b/projects/amdsmi/rust-interface/src/utils.rs new file mode 100644 index 0000000000..b3621e3f73 --- /dev/null +++ b/projects/amdsmi/rust-interface/src/utils.rs @@ -0,0 +1,184 @@ +// Copyright (C) 2024 Advanced Micro Devices. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +use std::fmt; + +// Re-export all the alias type +pub use crate::amdsmi_wrapper::{AmdsmiEventHandleT, AmdsmiProcessorHandle, AmdsmiSocketHandle}; + +// Re-export all the enums type +pub use crate::amdsmi_wrapper::{ + AmdsmiCachePropertyTypeT, AmdsmiCardFormFactorT, AmdsmiClkLimitTypeT, AmdsmiClkTypeT, + AmdsmiComputePartitionTypeT, AmdsmiCounterCommandT, AmdsmiDevPerfLevelT, AmdsmiEventGroupT, + AmdsmiEventTypeT, AmdsmiEvtNotificationTypeT, AmdsmiFreqIndT, AmdsmiFwBlockT, AmdsmiGpuBlockT, + AmdsmiInitFlagsT, AmdsmiIoLinkTypeT, AmdsmiMemoryPartitionTypeT, AmdsmiMemoryTypeT, + AmdsmiPowerProfilePresetMasksT, AmdsmiPowerTypeT, AmdsmiRasErrStateT, AmdsmiStatusT, + AmdsmiTemperatureMetricT, AmdsmiTemperatureTypeT, AmdsmiUtilizationCounterTypeT, + AmdsmiVoltageMetricT, AmdsmiVoltageTypeT, AmdsmiXgmiStatusT, ProcessorTypeT, AmdsmiAcceleratorPartitionTypeT +}; + +// Re-export all the struct type +pub use crate::amdsmi_wrapper::{ + AmdMetricsTableHeaderT, AmdsmiAcceleratorPartitionProfileT, AmdsmiAsicInfoT, AmdsmiBoardInfoT, + AmdsmiClkInfoT, AmdsmiCounterValueT, AmdsmiDpmPolicyEntryT, AmdsmiDpmPolicyT, + AmdsmiDriverInfoT, AmdsmiEngineUsageT, AmdsmiErrorCountT, AmdsmiEvtNotificationDataT, + AmdsmiFreqVoltRegionT, AmdsmiFrequenciesT, AmdsmiFrequencyRangeT, AmdsmiFwInfoT, + AmdsmiGpuCacheInfoT, AmdsmiGpuCacheInfoTCache, AmdsmiGpuMetricsT, AmdsmiKfdInfoT, + AmdsmiLinkMetricsT, AmdsmiLinkMetricsTLinks, AmdsmiLinkTypeT, AmdsmiNameValueT, + AmdsmiOdVoltFreqDataT, AmdsmiP2pCapabilityT, AmdsmiPcieBandwidthT, AmdsmiPcieInfoT, + AmdsmiPcieInfoTPcieMetric, AmdsmiPcieInfoTPcieStatic, AmdsmiPowerCapInfoT, AmdsmiPowerInfoT, + AmdsmiPowerProfileStatusT, AmdsmiProcInfoT, AmdsmiProcInfoTEngineUsage, + AmdsmiProcInfoTMemoryUsage, AmdsmiProcessInfoT, AmdsmiRangeT, AmdsmiRasFeatureT, + AmdsmiRegTypeT, AmdsmiRetiredPageRecordT, AmdsmiTopologyNearestT, AmdsmiUtilizationCounterT, + AmdsmiVbiosInfoT, AmdsmiVersionT, AmdsmiViolationStatusT, AmdsmiVramInfoT, AmdsmiVramUsageT, + AmdsmiXgmiInfoT, AmdsmiNpsCapsT, AmdsmiNpsCapsTNpsFlags +}; + +//Re-export all the union type +pub use crate::amdsmi_wrapper::AmdsmiBdfT; + +//Re-export the constant type +pub use crate::amdsmi_wrapper::{ + AMDSMI_MAX_AID, AMDSMI_MAX_CACHE_TYPES, AMDSMI_MAX_CONTAINER_TYPE, AMDSMI_MAX_DEVICES, + AMDSMI_MAX_ENGINES, AMDSMI_MAX_FAN_SPEED, AMDSMI_MAX_MM_IP_COUNT, AMDSMI_MAX_NUM_CLKS, + AMDSMI_MAX_NUM_FREQUENCIES, AMDSMI_MAX_NUM_GFX_CLKS, AMDSMI_MAX_NUM_JPEG, + AMDSMI_MAX_NUM_PM_POLICIES, AMDSMI_MAX_NUM_VCN, AMDSMI_MAX_NUM_XGMI_LINKS, + AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK, AMDSMI_MAX_UTILIZATION_VALUES, AMDSMI_NUM_HBM_INSTANCES, + AMDSMI_NUM_VOLTAGE_CURVE_POINTS, +}; + +pub type AmdsmiResult = Result; + +//#[macro_export] +macro_rules! call_unsafe { + ($call:expr) => {{ + let status = unsafe { $call }; + if status != AmdsmiStatusT::AmdsmiStatusSuccess { + return Err(status); + } + }}; +} + +macro_rules! define_cstr { + ($len:expr) => {{ + let buf = vec![0 as std::os::raw::c_char; $len as usize]; + let len = $len as usize; + (buf, len) + }}; +} + +macro_rules! cstr_to_string { + ($vec:expr) => {{ + let c_str = unsafe { std::ffi::CStr::from_ptr($vec.as_ptr()) }; + c_str.to_string_lossy().into_owned() + }}; +} + +// Implements getter methods for C string fields in the specified struct. +// +// This macro generates methods that convert C string fields to Rust `String`. +// +// # Arguments +// +// * `$struct_name` - The name of the struct for which the getter methods are being generated. +// * `$($field_name),+` - The names of the fields for which the getter methods are being generated. +// +// # Example +/// +// ```rust +// +// use std::ffi::c_char; +// +// pub struct AmdsmiVbiosInfoT { +// pub name: [c_char; 64usize], +// pub version: [c_char; 32usize], +// } +// +// impl_cstr_getters!(AmdsmiVbiosInfoT, name, version); +// ``` +macro_rules! impl_cstr_getters { + ($struct_name:ident, $($field_name:ident),+) => { + impl $struct_name { + $( + pub fn $field_name(&self) -> String { + unsafe { + std::ffi::CStr::from_ptr(self.$field_name.as_ptr()) + .to_string_lossy() + .into_owned() + } + } + )+ + } + }; +} + +impl fmt::Display for AmdsmiStatusT { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let status_str = crate::amdsmi_status_code_to_string(*self) + .unwrap_or("An unknown error occurred".to_string()); + write!(f, "{}", status_str) + } +} + +impl fmt::Display for AmdsmiBdfT { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.to_human_readable_string()) + } +} + +impl AmdsmiBdfT { + /// Converts the AmdsmiBdfT structure to a human-readable string. + pub fn to_human_readable_string(&self) -> String { + format!( + "{:04x}:{:02x}:{:02x}.{:x}", + unsafe { self.__bindgen_anon_1.domain_number() }, + unsafe { self.__bindgen_anon_1.bus_number() }, + unsafe { self.__bindgen_anon_1.device_number() }, + unsafe { self.__bindgen_anon_1.function_number() } + ) + } +} + +// Implement the getters for the C string fields in AmdsmiVbiosInfoT +impl_cstr_getters!(AmdsmiVbiosInfoT, name, build_date, part_number, version); + +// Implement the getters for the C string fields in AmdsmiAsicInfoT +impl_cstr_getters!(AmdsmiAsicInfoT, market_name, vendor_name, asic_serial); + +// Implement the getters for the C string fields in AmdsmiBoardInfoT +impl_cstr_getters!( + AmdsmiBoardInfoT, + model_number, + product_serial, + fru_id, + product_name, + manufacturer_name +); + +// Implement the getters for the C string fields in AmdsmiDriverInfoT +impl_cstr_getters!(AmdsmiDriverInfoT, driver_version, driver_date, driver_name); + +// Implement the getters for the C string fields in AmdsmiNameValueT +impl_cstr_getters!(AmdsmiNameValueT, name); + +// Implement the getters for the C string fields in AmdsmiProcInfoT +impl_cstr_getters!(AmdsmiProcInfoT, name, container_name); + +// Implement the getters for the C string fields in AmdsmiDpmPolicyEntryT +impl_cstr_getters!(AmdsmiDpmPolicyEntryT, policy_description);