From 35050bd586c91ea6a631e66aa5d9ad141f37de21 Mon Sep 17 00:00:00 2001 From: jussi Date: Fri, 20 Mar 2020 00:42:16 +0200 Subject: [PATCH] get AMD GPUs in plugin --- src/plugins/AMD.cpp | 81 ++++++++++++++++++++++++++++++++++++++++- src/plugins/meson.build | 16 +++++--- 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/plugins/AMD.cpp b/src/plugins/AMD.cpp index 88460ca..5b911ba 100644 --- a/src/plugins/AMD.cpp +++ b/src/plugins/AMD.cpp @@ -1,22 +1,56 @@ #include +#include +#include +#include +#include #include +#include +#include +#include +#include + +extern int errno; + +#ifndef DRM_RENDER_MINOR_NAME + #define DRM_RENDER_MINOR_NAME "renderD" +#endif + +#define _HWMON_NAME "hwmon" +#define _AMDGPU_NAME "amdgpu" +#define DEVICE_FILE_PREFIX DRM_DIR_NAME "/" DRM_RENDER_MINOR_NAME +#define RENDERD_OFFSET 128 using namespace TuxClocker::Plugin; using namespace TuxClocker::Device; using namespace TuxClocker; +namespace fs = std::filesystem; + +struct AMDAssignableInfo { + // Thus is Linux only + std::optional hwmonPath; + amdgpu_device_handle devHandle; +}; + class AMDPlugin : public DevicePlugin { public: AMDPlugin(); std::optional initializationError() {return std::nullopt;} void foo() {std::cout << "hi from AMD plugin\n";} TreeNode deviceRootNode(); - ~AMDPlugin() {} + ~AMDPlugin(); private: TreeNode m_rootNode; + std::vector m_assignableInfoVec; }; +AMDPlugin::~AMDPlugin() { + for (auto info : m_assignableInfoVec) { + amdgpu_device_deinitialize(info.devHandle); + } +} + AMDPlugin::AMDPlugin() { /*Assignable a([](auto arg) { return std::nullopt; @@ -24,6 +58,51 @@ AMDPlugin::AMDPlugin() { DeviceNode root{"AMD", a}; m_rootNode.appendChild(root);*/ + + struct FSInfo { + std::string path; + std::string filename; + }; + + std::vector infoVec; + // Iterate through files in GPU device folder and find which ones have amdgpu loaded + for (const auto &entry : fs::directory_iterator(DRM_DIR_NAME)) { + // Check if entry is renderD file + if (entry.path().string().find(DRM_RENDER_MINOR_NAME) != std::string::npos) { + infoVec.push_back(FSInfo{entry.path().string(), entry.path().filename().string()}); + } + } + + for (const auto &info : infoVec) { + auto fd = open(info.path.c_str(), O_RDONLY); + auto v_ptr = drmGetVersion(fd); + amdgpu_device_handle dev; + uint32_t m, n; + if (fd > 0 && + v_ptr && + amdgpu_device_initialize(fd, &m, &n, &dev) == 0 && + std::string(v_ptr->name).find(_AMDGPU_NAME) != std::string::npos) { + // Device uses amdgpu + // Find hwmon path if available + std::ostringstream stream; + stream << "/sys/class/drm/" << info.filename << "/device/hwmon"; + + std::optional hwmonPath = std::nullopt; + try { + for (const auto &entry : fs::directory_iterator(stream.str())) { + if (entry.path().filename().string().find("hwmon") != std::string::npos) { + hwmonPath = entry.path().string(); + break; + } + } + } + // This exception is only abnormal to get on Linux + catch (fs::filesystem_error &e) {} + m_assignableInfoVec.push_back(AMDAssignableInfo{hwmonPath, dev}); + } + close(fd); + drmFreeVersion(v_ptr); + } } TreeNode AMDPlugin::deviceRootNode() { diff --git a/src/plugins/meson.build b/src/plugins/meson.build index 3dacb0c..a2a4d1a 100644 --- a/src/plugins/meson.build +++ b/src/plugins/meson.build @@ -1,5 +1,11 @@ -shared_library('amd', 'AMD.cpp', - override_options : ['cpp_std=c++17'], - include_directories : incdir, - install_dir : get_option('libdir') / 'tuxclocker' / 'plugins', - install : true) +libdrm_amdgpu = cppc.find_library('libdrm_amdgpu', required : false) +libdrm_dep = dependency('libdrm', required : false) + +if libdrm_dep.found() and libdrm_amdgpu.found() + shared_library('amd', 'AMD.cpp', + override_options : ['cpp_std=c++17'], + include_directories : incdir, + dependencies : [libdrm_amdgpu, libdrm_dep], + install_dir : get_option('libdir') / 'tuxclocker' / 'plugins', + install : true) +endif