mirror of
https://github.com/xmrig/xmrig.git
synced 2024-10-30 21:17:52 +00:00
#2066 Fixed AMD GPUs health data readings.
This commit is contained in:
parent
7d52bd7454
commit
2c52a5a352
2 changed files with 75 additions and 33 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue