mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-10 00:40:09 +01:00
GPU (Linux): improves PCI GPU name resolution
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# Unreleased
|
||||
|
||||
Changes:
|
||||
* Improved PCI GPU name resolution by checking udev's hardware database and the NVIDIA driver's procfs before falling back to pci.ids. (GPU, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed libc version detection on FreeBSD without binutils installed, and on DragonFly BSD. (Libc, FreeBSD / DragonFly)
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/io.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/strutil.h"
|
||||
#include "modules/gpu/option.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static bool detectDriverFromSysfs(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, [[maybe_unused]] const char* drmKey) {
|
||||
uint32_t pciDirLength = pciDir->length;
|
||||
@@ -337,6 +335,64 @@ static inline uint16_t pcieWidthToLanes(const FFstrbuf* buffer) {
|
||||
return FF_GPU_PCIE_SPEED_UNSET;
|
||||
}
|
||||
|
||||
static bool parseModelName(const char* data, const char* key, bool stripVendorPrefix, FFstrbuf* name) {
|
||||
ffStrbufClear(name);
|
||||
if (!ffParsePropLines(data, key, name) || !name->length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufDecodeHexEscapeSequences(name); // udev hex-escapes characters that are not allowed in property values
|
||||
ffStrbufTrimSpace(name);
|
||||
|
||||
// hwdb names have the form `Codename [Marketing Name]`. Reduce them exactly like
|
||||
// ffGPUParsePciIdsFile() does, so displaying the name does not change with the source.
|
||||
if (name->length > 1 && name->chars[name->length - 1] == ']') {
|
||||
const char* openingBracket = memrchr(name->chars, '[', name->length - 1);
|
||||
if (openingBracket) {
|
||||
ffStrbufSubstrAfter(name, (uint32_t) (openingBracket - name->chars));
|
||||
ffStrbufSubstrBefore(name, name->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The driver repeats the vendor in its own model line. Dropping it keeps the pci.ids
|
||||
// shape and lets ffGPUDetectTypeByVendorAndName() see the product family prefix.
|
||||
if (stripVendorPrefix && ffStrbufStartsWithIgnCaseS(name, "NVIDIA ")) {
|
||||
ffStrbufSubstrAfter(name, (uint32_t) strlen("NVIDIA ") - 1); // excludes the index itself
|
||||
}
|
||||
|
||||
ffStrbufTrimSpace(name);
|
||||
return name->length > 0;
|
||||
}
|
||||
|
||||
static bool nameFromFile(const FFstrbuf* path, const char* key, bool stripVendorPrefix, FFstrbuf* buffer, FFstrbuf* name) {
|
||||
if (!ffReadFileBuffer(path->chars, buffer) || !parseModelName(buffer->chars, key, stripVendorPrefix, name)) {
|
||||
return false;
|
||||
}
|
||||
FF_DEBUG("GPU name resolved from %s: %s", path->chars, name->chars);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The driver and udev already resolved the model name at probe / boot time. Only `Model:` is
|
||||
// consumed: the sibling `power` file goes through the RM and can wake a GPU suspended in runtime D3.
|
||||
static bool resolveNameFromFiles(const char* pciPath, bool isNvidia, FFstrbuf* buffer, FFstrbuf* name) {
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(128);
|
||||
|
||||
if (isNvidia) {
|
||||
ffStrbufSetF(&path, "/proc/driver/nvidia/gpus/%s/information", pciPath);
|
||||
if (nameFromFile(&path, "Model:", true, buffer, name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufSetF(&path, "/run/udev/data/+pci:%s", pciPath);
|
||||
if (nameFromFile(&path, "E:ID_MODEL_FROM_DATABASE=", false, buffer, name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ffStrbufClear(name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) {
|
||||
const uint32_t drmDirPathLength = deviceDir->length;
|
||||
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
||||
@@ -465,7 +521,12 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0) {
|
||||
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
// Stop at the first hit; unknown vendors are left to pci.ids, which also fills in `vendor`.
|
||||
bool resolved = gpu->vendor.length > 0 &&
|
||||
resolveNameFromFiles(pPciPath, gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA, buffer, &gpu->name);
|
||||
if (!resolved) {
|
||||
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
}
|
||||
}
|
||||
|
||||
ffGPUDetectTypeByVendorAndName(gpu);
|
||||
|
||||
Reference in New Issue
Block a user