#2066 Fixed AMD GPUs health data readings.

This commit is contained in:
XMRig 2021-01-30 02:42:59 +07:00
parent 7d52bd7454
commit 2c52a5a352
No known key found for this signature in database
GPG key ID: 446A53638BE94409
2 changed files with 75 additions and 33 deletions

View file

@ -1,13 +1,6 @@
/* XMRig /* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com> * Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org> * Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -42,10 +35,15 @@ public:
PciTopology() = default; PciTopology() = default;
PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_valid(true), m_bus(bus), m_device(device), m_function(function) {} PciTopology(uint32_t bus, uint32_t device, uint32_t function) : m_valid(true), m_bus(bus), m_device(device), m_function(function) {}
inline bool isValid() const { return m_valid; } inline bool isEqual(const PciTopology &other) const { return m_valid == other.m_valid && toUint32() == other.toUint32(); }
inline uint8_t bus() const { return m_bus; } inline bool isValid() const { return m_valid; }
inline uint8_t device() const { return m_device; } inline uint8_t bus() const { return m_bus; }
inline uint8_t function() const { return m_function; } inline uint8_t device() const { return m_device; }
inline uint8_t function() const { return m_function; }
inline bool operator!=(const PciTopology &other) const { return !isEqual(other); }
inline bool operator<(const PciTopology &other) const { return toUint32() < other.toUint32(); }
inline bool operator==(const PciTopology &other) const { return isEqual(other); }
String toString() const String toString() const
{ {
@ -60,6 +58,8 @@ public:
} }
private: private:
inline uint32_t toUint32() const { return m_bus << 16 | m_device << 8 | m_function; }
bool m_valid = false; bool m_valid = false;
uint8_t m_bus = 0; uint8_t m_bus = 0;
uint8_t m_device = 0; uint8_t m_device = 0;

View file

@ -20,10 +20,13 @@
#include "backend/opencl/wrappers/AdlLib.h" #include "backend/opencl/wrappers/AdlLib.h"
#include "3rdparty/fmt/core.h"
#include "backend/opencl/wrappers/OclDevice.h" #include "backend/opencl/wrappers/OclDevice.h"
#include <dirent.h>
#include <fstream> #include <fstream>
#include <map>
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -35,18 +38,27 @@ namespace xmrig {
bool AdlLib::m_initialized = false; bool AdlLib::m_initialized = false;
bool AdlLib::m_ready = false; bool AdlLib::m_ready = false;
static const std::string kPrefix = "/sys/bus/pci/drivers/amdgpu/"; static const std::string kPrefix = "/sys/bus/pci/drivers/amdgpu/";
static std::map<PciTopology, std::string> hwmon_cache;
static inline bool sysfs_is_file(const std::string &path) static inline bool sysfs_is_file(const char *path)
{ {
struct stat sb; struct stat sb;
return stat(path.c_str(), &sb) == 0 && ((sb.st_mode & S_IFMT) == S_IFREG); return stat(path, &sb) == 0 && ((sb.st_mode & S_IFMT) == S_IFREG);
} }
static inline bool sysfs_is_amdgpu(const std::string &path) static inline int dir_filter(const struct dirent *dirp)
{ {
return strlen(dirp->d_name) > 5 ? 1 : 0;
}
static bool sysfs_is_amdgpu(const char *path, char *buf, const char *filename)
{
strcpy(buf, filename);
if (!sysfs_is_file(path)) { if (!sysfs_is_file(path)) {
return false; return false;
} }
@ -63,8 +75,10 @@ static inline bool sysfs_is_amdgpu(const std::string &path)
} }
uint32_t sysfs_read(const std::string &path) static uint32_t sysfs_read(const char *path, char *buf, const char *filename)
{ {
strcpy(buf, filename);
std::ifstream file(path); std::ifstream file(path);
if (!file.is_open()) { if (!file.is_open()) {
return 0; return 0;
@ -77,18 +91,44 @@ uint32_t sysfs_read(const std::string &path)
} }
static inline std::string sysfs_prefix(const PciTopology &topology) static size_t sysfs_prefix(char path[PATH_MAX], const PciTopology &topology)
{ {
const std::string path = kPrefix + "0000:" + topology.toString().data() + "/hwmon/hwmon"; const auto it = hwmon_cache.find(topology);
if (it != hwmon_cache.end()) {
strcpy(path, it->second.data());
for (uint32_t i = 1; i < 100; ++i) { return it->second.size();
const std::string prefix = path + std::to_string(i) + "/";
if (sysfs_is_amdgpu(prefix + "name") && (sysfs_read(prefix + "temp1_input") || sysfs_read(prefix + "power1_average"))) {
return prefix;
}
} }
return {}; char *base = fmt::format_to(path, "{}0000:{}/hwmon/", kPrefix, topology.toString());
*base = '\0';
char *end = nullptr;
struct dirent **namelist;
int n = scandir(path, &namelist, dir_filter, nullptr);
if (n < 0) {
return {};
}
while (n--) {
if (!end) {
char *tmp = fmt::format_to(base, "{}/", namelist[n]->d_name);
end = (sysfs_is_amdgpu(path, tmp, "name") && (sysfs_read(path, tmp, "temp1_input") || sysfs_read(path, tmp, "power1_average"))) ? tmp : nullptr;
}
free(namelist[n]);
}
free(namelist);
if (end) {
*end = '\0';
hwmon_cache.insert({ topology, path });
return end - path;
}
return 0;
} }
@ -124,20 +164,22 @@ AdlHealth xmrig::AdlLib::health(const OclDevice &device)
return {}; return {};
} }
const auto prefix = sysfs_prefix(device.topology()); static char path[PATH_MAX]{};
if (prefix.empty()) {
char *buf = path + sysfs_prefix(path, device.topology());
if (buf == path) {
return {}; return {};
} }
AdlHealth health; AdlHealth health;
health.clock = sysfs_read(prefix + "freq1_input") / 1000000; health.clock = sysfs_read(path, buf, "freq1_input") / 1000000;
health.memClock = sysfs_read(prefix + "freq2_input") / 1000000; health.memClock = sysfs_read(path, buf, "freq2_input") / 1000000;
health.power = sysfs_read(prefix + "power1_average") / 1000000; health.power = sysfs_read(path, buf, "power1_average") / 1000000;
health.rpm = sysfs_read(prefix + "fan1_input"); health.rpm = sysfs_read(path, buf, "fan1_input");
health.temperature = sysfs_read(prefix + "temp2_input") / 1000; health.temperature = sysfs_read(path, buf, "temp2_input") / 1000;
if (!health.temperature) { if (!health.temperature) {
health.temperature = sysfs_read(prefix + "temp1_input") / 1000; health.temperature = sysfs_read(path, buf, "temp1_input") / 1000;
} }
return health; return health;