Files
fastfetch/src/detection/gpu/gpu_linux.c
T

192 lines
6.8 KiB
C
Raw Normal View History

2023-02-14 17:50:53 +08:00
#include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h"
2022-09-25 15:23:00 +08:00
#include "detection/temps/temps_linux.h"
#include "common/io/io.h"
2024-02-12 00:43:06 +08:00
#include "common/properties.h"
2023-02-01 15:56:25 +01:00
#include "util/stringUtils.h"
2022-09-05 17:42:42 +02:00
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h"
#endif
#include <inttypes.h>
2022-09-05 17:42:42 +02:00
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
2022-09-05 17:42:42 +02:00
{
const FFlist* tempsResult = ffDetectTemps();
2022-09-05 17:42:42 +02:00
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
2022-09-05 17:42:42 +02:00
{
// FIXME: this code doesn't take multiGPUs into count
2022-09-05 17:42:42 +02:00
//The kernel exposes the device class multiplied by 256 for some reason
if(tempValue->deviceClass == deviceClass * 256)
2022-09-05 17:42:42 +02:00
{
gpu->temperature = tempValue->value;
return;
}
}
}
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
2023-01-12 11:41:07 +01:00
{
ffStrbufAppendS(pciDir, "/driver");
char pathBuf[PATH_MAX];
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
if(resultLength > 0)
2023-01-12 12:54:04 +01:00
{
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
if (slash)
{
slash++;
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
}
ffStrbufAppendS(pciDir, "/module/version");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
ffStrbufTrimRightSpace(buffer);
ffStrbufAppendC(&gpu->driver, ' ');
ffStrbufAppend(&gpu->driver, buffer);
}
}
2023-01-12 11:41:07 +01:00
}
static bool loadPciIds(FFstrbuf* pciids)
2022-09-05 17:42:42 +02:00
{
ffReadFileBuffer("/usr/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
2022-09-05 17:42:42 +02:00
ffReadFileBuffer("/usr/share/misc/pci.ids", pciids); // debian?
if (pciids->length > 0) return true;
2022-09-05 17:42:42 +02:00
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
2022-09-05 17:42:42 +02:00
return false;
}
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
const char* pciDirPath = "/sys/bus/pci/devices/";
2022-09-05 17:42:42 +02:00
DIR* dirp = opendir(pciDirPath);
if(dirp == NULL)
return "Failed to open `/sys/bus/pci/devices/`";
2022-09-05 17:42:42 +02:00
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
ffStrbufAppendS(&pciDir, pciDirPath);
2022-09-05 17:42:42 +02:00
const uint32_t pciBaseDirLength = pciDir.length;
2023-01-12 11:41:07 +01:00
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
loadPciIds(&pciids);
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
2023-10-27 21:05:03 +08:00
{
if(entry->d_name[0] == '.')
continue;
2022-09-05 17:42:42 +02:00
2024-01-31 18:58:48 +08:00
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
ffStrbufAppendS(&pciDir, entry->d_name);
const uint32_t pciDevDirLength = pciDir.length;
2022-09-05 17:42:42 +02:00
ffStrbufAppendS(&pciDir, "/modalias");
if (!ffReadFileBuffer(pciDir.chars, &buffer))
continue;
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
2024-02-11 23:01:14 +08:00
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
uint8_t classId, subclassId;
2024-02-11 23:01:14 +08:00
if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
continue;
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
continue;
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
2022-09-21 12:02:14 +02:00
2024-02-12 00:43:06 +08:00
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
ffStrbufAppendS(&pciDir, "/revision");
if (ffReadFileBuffer(pciDir.chars, &buffer))
{
char* pend;
uint64_t revision = strtoul(buffer.chars, &pend, 16);
if (pend != buffer.chars)
{
char query[32];
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
}
}
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
}
if (gpu->name.length == 0)
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, (uint16_t) subVendorId, (uint16_t) subDeviceId, gpu);
2022-09-05 17:42:42 +02:00
pciDetectDriver(gpu, &pciDir, &buffer);
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
2022-09-05 17:42:42 +02:00
#ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
#endif
2022-09-05 17:42:42 +02:00
}
2022-09-16 18:11:39 +08:00
return NULL;
2022-09-05 17:42:42 +02:00
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
2022-09-05 17:42:42 +02:00
{
#ifdef FF_HAVE_DIRECTX_HEADERS
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
if (!ffGPUDetectByDirectX(options, gpus))
return NULL;
#endif
return pciDetectGPUs(options, gpus);
2022-09-05 17:42:42 +02:00
}