From 827476e898ed2e3c12c605b728573dcca7055b01 Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Mon, 29 Oct 2018 17:59:24 -0500 Subject: [PATCH 1/7] Use sysfs file to get average power instead of debugfs [ROCm/amdsmi commit: 62ba2f578e9892bc0516bb532f1575799c765c07] --- projects/amdsmi/include/rocm_smi/rocm_smi.h | 4 ++-- projects/amdsmi/include/rocm_smi/rocm_smi_monitor.h | 1 + projects/amdsmi/include/rocm_smi/rocm_smi_power_mon.h | 1 - projects/amdsmi/src/rocm_smi.cc | 5 ++--- projects/amdsmi/src/rocm_smi_monitor.cc | 3 ++- projects/amdsmi/src/rocm_smi_power_mon.cc | 6 ------ .../amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc | 5 ++--- .../amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.h | 6 +++--- 8 files changed, 12 insertions(+), 19 deletions(-) diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 9c353980af..1c19e4a3ee 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -446,7 +446,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_set(uint32_t dv_ind, * @param[in] dv_ind a device index * * @param[inout] name a pointer to a caller provided char buffer to which the - * speed will be written + * name will be written * * @param[in] len the length of the caller provided buffer @p name. * @@ -588,7 +588,7 @@ rsmi_status_t rsmi_dev_fan_speed_set(uint32_t dv_ind, uint32_t sensor_ind, * * @details Given a device index @p dv_ind and a pointer to a uint64_t * @p power, this function will write the current average power consumption to - * the uint64_t in milliwatts pointed to by @p power. This function requires + * the uint64_t in microwatts pointed to by @p power. This function requires * root privilege. * * @param[in] dv_ind a device index diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_monitor.h b/projects/amdsmi/include/rocm_smi/rocm_smi_monitor.h index 68ca4921e2..217c600091 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_monitor.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_monitor.h @@ -63,6 +63,7 @@ enum MonitorTypes { kMonPowerCap, kMonPowerCapMax, kMonPowerCapMin, + kMonPowerAve, kMonTempMax, kMonTempMin, kMonTempMaxHyst, diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_power_mon.h b/projects/amdsmi/include/rocm_smi/rocm_smi_power_mon.h index fff1bbb819..71e4c0865e 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_power_mon.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_power_mon.h @@ -55,7 +55,6 @@ namespace smi { enum PowerMonTypes { kPowerMaxGPUPower, - kPowerAveGPUPower, }; diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index 6678b2644f..f772c13753 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -851,11 +851,10 @@ rsmi_dev_power_ave_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *power) { if (power == nullptr) { return RSMI_STATUS_INVALID_ARGS; } - (void)sensor_ind; // Not used yet - // ++sensor_ind; // power sysfs files have 1-based indices + ++sensor_ind; // power sysfs files have 1-based indices rsmi_status_t ret; - ret = get_power_mon_value(amd::smi::kPowerAveGPUPower, dv_ind, power); + ret = get_dev_mon_value(amd::smi::kMonPowerAve, dv_ind, sensor_ind, power); return ret; CATCH diff --git a/projects/amdsmi/src/rocm_smi_monitor.cc b/projects/amdsmi/src/rocm_smi_monitor.cc index 81dc0f097f..ed64e29de6 100755 --- a/projects/amdsmi/src/rocm_smi_monitor.cc +++ b/projects/amdsmi/src/rocm_smi_monitor.cc @@ -74,7 +74,7 @@ static const char *kMonNameFName = "name"; static const char *kMonPowerCapName = "power#_cap"; static const char *kMonPowerCapMaxName = "power#_cap_max"; static const char *kMonPowerCapMinName = "power#_cap_min"; - +static const char *kMonPowerAveName = "power#_average"; static const char *kMonTempMaxName = "temp#_max"; static const char *kMonTempMinName = "temp#_min"; static const char *kMonTempMaxHystName = "temp#_max_hyst"; @@ -99,6 +99,7 @@ static const std::map kMonitorNameMap = { {kMonPowerCap, kMonPowerCapName}, {kMonPowerCapMax, kMonPowerCapMaxName}, {kMonPowerCapMin, kMonPowerCapMinName}, + {kMonPowerAve, kMonPowerAveName}, {kMonTempMax, kMonTempMaxName}, {kMonTempMin, kMonTempMinName}, {kMonTempMaxHyst, kMonTempMaxHystName}, diff --git a/projects/amdsmi/src/rocm_smi_power_mon.cc b/projects/amdsmi/src/rocm_smi_power_mon.cc index 27dec0d7a9..cab97d8188 100755 --- a/projects/amdsmi/src/rocm_smi_power_mon.cc +++ b/projects/amdsmi/src/rocm_smi_power_mon.cc @@ -66,7 +66,6 @@ static const char *kPowerMonPMName = "amdgpu_pm_info"; // Using this map in case we add other files from dri directory to parse. static const std::map kMonitorNameMap = { {kPowerMaxGPUPower, kPowerMonPMName}, - {kPowerAveGPUPower, kPowerMonPMName}, }; PowerMon::PowerMon(std::string path, RocmSMI_env_vars const *e) : @@ -87,10 +86,6 @@ static int parse_power_str(std::string s, PowerMonTypes type, uint64_t *val) { search_str = "(max GPU)"; break; - case kPowerAveGPUPower: - search_str = "(average GPU)"; - break; - default: assert(!"Invalid search Power type requested"); return EINVAL; @@ -118,7 +113,6 @@ static int parse_power_str(std::string s, PowerMonTypes type, uint64_t *val) { switch (type) { case kPowerMaxGPUPower: - case kPowerAveGPUPower: l_ss >> num_units; l_ss >> sz; assert(sz == "W"); // We only expect Watts at this time diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index d5c88de4ce..0ca4aadda2 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -641,8 +641,8 @@ void TestSanity::Run(void) { std::cout << "\t**Power Cap Range: " << val2_ui64 << " to " << val_ui64 << " uW" << std::endl; } -#if 0 // Same as above (disable for now) - err = rsmi_dev_power_ave_get(i, &val_ui64); + + err = rsmi_dev_power_ave_get(i, 0, &val_ui64); IF_VERB(STANDARD) { std::cout << "\t**Averge Power Usage: "; CHK_RSMI_PERM_ERR(err) @@ -651,7 +651,6 @@ void TestSanity::Run(void) { } std::cout << "\t=======" << std::endl; } -#endif } IF_VERB(STANDARD) { std::cout << "***** Testing write api's" << std::endl; diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.h b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.h index 7cf3f0f81b..b6ab2addcb 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.h +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.h @@ -42,8 +42,8 @@ * DEALINGS WITH THE SOFTWARE. * */ -#ifndef ROCM_SMI_LIB_TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ -#define ROCM_SMI_LIB_TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ +#ifndef TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ +#define TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ #include "rocm_smi_test/test_base.h" @@ -70,4 +70,4 @@ class TestSanity : public TestBase { virtual void DisplayTestInfo(void); }; -#endif // ROCM_SMI_LIB_TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ +#endif // TESTS_ROCM_SMI_TEST_FUNCTIONAL_RSMI_SANITY_H_ From ee1e4998a7dff22278c477558b48847aea7c96a8 Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Mon, 5 Nov 2018 11:22:12 -0600 Subject: [PATCH 2/7] Add rsmi_dev_pci_id_get() to return BDFID for given device Also: * add some exception handling; * chop newline character off of device name returned from rsmi_dev_id_get() [ROCm/amdsmi commit: 59a952666f8afc61add11b65549d3402cf706667] --- projects/amdsmi/CMakeLists.txt | 1 + projects/amdsmi/include/rocm_smi/rocm_smi.h | 27 +++- .../amdsmi/include/rocm_smi/rocm_smi_device.h | 4 + .../include/rocm_smi/rocm_smi_exception.h | 72 ++++++++++ .../amdsmi/include/rocm_smi/rocm_smi_main.h | 6 +- projects/amdsmi/src/rocm_smi.cc | 19 +++ projects/amdsmi/src/rocm_smi_main.cc | 125 ++++++++++++++++-- projects/amdsmi/src/rocm_smi_utils.cc | 4 + .../amdsmi/tests/rocm_smi_test/CMakeLists.txt | 4 +- .../rocm_smi_test/functional/rsmi_sanity.cc | 7 + .../amdsmi/tests/rocm_smi_test/run_build.sh | 2 +- 11 files changed, 255 insertions(+), 16 deletions(-) create mode 100755 projects/amdsmi/include/rocm_smi/rocm_smi_exception.h diff --git a/projects/amdsmi/CMakeLists.txt b/projects/amdsmi/CMakeLists.txt index 4568c1e052..a5b2916fbc 100755 --- a/projects/amdsmi/CMakeLists.txt +++ b/projects/amdsmi/CMakeLists.txt @@ -110,6 +110,7 @@ set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_monitor.h") set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_power_mon.h") set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_utils.h") set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_common.h") +set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_exception.h") # rocm_smi_device.h diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 1c19e4a3ee..94f8921da3 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -84,6 +84,9 @@ typedef enum { RSMI_STATUS_INTERNAL_EXCEPTION, //!< An internal exception was caught RSMI_STATUS_INPUT_OUT_OF_BOUNDS, //!< The provided input is out of //!< allowable or safe range + RSMI_INITIALIZATION_ERROR, //!< An error occurred when rsmi + //!< initializing internal data + //!< structures RSMI_STATUS_UNKNOWN_ERROR = 0xFFFFFFFF, //!< An unknown error occurred } rsmi_status_t; @@ -271,13 +274,35 @@ rsmi_status_t rsmi_shut_down(void); */ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); +/** + * @brief Get the unique PCI device identifier associated for a device + * + * @details Give a device index @p dev_ind and a pointer to a uint64_t @p + * bdfid, this function will write the Bus/Device/Function PCI identifier + * (BDFID) associated with device @p dev_ind to the value pointed to by + * @bdfid. + * + * @param[in] dv_ind a device index + * + * @param[inout] bdfid a pointer to uint64_t to which the device bdfid value + * will be written + * + * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + + */ +rsmi_status_t rsmi_dev_pci_id_get(uint32_t dev_ind, uint64_t *bdfid); + /** * @brief Get the device id associated with the device with provided device * index. * * @details Given a device index @p dv_ind and a pointer to a uint32_t @p id, * this function will write the device id value to the uint64_t pointed to by - * @p id + * @p id. This ID is an identification of the type of device, so calling this + * function for different devices will give the same value if they are kind + * of device. Consequently, this function should not be used to distinguish + * one device from another. rsmi_dev_pci_id_get() should be used to get a + * unique identifier. * * @param[in] dv_ind a device index * diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h index 807d5f46fd..8a3c6448d4 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h @@ -86,6 +86,9 @@ class Device { uint32_t index(void) const {return index_;} void set_index(uint32_t index) {index_ = index;} static rsmi_dev_perf_level perfLvlStrToEnum(std::string s); + uint64_t bdfid(void) const {return bdfid_;} + void set_bdfid(uint64_t val) {bdfid_ = val;} + uint64_t get_bdfid(void) const {return bdfid_;} private: std::shared_ptr monitor_; @@ -97,6 +100,7 @@ class Device { int readDevInfoMultiLineStr(DevInfoTypes type, std::vector *retVec); int writeDevInfoStr(DevInfoTypes type, std::string valStr); + uint64_t bdfid_; }; } // namespace smi diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_exception.h b/projects/amdsmi/include/rocm_smi/rocm_smi_exception.h new file mode 100755 index 0000000000..26851dd62e --- /dev/null +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_exception.h @@ -0,0 +1,72 @@ +/* + * ============================================================================= + * ROC Runtime Conformance Release License + * ============================================================================= + * The University of Illinois/NCSA + * Open Source License (NCSA) + * + * Copyright (c) 2018, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Developed by: + * + * AMD Research and AMD ROC Software Development + * + * Advanced Micro Devices, Inc. + * + * www.amd.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal with 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in + * the documentation and/or other materials provided with the distribution. + * - Neither the names of , + * nor the names of its contributors may be used to endorse or promote + * products derived from this Software without specific prior written + * permission. + * + * 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 CONTRIBUTORS 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 WITH THE SOFTWARE. + * + */ + +#ifndef INCLUDE_ROCM_SMI_ROCM_SMI_EXCEPTION_H_ +#define INCLUDE_ROCM_SMI_ROCM_SMI_EXCEPTION_H_ + +#include +#include + +namespace amd { +namespace smi { + +/// @brief Exception type which carries an error code to return to the user. +class rsmi_exception : public std::exception { + public: + rsmi_exception(rsmi_status_t error, const char* description) : + err_(error), desc_(description) {} + rsmi_status_t error_code() const noexcept { return err_; } + const char* what() const noexcept override { return desc_.c_str(); } + + private: + rsmi_status_t err_; + std::string desc_; +}; + +} // namespace smi +} // namespace amd + +#endif // INCLUDE_ROCM_SMI_ROCM_SMI_EXCEPTION_H_ + diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_main.h b/projects/amdsmi/include/rocm_smi/rocm_smi_main.h index 9aed22df11..7ddcf3dc22 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_main.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_main.h @@ -74,9 +74,9 @@ class RocmSMI { uint32_t DiscoverAMDPowerMonitors(bool force_update = false); // Will execute "func" for every Device object known about, or until func - // returns true; - void IterateSMIDevices( - std::function&, void *)> func, void *); + // returns non-zero; + uint32_t IterateSMIDevices( + std::function&, void *)> func, void *); private: std::vector> devices_; diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index f772c13753..249a932ca8 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -58,6 +58,7 @@ #include "rocm_smi/rocm_smi_main.h" #include "rocm_smi/rocm_smi_device.h" #include "rocm_smi/rocm_smi_utils.h" +#include "rocm_smi/rocm_smi_exception.h" static const uint32_t kMaxOverdriveLevel = 20; @@ -67,6 +68,10 @@ static rsmi_status_t handleException() { } catch (const std::bad_alloc& e) { debug_print("RSMI exception: BadAlloc\n"); return RSMI_STATUS_OUT_OF_RESOURCES; + } catch (const amd::smi::rsmi_exception& e) { + debug_print("Exception caught: %s.\n", e.what()); + return e.error_code(); + return RSMI_STATUS_INTERNAL_EXCEPTION; } catch (const std::exception& e) { debug_print("Unhandled exception: %s\n", e.what()); assert(false && "Unhandled exception."); @@ -336,6 +341,20 @@ rsmi_num_monitor_devices(uint32_t *num_devices) { CATCH } +rsmi_status_t +rsmi_dev_pci_id_get(uint32_t dv_ind, uint64_t *bdfid) { + TRY + + if (bdfid == nullptr) { + return RSMI_STATUS_INVALID_ARGS; + } + GET_DEV_FROM_INDX + + *bdfid = dev->get_bdfid(); + return RSMI_STATUS_SUCCESS; + CATCH +} + rsmi_status_t rsmi_dev_id_get(uint32_t dv_ind, uint64_t *id) { TRY diff --git a/projects/amdsmi/src/rocm_smi_main.cc b/projects/amdsmi/src/rocm_smi_main.cc index 409e4687aa..96a71bda09 100755 --- a/projects/amdsmi/src/rocm_smi_main.cc +++ b/projects/amdsmi/src/rocm_smi_main.cc @@ -62,6 +62,7 @@ #include "rocm_smi/rocm_smi.h" #include "rocm_smi/rocm_smi_main.h" +#include "rocm_smi/rocm_smi_exception.h" static const char *kPathDRMRoot = "/sys/class/drm"; static const char *kPathHWMonRoot = "/sys/class/hwmon"; @@ -118,10 +119,104 @@ static int SameDevice(const std::string fileA, const std::string fileB) { return SameFile(fileA + "/device", fileB + "/device"); } +// Determine if provided string is a bdfid pci path directory of the form +// XXXX:XX:XX.X, +// domain:bus:device.function +// +// where X is a hex integer (lower case is expected) +static bool is_bdfid_path_str(const std::string in_name, uint64_t *bdfid) { + char *p = nullptr; + char *name_start; + char name[13] = {'\0'}; + uint32_t tmp; + + assert(bdfid != nullptr); + + if (in_name.size() != 12) { + return false; + } + + tmp = in_name.copy(name, 12); + assert(tmp == 12); + + // BDFID = (( & 0x1f) << 8) | ((device& 0x1f) <<3 ) | (function & 0x7). + *bdfid = 0; + name_start = name; + p = name_start; + + // Match this: XXXX:xx:xx.x + tmp = std::strtoul(p, &p, 16); + if (*p != ':' || p - name_start != 4) { + return false; + } + // We are ignoring the domain part for now as KFD is not encoding it yet + + // Match this: xxxx:XX:xx.x + p++; + tmp = std::strtoul(p, &p, 16); + if (*p != ':' || p - name_start != 7) { + return false; + } + *bdfid |= tmp << 8; + + // Match this: xxxx:xx:XX.x + p++; + tmp = std::strtoul(p, &p, 16); + if (*p != '.' || p - name_start != 10) { + return false; + } + *bdfid |= tmp << 3; + + // Match this: xxxx:xx:xx.X + p++; + tmp = std::strtoul(p, &p, 16); + if (*p != '\0' || p - name_start != 12) { + return false; + } + *bdfid |= tmp; + + return true; +} + +static uint32_t ConstructBDFID(std::string path, uint64_t *bdfid) { + assert(bdfid != nullptr); + char tpath[256]; + ssize_t ret; + + ret = readlink(path.c_str(), tpath, 256); + + assert(ret > 0); + assert(ret < 256); + + if (ret <= 0 || ret >= 256) { + return -1; + } + + // We are looking for the last element in the path that has the form + // XXXX:XX:XX.X, where X is a hex integer (lower case is expected) + std::size_t slash_i, end_i; + std::string tmp; + + std::string tpath_str(tpath); + + end_i = tpath_str.size() - 1; + while (end_i > 0) { + slash_i = tpath_str.find_last_of('/', end_i); + tmp = tpath_str.substr(slash_i + 1, end_i - slash_i); + + if (is_bdfid_path_str(tmp, bdfid)) { + return 0; + } + end_i = slash_i - 1; + } + + return 1; +} // Call-back function to append to a vector of Devices -static bool GetMonitorDevices(const std::shared_ptr &d, +static uint32_t GetMonitorDevices(const std::shared_ptr &d, void *p) { std::string val_str; + uint64_t bdfid; assert(p != nullptr); @@ -129,15 +224,21 @@ static bool GetMonitorDevices(const std::shared_ptr &d, reinterpret_cast> *>(p); if (d->monitor() != nullptr) { + // Calculate BDFID and set for this device + if (ConstructBDFID(d->path(), &bdfid) != 0) { + return -1; + } + d->set_bdfid(bdfid); device_list->push_back(d); } - return false; + return 0; } std::vector> RocmSMI::s_monitor_devices; RocmSMI::RocmSMI(void) { auto i = 0; + uint32_t ret; GetEnvVariables(); @@ -152,8 +253,13 @@ RocmSMI::RocmSMI(void) { // IterateSMIDevices will iterate through all the known devices and apply // the provided call-back to each device found. - IterateSMIDevices(GetMonitorDevices, + ret = IterateSMIDevices(GetMonitorDevices, reinterpret_cast(&s_monitor_devices)); + + if (ret != 0) { + throw amd::smi::rsmi_exception(RSMI_INITIALIZATION_ERROR, + "Failed to initialize rocm_smi library."); + } } RocmSMI::~RocmSMI() { @@ -356,20 +462,23 @@ uint32_t RocmSMI::DiscoverAMDPowerMonitors(bool force_update) { return 0; } -void RocmSMI::IterateSMIDevices( - std::function&, void *)> func, void *p) { +uint32_t RocmSMI::IterateSMIDevices( + std::function&, void *)> func, void *p) { if (func == nullptr) { - return; + return -1; } auto d = devices_.begin(); + uint32_t ret; while (d != devices_.end()) { - if (func(*d, p)) { - return; + ret = func(*d, p); + if (ret != 0) { + return ret; } ++d; } + return 0; } } // namespace smi diff --git a/projects/amdsmi/src/rocm_smi_utils.cc b/projects/amdsmi/src/rocm_smi_utils.cc index 02d0e58c58..d44524325d 100755 --- a/projects/amdsmi/src/rocm_smi_utils.cc +++ b/projects/amdsmi/src/rocm_smi_utils.cc @@ -50,6 +50,7 @@ #include #include #include +#include namespace amd { namespace smi { @@ -88,6 +89,9 @@ int ReadSysfsStr(std::string path, std::string *retStr) { fs.close(); *retStr = ss.str(); + + retStr->erase(std::remove(retStr->begin(), retStr->end(), '\n'), + retStr->end()); return ret; } diff --git a/projects/amdsmi/tests/rocm_smi_test/CMakeLists.txt b/projects/amdsmi/tests/rocm_smi_test/CMakeLists.txt index 112872e47d..30e88372d5 100755 --- a/projects/amdsmi/tests/rocm_smi_test/CMakeLists.txt +++ b/projects/amdsmi/tests/rocm_smi_test/CMakeLists.txt @@ -71,7 +71,7 @@ if (${IS64BIT} EQUAL 0) else() if(NOT EXISTS ${RSMI_LIB_DIR}/librocm_smi64.so) message("ERROR: Define RSMI_LIB_DIR pointing to RSMI library is not set") - message(" missing: ${RSMI_LIB_DIR}/librocm_smi.so") + message(" missing: ${RSMI_LIB_DIR}/librocm_smi64.so") return() endif() endif() @@ -204,8 +204,6 @@ include_directories(${RSMITST_ROOT}/gtest/include) # Build rules add_executable(${RSMITST} ${rsmitstSources} ${functionalSources}) -#target_link_libraries(${ROCRTST} ${ROCRTST_LIBS} c stdc++ dl pthread rt numa hwloc) - target_link_libraries(${RSMITST} ${RSMITST_LIBS} c stdc++ pthread) install(TARGETS ${RSMITST} diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index 0ca4aadda2..3c167dd5e0 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -556,6 +556,13 @@ void TestSanity::Run(void) { std::cout << "\t**Monitor name: " << name << std::endl; } + err = rsmi_dev_pci_id_get(i, &val_ui64); + CHK_ERR_ASRT(err) + IF_VERB(STANDARD) { + std::cout << "\t**PCI ID (BDFID): 0x" << std::hex << val_ui64; + std::cout << " (" << std::dec << val_ui64 << ")" << std::endl; + } + auto print_temp_metric = [&](rsmi_temperature_metric met, std::string label) { err = rsmi_dev_temp_metric_get(i, 0, met, &val_i64); diff --git a/projects/amdsmi/tests/rocm_smi_test/run_build.sh b/projects/amdsmi/tests/rocm_smi_test/run_build.sh index abce075479..c3e6b587eb 100755 --- a/projects/amdsmi/tests/rocm_smi_test/run_build.sh +++ b/projects/amdsmi/tests/rocm_smi_test/run_build.sh @@ -3,7 +3,7 @@ # these are required: -ROCM_DIR=/home/cfreehil/git/compute/out/ubuntu-16.04/16.04 +ROCM_DIR=/home/cfreehil/github/rocm_smi_lib/build #ROCM_DIR=/opt/rocm mkdir -p build From a409a4458a9c6c042526cd9f3266889454f8b64e Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Mon, 12 Nov 2018 17:25:14 -0600 Subject: [PATCH 3/7] Add rsmi_dev_busy_percent_get() Also: correct some comments, ifdef out unused code [ROCm/amdsmi commit: 861c2c2e331420528ac541da5d8dbba6b481f160] --- projects/amdsmi/include/rocm_smi/rocm_smi.h | 36 ++++++++++++++----- .../amdsmi/include/rocm_smi/rocm_smi_device.h | 6 +++- projects/amdsmi/src/rocm_smi.cc | 22 +++++++++++- projects/amdsmi/src/rocm_smi_device.cc | 14 +++++--- .../rocm_smi_test/functional/rsmi_sanity.cc | 17 +++++++++ projects/amdsmi/tests/rocm_smi_test/main.cc | 20 +---------- 6 files changed, 81 insertions(+), 34 deletions(-) diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 94f8921da3..28dcb053a6 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -277,10 +277,10 @@ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); /** * @brief Get the unique PCI device identifier associated for a device * - * @details Give a device index @p dev_ind and a pointer to a uint64_t @p + * @details Give a device index @p dv_ind and a pointer to a uint64_t @p * bdfid, this function will write the Bus/Device/Function PCI identifier - * (BDFID) associated with device @p dev_ind to the value pointed to by - * @bdfid. + * (BDFID) associated with device @p dv_ind to the value pointed to by + * @p bdfid. * * @param[in] dv_ind a device index * @@ -290,7 +290,7 @@ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); * @retval RSMI_STATUS_SUCCESS is returned upon successful call. */ -rsmi_status_t rsmi_dev_pci_id_get(uint32_t dev_ind, uint64_t *bdfid); +rsmi_status_t rsmi_dev_pci_id_get(uint32_t dv_ind, uint64_t *bdfid); /** * @brief Get the device id associated with the device with provided device @@ -739,8 +739,8 @@ rsmi_dev_power_max_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *power); * * @param[in] dv_ind a device index * - * @param[in] sensor_ind a 0-based sensor index. Normally, this will be 0. - * If a device has more than one sensor, it could be greater than 0. + * @param[in] sensor_ind a 0-based sensor index. Normally, this will be 0. + * If a device has more than one sensor, it could be greater than 0. * * @param[inout] status a pointer to rsmi_power_profile_status that will be * populated by a call to this function @@ -769,7 +769,7 @@ rsmi_dev_power_profile_presets_get(uint32_t dv_ind, uint32_t sensor_ind, * @param[in] profile a rsmi_power_profile_preset_masks that hold the mask * of the desired new power profile * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -786,11 +786,31 @@ rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t sensor_ind, * @param[inout] status_string A pointer to a const char * which will be made * to point to a description of the provided error code * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call + * @retval RSMI_STATUS_SUCCESS is returned upon successful call * */ rsmi_status_t rsmi_status_string(rsmi_status_t status, const char **status_string); + +/** + * @brief Get percentage of time device is busy doing any processing + * + * @details Given a device index @p dv_ind, this function returns the + * percentage of time that the specified device is busy. The device is + * considered busy if any one or more of its sub-blocks are working, and idle + * if none of the sub-blocks are working. + * + * @param[in] dv_ind a device index + * + * @param[inout] busy_percent a pointer to the uint32_t to which the busy + * percent will be written + * + * @retval RSMI_STATUS_SUCCESS is returned upon successful call + * + */ +rsmi_status_t +rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h index 8a3c6448d4..b306b54606 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h @@ -64,7 +64,8 @@ enum DevInfoTypes { kDevDevID, kDevGPUMClk, kDevGPUSClk, - kDevPowerProfileMode + kDevPowerProfileMode, + kDevUsage, }; class Device { @@ -78,7 +79,10 @@ class Device { const std::shared_ptr& power_monitor() {return power_monitor_;} void set_power_monitor(std::shared_ptr pm) {power_monitor_ = pm;} +#if 0 // This is not being used right now. int readDevInfo(DevInfoTypes type, uint32_t *val); +#endif + int readDevInfo(DevInfoTypes type, std::string *val); int readDevInfo(DevInfoTypes type, std::vector *retVec); int writeDevInfo(DevInfoTypes type, uint64_t val); diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index 249a932ca8..6d7e7ff658 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -102,7 +102,8 @@ static rsmi_status_t errno_to_rsmi_status(uint32_t err) { case 0: return RSMI_STATUS_SUCCESS; case EACCES: return RSMI_STATUS_PERMISSION; case EPERM: return RSMI_STATUS_NOT_SUPPORTED; - case ENOENT: return RSMI_STATUS_FILE_ERROR; + case ENOENT: + case EISDIR: return RSMI_STATUS_FILE_ERROR; default: return RSMI_STATUS_UNKNOWN_ERROR; } } @@ -1026,3 +1027,22 @@ rsmi_status_string(rsmi_status_t status, const char **status_string) { return RSMI_STATUS_SUCCESS; CATCH } + +rsmi_status_t +rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent) { + TRY + std::string val_str; + rsmi_status_t ret = get_dev_value_str(amd::smi::kDevUsage, dv_ind, + &val_str); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + errno = 0; + *busy_percent = strtoul(val_str.c_str(), nullptr, 10); + assert(errno == 0); + + return RSMI_STATUS_SUCCESS; + + CATCH +} diff --git a/projects/amdsmi/src/rocm_smi_device.cc b/projects/amdsmi/src/rocm_smi_device.cc index 1f1a63cdc9..3ec5382850 100755 --- a/projects/amdsmi/src/rocm_smi_device.cc +++ b/projects/amdsmi/src/rocm_smi_device.cc @@ -64,7 +64,9 @@ static const char *kDevDevIDFName = "device"; static const char *kDevOverDriveLevelFName = "pp_sclk_od"; static const char *kDevGPUSClkFName = "pp_dpm_sclk"; static const char *kDevGPUMClkFName = "pp_dpm_mclk"; -static const char *kDevPowerProfileModeName = "pp_power_profile_mode"; +static const char *kDevPowerProfileModeFName = "pp_power_profile_mode"; +static const char *kDevUsageFName = "gpu_busy_percent"; + static const char *kDevPerfLevelAutoStr = "auto"; static const char *kDevPerfLevelLowStr = "low"; static const char *kDevPerfLevelHighStr = "high"; @@ -81,7 +83,8 @@ static const std::map kDevAttribNameMap = { {kDevDevID, kDevDevIDFName}, {kDevGPUMClk, kDevGPUMClkFName}, {kDevGPUSClk, kDevGPUSClkFName}, - {kDevPowerProfileMode, kDevPowerProfileModeName}, + {kDevPowerProfileMode, kDevPowerProfileModeFName}, + {kDevUsage, kDevUsageFName}, }; static const std::map kDevPerfLvlMap = { @@ -114,7 +117,6 @@ Device::Device(std::string p, RocmSMI_env_vars const *e) : path_(p), env_(e) { Device:: ~Device() { } -// TODO(cfreehil): cache values that are constant int Device::readDevInfoStr(DevInfoTypes type, std::string *retStr) { auto tempPath = path_; @@ -242,12 +244,12 @@ int Device::readDevInfoMultiLineStr(DevInfoTypes type, return 0; } +#if 0 int Device::readDevInfo(DevInfoTypes type, uint32_t *val) { assert(val != nullptr); std::string tempStr; int ret; - switch (type) { case kDevDevID: ret = readDevInfoStr(type, &tempStr); @@ -255,6 +257,7 @@ int Device::readDevInfo(DevInfoTypes type, uint32_t *val) { *val = std::stoi(tempStr, 0, 16); break; + case kDevUsage: case kDevOverDriveLevel: ret = readDevInfoStr(type, &tempStr); RET_IF_NONZERO(ret); @@ -266,7 +269,7 @@ int Device::readDevInfo(DevInfoTypes type, uint32_t *val) { } return 0; } - +#endif int Device::readDevInfo(DevInfoTypes type, std::vector *val) { assert(val != nullptr); @@ -289,6 +292,7 @@ int Device::readDevInfo(DevInfoTypes type, std::string *val) { switch (type) { case kDevPerfLevel: + case kDevUsage: case kDevOverDriveLevel: case kDevDevID: return readDevInfoStr(type, val); diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index 3c167dd5e0..d75f9bd5ff 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -549,6 +549,23 @@ void TestSanity::Run(void) { std::cout << f.num_supported << std::endl; print_frequencies(&f); } + err = rsmi_dev_busy_percent_get(i, &val_ui32); + if (err != RSMI_STATUS_SUCCESS) { + if (err == RSMI_STATUS_FILE_ERROR) { + IF_VERB(STANDARD) { + std::cout << "\t**GPU Busy Percent: Not supported on this machine" + << std::endl; + } + } else { + CHK_ERR_ASRT(err) + } + } else { + IF_VERB(STANDARD) { + std::cout << "\t**GPU Busy Percent (Percent Idle):" << std::dec << + val_ui32 << " (" << 100 - val_ui32 << ")" << std::endl; + } + } + char name[20]; err = rsmi_dev_name_get(i, name, 20); CHK_ERR_ASRT(err) diff --git a/projects/amdsmi/tests/rocm_smi_test/main.cc b/projects/amdsmi/tests/rocm_smi_test/main.cc index d6b548cf9d..20f13ec56a 100755 --- a/projects/amdsmi/tests/rocm_smi_test/main.cc +++ b/projects/amdsmi/tests/rocm_smi_test/main.cc @@ -103,24 +103,6 @@ TEST(rsmitst, RSMISanityTest) { RunGenericTest(&tst); } -#if 0 - -TEST(rocrtstFunc, IPC) { - IPCTest ipc; - RunGenericTest(&ipc); -} - -TEST(rocrtstFunc, MemoryAccessTests) { - MemoryAccessTest mt; - RunCustomTestProlog(&mt); - mt.CPUAccessToGPUMemoryTest(); - mt.GPUAccessToCPUMemoryTest(); - RunCustomTestEpilog(&mt); -} - - - -#endif int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); @@ -130,7 +112,7 @@ int main(int argc, char** argv) { // Set some default values settings.verbosity = 1; settings.monitor_verbosity = 1; - settings.num_iterations = 5; + settings.num_iterations = 1; if (ProcessCmdline(&settings, argc, argv)) { From 664731b39c4ca918e8a6acf0af88593dbf652665 Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Fri, 16 Nov 2018 15:55:38 -0600 Subject: [PATCH 4/7] Add get and set routines for PCIe bandwidth [ROCm/amdsmi commit: 9c897ab86dbb69ffd140c21ab3509c6d6f04e1a7] --- projects/amdsmi/include/rocm_smi/rocm_smi.h | 66 +++++++++- .../amdsmi/include/rocm_smi/rocm_smi_device.h | 1 + projects/amdsmi/src/rocm_smi.cc | 123 ++++++++++++++---- projects/amdsmi/src/rocm_smi_device.cc | 5 + .../rocm_smi_test/functional/rsmi_sanity.cc | 70 +++++++++- 5 files changed, 236 insertions(+), 29 deletions(-) diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 28dcb053a6..476134b09e 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -124,7 +124,6 @@ typedef enum { RSMI_CLK_TYPE_FIRST = RSMI_CLK_TYPE_SYS, RSMI_CLK_TYPE_MEM, //!< Memory clock - RSMI_CLK_TYPE_LAST = RSMI_CLK_TYPE_MEM } rsmi_clk_type; @@ -239,6 +238,24 @@ typedef struct { uint64_t frequency[RSMI_MAX_NUM_FREQUENCIES]; } rsmi_frequencies; +/** + * @brief This structure holds information about the possible PCIe + * bandwidths. Specifically, the possible transfer rates and their + * associated numbers of lanes are stored here. + */ +typedef struct { + /** + * Transfer rates (T/s) that are possible + */ + rsmi_frequencies transfer_rate; + + /** + * List of lanes for corresponding transfer rate. + * Only the first num_supported bandwidths are valid. + */ + uint32_t lanes[RSMI_MAX_NUM_FREQUENCIES]; +} rsmi_pcie_bandwidth; + /** * @brief Initialize Rocm SMI. @@ -274,6 +291,51 @@ rsmi_status_t rsmi_shut_down(void); */ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); +/** + * @brief Get the list of possible pci bandwidths that are available. + * + * @details Given a device index @p dv_ind and a pointer to a to an + * rsmi_pcie_bandwidth structure @p bandwidth, this function will fill in + * @p bandwidth with the possible T/s values and associated number of lanes, + * and indication of the current selection. + * + * @param[in] dv_ind a device index + * + * @param[inout] bandwidth a pointer to a caller provided rsmi_pcie_bandwidth + * structure to which the frequency information will be written + * + * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * + */ +rsmi_status_t +rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth *bandwidth); + +/** + * @brief Control the set of allowed PCIe bandwidths that can be used. + * + * @details Given a device index @p dv_ind and a 64 bit bitmask @p bw_bitmask, + * this function will limit the set of allowable bandwidths. If a bit in @p + * bw_bitmask has a value of 1, then the frequency (as ordered in an + * rsmi_frequencies returned by rsmi_dev_get_gpu_clk_freq()) corresponding + * to that bit index will be allowed. + * + * This function will change the performance level to + * ::RSMI_DEV_PERF_LEVEL_MANUAL in order to modify the set of allowable + * band_widths. Caller will need to set to ::RSMI_DEV_PERF_LEVEL_AUTO in order + * to get back to default state. + * + * All bits with indices greater than or equal to + * rsmi_pcie_bandwidth.transfer_rate.num_supported will be ignored. + * + * @param[in] dv_ind a device index + * + * @param[in] bw_bitmask A bitmask indicating the indices of the + * bandwidths that are to be enabled (1) and disabled (0). Only the lowest + * rsmi_pcie_bandwidth.transfer_rate.num_supported bits of this mask are + * relevant. + */ +rsmi_status_t rsmi_dev_pci_bandwidth_set(uint32_t dv_ind, uint64_t bw_bitmask); + /** * @brief Get the unique PCI device identifier associated for a device * @@ -436,7 +498,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_get(uint32_t dv_ind, * specified clock. * * @details Given a device index @p dv_ind, a clock type @p clk_type, and a - * 32 bit bitmask @p freq_bitmask, this function will limit the set of + * 64 bit bitmask @p freq_bitmask, this function will limit the set of * allowable frequencies. If a bit in @p freq_bitmask has a value of 1, then * the frequency (as ordered in an rsmi_frequencies returned by * rsmi_dev_get_gpu_clk_freq()) corresponding to that bit index will be diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h index b306b54606..61f7774660 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi_device.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi_device.h @@ -64,6 +64,7 @@ enum DevInfoTypes { kDevDevID, kDevGPUMClk, kDevGPUSClk, + kDevPCIEBW, kDevPowerProfileMode, kDevUsage, }; diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index 6d7e7ff658..1f210d8a3a 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -108,15 +108,17 @@ static rsmi_status_t errno_to_rsmi_status(uint32_t err) { } } /** - * Parse a string of the form ": <|*>" + * Parse a string of the form: + * ": <|*>" */ -static uint32_t freq_string_to_int(std::string freq_line, bool *is_curr) { +static uint64_t freq_string_to_int(const std::vector &freq_lines, + bool *is_curr, uint32_t lanes[], int i) { assert(is_curr != nullptr); - std::istringstream fs(freq_line); + std::istringstream fs(freq_lines[i]); uint32_t ind; - uint32_t freq; + float freq; std::string junk; std::string units_str; std::string star_str; @@ -128,7 +130,7 @@ static uint32_t freq_string_to_int(std::string freq_line, bool *is_curr) { fs >> star_str; if (is_curr != nullptr) { - if (freq_line.find("*") != std::string::npos) { + if (freq_lines[i].find("*") != std::string::npos) { *is_curr = true; } else { *is_curr = false; @@ -136,18 +138,33 @@ static uint32_t freq_string_to_int(std::string freq_line, bool *is_curr) { } uint32_t multiplier = 0; - if (units_str == "Mhz") { - multiplier = 1000000; - } else if (units_str == "Ghz") { - multiplier = 1000000000; - } else if (units_str == "Khz") { - multiplier = 1000; - } else if (units_str == "Hz") { - multiplier = 1; - } else { - assert(!"Unexpected units for frequency"); + switch (units_str[0]) { + case 'G': // GT or GHz + multiplier = 1000000000; + break; + + case 'M': // MT or MHz + multiplier = 1000000; + break; + + case 'K': // KT or KHz + multiplier = 1000; + break; + + case 'T': // Transactions + case 'H': // Hertz + multiplier = 1; + break; + default: + assert(!"Unexpected units for frequency"); } + if (star_str[0] == 'x') { + assert(lanes != nullptr && "Lanes are provided but null lanes pointer"); + if (lanes) { + lanes[i] = std::stoi(star_str.substr(1), nullptr); + } + } return freq*multiplier; } @@ -431,7 +448,7 @@ rsmi_dev_perf_level_set(int32_t dv_ind, rsmi_dev_perf_level perf_level) { } static rsmi_status_t get_frequencies(amd::smi::DevInfoTypes type, - uint32_t dv_ind, rsmi_frequencies *f) { + uint32_t dv_ind, rsmi_frequencies *f, uint32_t *lanes = nullptr) { TRY std::vector val_vec; rsmi_status_t ret; @@ -451,7 +468,7 @@ static rsmi_status_t get_frequencies(amd::smi::DevInfoTypes type, f->current = RSMI_MAX_NUM_FREQUENCIES + 1; // init to an invalid value for (uint32_t i = 0; i < f->num_supported; ++i) { - f->frequency[i] = freq_string_to_int(val_vec[i], ¤t); + f->frequency[i] = freq_string_to_int(val_vec, ¤t, lanes, i); // Our assumption is that frequencies are read in from lowest to highest. // Check that that is true. @@ -666,6 +683,60 @@ rsmi_dev_name_get(uint32_t dv_ind, char *name, size_t len) { CATCH } +rsmi_status_t +rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth *b) { + TRY + assert(b != nullptr); + + if (b == nullptr) { + return RSMI_STATUS_INVALID_ARGS; + } + + return get_frequencies(amd::smi::kDevPCIEBW, dv_ind, + &b->transfer_rate, b->lanes); + + CATCH +} + +rsmi_status_t +rsmi_dev_pci_bandwidth_set(uint32_t dv_ind, uint64_t bw_bitmask) { + rsmi_status_t ret; + rsmi_pcie_bandwidth bws; + + TRY + ret = rsmi_dev_pci_bandwidth_get(dv_ind, &bws); + + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + assert(bws.transfer_rate.num_supported <= RSMI_MAX_NUM_FREQUENCIES); + + amd::smi::RocmSMI smi = amd::smi::RocmSMI::getInstance(); + + // Above call to rsmi_dev_pci_bandwidth_get() should have emitted an error + // if assert below is not true + assert(dv_ind < smi.monitor_devices().size()); + + std::string freq_enable_str = + bitfield_to_freq_string(bw_bitmask, bws.transfer_rate.num_supported); + + std::shared_ptr dev = smi.monitor_devices()[dv_ind]; + assert(dev != nullptr); + + ret = rsmi_dev_perf_level_set(dv_ind, RSMI_DEV_PERF_LEVEL_MANUAL); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + uint32_t ret_i; + ret_i = dev->writeDevInfo(amd::smi::kDevPCIEBW, freq_enable_str); + + return errno_to_rsmi_status(ret_i); + + CATCH +} + rsmi_status_t rsmi_dev_temp_metric_get(uint32_t dv_ind, uint32_t sensor_ind, rsmi_temperature_metric metric, int64_t *temperature) { @@ -1032,17 +1103,17 @@ rsmi_status_t rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent) { TRY std::string val_str; - rsmi_status_t ret = get_dev_value_str(amd::smi::kDevUsage, dv_ind, - &val_str); - if (ret != RSMI_STATUS_SUCCESS) { - return ret; - } + rsmi_status_t ret = get_dev_value_str(amd::smi::kDevUsage, dv_ind, + &val_str); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } - errno = 0; - *busy_percent = strtoul(val_str.c_str(), nullptr, 10); - assert(errno == 0); + errno = 0; + *busy_percent = strtoul(val_str.c_str(), nullptr, 10); + assert(errno == 0); - return RSMI_STATUS_SUCCESS; + return RSMI_STATUS_SUCCESS; CATCH } diff --git a/projects/amdsmi/src/rocm_smi_device.cc b/projects/amdsmi/src/rocm_smi_device.cc index 3ec5382850..98cbb48422 100755 --- a/projects/amdsmi/src/rocm_smi_device.cc +++ b/projects/amdsmi/src/rocm_smi_device.cc @@ -64,6 +64,7 @@ static const char *kDevDevIDFName = "device"; static const char *kDevOverDriveLevelFName = "pp_sclk_od"; static const char *kDevGPUSClkFName = "pp_dpm_sclk"; static const char *kDevGPUMClkFName = "pp_dpm_mclk"; +static const char *kDevGPUPCIEClkFname = "pp_dpm_pcie"; static const char *kDevPowerProfileModeFName = "pp_power_profile_mode"; static const char *kDevUsageFName = "gpu_busy_percent"; @@ -83,6 +84,7 @@ static const std::map kDevAttribNameMap = { {kDevDevID, kDevDevIDFName}, {kDevGPUMClk, kDevGPUMClkFName}, {kDevGPUSClk, kDevGPUSClkFName}, + {kDevPCIEBW, kDevGPUPCIEClkFname}, {kDevPowerProfileMode, kDevPowerProfileModeFName}, {kDevUsage, kDevUsageFName}, }; @@ -195,6 +197,7 @@ int Device::writeDevInfo(DevInfoTypes type, uint64_t val) { case kDevGPUMClk: // integer (index within num-freq range) case kDevGPUSClk: // integer (index within num-freq range) + case kDevPCIEBW: // integer (index within num-freq range) case kDevDevID: // string (read-only) default: break; @@ -207,6 +210,7 @@ int Device::writeDevInfo(DevInfoTypes type, std::string val) { switch (type) { case kDevGPUMClk: case kDevGPUSClk: + case kDevPCIEBW: return writeDevInfoStr(type, val); case kDevOverDriveLevel: @@ -276,6 +280,7 @@ int Device::readDevInfo(DevInfoTypes type, std::vector *val) { switch (type) { case kDevGPUMClk: case kDevGPUSClk: + case kDevPCIEBW: case kDevPowerProfileMode: return readDevInfoMultiLineStr(type, val); break; diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index d75f9bd5ff..d99980e472 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -451,10 +451,66 @@ static rsmi_status_t test_set_freq(uint32_t dv_ind) { return RSMI_STATUS_SUCCESS; } -static void print_frequencies(rsmi_frequencies *f) { +static rsmi_status_t test_set_pci_bw(uint32_t dv_ind) { + rsmi_status_t ret; + rsmi_pcie_bandwidth bw; + uint32_t freq_bitmask; + + print_test_header("PCIe Bandwidth Control", dv_ind); + + ret = rsmi_dev_pci_bandwidth_get(dv_ind, &bw); + CHK_ERR_RET(ret) + + IF_VERB(STANDARD) { + std::cout << "Initial PCIe is " << bw.transfer_rate.current << std::endl; + } + + // First set the bitmask to all supported bandwidths + freq_bitmask = ~(~0 << bw.transfer_rate.num_supported); + + // Then, set the bitmask to all bandwidths besides the initial BW + freq_bitmask ^= (1 << bw.transfer_rate.current); + + std::string freq_bm_str = + std::bitset(freq_bitmask).to_string(); + + freq_bm_str.erase(0, std::min(freq_bm_str.find_first_not_of('0'), + freq_bm_str.size()-1)); + + IF_VERB(STANDARD) { + std::cout << "Setting bandwidth mask to " << "0b" << freq_bm_str << + " ..." << std::endl; + } + ret = rsmi_dev_pci_bandwidth_set(dv_ind, freq_bitmask); + CHK_ERR_RET(ret) + + ret = rsmi_dev_pci_bandwidth_get(dv_ind, &bw); + CHK_ERR_RET(ret) + + IF_VERB(STANDARD) { + std::cout << "Bandwidth is now index " << bw.transfer_rate.current << + std::endl; + std::cout << "Resetting mask to all bandwidths." << std::endl; + } + ret = rsmi_dev_pci_bandwidth_set(dv_ind, 0xFFFFFFFF); + CHK_ERR_RET(ret) + + ret = rsmi_dev_perf_level_set(dv_ind, RSMI_DEV_PERF_LEVEL_AUTO); + CHK_ERR_RET(ret) + + return RSMI_STATUS_SUCCESS; +} + +static void print_frequencies(rsmi_frequencies *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]; + if (l != nullptr) { + std::cout << "T/s; x" << l[j]; + } else { + std::cout << "Hz"; + } + if (j == f->current) { std::cout << " *"; } @@ -500,6 +556,7 @@ void TestSanity::Run(void) { uint32_t val_ui32; rsmi_dev_perf_level pfl; rsmi_frequencies f; + rsmi_pcie_bandwidth b; uint32_t num_monitor_devs = 0; @@ -542,6 +599,14 @@ void TestSanity::Run(void) { std::cout << f.num_supported << std::endl; print_frequencies(&f); } + err = rsmi_dev_pci_bandwidth_get(i, &b); + 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); + } + err = rsmi_dev_gpu_clk_freq_get(i, RSMI_CLK_TYPE_SYS, &f); CHK_ERR_ASRT(err) IF_VERB(STANDARD) { @@ -689,6 +754,9 @@ void TestSanity::Run(void) { err = test_set_freq(i); CHK_RSMI_PERM_ERR(err) + err = test_set_pci_bw(i); + CHK_RSMI_PERM_ERR(err) + err = test_set_fan_speed(i); CHK_RSMI_PERM_ERR(err) From 0c669a84ae26eaaf796723c767036df1158eb641 Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Fri, 16 Nov 2018 15:55:38 -0600 Subject: [PATCH 5/7] Add get and set routines for PCIe bandwidth [ROCm/amdsmi commit: bc200d205e4fd4e9f9f432322cdc9fb22572fb93] --- projects/amdsmi/include/rocm_smi/rocm_smi.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 476134b09e..5ee6fe857c 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -312,18 +312,18 @@ rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth *bandwidth); /** * @brief Control the set of allowed PCIe bandwidths that can be used. - * + * * @details Given a device index @p dv_ind and a 64 bit bitmask @p bw_bitmask, * this function will limit the set of allowable bandwidths. If a bit in @p * bw_bitmask has a value of 1, then the frequency (as ordered in an * rsmi_frequencies returned by rsmi_dev_get_gpu_clk_freq()) corresponding * to that bit index will be allowed. - * + * * This function will change the performance level to * ::RSMI_DEV_PERF_LEVEL_MANUAL in order to modify the set of allowable * band_widths. Caller will need to set to ::RSMI_DEV_PERF_LEVEL_AUTO in order * to get back to default state. - * + * * All bits with indices greater than or equal to * rsmi_pcie_bandwidth.transfer_rate.num_supported will be ignored. * @@ -630,7 +630,7 @@ rsmi_status_t rsmi_dev_fan_speed_get(uint32_t dv_ind, * @brief Get the max. fan speed of the device with provided device index. * * @details Given a device index @p dv_ind and a pointer to a uint32_t - * @p max_speed, this function will write the maxirsmi_dev_power_profile_semum fan speed possible to + * @p max_speed, this function will write the maximum fan speed possible to * the uint32_t pointed to by @p max_speed * * @param[in] dv_ind a device index From 01ffc5f17fa57522fd464bfe13a9d2d5f9b991ac Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Thu, 6 Dec 2018 13:48:59 -0600 Subject: [PATCH 6/7] Add rsmi_version_get() function Also, modify CMakeLists.txt to use git tags to determine the shared library version for the SONAME and the ROCm build for the package name. [ROCm/amdsmi commit: 5a9a729b317b84c7cb9a1868cc8cd18987544f31] --- projects/amdsmi/CMakeLists.txt | 82 ++++++------ projects/amdsmi/cmake_modules/utils.cmake | 5 +- projects/amdsmi/include/rocm_smi/rocm_smi.h | 121 +++++++++++------- projects/amdsmi/src/rocm_smi.cc | 18 +++ projects/amdsmi/src/rocm_smi64Config.in | 56 ++++++++ .../rocm_smi_test/functional/rsmi_sanity.cc | 15 ++- 6 files changed, 206 insertions(+), 91 deletions(-) mode change 100644 => 100755 projects/amdsmi/cmake_modules/utils.cmake create mode 100755 projects/amdsmi/src/rocm_smi64Config.in diff --git a/projects/amdsmi/CMakeLists.txt b/projects/amdsmi/CMakeLists.txt index a5b2916fbc..69fb0c4f14 100755 --- a/projects/amdsmi/CMakeLists.txt +++ b/projects/amdsmi/CMakeLists.txt @@ -28,39 +28,56 @@ # cmake_minimum_required(VERSION 3.5.0) -set(ROCM_SMI "rocm_smi") -set(ROCM_SMI_COMPONENT "lib${ROCM_SMI}") -set(ROCM_SMI_TARGET "${ROCM_SMI}64") - -project(${ROCM_SMI_TARGET}) - ## Set default module path if not already set if(NOT DEFINED CMAKE_MODULE_PATH) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/") endif() - ## Include common cmake modules include(utils) -## Setup the package version. -get_version ("1.0.0") +set(ROCM_SMI "rocm_smi") +set(ROCM_SMI_COMPONENT "lib${ROCM_SMI}") +set(ROCM_SMI_TARGET "${ROCM_SMI}64") + +# The following default version values should be updated as appropriate for +# ABI breaks (update MAJOR and MINOR), and ABI/API additions (update MINOR). +# Until ABI stabilizes VERSION_MAJOR will be 0. This should be over-ridden +# by git tags (through "git describe") when they are present. +set(ROCM_SMI_LIB_VERSION_MAJOR 0) +set(ROCM_SMI_LIB_VERSION_MINOR 1) + +################# Determine the library version ######################### +## Setup the package version based on git tags. +set(LIB_SO_VERSION_STR + "${ROCM_SMI_LIB_VERSION_MAJOR}.${ROCM_SMI_LIB_VERSION_MINOR}.0") +get_version(${LIB_SO_VERSION_STR} "rsmi") + +# VERSION_* variables should be set by get_version +set(LIB_SO_VERSION_STR ${VERSION_STRING}) +set(${ROCM_SMI}_VERSION_MAJOR "${VERSION_MAJOR}") +set(${ROCM_SMI}_VERSION_MINOR "${VERSION_MINOR}") +set(${ROCM_SMI}_VERSION_PATCH "${VERSION_PATCH}") +set(${ROCM_SMI}_VERSION_BUILD "${VERSION_BUILD}") + +# Debian package specific variables +# Set a default value for the package version +set(VERSION_STRING "1.0.0") +get_version(${VERSION_STRING} "roc") + +# VERSION_* variables should be set by get_version +set(BUILD_VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") + +project(${ROCM_SMI_TARGET}) + +# Create a configure file to get version info from within library +configure_file( + "${PROJECT_SOURCE_DIR}/src/${ROCM_SMI_TARGET}Config.in" + "${PROJECT_SOURCE_DIR}/include/rocm_smi/${ROCM_SMI_TARGET}Config.h") if (NOT DEFINED CPACK_PACKAGE_VENDOR) set(CPACK_PACKAGE_VENDOR "AMD") endif() -if (NOT DEFINED CPACK_PACKAGE_VERSION_MAJOR) - set(CPACK_PACKAGE_VERSION_MAJOR "1") -endif() - -if (NOT DEFINED CPACK_PACKAGE_VERSION_MINOR) - set(CPACK_PACKAGE_VERSION_MINOR "0") -endif() - -if (NOT DEFINED CPACK_PACKAGE_VERSION_PATCH) - set(CPACK_PACKAGE_VERSION_PATCH "0") -endif() - if (NOT DEFINED CPACK_PACKAGE_CONTACT) set(CPACK_PACKAGE_CONTACT "Advanced Micro Devices Inc.") endif() @@ -70,14 +87,7 @@ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ROCm System Management Interface library") endif() -set(LIB_VERSION_STRING - "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") -# Debian package specific variables - -set(BUILD_VERSION_STRING - "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_PATCH}") - -set(CPACK_PACKAGE_FILE_NAME "rocm_smi_lib64-${LIB_VERSION_STRING}") +set(CPACK_PACKAGE_FILE_NAME "rocm_smi_lib64-${BUILD_VERSION_STRING}") ## Verbose output. set(CMAKE_VERBOSE_MAKEFILE on) @@ -112,10 +122,6 @@ set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_utils.h") set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_common.h") set(SMI_INC_LIST ${SMI_INC_LIST} "${INC_DIR}/rocm_smi_exception.h") - -# rocm_smi_device.h -# rocm_smi.h rocm_smi_main.h rocm_smi_monitor.h") - set(SMI_EXAMPLE_EXE "rocm_smi_ex") add_executable(${SMI_EXAMPLE_EXE} "example/rocm_smi_example.cc") @@ -123,10 +129,10 @@ target_link_libraries(${SMI_EXAMPLE_EXE} ${ROCM_SMI_TARGET}) add_library(${ROCM_SMI_TARGET} SHARED ${SMI_SRC_LIST} ${SMI_INC_LIST}) ## Set the VERSION and SOVERSION values -set_property(TARGET ${ROCM_SMI_TARGET} PROPERTY VERSION "${LIB_VERSION_STRING}") set_property(TARGET ${ROCM_SMI_TARGET} - PROPERTY SOVERSION "${CPACK_PACKAGE_VERSION_MAJOR}") - + PROPERTY VERSION "${LIB_SO_VERSION_STR}") +set_property(TARGET ${ROCM_SMI_TARGET} + PROPERTY SOVERSION "${ROCM_SMI_LIB_VERSION_MAJOR}") ## If the library is a release, strip the target library if ("${CMAKE_BUILD_TYPE}" STREQUAL Release) @@ -148,7 +154,8 @@ set(CPACK_GENERATOR "DEB;RPM" CACHE STRING "Default packaging generators.") ## Add the install directives for the runtime library. install(TARGETS ${ROCM_SMI_TARGET} LIBRARY DESTINATION ${ROCM_SMI}/lib COMPONENT ${ROCM_SMI_COMPONENT}) -install(FILES ${SOURCE_DIR}/include/rocm_smi/rocm_smi.h DESTINATION rocm_smi/include/rocm_smi) +install(FILES ${SOURCE_DIR}/include/rocm_smi/rocm_smi.h + DESTINATION rocm_smi/include/rocm_smi) ## Add the packaging directives for the runtime library. @@ -177,4 +184,3 @@ else() message("Doxygen is not found. Will not generate documents.") endif(DOXYGEN_FOUND) - diff --git a/projects/amdsmi/cmake_modules/utils.cmake b/projects/amdsmi/cmake_modules/utils.cmake old mode 100644 new mode 100755 index 5b4e73ce23..480ae6f111 --- a/projects/amdsmi/cmake_modules/utils.cmake +++ b/projects/amdsmi/cmake_modules/utils.cmake @@ -85,15 +85,14 @@ endfunction () ## using versioning tags and git describe. ## Passes back a packaging version string ## and a library version string. -function ( get_version DEFAULT_VERSION_STRING ) +function(get_version DEFAULT_VERSION_STRING VERSION_PREFIX) parse_version ( ${DEFAULT_VERSION_STRING} ) find_program ( GIT NAMES git ) if ( GIT ) - - execute_process ( COMMAND git describe --dirty --long --match [0-9]* + execute_process ( COMMAND git describe --dirty --long --match ${VERSION_PREFIX}-[0-9.]* WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_TAG_STRING OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 5ee6fe857c..151faea772 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -256,6 +256,15 @@ typedef struct { uint32_t lanes[RSMI_MAX_NUM_FREQUENCIES]; } rsmi_pcie_bandwidth; +/** + * @brief This structure holds version information. + */ +typedef struct { + uint32_t major; //!< Major version + uint32_t minor; //!< Minor version + uint32_t patch; //!< Patch, build or stepping version + const char *build; //!< Build string +} rsmi_version; /** * @brief Initialize Rocm SMI. @@ -266,7 +275,7 @@ typedef struct { * @param[in] init_flags Bit flags that tell SMI how to initialze. Not * currently used. * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. */ rsmi_status_t rsmi_init(uint64_t init_flags); @@ -287,7 +296,7 @@ rsmi_status_t rsmi_shut_down(void); * successful call, the value num_devices will contain the number of monitor * devices. * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. */ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); @@ -304,19 +313,38 @@ rsmi_status_t rsmi_num_monitor_devices(uint32_t *num_devices); * @param[inout] bandwidth a pointer to a caller provided rsmi_pcie_bandwidth * structure to which the frequency information will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth *bandwidth); +/** + * @brief Get percentage of time device is busy doing any processing + * + * @details Given a device index @p dv_ind, this function returns the + * percentage of time that the specified device is busy. The device is + * considered busy if any one or more of its sub-blocks are working, and idle + * if none of the sub-blocks are working. + * + * @param[in] dv_ind a device index + * + * @param[inout] busy_percent a pointer to the uint32_t to which the busy + * percent will be written + * + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call + * + */ +rsmi_status_t +rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent); + /** * @brief Control the set of allowed PCIe bandwidths that can be used. * * @details Given a device index @p dv_ind and a 64 bit bitmask @p bw_bitmask, * this function will limit the set of allowable bandwidths. If a bit in @p * bw_bitmask has a value of 1, then the frequency (as ordered in an - * rsmi_frequencies returned by rsmi_dev_get_gpu_clk_freq()) corresponding + * ::rsmi_frequencies returned by rsmi_dev_get_gpu_clk_freq()) corresponding * to that bit index will be allowed. * * This function will change the performance level to @@ -349,7 +377,7 @@ rsmi_status_t rsmi_dev_pci_bandwidth_set(uint32_t dv_ind, uint64_t bw_bitmask); * @param[inout] bdfid a pointer to uint64_t to which the device bdfid value * will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. */ rsmi_status_t rsmi_dev_pci_id_get(uint32_t dv_ind, uint64_t *bdfid); @@ -371,7 +399,7 @@ rsmi_status_t rsmi_dev_pci_id_get(uint32_t dv_ind, uint64_t *bdfid); * @param[inout] id a pointer to uint64_t to which the device id will be * written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_id_get(uint32_t dv_ind, uint64_t *id); @@ -382,15 +410,15 @@ rsmi_status_t rsmi_dev_id_get(uint32_t dv_ind, uint64_t *id); * device index. * * @details Given a device index @p dv_ind and a pointer to a uint32_t @p - * perf, this function will write the rsmi_dev_perf_level to the uint32_t + * perf, this function will write the ::rsmi_dev_perf_level to the uint32_t * pointed to by @p perf * * @param[in] dv_ind a device index * - * @param[inout] perf a pointer to rsmi_dev_perf_level to which the + * @param[inout] perf a pointer to ::rsmi_dev_perf_level to which the * performance level will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_perf_level_get(uint32_t dv_ind, @@ -408,7 +436,7 @@ rsmi_status_t rsmi_dev_perf_level_get(uint32_t dv_ind, * * @param[in] perf_lvl the value to which the performance level should be set * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -427,7 +455,7 @@ rsmi_dev_perf_level_set(int32_t dv_ind, rsmi_dev_perf_level perf_lvl); * @param[inout] od a pointer to uint32_t to which the overdrive percentage * will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_overdrive_level_get(uint32_t dv_ind, uint32_t *od); @@ -466,7 +494,7 @@ rsmi_status_t rsmi_dev_overdrive_level_get(uint32_t dv_ind, uint32_t *od); * * @param[in] od the value to which the overdrive level should be set * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_overdrive_level_set(int32_t dv_ind, uint32_t od); @@ -476,7 +504,7 @@ rsmi_status_t rsmi_dev_overdrive_level_set(int32_t dv_ind, uint32_t od); * specified clock type. * * @details Given a device index @p dv_ind, a clock type @p clk_type, and a - * pointer to a to an rsmi_frequencies structure @p f, this function will + * pointer to a to an ::rsmi_frequencies structure @p f, this function will * fill in @p f with the possible clock speeds, and indication of the current * clock speed selection. * @@ -484,10 +512,10 @@ rsmi_status_t rsmi_dev_overdrive_level_set(int32_t dv_ind, uint32_t od); * * @param[in] clk_type the type of clock for which the frequency is desired * - * @param[inout] f a pointer to a caller provided rsmi_frequencies structure + * @param[inout] f a pointer to a caller provided ::rsmi_frequencies structure * to which the frequency information will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_gpu_clk_freq_get(uint32_t dv_ind, @@ -500,7 +528,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_get(uint32_t dv_ind, * @details Given a device index @p dv_ind, a clock type @p clk_type, and a * 64 bit bitmask @p freq_bitmask, this function will limit the set of * allowable frequencies. If a bit in @p freq_bitmask has a value of 1, then - * the frequency (as ordered in an rsmi_frequencies returned by + * the frequency (as ordered in an ::rsmi_frequencies returned by * rsmi_dev_get_gpu_clk_freq()) corresponding to that bit index will be * allowed. * @@ -510,7 +538,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_get(uint32_t dv_ind, * to get back to default state. * * All bits with indices greater than or equal to - * rsmi_frequencies::num_supported will be ignored. + * ::rsmi_frequencies::num_supported will be ignored. * * @param[in] dv_ind a device index * @@ -519,7 +547,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_get(uint32_t dv_ind, * * @param[in] freq_bitmask A bitmask indicating the indices of the * frequencies that are to be enabled (1) and disabled (0). Only the lowest - * rsmi_frequencies.num_supported bits of this mask are relevant. + * ::rsmi_frequencies.num_supported bits of this mask are relevant. */ rsmi_status_t rsmi_dev_gpu_clk_freq_set(uint32_t dv_ind, rsmi_clk_type clk_type, uint64_t freq_bitmask); @@ -537,7 +565,7 @@ rsmi_status_t rsmi_dev_gpu_clk_freq_set(uint32_t dv_ind, * * @param[in] len the length of the caller provided buffer @p name. * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_name_get(uint32_t dv_ind, char *name, size_t len); @@ -559,7 +587,7 @@ rsmi_status_t rsmi_dev_name_get(uint32_t dv_ind, char *name, size_t len); * @param[inout] temperature a pointer to int64_t to which the temperature * will be written, in millidegrees Celcius. * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_temp_metric_get(uint32_t dv_ind, uint32_t sensor_ind, @@ -574,7 +602,7 @@ rsmi_status_t rsmi_dev_temp_metric_get(uint32_t dv_ind, uint32_t sensor_ind, * @param[in] sensor_ind a 0-based sensor index. Normally, this will be 0. * If a device has more than one sensor, it could be greater than 0. * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. */ rsmi_status_t rsmi_dev_fan_reset(uint32_t dv_ind, uint32_t sensor_ind); @@ -594,7 +622,7 @@ rsmi_status_t rsmi_dev_fan_reset(uint32_t dv_ind, uint32_t sensor_ind); * @param[inout] speed a pointer to uint32_t to which the speed will be * written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_fan_rpms_get(uint32_t dv_ind, uint32_t sensor_ind, @@ -620,7 +648,7 @@ rsmi_status_t rsmi_dev_fan_rpms_get(uint32_t dv_ind, uint32_t sensor_ind, * @param[inout] speed a pointer to uint32_t to which the speed will be * written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_fan_speed_get(uint32_t dv_ind, @@ -641,7 +669,7 @@ rsmi_status_t rsmi_dev_fan_speed_get(uint32_t dv_ind, * @param[inout] max_speed a pointer to uint32_t to which the maximum speed * will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t rsmi_dev_fan_speed_max_get(uint32_t dv_ind, @@ -663,7 +691,7 @@ rsmi_status_t rsmi_dev_fan_speed_max_get(uint32_t dv_ind, * * @param[in] speed the speed to which the function will attempt to set the fan * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. */ rsmi_status_t rsmi_dev_fan_speed_set(uint32_t dv_ind, uint32_t sensor_ind, uint64_t speed); @@ -686,7 +714,7 @@ rsmi_status_t rsmi_dev_fan_speed_set(uint32_t dv_ind, uint32_t sensor_ind, * @param[inout] power a pointer to uint64_t to which the average power * consumption will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -708,7 +736,7 @@ rsmi_dev_power_ave_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *power); * @param[inout] cap a pointer to a uint64_t that indicates the power cap, * in microwatts * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -731,7 +759,7 @@ rsmi_dev_power_cap_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *cap); * @param[inout] min a pointer to a uint64_t that indicates the minimum * possible power cap, in microwatts * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -753,7 +781,7 @@ rsmi_dev_power_cap_range_get(uint32_t dv_ind, uint32_t sensor_ind, * @param[inout] cap a uint64_t that indicates the desired power cap, in * microwatts * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -776,7 +804,7 @@ rsmi_dev_power_cap_set(uint32_t dv_ind, uint32_t sensor_ind, uint64_t cap); * @param[inout] power a pointer to uint64_t to which the maximum power * consumption will be written * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -807,7 +835,7 @@ rsmi_dev_power_max_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *power); * @param[inout] status a pointer to rsmi_power_profile_status that will be * populated by a call to this function * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -831,7 +859,7 @@ rsmi_dev_power_profile_presets_get(uint32_t dv_ind, uint32_t sensor_ind, * @param[in] profile a rsmi_power_profile_preset_masks that hold the mask * of the desired new power profile * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call. + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call. * */ rsmi_status_t @@ -848,30 +876,27 @@ rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t sensor_ind, * @param[inout] status_string A pointer to a const char * which will be made * to point to a description of the provided error code * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call * */ rsmi_status_t rsmi_status_string(rsmi_status_t status, const char **status_string); /** - * @brief Get percentage of time device is busy doing any processing - * - * @details Given a device index @p dv_ind, this function returns the - * percentage of time that the specified device is busy. The device is - * considered busy if any one or more of its sub-blocks are working, and idle - * if none of the sub-blocks are working. - * - * @param[in] dv_ind a device index - * - * @param[inout] busy_percent a pointer to the uint32_t to which the busy - * percent will be written - * - * @retval RSMI_STATUS_SUCCESS is returned upon successful call - * + * @brief Get the build version information for the currently running build of + * RSMI. + * + * @details Get the major, minor, patch and build string for RSMI build + * currently in use through @p version + * + * @paramp[inout] version A pointer to an ::rsmi_version structure that will + * be updated with the version information upon return. + * + * @retval ::RSMI_STATUS_SUCCESS is returned upon successful call + * */ rsmi_status_t -rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent); +rsmi_version_get(rsmi_version *version); #ifdef __cplusplus } diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index 1f210d8a3a..11cad49a07 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -59,6 +59,7 @@ #include "rocm_smi/rocm_smi_device.h" #include "rocm_smi/rocm_smi_utils.h" #include "rocm_smi/rocm_smi_exception.h" +#include "rocm_smi/rocm_smi64Config.h" static const uint32_t kMaxOverdriveLevel = 20; @@ -1117,3 +1118,20 @@ rsmi_dev_busy_percent_get(uint32_t dv_ind, uint32_t *busy_percent) { CATCH } + +rsmi_status_t +rsmi_version_get(rsmi_version *version) { + TRY + + if (version == nullptr) { + return RSMI_STATUS_INVALID_ARGS; + } + version->major = rocm_smi_VERSION_MAJOR; + version->minor = rocm_smi_VERSION_MINOR; + version->patch = rocm_smi_VERSION_PATCH; + version->build = rocm_smi_VERSION_BUILD; + + return RSMI_STATUS_SUCCESS; + + CATCH +} diff --git a/projects/amdsmi/src/rocm_smi64Config.in b/projects/amdsmi/src/rocm_smi64Config.in new file mode 100755 index 0000000000..bde279ced1 --- /dev/null +++ b/projects/amdsmi/src/rocm_smi64Config.in @@ -0,0 +1,56 @@ +/* + * ============================================================================= + * ROC Runtime Conformance Release License + * ============================================================================= + * The University of Illinois/NCSA + * Open Source License (NCSA) + * + * Copyright (c) 2017, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Developed by: + * + * AMD Research and AMD ROC Software Development + * + * Advanced Micro Devices, Inc. + * + * www.amd.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal with 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in + * the documentation and/or other materials provided with the distribution. + * - Neither the names of , + * nor the names of its contributors may be used to endorse or promote + * products derived from this Software without specific prior written + * permission. + * + * 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 CONTRIBUTORS 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 WITH THE SOFTWARE. + * + */ + +#ifndef INCLUDE_ROCM_SMI_ROCM_SMI64CONFIG_H_ +#define INCLUDE_ROCM_SMI_ROCM_SMI64CONFIG_H_ + +// This file is generated on build. + +#define rocm_smi_VERSION_MAJOR @rocm_smi_VERSION_MAJOR@ +#define rocm_smi_VERSION_MINOR @rocm_smi_VERSION_MINOR@ +#define rocm_smi_VERSION_PATCH @rocm_smi_VERSION_PATCH@ +#define rocm_smi_VERSION_BUILD "@rocm_smi_VERSION_BUILD@" + +#endif // INCLUDE_ROCM_SMI_ROCM_SMI64CONFIG_H_ \ No newline at end of file diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index d99980e472..be96b41292 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -501,7 +501,7 @@ static rsmi_status_t test_set_pci_bw(uint32_t dv_ind) { return RSMI_STATUS_SUCCESS; } -static void print_frequencies(rsmi_frequencies *f, uint32_t *l=nullptr) { +static void print_frequencies(rsmi_frequencies *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]; @@ -557,9 +557,20 @@ void TestSanity::Run(void) { rsmi_dev_perf_level pfl; rsmi_frequencies f; rsmi_pcie_bandwidth b; - + rsmi_version ver = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, nullptr}; uint32_t num_monitor_devs = 0; + err = rsmi_version_get(&ver); + CHK_ERR_ASRT(err) + + ASSERT_TRUE(ver.major != 0xFFFFFFFF && ver.minor != 0xFFFFFFFF && + ver.patch != 0xFFFFFFFF && ver.build != nullptr); + + IF_VERB(STANDARD) { + std::cout << "\t**RocM SMI Library version: " << ver.major << "." << + ver.minor << "." << ver.patch << " (" << ver.build << ")" << std::endl; + } + for (uint32_t i = 0; i < num_iteration(); i++) { IF_VERB(PROGRESS) { std::cout << "Iteration: " << i << std::endl; From 6ff5fbf385ffcbf95d521167f841363fa29a0ed3 Mon Sep 17 00:00:00 2001 From: Chris Freehill Date: Wed, 19 Dec 2018 17:24:27 -0600 Subject: [PATCH 7/7] Handle case where PCIe information is not implemented in system Also add a new error code for this. [ROCm/amdsmi commit: 5e6424cab32dab934964f7134ff5cbbb9cf859d1] --- projects/amdsmi/include/rocm_smi/rocm_smi.h | 7 +++++- projects/amdsmi/src/rocm_smi.cc | 14 +++++++++++ .../rocm_smi_test/functional/rsmi_sanity.cc | 24 ++++++++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/projects/amdsmi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/include/rocm_smi/rocm_smi.h index 151faea772..9a94263c61 100755 --- a/projects/amdsmi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/include/rocm_smi/rocm_smi.h @@ -84,9 +84,14 @@ typedef enum { RSMI_STATUS_INTERNAL_EXCEPTION, //!< An internal exception was caught RSMI_STATUS_INPUT_OUT_OF_BOUNDS, //!< The provided input is out of //!< allowable or safe range - RSMI_INITIALIZATION_ERROR, //!< An error occurred when rsmi + RSMI_STATUS_INIT_ERROR, //!< An error occurred when rsmi //!< initializing internal data //!< structures + RSMI_INITIALIZATION_ERROR = RSMI_STATUS_INIT_ERROR, + RSMI_STATUS_NOT_YET_IMPLEMENTED, //!< The requested function has not + //!< yet been implemented in the + //!< current system for the current + //!< devices RSMI_STATUS_UNKNOWN_ERROR = 0xFFFFFFFF, //!< An unknown error occurred } rsmi_status_t; diff --git a/projects/amdsmi/src/rocm_smi.cc b/projects/amdsmi/src/rocm_smi.cc index 11cad49a07..cdebed6e82 100755 --- a/projects/amdsmi/src/rocm_smi.cc +++ b/projects/amdsmi/src/rocm_smi.cc @@ -464,6 +464,10 @@ static rsmi_status_t get_frequencies(amd::smi::DevInfoTypes type, } assert(val_vec.size() <= RSMI_MAX_NUM_FREQUENCIES); + if (val_vec.size() == 0) { + return RSMI_STATUS_NOT_YET_IMPLEMENTED; + } + f->num_supported = val_vec.size(); bool current = false; f->current = RSMI_MAX_NUM_FREQUENCIES + 1; // init to an invalid value @@ -1092,6 +1096,16 @@ rsmi_status_string(rsmi_status_t status, const char **status_string) { *status_string = "The provided input is out of allowable or safe range"; break; + case RSMI_STATUS_INIT_ERROR: + *status_string = "An error occurred during initialization, during " + "monitor discovery or when when initializing internal data structures"; + break; + + case RSMI_STATUS_NOT_YET_IMPLEMENTED: + *status_string = "The called function has not been implemented in this " + "system for this device type"; + break; + default: *status_string = "An unknown error occurred"; return RSMI_STATUS_UNKNOWN_ERROR; diff --git a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc index be96b41292..6ee8bbc666 100755 --- a/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc +++ b/projects/amdsmi/tests/rocm_smi_test/functional/rsmi_sanity.cc @@ -611,13 +611,17 @@ void TestSanity::Run(void) { print_frequencies(&f); } err = rsmi_dev_pci_bandwidth_get(i, &b); - 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); + if (err == RSMI_STATUS_NOT_YET_IMPLEMENTED) { + std::cout << "\t**Get PCIE Bandwidth: Not supported 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); + } } - err = rsmi_dev_gpu_clk_freq_get(i, RSMI_CLK_TYPE_SYS, &f); CHK_ERR_ASRT(err) IF_VERB(STANDARD) { @@ -766,8 +770,12 @@ void TestSanity::Run(void) { CHK_RSMI_PERM_ERR(err) err = test_set_pci_bw(i); - CHK_RSMI_PERM_ERR(err) - + if (err == RSMI_STATUS_NOT_YET_IMPLEMENTED) { + std::cout << "\t**Set PCIE Bandwidth: Not supported on this machine" + << std::endl; + } else { + CHK_RSMI_PERM_ERR(err) + } err = test_set_fan_speed(i); CHK_RSMI_PERM_ERR(err)