diff --git a/CMakeLists.txt b/CMakeLists.txt index 97fa12d871..ef5b8756d2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # # Minimum version of cmake required # -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.14) set(AMD_SMI "amd_smi") set(AMD_SMI_COMPONENT "lib${AMD_SMI}") @@ -49,6 +49,8 @@ set(AMD_SMI_PACKAGE CACHE STRING "") project(${AMD_SMI_LIBS_TARGET}) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) include(GNUInstallDirs) @@ -78,7 +80,7 @@ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY generic_package() ## Compiler flags -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-rtti -m64 -msse -msse2 -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-rtti -m64 -msse -msse2") # Security options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion -Wcast-align") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2 -fno-common -Wstrict-overflow") diff --git a/amdsmi_cli/amdsmi_cli.py b/amdsmi_cli/amdsmi_cli.py index d1232b2b26..3a88ae5acc 100755 --- a/amdsmi_cli/amdsmi_cli.py +++ b/amdsmi_cli/amdsmi_cli.py @@ -42,6 +42,12 @@ def _print_error(e, destination): if __name__ == "__main__": + # Disable traceback before possible init errors in AMDSMICommands and AMDSMIParser + if "DEBUG" in sys.argv: + sys.tracebacklimit = 10 + else: + sys.tracebacklimit = -1 + amd_smi_commands = AMDSMICommands() amd_smi_parser = AMDSMIParser(amd_smi_commands.version, amd_smi_commands.list, @@ -80,7 +86,9 @@ if __name__ == "__main__": logging.basicConfig(format='%(levelname)s: %(message)s', level=logging_dict[args.loglevel]) # Disable traceback for non-debug log levels - if args.loglevel != "DEBUG": + if args.loglevel == "DEBUG": + sys.tracebacklimit = 10 + else: sys.tracebacklimit = -1 # Execute subcommands diff --git a/amdsmi_cli/amdsmi_commands.py b/amdsmi_cli/amdsmi_commands.py index 8e7d901789..78b7435ac1 100644 --- a/amdsmi_cli/amdsmi_commands.py +++ b/amdsmi_cli/amdsmi_commands.py @@ -21,6 +21,7 @@ # import logging +import sys import threading import time @@ -42,7 +43,12 @@ class AMDSMICommands(): try: self.device_handles = amdsmi_interface.amdsmi_get_processor_handles() except amdsmi_exception.AmdSmiLibraryException as e: - raise e + if e.err_code in (amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT, + amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED): + logging.error('Unable to get devices, driver not initialized (amdgpu not found in modules)') + sys.exit(-1) + else: + raise e self.stop = '' self.all_arguments = False @@ -220,27 +226,21 @@ class AMDSMICommands(): bus_info['max_pcie_speed'] = pcie_speed_GTs_value - try: - slot_type = amdsmi_interface.amdsmi_topo_get_link_type(args.gpu, args.gpu)['type'] - except amdsmi_exception.AmdSmiLibraryException as e: - slot_type = e.get_error_info() + slot_type = bus_info.pop('pcie_slot_type') + if isinstance(slot_type, int): + slot_types = amdsmi_interface.amdsmi_wrapper.amdsmi_pcie_slot_type_t__enumvalues + if slot_type in slot_types: + bus_info['slot_type'] = slot_types[slot_type].replace("AMDSMI_SLOT_TYPE__", "") + else: + bus_info['slot_type'] = "Unknown" + else: + bus_info['slot_type'] = "N/A" if self.logger.is_human_readable_format(): unit ='GT/s' bus_info['max_pcie_speed'] = f"{bus_info['max_pcie_speed']} {unit}" - if bus_info['pcie_interface_version'] > 0: bus_info['pcie_interface_version'] = f"Gen {bus_info['pcie_interface_version']}" - - bus_info['slot_type'] = 'XXXX' - if isinstance(slot_type, int): - if slot_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_IOLINK_TYPE_UNDEFINED: - bus_info['slot_type'] = "UNKNOWN" - elif slot_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_IOLINK_TYPE_PCIEXPRESS: - bus_info['slot_type'] = "PCIE" - elif slot_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_IOLINK_TYPE_XGMI: - bus_info['slot_type'] = "XGMI" - except amdsmi_exception.AmdSmiLibraryException as e: bus_info = "N/A" logging.debug("Failed to get bus info for gpu %s | %s", gpu_id, e.get_error_info()) @@ -263,18 +263,19 @@ class AMDSMICommands(): if self.helpers.is_linux() and self.helpers.is_baremetal(): if args.board: + static_dict['board'] = {"model_number": "N/A", + "product_serial": "N/A", + "fru_id": "N/A", + "manufacturer_name": "N/A", + "product_name": "N/A"} try: board_info = amdsmi_interface.amdsmi_get_gpu_board_info(args.gpu) - board_info['serial_number'] = hex(board_info['serial_number']) - board_info['model_number'] = board_info['model_number'].strip() - board_info['product_name'] = board_info['product_name'].strip() - board_info['manufacturer_name'] = board_info['manufacturer_name'].strip() - board_info.pop('product_serial') - board_info.pop('manufacturer_name') - + for key, value in board_info.items(): + if isinstance(value, str): + if value.strip() == '': + board_info[key] = "N/A" static_dict['board'] = board_info except amdsmi_exception.AmdSmiLibraryException as e: - static_dict['board'] = "N/A" logging.debug("Failed to get board info for gpu %s | %s", gpu_id, e.get_error_info()) if args.limit: # Power limits @@ -390,14 +391,16 @@ class AMDSMICommands(): static_dict['limit'] = limit_info if args.driver: + driver_info = {"driver_name" : "N/A", + "driver_version" : "N/A", + "driver_date" : "N/A"} + try: - driver_info = {} driver_info = amdsmi_interface.amdsmi_get_gpu_driver_info(args.gpu) - static_dict['driver'] = driver_info except amdsmi_exception.AmdSmiLibraryException as e: - static_dict['driver'] = "N/A" logging.debug("Failed to get driver info for gpu %s | %s", gpu_id, e.get_error_info()) + static_dict['driver'] = driver_info if self.helpers.is_hypervisor() or self.helpers.is_baremetal(): if args.ras: try: @@ -1006,7 +1009,7 @@ class AMDSMICommands(): values_dict['ecc_block'] = "N/A" logging.debug("Failed to get ecc block features for gpu %s | %s", gpu_id, e.get_error_info()) if args.pcie: - pcie_dict = {'current_width': "N/A", + pcie_dict = {'current_lanes': "N/A", 'current_speed': "N/A", 'replay_count' : "N/A", 'current_bandwith_sent': "N/A", @@ -1022,7 +1025,7 @@ class AMDSMICommands(): pcie_speed_GTs_value = round(pcie_link_status['pcie_speed'] / 1000) pcie_dict['current_speed'] = pcie_speed_GTs_value - pcie_dict['current_width'] = pcie_link_status['pcie_lanes'] + pcie_dict['current_lanes'] = pcie_link_status['pcie_lanes'] if self.logger.is_human_readable_format(): unit = 'GT/s' diff --git a/amdsmi_cli/amdsmi_helpers.py b/amdsmi_cli/amdsmi_helpers.py index 8b88c10c05..f4914e01a4 100644 --- a/amdsmi_cli/amdsmi_helpers.py +++ b/amdsmi_cli/amdsmi_helpers.py @@ -141,8 +141,17 @@ class AMDSMIHelpers(): gpu_choices = {} gpu_choices_str = "" - # amdsmi_get_processor_handles returns the device_handles storted for gpu_id - device_handles = amdsmi_interface.amdsmi_get_processor_handles() + try: + # amdsmi_get_processor_handles returns the device_handles storted for gpu_id + device_handles = amdsmi_interface.amdsmi_get_processor_handles() + except amdsmi_interface.AmdSmiLibraryException as e: + if e.err_code in (amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT, + amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED): + logging.error('Unable to get device choices, driver not initialized (amdgpu not found in modules)') + sys.exit(-1) + else: + raise e + for gpu_id, device_handle in enumerate(device_handles): bdf = amdsmi_interface.amdsmi_get_gpu_device_bdf(device_handle) uuid = amdsmi_interface.amdsmi_get_gpu_device_uuid(device_handle) diff --git a/amdsmi_cli/amdsmi_init.py b/amdsmi_cli/amdsmi_init.py index 7e837026cc..a1cb955d02 100644 --- a/amdsmi_cli/amdsmi_init.py +++ b/amdsmi_cli/amdsmi_init.py @@ -36,9 +36,9 @@ from amdsmi import amdsmi_interface from amdsmi import amdsmi_exception # Using basic python logging for user errors and development -logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.ERROR) # User level logging +logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.ERROR) # User level logging # This traceback limit only affects this file, once the code hit's the cli portion it get's reset to the user's preference -sys.tracebacklimit = -1 # Disable traceback for user errors +sys.tracebacklimit = -1 # Disable traceback when raising errors # On initial import set initialized variable AMDSMI_INITIALIZED = False @@ -47,11 +47,9 @@ AMD_VENDOR_ID = 4098 def check_amdgpu_driver(): """ Returns true if amdgpu is found in the list of initialized modules """ amd_gpu_status_file = Path("/sys/module/amdgpu/initstate") - if amd_gpu_status_file.exists(): - if amd_gpu_status_file.read_text(encoding='ascii').strip() == 'live': + if amd_gpu_status_file.read_text(encoding="ascii").strip() == "live": return True - return False @@ -61,17 +59,22 @@ def init_amdsmi(flag=amdsmi_interface.AmdSmiInitFlags.INIT_AMD_GPUS): Raises: err: AmdSmiLibraryException if not successful """ - # Check if amdgpu driver is up & Handle error gracefully + # # Check if amdgpu driver is up & Handle error gracefully if check_amdgpu_driver(): # Only init AMD GPUs for now, waiting for future support for AMD CPUs try: amdsmi_interface.amdsmi_init(flag) - except (amdsmi_interface.AmdSmiLibraryException, amdsmi_interface.AmdSmiParameterException) as err: - raise err - logging.debug('AMDSMI initialized successfully') + except (amdsmi_interface.AmdSmiLibraryException, amdsmi_interface.AmdSmiParameterException) as e: + if e.err_code in (amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT, + amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED): + logging.error("Driver not loaded (amdgpu not found in modules)") + sys.exit(-1) + else: + raise e + logging.debug("AMDSMI initialized successfully, but initstate was not live") else: - logging.error('Driver not initialized (amdgpu not found in modules)') - exit(-1) + logging.error("Driver not found (amdgpu not found in modules)") + sys.exit(-1) def shut_down_amdsmi(): @@ -82,12 +85,13 @@ def shut_down_amdsmi(): """ try: amdsmi_interface.amdsmi_shut_down() - except amdsmi_exception.AmdSmiLibraryException as err: - raise err + except amdsmi_exception.AmdSmiLibraryException as e: + logging.error("Unable to cleanly shut down amd-smi-lib") + raise e def signal_handler(sig, frame): - logging.debug(f'Handling signal: {sig}') + logging.debug(f"Handling signal: {sig}") sys.exit(0) diff --git a/amdsmi_cli/amdsmi_parser.py b/amdsmi_cli/amdsmi_parser.py index 54cba3081e..af95a8641f 100644 --- a/amdsmi_cli/amdsmi_parser.py +++ b/amdsmi_cli/amdsmi_parser.py @@ -348,7 +348,7 @@ class AMDSMIParser(argparse.ArgumentParser): err_records_help = "All error records information" # Create firmware subparser - firmware_parser = subparsers.add_parser('firmware', help=firmware_help, description=firmware_subcommand_help) + firmware_parser = subparsers.add_parser('firmware', help=firmware_help, description=firmware_subcommand_help, aliases=['ucode']) firmware_parser._optionals.title = firmware_optionals_title firmware_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) firmware_parser.set_defaults(func=func) diff --git a/cmake_modules/utils.cmake b/cmake_modules/utils.cmake index 76f910a20b..afaa442e59 100755 --- a/cmake_modules/utils.cmake +++ b/cmake_modules/utils.cmake @@ -52,7 +52,7 @@ function( parse_version VERSION_STRING ) string ( SUBSTRING ${VERSION_STRING} ${STRING_INDEX} -1 VERSION_BUILD ) endif () - string ( REGEX MATCHALL "[0123456789]+" VERSIONS ${VERSION_STRING} ) + string ( REGEX MATCHALL "[0-9]+" VERSIONS ${VERSION_STRING} ) list ( LENGTH VERSIONS VERSION_COUNT ) if ( ${VERSION_COUNT} GREATER 0) diff --git a/example/CMakeLists.txt.in b/example/CMakeLists.txt.in index c4c4c6a854..589fcd6c3e 100644 --- a/example/CMakeLists.txt.in +++ b/example/CMakeLists.txt.in @@ -1,13 +1,11 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.14) option(CMAKE_VERBOSE_MAKEFILE "Enable verbose output" ON) option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compile commands for linters and autocompleters" ON) project(main LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD - 11 - CACHE STRING "The C++ standard to use") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(amd_smi HINTS diff --git a/example/amd_smi_drm_example.cc b/example/amd_smi_drm_example.cc index 09ae1144ee..2ee0bb3127 100644 --- a/example/amd_smi_drm_example.cc +++ b/example/amd_smi_drm_example.cc @@ -322,6 +322,7 @@ int main() { ret = amdsmi_get_gpu_driver_info(processor_handles[j], &driver_info); CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_gpu_driver_info:\n"); + printf("\tDriver name: %s\n", driver_info.driver_name); printf("\tDriver version: %s\n", driver_info.driver_version); printf("\tDriver date: %s\n\n", driver_info.driver_date); @@ -379,9 +380,10 @@ int main() { ret = amdsmi_get_pcie_link_status(processor_handles[j], &pcie_info); CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_pcie_link_status:\n"); - printf("\tPCIe lanes: %d\n", pcie_info.pcie_lanes); - printf("\tPCIe speed: %d\n\n", pcie_info.pcie_speed); - printf("\tPCIe Interface Version: %d\n\n", pcie_info.pcie_interface_version); + printf("\tCurrent PCIe lanes: %d\n", pcie_info.pcie_lanes); + printf("\tCurrent PCIe speed: %d\n", pcie_info.pcie_speed); + printf("\tCurrent PCIe Interface Version: %d\n", pcie_info.pcie_interface_version); + printf("\tPCIe slot type: %d\n\n", pcie_info.pcie_slot_type); // Get PCIe caps amdsmi_pcie_info_t pcie_caps_info = {}; @@ -389,7 +391,7 @@ int main() { CHK_AMDSMI_RET(ret) printf(" Output of amdsmi_get_pcie_link_caps:\n"); printf("\tPCIe max lanes: %d\n", pcie_caps_info.pcie_lanes); - printf("\tPCIe max speed: %d\n\n", pcie_caps_info.pcie_speed); + printf("\tPCIe max speed: %d\n", pcie_caps_info.pcie_speed); printf("\tPCIe Interface Version: %d\n\n", pcie_caps_info.pcie_interface_version); // Get VRAM temperature limit diff --git a/include/amd_smi/amdsmi.h b/include/amd_smi/amdsmi.h index 4f8f2536f1..ce70d58f30 100644 --- a/include/amd_smi/amdsmi.h +++ b/include/amd_smi/amdsmi.h @@ -444,6 +444,7 @@ typedef struct{ typedef struct { + char driver_name[AMDSMI_MAX_STRING_LENGTH]; char driver_version[AMDSMI_MAX_STRING_LENGTH]; char driver_date[AMDSMI_MAX_STRING_LENGTH]; } amdsmi_driver_info_t; @@ -1150,6 +1151,16 @@ typedef struct { uint64_t reserved[2]; } amdsmi_error_count_t; +/** + * @brief This is a enum translation for pcie_slot_type + */ +typedef enum { + AMDSMI_SLOT_TYPE__PCIE = 0, + AMDSMI_SLOT_TYPE__CEM = 1, + AMDSMI_SLOT_TYPE__OAM = 2, + AMDSMI_SLOT_TYPE__RESERVED = 3, +} amdsmi_pcie_slot_type_t; + /** * @brief This structure holds pcie info. */ @@ -1157,8 +1168,10 @@ typedef struct { uint16_t pcie_lanes; uint32_t pcie_speed; uint32_t pcie_interface_version; - uint32_t reserved[5]; + amdsmi_pcie_slot_type_t pcie_slot_type; // 0: PCIE, 1: CEM, 2: OAM, 3: Reserved + uint32_t reserved[4]; } amdsmi_pcie_info_t; + /** * @brief This structure contains information specific to a process. */ diff --git a/include/amd_smi/impl/amd_smi_drm.h b/include/amd_smi/impl/amd_smi_drm.h index cb9fde0c42..88da83e82a 100644 --- a/include/amd_smi/impl/amd_smi_drm.h +++ b/include/amd_smi/impl/amd_smi_drm.h @@ -75,6 +75,7 @@ class AMDSmiDrm { amdsmi_status_t amdgpu_query_hw_ip(int fd, unsigned info_id, unsigned hw_ip_type, unsigned size, void *value); amdsmi_status_t amdgpu_query_vbios(int fd, void *info); + amdsmi_status_t amdgpu_query_driver_name(int fd, std::string& driver_name); amdsmi_status_t amdgpu_query_driver_date(int fd, std::string& driver_date); private: diff --git a/include/amd_smi/impl/amd_smi_gpu_device.h b/include/amd_smi/impl/amd_smi_gpu_device.h index fdd97d8cfd..c191b29421 100644 --- a/include/amd_smi/impl/amd_smi_gpu_device.h +++ b/include/amd_smi/impl/amd_smi_gpu_device.h @@ -81,6 +81,7 @@ class AMDSmiGPUDevice: public AMDSmiProcessor { amdsmi_status_t amdgpu_query_fw(unsigned info_id, unsigned fw_type, unsigned size, void *value) const; amdsmi_status_t amdgpu_query_vbios(void *info) const; + amdsmi_status_t amdgpu_query_driver_name(std::string& name) const; amdsmi_status_t amdgpu_query_driver_date(std::string& date) const; private: uint32_t gpu_id_; diff --git a/py-interface/README.md b/py-interface/README.md index 6efba3b16d..72f9f843fd 100644 --- a/py-interface/README.md +++ b/py-interface/README.md @@ -310,7 +310,13 @@ Input parameters: * `processor_handle` dev for which to query -Output: Driver info that is handling the device +Output: Dictionary with fields + +Field | Content +---|--- +`driver_name` | driver name +`driver_version` | driver_version +`driver_date` | driver_date Exceptions that can be thrown by `amdsmi_get_gpu_driver_info` function: diff --git a/py-interface/amdsmi_exception.py b/py-interface/amdsmi_exception.py index 162e4f7a00..309831101b 100644 --- a/py-interface/amdsmi_exception.py +++ b/py-interface/amdsmi_exception.py @@ -72,7 +72,7 @@ class AmdSmiLibraryException(AmdSmiException): amdsmi_wrapper.AMDSMI_STATUS_NOT_FOUND : "AMDSMI_STATUS_NOT_FOUND - Device Not found", amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT : "AMDSMI_STATUS_NOT_INIT - Device not initialized", amdsmi_wrapper.AMDSMI_STATUS_NO_SLOT : "AMDSMI_STATUS_NO_SLOT - No more free slot", - amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED : "AMDSMI_STATUS_DRIVER_NOT_LOADED - Processor driver not loaded", + amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED : "AMDSMI_STATUS_DRIVER_NOT_LOADED - Driver not loaded", amdsmi_wrapper.AMDSMI_STATUS_NO_DATA : "AMDSMI_STATUS_NO_DATA - No data was found for given input", amdsmi_wrapper.AMDSMI_STATUS_INSUFFICIENT_SIZE : "AMDSMI_STATUS_INSUFFICIENT_SIZE - Insufficient size for operation", amdsmi_wrapper.AMDSMI_STATUS_UNEXPECTED_SIZE : "AMDSMI_STATUS_UNEXPECTED_SIZE - unexpected size of data was read", diff --git a/py-interface/amdsmi_interface.py b/py-interface/amdsmi_interface.py index 9731bf6c65..9c439e3104 100644 --- a/py-interface/amdsmi_interface.py +++ b/py-interface/amdsmi_interface.py @@ -823,11 +823,11 @@ def amdsmi_get_gpu_board_info( ) return { - "serial_number": board_info.serial_number, - "model_number": board_info.model_number.decode("utf-8"), - "product_serial": board_info.product_serial.decode("utf-8"), - "product_name": board_info.product_name.decode("utf-8"), - "manufacturer_name" : board_info.product_name.decode("utf-8") + "model_number": board_info.model_number.decode("utf-8").strip(), + "product_serial": board_info.serial_number, + "fru_id": board_info.fru_id.decode("utf-8").strip(), + "manufacturer_name" : board_info.manufacturer_name.decode("utf-8").strip(), + "product_name": board_info.product_name.decode("utf-8").strip() } @@ -962,6 +962,7 @@ def amdsmi_get_gpu_driver_info( ) return { + "driver_name": info.driver_name.decode("utf-8"), "driver_version": info.driver_version.decode("utf-8"), "driver_date": info.driver_date.decode("utf-8") } @@ -1061,7 +1062,8 @@ def amdsmi_get_pcie_link_status( return {"pcie_speed": pcie_info.pcie_speed, "pcie_lanes": pcie_info.pcie_lanes, - "pcie_interface_version": pcie_info.pcie_interface_version} + "pcie_interface_version": pcie_info.pcie_interface_version, + "pcie_slot_type": pcie_info.pcie_slot_type} def amdsmi_get_pcie_link_caps( processor_handle: amdsmi_wrapper.amdsmi_processor_handle, @@ -1079,7 +1081,8 @@ def amdsmi_get_pcie_link_caps( return {"max_pcie_speed": pcie_info.pcie_speed, "max_pcie_lanes": pcie_info.pcie_lanes, - "pcie_interface_version": pcie_info.pcie_interface_version} + "pcie_interface_version": pcie_info.pcie_interface_version, + "pcie_slot_type": pcie_info.pcie_slot_type} def amdsmi_get_processor_handle_from_bdf(bdf): diff --git a/py-interface/amdsmi_wrapper.py b/py-interface/amdsmi_wrapper.py index 2c0fcfe1ab..74240ad597 100644 --- a/py-interface/amdsmi_wrapper.py +++ b/py-interface/amdsmi_wrapper.py @@ -774,6 +774,7 @@ class struct_amdsmi_driver_info_t(Structure): struct_amdsmi_driver_info_t._pack_ = 1 # source:False struct_amdsmi_driver_info_t._fields_ = [ + ('driver_name', ctypes.c_char * 64), ('driver_version', ctypes.c_char * 64), ('driver_date', ctypes.c_char * 64), ] @@ -1424,6 +1425,19 @@ struct_amdsmi_error_count_t._fields_ = [ ] amdsmi_error_count_t = struct_amdsmi_error_count_t + +# values for enumeration 'amdsmi_pcie_slot_type_t' +amdsmi_pcie_slot_type_t__enumvalues = { + 0: 'AMDSMI_SLOT_TYPE__PCIE', + 1: 'AMDSMI_SLOT_TYPE__CEM', + 2: 'AMDSMI_SLOT_TYPE__OAM', + 3: 'AMDSMI_SLOT_TYPE__RESERVED', +} +AMDSMI_SLOT_TYPE__PCIE = 0 +AMDSMI_SLOT_TYPE__CEM = 1 +AMDSMI_SLOT_TYPE__OAM = 2 +AMDSMI_SLOT_TYPE__RESERVED = 3 +amdsmi_pcie_slot_type_t = ctypes.c_uint32 # enum class struct_amdsmi_pcie_info_t(Structure): pass @@ -1433,7 +1447,8 @@ struct_amdsmi_pcie_info_t._fields_ = [ ('PADDING_0', ctypes.c_ubyte * 2), ('pcie_speed', ctypes.c_uint32), ('pcie_interface_version', ctypes.c_uint32), - ('reserved', ctypes.c_uint32 * 5), + ('pcie_slot_type', amdsmi_pcie_slot_type_t), + ('reserved', ctypes.c_uint32 * 4), ] amdsmi_pcie_info_t = struct_amdsmi_pcie_info_t @@ -1804,7 +1819,9 @@ __all__ = \ 'AMDSMI_RAS_ERR_STATE_INVALID', 'AMDSMI_RAS_ERR_STATE_LAST', 'AMDSMI_RAS_ERR_STATE_MULT_UC', 'AMDSMI_RAS_ERR_STATE_NONE', 'AMDSMI_RAS_ERR_STATE_PARITY', 'AMDSMI_RAS_ERR_STATE_POISON', - 'AMDSMI_RAS_ERR_STATE_SING_C', 'AMDSMI_STATUS_ADDRESS_FAULT', + 'AMDSMI_RAS_ERR_STATE_SING_C', 'AMDSMI_SLOT_TYPE__CEM', + 'AMDSMI_SLOT_TYPE__OAM', 'AMDSMI_SLOT_TYPE__PCIE', + 'AMDSMI_SLOT_TYPE__RESERVED', 'AMDSMI_STATUS_ADDRESS_FAULT', 'AMDSMI_STATUS_API_FAILED', 'AMDSMI_STATUS_BUSY', 'AMDSMI_STATUS_DRIVER_NOT_LOADED', 'AMDSMI_STATUS_DRM_ERROR', 'AMDSMI_STATUS_FAIL_LOAD_MODULE', @@ -1954,8 +1971,8 @@ __all__ = \ 'amdsmi_mm_ip_t', 'amdsmi_od_vddc_point_t', 'amdsmi_od_volt_curve_t', 'amdsmi_od_volt_freq_data_t', 'amdsmi_pcie_bandwidth_t', 'amdsmi_pcie_info_t', - 'amdsmi_power_cap_info_t', 'amdsmi_power_info_t', - 'amdsmi_power_profile_preset_masks_t', + 'amdsmi_pcie_slot_type_t', 'amdsmi_power_cap_info_t', + 'amdsmi_power_info_t', 'amdsmi_power_profile_preset_masks_t', 'amdsmi_power_profile_status_t', 'amdsmi_proc_info_t', 'amdsmi_process_handle_t', 'amdsmi_process_info_t', 'amdsmi_processor_handle', 'amdsmi_range_t', diff --git a/rocm_smi/include/rocm_smi/rocm_smi.h b/rocm_smi/include/rocm_smi/rocm_smi.h index 6f8cb475ac..31064f3cc9 100755 --- a/rocm_smi/include/rocm_smi/rocm_smi.h +++ b/rocm_smi/include/rocm_smi/rocm_smi.h @@ -625,6 +625,19 @@ typedef enum { typedef rsmi_freq_ind_t rsmi_freq_ind; /// \endcond +/** + * @brief The values of this enum are used as PCIe slot type. + */ +typedef enum { + RSMI_PCIE_SLOT_PCIE = 0, + RSMI_PCIE_SLOT_CEM = 1, + RSMI_PCIE_SLOT_OAM = 2, + RSMI_PCIE_SLOT_UNKNOWN = 3 //!< An unknown +} rsmi_pcie_slot_type_t; +/// \cond Ignore in docs. +typedef rsmi_pcie_slot_type_t rsmi_pcie_slot_type; +/// \endcond + /** * @brief The values of this enum are used to identify the various firmware @@ -1391,6 +1404,26 @@ rsmi_status_t rsmi_dev_vendor_name_get(uint32_t dv_ind, char *name, rsmi_status_t rsmi_dev_vram_vendor_get(uint32_t dv_ind, char *brand, uint32_t len); + +/** + * @brief Get the PCIe slot type of a gpu device. + * + * @details Given a device index @p dv_ind, a pointer to a caller provided + * char buffer @p type, this function will write the PCIe slot type of the + * device to @p type. + * + * + * @param[in] dv_ind a device index + * + * @param[inout] type a pointer to a caller provided buffer to which the + * type info will be written + * + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. + * + */ +rsmi_status_t rsmi_dev_pcie_slot_type_get(uint32_t dv_ind, + rsmi_pcie_slot_type_t* type); + /** * @brief Get the serial number string for a device * diff --git a/rocm_smi/include/rocm_smi/rocm_smi_device.h b/rocm_smi/include/rocm_smi/rocm_smi_device.h index e9a61af972..8640bae9c1 100755 --- a/rocm_smi/include/rocm_smi/rocm_smi_device.h +++ b/rocm_smi/include/rocm_smi/rocm_smi_device.h @@ -105,6 +105,7 @@ enum DevInfoTypes { kDevDevRevID, kDevDevProdName, kDevDevProdNum, + kDevBoardInfo, kDevVendorID, kDevSubSysDevID, kDevSubSysVendorID, @@ -200,6 +201,9 @@ class Device { int readDevInfo(DevInfoTypes type, std::vector *retVec); int readDevInfo(DevInfoTypes type, std::size_t b_size, void *p_binary_data); + // Get the property from a file which may contain multiple properties. + int readDevInfo(DevInfoTypes type, const std::string& property, + std::string& value); int writeDevInfo(DevInfoTypes type, uint64_t val); int writeDevInfo(DevInfoTypes type, std::string val); diff --git a/rocm_smi/include/rocm_smi/rocm_smi_utils.h b/rocm_smi/include/rocm_smi/rocm_smi_utils.h index f66eedf314..174ae3e988 100755 --- a/rocm_smi/include/rocm_smi/rocm_smi_utils.h +++ b/rocm_smi/include/rocm_smi/rocm_smi_utils.h @@ -269,6 +269,9 @@ class ScopedAcquire { // In VM environment, the /proc/cpuinfo set hypervisor flag by default bool is_vm_guest(); +// trim a string +std::string trim(const std::string &s); + } // namespace smi } // namespace amd diff --git a/rocm_smi/python_smi_tools/rocm_smi.py b/rocm_smi/python_smi_tools/rocm_smi.py index 6f7ba1a8e0..8db2d7eeea 100755 --- a/rocm_smi/python_smi_tools/rocm_smi.py +++ b/rocm_smi/python_smi_tools/rocm_smi.py @@ -30,8 +30,8 @@ from rsmiBindings import * # Minor version - Increment when adding a new feature, set to 0 when major is incremented # Patch version - Increment when adding a fix, set to 0 when minor is incremented SMI_MAJ = 1 -SMI_MIN = 4 -SMI_PAT = 1 +SMI_MIN = 5 +SMI_PAT = 0 __version__ = '%s.%s.%s' % (SMI_MAJ, SMI_MIN, SMI_PAT) # Set to 1 if an error occurs @@ -1675,6 +1675,32 @@ def setNPSMode(deviceList, npsMode): printErrLog(device, 'Failed to retrieve NPS mode, even though device supports it.') printLogSpacer() +def showVersion(isCSV=False): + values = { 'ROCM-SMI version': __version__ } + + version = rsmi_version_t() + status = rocmsmi.rsmi_version_get(byref(version)) + if status == 0: + version_string = "%u.%u.%u" % (version.major, version.minor, version.patch) + values['ROCM-SMI-LIB version'] = version_string + + if isCSV: + print('name, value') + for k in values.keys(): + print('%s, %s' % (k, values[k])) + return + if PRINT_JSON: + temp_str = '{\n' + for k in values.keys(): + temp_str += ' "%s": "%s",\n' % (k, values[k]) + if len(values.keys()) > 1: + # replace ',\n' with '\n}' + temp_str = temp_str[:-2] + temp_str += '\n}' + print(temp_str) + return + for k in values.keys(): + print('%s: %s' % (k, values[k])) def showAllConcise(deviceList): """ Display critical info for all devices in a concise format @@ -2052,7 +2078,7 @@ def showFwInfo(deviceList, fwType): ret = rocmsmi.rsmi_dev_firmware_version_get(device, fw_block_names_l.index(fw_name), byref(fw_ver)) if rsmi_ret_ok(ret, device, 'get_firmware_version_' + str(fw_name)): # The VCN, VCE, UVD, SOS and ASD firmware's value needs to be in hexadecimal - if fw_name in ['VCN', 'VCE', 'UVD', 'SOS', 'ASD']: + if fw_name in ['VCN', 'VCE', 'UVD', 'SOS', 'ASD', 'MES', 'MES KIQ']: printLog(device, '%s firmware version' % (fw_name), '\t0x%s' % (str(hex(fw_ver.value))[2:].zfill(8))) # The TA XGMI, TA RAS, and SMC firmware's hex value looks like 0x12345678 @@ -2955,7 +2981,7 @@ def showTempGraph(deviceList): printLogSpacer() -def showVersion(deviceList, component): +def showDriverVersion(deviceList, component): """ Display the software version for the specified component @param deviceList: List of DRM devices (can be a single-item list) @@ -3614,6 +3640,7 @@ if __name__ == '__main__': parser = argparse.ArgumentParser( description='AMD ROCm System Management Interface | ROCM-SMI version: %s' % __version__, formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=90, width=120)) + groupVersion = parser.add_argument_group() groupDev = parser.add_argument_group() groupDisplayOpt = parser.add_argument_group('Display Options') groupDisplayTop = parser.add_argument_group('Topology') @@ -3627,6 +3654,7 @@ if __name__ == '__main__': groupResponse = parser.add_argument_group('Auto-response options') groupActionOutput = parser.add_argument_group('Output options') + groupVersion.add_argument('-V', '--version', help='Show version information', action='store_true') groupDev.add_argument('-d', '--device', help='Execute command on specified device', type=int, nargs='+') groupDisplayOpt.add_argument('--alldevices', action='store_true') # ------------- function deprecated, no help menu groupDisplayOpt.add_argument('--showhw', help='Show Hardware details', action='store_true') @@ -3775,11 +3803,16 @@ if __name__ == '__main__': # Must set PRINT_JSON early so the prints can be silenced if args.json or args.csv: PRINT_JSON = True + # Initialize rsmiBindings rocmsmi = initRsmiBindings(silent=PRINT_JSON) # Initialize the rocm SMI library initializeRsmi() + if args.version: + showVersion(isCSV=args.csv) + sys.exit() + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING) if args.loglevel is not None: numericLogLevel = getattr(logging, args.loglevel.upper(), logging.WARNING) @@ -3878,7 +3911,7 @@ if __name__ == '__main__': if args.showhw: showAllConciseHw(deviceList) if args.showdriverversion: - showVersion(deviceList, rsmi_sw_component_t.RSMI_SW_COMP_DRIVER) + showDriverVersion(deviceList, rsmi_sw_component_t.RSMI_SW_COMP_DRIVER) if args.showtempgraph: showTempGraph(deviceList) if args.showid: diff --git a/rocm_smi/python_smi_tools/rsmiBindings.py b/rocm_smi/python_smi_tools/rsmiBindings.py index 36dbb6e5ff..f913d99936 100644 --- a/rocm_smi/python_smi_tools/rsmiBindings.py +++ b/rocm_smi/python_smi_tools/rsmiBindings.py @@ -37,8 +37,6 @@ def initRsmiBindings(silent=False): print_silent('Using lib from %s' % path_librocm) else: print('Unable to find librocm_smi64.so.@VERSION_MAJOR@') - else: - print_silent('Library loaded from: %s ' % path_librocm) # ----------> TODO: Support static libs as well as SO try: @@ -419,25 +417,27 @@ class rsmi_fw_block_t(c_int): RSMI_FW_BLOCK_ME = 4 RSMI_FW_BLOCK_MEC = 5 RSMI_FW_BLOCK_MEC2 = 6 - RSMI_FW_BLOCK_PFP = 7 - RSMI_FW_BLOCK_RLC = 8 - RSMI_FW_BLOCK_RLC_SRLC = 9 - RSMI_FW_BLOCK_RLC_SRLG = 10 - RSMI_FW_BLOCK_RLC_SRLS = 11 - RSMI_FW_BLOCK_SDMA = 12 - RSMI_FW_BLOCK_SDMA2 = 13 - RSMI_FW_BLOCK_SMC = 14 - RSMI_FW_BLOCK_SOS = 15 - RSMI_FW_BLOCK_TA_RAS = 16 - RSMI_FW_BLOCK_TA_XGMI = 17 - RSMI_FW_BLOCK_UVD = 18 - RSMI_FW_BLOCK_VCE = 19 - RSMI_FW_BLOCK_VCN = 20 + RSMI_FW_BLOCK_MES = 7 + RSMI_FW_BLOCK_MES_KIQ = 8 + RSMI_FW_BLOCK_PFP = 9 + RSMI_FW_BLOCK_RLC = 10 + RSMI_FW_BLOCK_RLC_SRLC = 11 + RSMI_FW_BLOCK_RLC_SRLG = 12 + RSMI_FW_BLOCK_RLC_SRLS = 13 + RSMI_FW_BLOCK_SDMA = 14 + RSMI_FW_BLOCK_SDMA2 = 15 + RSMI_FW_BLOCK_SMC = 16 + RSMI_FW_BLOCK_SOS = 17 + RSMI_FW_BLOCK_TA_RAS = 18 + RSMI_FW_BLOCK_TA_XGMI = 19 + RSMI_FW_BLOCK_UVD = 20 + RSMI_FW_BLOCK_VCE = 21 + RSMI_FW_BLOCK_VCN = 22 RSMI_FW_BLOCK_LAST = RSMI_FW_BLOCK_VCN # The following list correlated to the rsmi_fw_block_t -fw_block_names_l = ['ASD', 'CE', 'DMCU', 'MC', 'ME', 'MEC', 'MEC2', 'PFP',\ +fw_block_names_l = ['ASD', 'CE', 'DMCU', 'MC', 'ME', 'MEC', 'MEC2', 'MES', 'MES KIQ', 'PFP',\ 'RLC', 'RLC SRLC', 'RLC SRLG', 'RLC SRLS', 'SDMA', 'SDMA2',\ 'SMC', 'SOS', 'TA RAS', 'TA XGMI', 'UVD', 'VCE', 'VCN'] diff --git a/rocm_smi/src/rocm_smi.cc b/rocm_smi/src/rocm_smi.cc index 79c703bc31..10cca04b8d 100755 --- a/rocm_smi/src/rocm_smi.cc +++ b/rocm_smi/src/rocm_smi.cc @@ -910,6 +910,29 @@ rsmi_dev_vendor_id_get(uint32_t dv_ind, uint16_t *id) { return get_id(dv_ind, amd::smi::kDevVendorID, id); } +rsmi_status_t +rsmi_dev_pcie_slot_type_get(uint32_t dv_ind, rsmi_pcie_slot_type_t* type) { + TRY + + std::ostringstream ss; + ss << __PRETTY_FUNCTION__ << "| ======= start ======="; + LOG_TRACE(ss); + CHK_SUPPORT_NAME_ONLY(type) + DEVICE_MUTEX + + std::string value; + int ret = dev->readDevInfo(amd::smi::kDevBoardInfo, "type", value); + if (ret != 0) return RSMI_STATUS_NOT_SUPPORTED; + + *type = RSMI_PCIE_SLOT_PCIE; + if (value.compare("oam") == 0) *type=RSMI_PCIE_SLOT_OAM; + else if (value.compare("cem") == 0 ) *type=RSMI_PCIE_SLOT_CEM; + else if (value.compare("unknown") == 0 ) *type=RSMI_PCIE_SLOT_UNKNOWN; + return RSMI_STATUS_SUCCESS; + + CATCH +} + rsmi_status_t rsmi_dev_subsystem_vendor_id_get(uint32_t dv_ind, uint16_t *id) { std::ostringstream ss; diff --git a/rocm_smi/src/rocm_smi_device.cc b/rocm_smi/src/rocm_smi_device.cc index 1310b27956..a1a45795e2 100755 --- a/rocm_smi/src/rocm_smi_device.cc +++ b/rocm_smi/src/rocm_smi_device.cc @@ -87,6 +87,7 @@ static const char *kDevDevProdNumFName = "product_number"; static const char *kDevDevIDFName = "device"; static const char *kDevDevRevIDFName = "revision"; static const char *kDevVendorIDFName = "vendor"; +static const char *kDevBoardInfoFName = "board_info"; static const char *kDevSubSysDevIDFName = "subsystem_device"; static const char *kDevSubSysVendorIDFName = "subsystem_vendor"; static const char *kDevOverDriveLevelFName = "pp_sclk_od"; @@ -238,6 +239,7 @@ static const std::map kDevAttribNameMap = { {kDevPerfLevel, kDevPerfLevelFName}, {kDevOverDriveLevel, kDevOverDriveLevelFName}, {kDevMemOverDriveLevel, kDevMemOverDriveLevelFName}, + {kDevBoardInfo, kDevBoardInfoFName}, {kDevDevProdName, kDevDevProdNameFName}, {kDevDevProdNum, kDevDevProdNumFName}, {kDevDevID, kDevDevIDFName}, @@ -388,6 +390,7 @@ static const std::map kDevFuncDependsMap = { {"rsmi_dev_name_get", {{kDevVendorIDFName, kDevDevIDFName}, {}}}, {"rsmi_dev_sku_get", {{kDevDevProdNumFName}, {}}}, + {"rsmi_dev_pcie_slot_type_get", {{kDevBoardInfoFName}, {}}}, {"rsmi_dev_brand_get", {{kDevVendorIDFName, kDevVBiosVerFName}, {}}}, {"rsmi_dev_vendor_name_get", {{kDevVendorIDFName}, {}}}, @@ -1003,6 +1006,34 @@ int Device::readDevInfo(DevInfoTypes type, uint64_t *val) { return 0; } +// Read a property from a file which may contain multiple properties +int Device::readDevInfo(DevInfoTypes type, const std::string& property, + std::string& value) { + std::vector val; + int ret = 0; + switch (type) { + case kDevBoardInfo: + ret = readDevInfoMultiLineStr(type, &val); + break; + default: + return EINVAL; + } + if (ret != 0) return ret; + + // Find the property from the file + for (unsigned int i = 0; i < val.size(); i++) { + auto pos = val[i].find(":"); // delimiter + if (pos == std::string::npos) continue; + auto name = trim(val[i].substr(0, pos)); + if (name != property) continue; + value = trim(val[i].substr(pos+1)); + return 0; + } + + + return EINVAL; +} + int Device::readDevInfo(DevInfoTypes type, std::vector *val) { assert(val != nullptr); diff --git a/rocm_smi/src/rocm_smi_main.cc b/rocm_smi/src/rocm_smi_main.cc index 9089e9093d..2e5b322f28 100755 --- a/rocm_smi/src/rocm_smi_main.cc +++ b/rocm_smi/src/rocm_smi_main.cc @@ -86,6 +86,7 @@ amd::smi::RocmSMI::devInfoTypesStrings = { {amd::smi::kDevDevID, amdSMI + "kDevDevID"}, {amd::smi::kDevDevRevID, amdSMI + "kDevDevRevID"}, {amd::smi::kDevDevProdName, amdSMI + "kDevDevProdName"}, + {amd::smi::kDevBoardInfo, amdSMI + "kDevBoardInfo"}, {amd::smi::kDevDevProdNum, amdSMI + "kDevDevProdNum"}, {amd::smi::kDevVendorID, amdSMI + "kDevVendorID"}, {amd::smi::kDevSubSysDevID, amdSMI + "kDevSubSysDevID"}, diff --git a/src/amd_smi/amd_smi.cc b/src/amd_smi/amd_smi.cc index f6a3fbef4c..7040860e06 100644 --- a/src/amd_smi/amd_smi.cc +++ b/src/amd_smi/amd_smi.cc @@ -457,7 +457,7 @@ amdsmi_status_t amdsmi_get_gpu_board_info(amdsmi_processor_handle processor_hand return r; if (gpu_device->check_if_drm_is_supported()) { - // Get from sys file + // Populate product_serial, product_name, & product_number from sysfs status = smi_amdgpu_get_board_info(gpu_device, board_info); } else { @@ -472,6 +472,9 @@ amdsmi_status_t amdsmi_get_gpu_board_info(amdsmi_processor_handle processor_hand } } + // Get FRU ID + // Get manufacturer name + return AMDSMI_STATUS_SUCCESS; } @@ -1718,18 +1721,30 @@ amdsmi_status_t amdsmi_get_gpu_driver_info(amdsmi_processor_handle processor_han return r; int length = AMDSMI_MAX_STRING_LENGTH; + + // Get the driver version status = smi_amdgpu_get_driver_version(gpu_device, &length, info->driver_version); + + // Get the driver date std::string driver_date; status = gpu_device->amdgpu_query_driver_date(driver_date); - if (status != AMDSMI_STATUS_SUCCESS) return r; - + if (status != AMDSMI_STATUS_SUCCESS) + return r; // Reformat the driver date from 20150101 to 2015/01/01 00:00 if (driver_date.length() == 8) { driver_date = driver_date.substr(0, 4) + "/" + driver_date.substr(4, 2) + "/" + driver_date.substr(6, 2) + " 00:00"; } strncpy(info->driver_date, driver_date.c_str(), AMDSMI_MAX_STRING_LENGTH-1); + + // Get the driver name + std::string driver_name; + status = gpu_device->amdgpu_query_driver_name(driver_name); + if (status != AMDSMI_STATUS_SUCCESS) + return r; + strncpy(info->driver_name, driver_name.c_str(), AMDSMI_MAX_STRING_LENGTH-1); + return status; } @@ -1813,7 +1828,16 @@ amdsmi_get_pcie_link_status(amdsmi_processor_handle processor_handle, amdsmi_pci info->pcie_interface_version = 0; } - return status; + // default to PCIe + info->pcie_slot_type = AMDSMI_SLOT_TYPE__PCIE; + rsmi_pcie_slot_type_t slot_type; + status = rsmi_wrapper(rsmi_dev_pcie_slot_type_get, + processor_handle, &slot_type); + if (status == AMDSMI_STATUS_SUCCESS) { + info->pcie_slot_type = static_cast(slot_type); + } + + return AMDSMI_STATUS_SUCCESS; } amdsmi_status_t amdsmi_get_pcie_link_caps(amdsmi_processor_handle processor_handle, amdsmi_pcie_info_t *info) { @@ -1887,7 +1911,16 @@ amdsmi_status_t amdsmi_get_pcie_link_caps(amdsmi_processor_handle processor_hand info->pcie_interface_version = 0; } - return status; + // default to PCIe + info->pcie_slot_type = AMDSMI_SLOT_TYPE__PCIE; + rsmi_pcie_slot_type_t slot_type; + status = rsmi_wrapper(rsmi_dev_pcie_slot_type_get, + processor_handle, &slot_type); + if (status == AMDSMI_STATUS_SUCCESS) { + info->pcie_slot_type = static_cast(slot_type); + } + + return AMDSMI_STATUS_SUCCESS; } amdsmi_status_t amdsmi_get_processor_handle_from_bdf(amdsmi_bdf_t bdf, diff --git a/src/amd_smi/amd_smi_drm.cc b/src/amd_smi/amd_smi_drm.cc index 49677e77e8..f3c6d8e090 100644 --- a/src/amd_smi/amd_smi_drm.cc +++ b/src/amd_smi/amd_smi_drm.cc @@ -197,6 +197,18 @@ amdsmi_status_t AMDSmiDrm::cleanup() { return AMDSMI_STATUS_SUCCESS; } +amdsmi_status_t AMDSmiDrm::amdgpu_query_driver_name(int fd, std::string& driver_name) { + // RAII handler + using drm_version_ptr = std::unique_ptr; + std::lock_guard guard(drm_mutex_); + auto version = drm_version_ptr( + drm_get_version_(fd), drm_free_version_); + if (version == nullptr) return AMDSMI_STATUS_DRM_ERROR; + driver_name = version->name; + return AMDSMI_STATUS_SUCCESS; +} + amdsmi_status_t AMDSmiDrm::amdgpu_query_driver_date(int fd, std::string& driver_date) { // RAII handler using drm_version_ptr = std::unique_ptrserial_number); + fscanf(fp, "%lx", &info->product_serial); fclose(fp); } diff --git a/tests/amd_smi_test/CMakeLists.txt b/tests/amd_smi_test/CMakeLists.txt index d87bdec4c2..865042b89b 100644 --- a/tests/amd_smi_test/CMakeLists.txt +++ b/tests/amd_smi_test/CMakeLists.txt @@ -7,20 +7,13 @@ set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../../../lib" CACHE STRING "RUNPATH for tests. Helps find libgtest.so and libamd_smi.so") -# Try to find googletest -find_package(GTest 1.12.0) - -# GTest_FOUND is set to TRUE if ANY version is found -# GTest_VERSION is set if 1.11.0 or newer version is found -if(NOT GTest_FOUND STREQUAL "TRUE" OR NOT DEFINED GTest_VERSION) - # Google Test wasn't found. Download and compile ourselves - include(FetchContent) - FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.12.0) - FetchContent_MakeAvailable(googletest) -endif() +# Download and compile googletest +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0) +FetchContent_MakeAvailable(googletest) enable_testing() @@ -70,10 +63,9 @@ target_link_libraries(${TEST} stdc++ pthread) -# Install tests and gtest -# TODO: Remove GTest from here in the future and rely on INSTALL_GTEST? +# Install tests install( - TARGETS ${TEST} gtest gtest_main + TARGETS ${TEST} DESTINATION ${SHARE_INSTALL_PREFIX}/tests COMPONENT ${TESTS_COMPONENT}) @@ -81,3 +73,9 @@ install( FILES amdsmitst.exclude DESTINATION ${SHARE_INSTALL_PREFIX}/tests COMPONENT ${TESTS_COMPONENT}) + +# Install googletest libraries with tests +install(TARGETS gtest gtest_main + DESTINATION ${SHARE_INSTALL_PREFIX}/tests + COMPONENT ${TESTS_COMPONENT}) + diff --git a/tests/amd_smi_test/amdsmitst.exclude b/tests/amd_smi_test/amdsmitst.exclude index f498de400f..5a49f0dc0a 100644 --- a/tests/amd_smi_test/amdsmitst.exclude +++ b/tests/amd_smi_test/amdsmitst.exclude @@ -14,12 +14,13 @@ PERMANENT_BLACKLIST_ALL_ASICS= # is failing consistently TEMPORARY_BLACKLIST_ALL_ASICS= -if [ -z $PERMANENT_BLACKLIST_ALL_ASICS -a -z $TEMPORARY_BLACKLIST_ALL_ASICS ]; then + +if [ -z "$PERMANENT_BLACKLIST_ALL_ASICS" -a -z "$TEMPORARY_BLACKLIST_ALL_ASICS" ]; then BLACKLIST_ALL_ASICS= else BLACKLIST_ALL_ASICS=\ - "$PERMANENT_BLACKLIST_ALL_ASICS:"\ - "$TEMPORARY_BLACKLIST_ALL_ASICS" +"$PERMANENT_BLACKLIST_ALL_ASICS:"\ +"$TEMPORARY_BLACKLIST_ALL_ASICS:" fi # Device specific blacklists @@ -55,6 +56,18 @@ FILTER[sienna_cichlid]=\ $BLACKLIST_ALL_ASICS\ "amdsmitstReadWrite.TestPerfLevelReadWrite" +# SWDEV-391407 +# aqua_vanjaram and later systems show 'ip discovery' in +# /sys/class/kfd/kfd/topology/nodes/*/name +# +# For those systems gfx_target_version must be used. It can be found in +# /sys/class/kfd/kfd/topology/nodes/*/properties +FILTER[90400]=\ +$BLACKLIST_ALL_ASICS\ +"amdsmitstReadOnly.TestVoltCurvRead" +FILTER[90401]=${FILTER[90400]} +FILTER[90402]=${FILTER[90400]} + # SWDEV-321166 FILTER[virtualization]=\ $BLACKLIST_ALL_ASICS\ @@ -63,4 +76,4 @@ $BLACKLIST_ALL_ASICS\ "amdsmitstReadWrite.FanReadWrite:"\ "amdsmitstReadWrite.TestOverdriveReadWrite:"\ "amdsmitstReadWrite.TestPowerReadWrite:"\ -"amdsmitstReadWrite.TestPowerCapReadWrite" \ No newline at end of file +"amdsmitstReadWrite.TestPowerCapReadWrite" diff --git a/tests/amd_smi_test/functional/frequencies_read.cc b/tests/amd_smi_test/functional/frequencies_read.cc index eae1c7abeb..33d678e7da 100755 --- a/tests/amd_smi_test/functional/frequencies_read.cc +++ b/tests/amd_smi_test/functional/frequencies_read.cc @@ -43,9 +43,7 @@ * */ -#include -#include - +#include #include #include @@ -87,15 +85,23 @@ void TestFrequenciesRead::Close() { static void print_frequencies(amdsmi_frequencies_t *f, uint32_t *l = nullptr) { assert(f != nullptr); - for (uint32_t j = 0; j < f->num_supported; ++j) { - std::cout << "\t** " << j << ": " << f->frequency[j]; + for (uint32_t clk_i = 0; clk_i < f->num_supported; ++clk_i) { + std::string clk_i_str; + if (f->has_deep_sleep) { + clk_i_str = (clk_i == 0) ? "S" : std::to_string(clk_i-1); + } else { + clk_i_str = std::to_string(clk_i); + } + std::cout << "\t** " << + std::setw(2) << std::right << clk_i_str << ": " << + std::setw(11) << std::right << f->frequency[clk_i]; if (l != nullptr) { - std::cout << "T/s; x" << l[j]; + std::cout << "T/s; x" << l[clk_i]; } else { std::cout << "Hz"; } - if (j == f->current) { + if (clk_i == f->current) { std::cout << " *"; } std::cout << std::endl; @@ -123,23 +129,30 @@ void TestFrequenciesRead::Run(void) { // Verify api support checking functionality is working err = amdsmi_get_clk_freq(processor_handles_[i], t, nullptr); ASSERT_EQ(err, AMDSMI_STATUS_INVAL); - } else if (err == AMDSMI_STATUS_NOT_YET_IMPLEMENTED) { + return; + } + + if (err == AMDSMI_STATUS_NOT_YET_IMPLEMENTED) { std::cout << "\t**Get " << name << ": Not implemented on this machine" << std::endl; - // special driver issue, shouldn't normally occur - } else if (err == AMDSMI_STATUS_UNEXPECTED_DATA) { + return; + } + + if (err == AMDSMI_STATUS_UNEXPECTED_DATA) { + // special driver issue, shouldn't normally occur std::cerr << "WARN: Clock file [" << FreqEnumToStr(t) << "] exists on device [" << i << "] but empty!" << std::endl; std::cerr << " Likely a driver issue!" << std::endl; - } else { - CHK_ERR_ASRT(err) - IF_VERB(STANDARD) { - std::cout << "\t**Supported " << name << " clock frequencies: "; - std::cout << f.num_supported << std::endl; - print_frequencies(&f); - // Verify api support checking functionality is working - err = amdsmi_get_clk_freq(processor_handles_[i], t, nullptr); - ASSERT_EQ(err, AMDSMI_STATUS_INVAL); - } + return; + } + + CHK_ERR_ASRT(err) + IF_VERB(STANDARD) { + std::cout << "\t**Supported " << name << " clock frequencies: "; + std::cout << f.num_supported << std::endl; + print_frequencies(&f); + // Verify api support checking functionality is working + err = amdsmi_get_clk_freq(processor_handles_[i], t, nullptr); + ASSERT_EQ(err, AMDSMI_STATUS_INVAL); } }; @@ -162,15 +175,15 @@ void TestFrequenciesRead::Run(void) { std::cout << "\t**Get PCIE Bandwidth " << ": Not implemented on this machine" << std::endl; } else { - CHK_ERR_ASRT(err) - IF_VERB(STANDARD) { - std::cout << "\t**Supported PCIe bandwidths: "; - std::cout << b.transfer_rate.num_supported << std::endl; - print_frequencies(&b.transfer_rate, b.lanes); - // Verify api support checking functionality is working - err = amdsmi_get_gpu_pci_bandwidth(processor_handles_[i], nullptr); - ASSERT_EQ(err, AMDSMI_STATUS_INVAL); - } + CHK_ERR_ASRT(err) + IF_VERB(STANDARD) { + std::cout << "\t**Supported PCIe bandwidths: "; + std::cout << b.transfer_rate.num_supported << std::endl; + print_frequencies(&b.transfer_rate, b.lanes); + // Verify api support checking functionality is working + err = amdsmi_get_gpu_pci_bandwidth(processor_handles_[i], nullptr); + ASSERT_EQ(err, AMDSMI_STATUS_INVAL); + } } } }