From 22f99484972c43802b1924f99bdd3f4407aeb360 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 14 Jun 2026 17:36:54 +0800 Subject: [PATCH] GPU: detect current pcie link speed --- src/detection/gpu/gpu.h | 16 +++++-- src/detection/gpu/gpu_amd.c | 30 ++++++++---- src/detection/gpu/gpu_apple.c | 2 +- src/detection/gpu/gpu_bsddrm.c | 2 +- src/detection/gpu/gpu_driver_specific.h | 4 +- src/detection/gpu/gpu_drm.c | 10 ++-- src/detection/gpu/gpu_gnu.c | 2 +- src/detection/gpu/gpu_haiku.c | 2 +- src/detection/gpu/gpu_intel.c | 23 +++++++-- src/detection/gpu/gpu_linux.c | 64 +++++++++++++++++-------- src/detection/gpu/gpu_nbsd.c | 2 +- src/detection/gpu/gpu_nvidia.c | 20 ++++++-- src/detection/gpu/gpu_obsd.c | 2 +- src/detection/gpu/gpu_sunos.c | 2 +- src/detection/gpu/gpu_windows.c | 41 ++++++++++++---- src/detection/gpu/igcl.h | 10 ++++ src/detection/gpu/nvml.h | 6 ++- src/modules/gpu/gpu.c | 31 ++++++------ 18 files changed, 190 insertions(+), 79 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 38de5a0ba..e993b512e 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,7 +7,7 @@ #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t) -1) #define FF_GPU_FREQUENCY_UNSET 0 -#define FF_GPU_PCI_INFO_UNSET 0 +#define FF_GPU_PCIE_SPEED_UNSET 0 #define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX) #define FF_GPU_INDEX_UNSET ((uint32_t) -1) @@ -35,6 +35,11 @@ typedef struct FFGPUMemory { uint64_t used; } FFGPUMemory; +typedef struct FFGPUPcieSpeed { + uint16_t gen; + uint16_t lanes; +} FFGPUPcieSpeed; + typedef struct FFGPUResult { uint32_t index; FFGPUType type; @@ -47,8 +52,13 @@ typedef struct FFGPUResult { double coreUsage; int32_t coreCount; uint32_t frequency; // Maximum time clock frequency in MHz - uint16_t pcieGen; - uint16_t pcieLanes; + union { + struct { + FFGPUPcieSpeed psMax; + FFGPUPcieSpeed psCurr; + }; + uint64_t pcieSpeed; + }; FFGPUMemory dedicated; FFGPUMemory shared; uint64_t deviceId; diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index cac00d6a2..4a8134cf8 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -235,20 +235,34 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist); } - if (result.pcieGen || result.pcieLanes) { + if (result.psMax || result.psCurr) { ADLChipSetInfo chipSetInfo; int status = adlData.ffADL2_Adapter_ChipSetInfo_Get(adlData.apiHandle, device->iAdapterIndex, &chipSetInfo); FF_DEBUG("ADL2_Adapter_ChipSetInfo_Get returned %s (%d)", ffAdlStatusToString(status), status); if (status == ADL_OK) { - FF_DEBUG("Chipset info - Bus Type: %d, PCIe Lane Width: %d", chipSetInfo.iBusType, chipSetInfo.iMaxPCIELaneWidth); - if (result.pcieGen && chipSetInfo.iBusType >= 2) { - *result.pcieGen = (uint16_t) (chipSetInfo.iBusType - 2); - FF_DEBUG("Got PCIe Gen: %u", *result.pcieGen); + FF_DEBUG("Chipset info - iBusSpeedType: %d, iMaxPCIELaneWidth: %d", chipSetInfo.iBusSpeedType, chipSetInfo.iMaxPCIELaneWidth); + if (result.psMax) { + if (chipSetInfo.iBusSpeedType >= 2) { + result.psMax->gen = (uint16_t) (chipSetInfo.iBusSpeedType - 2); + FF_DEBUG("Got PCIe Max Gen: %u", result.psMax->gen); + } + if (chipSetInfo.iMaxPCIELaneWidth > 0) { + result.psMax->lanes = (uint16_t) chipSetInfo.iMaxPCIELaneWidth; + FF_DEBUG("Got PCIe Max Lanes: %u", result.psMax->lanes); + } } - if (result.pcieLanes && chipSetInfo.iMaxPCIELaneWidth > 0) { - *result.pcieLanes = (uint16_t) chipSetInfo.iMaxPCIELaneWidth; - FF_DEBUG("Got PCIe Lanes: %u", *result.pcieLanes); + + FF_DEBUG("Chipset info - iBusType: %d, iCurrentPCIELaneWidth: %d", chipSetInfo.iBusType, chipSetInfo.iCurrentPCIELaneWidth); + if (result.psCurr) { + if (chipSetInfo.iBusType >= 2) { + result.psCurr->gen = (uint16_t) (chipSetInfo.iBusType - 2); + FF_DEBUG("Got PCIe Current Gen: %u", result.psCurr->gen); + } + if (chipSetInfo.iCurrentPCIELaneWidth > 0) { + result.psCurr->lanes = (uint16_t) chipSetInfo.iCurrentPCIELaneWidth; + FF_DEBUG("Got PCIe Current Lanes: %u", result.psCurr->lanes); + } } } else { FF_DEBUG("Failed to get chipset information"); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 6ae10d269..623f081d8 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -118,7 +118,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId); ffStrbufInitStatic(&gpu->platformApi, "IOKit"); diff --git a/src/detection/gpu/gpu_bsddrm.c b/src/detection/gpu/gpu_bsddrm.c index d9a66108e..99bb11af8 100644 --- a/src/detection/gpu/gpu_bsddrm.c +++ b/src/detection/gpu/gpu_bsddrm.c @@ -148,7 +148,7 @@ const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) { gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(pciInfo.domain, pciInfo.bus, pciInfo.dev, pciInfo.func); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; char driverName[64]; driverName[0] = '\0'; diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index a291287fe..807a0eb6e 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -36,8 +36,8 @@ typedef struct FFGpuDriverResult { FFGPUType* type; uint32_t* frequency; FFstrbuf* name; - uint16_t* pcieGen; - uint16_t* pcieLanes; + FFGPUPcieSpeed* psMax; + FFGPUPcieSpeed* psCurr; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_drm.c b/src/detection/gpu/gpu_drm.c index d3a832626..b9fe20b07 100644 --- a/src/detection/gpu/gpu_drm.c +++ b/src/detection/gpu/gpu_drm.c @@ -113,8 +113,8 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con gpu->frequency = (uint32_t) (devInfo.max_engine_clock / 1000u); gpu->index = FF_GPU_INDEX_UNSET; gpu->type = devInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - gpu->pcieGen = (uint16_t) devInfo.pcie_gen; - gpu->pcieLanes = (uint16_t) devInfo.pcie_num_lanes; + gpu->psMax.gen = (uint16_t) devInfo.pcie_gen; + gpu->psMax.lanes = (uint16_t) devInfo.pcie_num_lanes; #define FF_VRAM_CASE(name, value) \ case value /* AMDGPU_VRAM_TYPE_ ## name */: \ ffStrbufSetStatic(&gpu->memoryType, #name); \ @@ -370,13 +370,15 @@ const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .sharedMemory = options->driverSpecific ? &gpu->shared : NULL, + .memoryType = options->driverSpecific ? &gpu->memoryType : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, .name = &gpu->name, - .pcieGen = options->driverSpecific ? &gpu->pcieGen : NULL, - .pcieLanes = options->driverSpecific ? &gpu->pcieLanes : NULL, + .psCurr = options->driverSpecific ? &gpu->psCurr : NULL, + .psMax = options->driverSpecific ? &gpu->psMax : NULL, }, soName); } diff --git a/src/detection/gpu/gpu_gnu.c b/src/detection/gpu/gpu_gnu.c index d7d27792c..30cadf81b 100644 --- a/src/detection/gpu/gpu_gnu.c +++ b/src/detection/gpu/gpu_gnu.c @@ -130,7 +130,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { ffGPUQueryAmdGpuName(deviceId, revision, gpu); diff --git a/src/detection/gpu/gpu_haiku.c b/src/detection/gpu/gpu_haiku.c index 86f959e5c..20a4ae5f6 100644 --- a/src/detection/gpu/gpu_haiku.c +++ b/src/detection/gpu/gpu_haiku.c @@ -37,7 +37,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { ffGPUQueryAmdGpuName(dev.device_id, dev.revision, gpu); diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index fe5d57d84..fea111ef4 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -17,6 +17,7 @@ struct FFIgclData { FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains) FF_LIBRARY_SYMBOL(ctlFrequencyGetProperties) FF_LIBRARY_SYMBOL(ctlPciGetProperties) + FF_LIBRARY_SYMBOL(ctlPciGetState) bool inited; ctl_api_handle_t apiHandle; @@ -45,6 +46,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlPciGetProperties) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlPciGetState) if (ffctlInit(&(ctl_init_args_t) { .AppVersion = CTL_IMPL_VERSION, @@ -229,14 +231,25 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe ffStrbufSetS(result.name, properties.name); } - if (result.pcieGen || result.pcieLanes) { + if (result.psMax) { ctl_pci_properties_t pciProps = { .Size = sizeof(pciProps), .Version = 0 }; if (igclData.ffctlPciGetProperties(device, &pciProps) == CTL_RESULT_SUCCESS) { - if (result.pcieGen && pciProps.maxSpeed.gen > 0) { - *result.pcieGen = (uint16_t) pciProps.maxSpeed.gen; + if (pciProps.maxSpeed.gen > 0) { + result.psMax->gen = (uint16_t) pciProps.maxSpeed.gen; } - if (result.pcieLanes && pciProps.maxSpeed.width > 0) { - *result.pcieLanes = (uint16_t) pciProps.maxSpeed.width; + if (pciProps.maxSpeed.width > 0) { + result.psMax->lanes = (uint16_t) pciProps.maxSpeed.width; + } + } + } + if (result.psCurr) { + ctl_pci_state_t pciState = { .Size = sizeof(pciState), .Version = 0 }; + if (igclData.ffctlPciGetState(device, &pciState) == CTL_RESULT_SUCCESS) { + if (pciState.speed.gen > 0) { + result.psMax->gen = (uint16_t) pciState.speed.gen; + } + if (pciState.speed.width > 0) { + result.psMax->lanes = (uint16_t) pciState.speed.width; } } } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 5c0c3be8e..22039c1e9 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -313,6 +313,32 @@ static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* return NULL; } +static inline uint16_t pcieLinkSpeedToGen(const FFstrbuf* buffer) { + int64_t speed = ffStrbufToSInt(buffer, FF_GPU_PCIE_SPEED_UNSET); + if (speed >= 64) { + return 6; + } else if (speed >= 32) { + return 5; + } else if (speed >= 16) { + return 4; + } else if (speed >= 8) { + return 3; + } else if (speed >= 5) { + return 2; + } else if (speed >= 2) { // 2.5 + return 1; + } + return FF_GPU_PCIE_SPEED_UNSET; +} + +static inline uint16_t pcieWidthToLanes(const FFstrbuf* buffer) { + int64_t width = ffStrbufToSInt(buffer, FF_GPU_PCIE_SPEED_UNSET); + if (width > 0 && width < 255) { // kernel returns 255 if the value is unknown + return (uint16_t) width; + } + return FF_GPU_PCIE_SPEED_UNSET; +} + 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; @@ -368,7 +394,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(pciDomain, pciBus, pciDevice, pciFunc); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; char drmKeyBuffer[8]; if (!drmKey) { @@ -396,30 +422,28 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffStrbufAppendS(deviceDir, "/max_link_speed"); if (ffReadFileBuffer(deviceDir->chars, buffer)) { - int32_t maxLinkSpeed = (int32_t) ffStrbufToSInt(buffer, FF_GPU_PCI_INFO_UNSET); - if (maxLinkSpeed >= 64) { - gpu->pcieGen = 6; - } else if (maxLinkSpeed >= 32) { - gpu->pcieGen = 5; - } else if (maxLinkSpeed >= 16) { - gpu->pcieGen = 4; - } else if (maxLinkSpeed >= 8) { - gpu->pcieGen = 3; - } else if (maxLinkSpeed >= 5) { - gpu->pcieGen = 2; - } else if (maxLinkSpeed >= 2) { // 2.5 - gpu->pcieGen = 1; - } + gpu->psMax.gen = pcieLinkSpeedToGen(buffer); } ffStrbufSubstrBefore(deviceDir, drmDirPathLength); - if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET) { + if (gpu->psMax.gen != FF_GPU_PCIE_SPEED_UNSET) { ffStrbufAppendS(deviceDir, "/max_link_width"); if (ffReadFileBuffer(deviceDir->chars, buffer)) { - int32_t maxLinkWidth = (int32_t) ffStrbufToSInt(buffer, FF_GPU_PCI_INFO_UNSET); - if (maxLinkWidth > 0 && maxLinkWidth < 255) { // kernel returns 255 if the value is unknown - gpu->pcieLanes = (uint16_t) maxLinkWidth; - } + gpu->psMax.lanes = pcieWidthToLanes(buffer); + } + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + } + + ffStrbufAppendS(deviceDir, "/current_link_speed"); + if (ffReadFileBuffer(deviceDir->chars, buffer)) { + gpu->psCurr.gen = pcieLinkSpeedToGen(buffer); + } + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + + if (gpu->psCurr.gen != FF_GPU_PCIE_SPEED_UNSET) { + ffStrbufAppendS(deviceDir, "/current_link_width"); + if (ffReadFileBuffer(deviceDir->chars, buffer)) { + gpu->psCurr.lanes = pcieWidthToLanes(buffer); } ffStrbufSubstrBefore(deviceDir, drmDirPathLength); } diff --git a/src/detection/gpu/gpu_nbsd.c b/src/detection/gpu/gpu_nbsd.c index 065411bd3..10b920da9 100644 --- a/src/detection/gpu/gpu_nbsd.c +++ b/src/detection/gpu/gpu_nbsd.c @@ -97,7 +97,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu); diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 7418801d3..ff9228571 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -16,6 +16,8 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkGeneration) FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkWidth) + FF_LIBRARY_SYMBOL(nvmlDeviceGetCurrPcieLinkGeneration) + FF_LIBRARY_SYMBOL(nvmlDeviceGetCurrPcieLinkWidth) FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand) FF_LIBRARY_SYMBOL(nvmlDeviceGetIndex) FF_LIBRARY_SYMBOL(nvmlDeviceGetName) @@ -163,6 +165,8 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkGeneration) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkWidth) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCurrPcieLinkGeneration) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCurrPcieLinkWidth) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex) @@ -292,17 +296,23 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR } } - if (result.pcieGen) { + if (result.psMax) { unsigned int value; if (nvmlData.ffnvmlDeviceGetMaxPcieLinkGeneration(device, &value) == NVML_SUCCESS) { - *result.pcieGen = (uint16_t) value; + result.psMax->gen = (uint16_t) value; + } + if (nvmlData.ffnvmlDeviceGetMaxPcieLinkWidth(device, &value) == NVML_SUCCESS) { + result.psMax->lanes = (uint16_t) value; } } - if (result.pcieLanes) { + if (result.psCurr) { unsigned int value; - if (nvmlData.ffnvmlDeviceGetMaxPcieLinkWidth(device, &value) == NVML_SUCCESS) { - *result.pcieLanes = (uint16_t) value; + if (nvmlData.ffnvmlDeviceGetCurrPcieLinkGeneration(device, &value) == NVML_SUCCESS) { + result.psCurr->gen = (uint16_t) value; + } + if (nvmlData.ffnvmlDeviceGetCurrPcieLinkWidth(device, &value) == NVML_SUCCESS) { + result.psCurr->lanes = (uint16_t) value; } } diff --git a/src/detection/gpu/gpu_obsd.c b/src/detection/gpu/gpu_obsd.c index b043dd88b..8d0ee9a31 100644 --- a/src/detection/gpu/gpu_obsd.c +++ b/src/detection/gpu/gpu_obsd.c @@ -86,7 +86,7 @@ const char* detectByPci(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpus) { gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu); diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index a7c5509d2..dbf168c57 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -21,7 +21,7 @@ static int walkDevTree(di_node_t node, FF_A_UNUSED di_minor_t minor, FFlist* gpu gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16); gpu->frequency = FF_GPU_FREQUENCY_UNSET; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { int* revId; diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 7945f2b80..18f07d2d5 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -27,6 +27,8 @@ static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds static FFlist deviceIdsCache; static bool initialized; typedef struct { + uint32_t currentLinkSpeed; + uint32_t currentLinkWidth; uint32_t maxLinkSpeed; uint32_t maxLinkWidth; D3DKMT_DEVICE_IDS deviceIds; @@ -105,17 +107,18 @@ static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds FF_DEBUG("Failed to get PCI bus number"); } - pciBufLen = sizeof(entry->maxLinkSpeed); DEVPROPTYPE propType; + + pciBufLen = sizeof(entry->maxLinkSpeed); // Reports PCEe gen despite the PKEY name CONFIGRET ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkSpeed, &propType, (PBYTE) &entry->maxLinkSpeed, &pciBufLen, 0); if (ret == CR_SUCCESS) { - FF_DEBUG("PCIe GEN: %u", entry->maxLinkSpeed); + FF_DEBUG("PCIe max GEN: %u", entry->maxLinkSpeed); } else { - FF_DEBUG("Failed to get PCIe GEN: %s", ffDebugConfigRet(ret)); + FF_DEBUG("Failed to get PCIe max GEN: %s", ffDebugConfigRet(ret)); } - if (entry->maxLinkSpeed != FF_GPU_PCI_INFO_UNSET) { + if (entry->maxLinkSpeed != FF_GPU_PCIE_SPEED_UNSET) { pciBufLen = sizeof(entry->maxLinkWidth); ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkWidth, &propType, (PBYTE) &entry->maxLinkWidth, &pciBufLen, 0); if (ret == CR_SUCCESS) { @@ -124,6 +127,24 @@ static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds FF_DEBUG("Failed to get PCIe max link width: %s", ffDebugConfigRet(ret)); } } + + pciBufLen = sizeof(entry->currentLinkSpeed); + ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_CurrentLinkSpeed, &propType, (PBYTE) &entry->currentLinkSpeed, &pciBufLen, 0); + if (ret == CR_SUCCESS) { + FF_DEBUG("PCIe GEN: %u", entry->currentLinkSpeed); + } else { + FF_DEBUG("Failed to get PCIe GEN: %s", ffDebugConfigRet(ret)); + } + + if (entry->currentLinkSpeed != FF_GPU_PCIE_SPEED_UNSET) { + pciBufLen = sizeof(entry->currentLinkWidth); + ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_CurrentLinkWidth, &propType, (PBYTE) &entry->currentLinkWidth, &pciBufLen, 0); + if (ret == CR_SUCCESS) { + FF_DEBUG("PCIe current link width: %u", entry->currentLinkWidth); + } else { + FF_DEBUG("Failed to get PCIe current link width: %s", ffDebugConfigRet(ret)); + } + } } } @@ -133,8 +154,10 @@ static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds if (outDeviceIds->VendorID != -1u) { *outDeviceIds = entry->deviceIds; } - gpu->pcieGen = (uint16_t) entry->maxLinkSpeed; - gpu->pcieLanes = (uint16_t) entry->maxLinkWidth; + gpu->psMax.gen = (uint16_t) entry->maxLinkSpeed; + gpu->psMax.lanes = (uint16_t) entry->maxLinkWidth; + gpu->psCurr.gen = (uint16_t) entry->currentLinkSpeed; + gpu->psCurr.lanes = (uint16_t) entry->currentLinkWidth; return true; } } @@ -291,7 +314,7 @@ ffGPUDetectWsl2 : adapterType.HybridDiscrete ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_UNKNOWN; - gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET; + gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET; D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_2_0; status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) { @@ -407,8 +430,10 @@ ffGPUDetectWsl2 .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, - .name = &gpu->name, .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .name = &gpu->name, + .psCurr = options->driverSpecific ? &gpu->psCurr : NULL, + .psMax = options->driverSpecific ? &gpu->psMax : NULL, }, dllName); FF_DEBUG("Driver-specific detection completed: %s", error ?: "Success"); diff --git a/src/detection/gpu/igcl.h b/src/detection/gpu/igcl.h index 0e570742e..eb4e92e81 100644 --- a/src/detection/gpu/igcl.h +++ b/src/detection/gpu/igcl.h @@ -248,3 +248,13 @@ typedef struct ctl_pci_properties_t { // https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlpcigetproperties extern ctl_result_t ctlPciGetProperties(ctl_device_adapter_handle_t hDAhandle, ctl_pci_properties_t* pProperties); + +// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctl-pci-state-t +typedef struct _ctl_pci_state_t { + uint32_t Size; + uint8_t Version; + ctl_pci_speed_t speed; +} ctl_pci_state_t; + +// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlpcigetstate +extern ctl_result_t ctlPciGetState(ctl_device_adapter_handle_t hDAhandle, ctl_pci_state_t* pState); diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index 1fb3508eb..fcfe1029b 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -145,7 +145,11 @@ extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType // Retrieves the maximum PCIe link generation possible with this device and system extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkGeneration(nvmlDevice_t device, unsigned int* maxLinkGen); // Retrieves the maximum PCIe link width possible with this device and system -extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkWidth (nvmlDevice_t device, unsigned int* maxLinkWidth); +extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkWidth(nvmlDevice_t device, unsigned int* maxLinkWidth); +// Retrieves the current PCIe link generation +extern nvmlReturn_t nvmlDeviceGetCurrPcieLinkGeneration(nvmlDevice_t device, unsigned int* currLinkGen); +// Retrieves the current PCIe link width +extern nvmlReturn_t nvmlDeviceGetCurrPcieLinkWidth(nvmlDevice_t device, unsigned int* currLinkWidth); // Retrieves the brand of this device extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type); // Retrieves the current utilization rates for the device diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d38b841f0..35fbb3559 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -139,9 +139,10 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu } } - char pcieSpeed[32] = ""; - if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET && gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) { - snprintf(pcieSpeed, sizeof(pcieSpeed), "PCI Gen %d x%d", gpu->pcieGen, gpu->pcieLanes); + char maxSpeed[32] = "", currSpeed[32] = ""; + if (gpu->pcieSpeed != FF_GPU_PCIE_SPEED_UNSET) { + snprintf(maxSpeed, sizeof(maxSpeed), "%d x%d", gpu->psMax.gen, gpu->psMax.lanes); + snprintf(currSpeed, sizeof(currSpeed), "%d x%d", gpu->psCurr.gen, gpu->psCurr.lanes); } FF_PRINT_FORMAT_CHECKED(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { @@ -165,7 +166,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_ARG(coreUsageNum, "core-usage-num"), FF_ARG(coreUsageBar, "core-usage-bar"), FF_ARG(gpu->memoryType, "memory-type"), - FF_ARG(pcieSpeed, "pcie-speed"), + FF_ARG(maxSpeed, "pcie-max-speed"), + FF_ARG(currSpeed, "pcie-curr-speed"), })); } } @@ -427,18 +429,14 @@ bool ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId); - if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET || gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) { + if (gpu->pcieSpeed != FF_GPU_PCIE_SPEED_UNSET) { yyjson_mut_val* pcieSpeed = yyjson_mut_obj_add_obj(doc, obj, "pcieSpeed"); - if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET) { - yyjson_mut_obj_add_uint(doc, pcieSpeed, "gen", gpu->pcieGen); - } else { - yyjson_mut_obj_add_null(doc, pcieSpeed, "gen"); - } - if (gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) { - yyjson_mut_obj_add_uint(doc, pcieSpeed, "lanes", gpu->pcieLanes); - } else { - yyjson_mut_obj_add_null(doc, pcieSpeed, "lanes"); - } + yyjson_mut_val* maxSpeed = yyjson_mut_obj_add_obj(doc, pcieSpeed, "max"); + yyjson_mut_obj_add_uint(doc, maxSpeed, "gen", gpu->psMax.gen); + yyjson_mut_obj_add_uint(doc, maxSpeed, "lanes", gpu->psMax.lanes); + yyjson_mut_val* currSpeed = yyjson_mut_obj_add_obj(doc, pcieSpeed, "current"); + yyjson_mut_obj_add_uint(doc, currSpeed, "gen", gpu->psCurr.gen); + yyjson_mut_obj_add_uint(doc, currSpeed, "lanes", gpu->psCurr.lanes); } else { yyjson_mut_obj_add_null(doc, obj, "pcieSpeed"); } @@ -506,6 +504,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { { "Core usage percentage num", "core-usage-num" }, { "Core usage percentage bar", "core-usage-bar" }, { "Memory type (Windows only)", "memory-type" }, - { "Maximum PCIe speed in gen and lanes", "pcie-speed" }, + { "PCIe maximum speed in gen and lanes", "pcie-max-speed" }, + { "PCIe current speed in gen and lanes", "pcie-curr-speed" }, })), };