From 1663a361351f5bcb5c4b3bbfbfade41d15e7f740 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Thu, 9 Dec 2021 20:18:39 +0100 Subject: [PATCH] [v0.11] Fetch and print max Intel iGPU frequency using sysfs --- CMakeLists.txt | 2 +- src/common/pci.cpp | 18 +++++++++ src/common/pci.hpp | 4 ++ src/common/printer.cpp | 2 + src/intel/intel.cpp | 2 + src/intel/udev.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++ src/intel/udev.hpp | 7 ++++ 7 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/intel/udev.cpp create mode 100644 src/intel/udev.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 57150dd..4ceca41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(CMAKE_CXX_FLAGS "${SANITY_FLAGS} -Wall -Wextra -pedantic -fstack-protector-a if(ENABLE_INTEL_BACKEND) target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL) - add_library(intel_backend STATIC ${INTEL_DIR}/intel.cpp ${INTEL_DIR}/pci.cpp ${INTEL_DIR}/uarch.cpp) + add_library(intel_backend STATIC ${INTEL_DIR}/intel.cpp ${INTEL_DIR}/pci.cpp ${INTEL_DIR}/uarch.cpp ${INTEL_DIR}/udev.cpp) if(NOT ${PCIUTILS_FOUND}) add_dependencies(intel_backend pciutils) diff --git a/src/common/pci.cpp b/src/common/pci.cpp index 3f374da..62cf60f 100644 --- a/src/common/pci.cpp +++ b/src/common/pci.cpp @@ -26,11 +26,29 @@ uint16_t pciutils_get_pci_device_id(struct pci_dev *devices, int id) { return 0; } +void pciutils_set_pci_bus(struct pci* pci, struct pci_dev *devices, int id) { + bool found = false; + + for(struct pci_dev *dev=devices; dev != NULL; dev=dev->next) { + if(dev->vendor_id == id && dev->device_class == CLASS_VGA_CONTROLLER) { + pci->domain = dev->domain; + pci->bus = dev->bus; + pci->dev = dev->dev; + pci->func = dev->func; + found = true; + } + } + + if(!found) printErr("Unable to find a valid device for id %d using pciutils", id); +} + struct pci* get_pci_from_pciutils(struct pci_dev *devices, int id) { struct pci* pci = (struct pci*) emalloc(sizeof(struct pci)); + // TODO: Refactor this; instead of 2xGet + 1xSet, do it better pci->vendor_id = pciutils_get_pci_vendor_id(devices, id); pci->device_id = pciutils_get_pci_device_id(devices, id); + pciutils_set_pci_bus(pci, devices, id); return pci; } diff --git a/src/common/pci.hpp b/src/common/pci.hpp index 73cf372..7214545 100644 --- a/src/common/pci.hpp +++ b/src/common/pci.hpp @@ -9,6 +9,10 @@ extern "C" { struct pci { uint16_t vendor_id; uint16_t device_id; + uint16_t domain; + uint16_t bus; + uint16_t dev; + uint16_t func; }; struct pci* get_pci_from_pciutils(struct pci_dev *devices, int id); diff --git a/src/common/printer.cpp b/src/common/printer.cpp index a5650c0..6806fb5 100644 --- a/src/common/printer.cpp +++ b/src/common/printer.cpp @@ -371,10 +371,12 @@ bool print_gpufetch_intel(struct gpu_info* gpu, STYLE s, struct color** cs, stru char* gt = get_str_gt(gpu->arch); char* manufacturing_process = get_str_process(gpu->arch); char* eus = get_str_eu(gpu); + char* max_frequency = get_str_freq(gpu); setAttribute(art, ATTRIBUTE_NAME, gpu_name); setAttribute(art, ATTRIBUTE_UARCH, uarch); setAttribute(art, ATTRIBUTE_TECHNOLOGY, manufacturing_process); + setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency); setAttribute(art, ATTRIBUTE_GT, gt); setAttribute(art, ATTRIBUTE_EUS, eus); diff --git a/src/intel/intel.cpp b/src/intel/intel.cpp index 1ea5bb3..fa8647b 100644 --- a/src/intel/intel.cpp +++ b/src/intel/intel.cpp @@ -4,6 +4,7 @@ #include "intel.hpp" #include "uarch.hpp" #include "chips.hpp" +#include "udev.hpp" #include "../common/pci.hpp" #include "../common/global.hpp" @@ -16,6 +17,7 @@ struct gpu_info* get_gpu_info_intel() { gpu->arch = get_uarch_from_pci(gpu->pci); gpu->name = get_name_from_uarch(gpu->arch); gpu->topo_i = get_topology_info(gpu->arch); + gpu->freq = get_max_freq_from_file(gpu->pci); return gpu; } diff --git a/src/intel/udev.cpp b/src/intel/udev.cpp new file mode 100644 index 0000000..91e4142 --- /dev/null +++ b/src/intel/udev.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/global.hpp" +#include "../common/pci.hpp" + +#define _PATH_SYS_SYSTEM "/sys/devices/pci0000:00" +#define _PATH_SYS_DRM "/drm" +#define _PATH_CARD "/card0" +#define _PATH_FREQUENCY_MAX "/gt_max_freq_mhz" +#define _PATH_FREQUENCY_MIN "/gt_min_freq_mhz" + +#define _PATH_FREQUENCY_MAX_LEN 100 +#define DEFAULT_FILE_SIZE 4096 +#define UNKNOWN_DATA -1 + +char* read_file(char* path, int* len) { + int fd = open(path, O_RDONLY); + + if(fd == -1) { + return NULL; + } + + //File exists, read it + int bytes_read = 0; + int offset = 0; + int block = 128; + char* buf = (char *) emalloc(sizeof(char)*DEFAULT_FILE_SIZE); + memset(buf, 0, sizeof(char)*DEFAULT_FILE_SIZE); + + while ( (bytes_read = read(fd, buf+offset, block)) > 0 ) { + offset += bytes_read; + } + + if (close(fd) == -1) { + return NULL; + } + + *len = offset; + return buf; +} + +long get_freq_from_file(char* path) { + int filelen; + char* buf; + if((buf = read_file(path, &filelen)) == NULL) { + printWarn("Could not open '%s'", path); + return UNKNOWN_DATA; + } + + char* end; + errno = 0; + long ret = strtol(buf, &end, 10); + if(errno != 0) { + printBug("strtol: %s", strerror(errno)); + free(buf); + return UNKNOWN_DATA; + } + + // We will be getting the frequency in MHz + // We consider it is an error if frequency is + // greater than 10 GHz or less than 100 MHz + if(ret > 10000 || ret < 100) { + printBug("Invalid data was read from file '%s': %ld\n", path, ret); + return UNKNOWN_DATA; + } + + free(buf); + + return ret; +} + +long get_max_freq_from_file(struct pci* pci) { + char path[_PATH_FREQUENCY_MAX_LEN]; + sprintf(path, "%s/%04x:%02x:%02x.%d%s%s%s", _PATH_SYS_SYSTEM, pci->domain, pci->bus, pci->dev, pci->func, _PATH_SYS_DRM, _PATH_CARD, _PATH_FREQUENCY_MAX); + return get_freq_from_file(path); +} + +long get_min_freq_from_file(struct pci* pci) { + char path[_PATH_FREQUENCY_MAX_LEN]; + sprintf(path, "%s/%04x:%02x:%02x.%d%s%s%s", _PATH_SYS_SYSTEM, pci->domain, pci->bus, pci->dev, pci->func, _PATH_SYS_DRM, _PATH_CARD, _PATH_FREQUENCY_MIN); + return get_freq_from_file(path); +} diff --git a/src/intel/udev.hpp b/src/intel/udev.hpp new file mode 100644 index 0000000..eb5aaae --- /dev/null +++ b/src/intel/udev.hpp @@ -0,0 +1,7 @@ +#ifndef __UDEV__ +#define __UDEV__ + +long get_max_freq_from_file(struct pci* pci); +long get_min_freq_from_file(struct pci* pci); + +#endif