File indexing completed on 2024-05-12 17:00:15

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "LinuxNvidiaGpu.h"
0008 
0009 #include <libudev.h>
0010 
0011 NvidiaSmiProcess *LinuxNvidiaGpu::s_smiProcess = nullptr;
0012 
0013 LinuxNvidiaGpu::LinuxNvidiaGpu(const QString &id, const QString &name, udev_device *device)
0014     : GpuDevice(id, name)
0015     , m_device(device)
0016 {
0017     if (!s_smiProcess) {
0018         s_smiProcess = new NvidiaSmiProcess();
0019     }
0020 
0021     connect(s_smiProcess, &NvidiaSmiProcess::dataReceived, this, &LinuxNvidiaGpu::onDataReceived);
0022 }
0023 
0024 LinuxNvidiaGpu::~LinuxNvidiaGpu()
0025 {
0026     for (auto sensor : {m_usageProperty, m_totalVramProperty, m_usedVramProperty, m_temperatureProperty, m_coreFrequencyProperty, m_memoryFrequencyProperty}) {
0027         if (sensor->isSubscribed()) {
0028             LinuxNvidiaGpu::s_smiProcess->unref();
0029         }
0030     }
0031 }
0032 
0033 void LinuxNvidiaGpu::initialize()
0034 {
0035     GpuDevice::initialize();
0036 
0037     for (auto sensor : {m_usageProperty,
0038                         m_totalVramProperty,
0039                         m_usedVramProperty,
0040                         m_temperatureProperty,
0041                         m_coreFrequencyProperty,
0042                         m_memoryFrequencyProperty,
0043                         m_powerProperty}) {
0044         connect(sensor, &KSysGuard::SensorProperty::subscribedChanged, sensor, [sensor]() {
0045             if (sensor->isSubscribed()) {
0046                 LinuxNvidiaGpu::s_smiProcess->ref();
0047             } else {
0048                 LinuxNvidiaGpu::s_smiProcess->unref();
0049             }
0050         });
0051     }
0052 
0053     const auto queryResult = s_smiProcess->query();
0054     const auto sysName = QString::fromLocal8Bit(udev_device_get_sysname(m_device));
0055     auto it = std::find_if(queryResult.cbegin(), queryResult.cend(), [&sysName] (const NvidiaSmiProcess::GpuQueryResult &result) {
0056         return result.pciPath == sysName;
0057     });
0058     if (it == queryResult.cend()) {
0059         qWarning() << "Could not retrieve information for NVidia GPU" << sysName;
0060     } else {
0061         m_index = it - queryResult.cbegin();
0062         m_nameProperty->setValue(it->name);
0063         m_totalVramProperty->setValue(it->totalMemory);
0064         m_usedVramProperty->setMax(it->totalMemory);
0065         m_coreFrequencyProperty->setMax(it->maxCoreFrequency);
0066         m_memoryFrequencyProperty->setMax(it->maxMemoryFrequency);
0067         m_temperatureProperty->setMax(it->maxTemperature);
0068         m_powerProperty->setMax(it->maxPower);
0069     }
0070 
0071     m_usedVramProperty->setUnit(KSysGuard::UnitMegaByte);
0072     m_totalVramProperty->setUnit(KSysGuard::UnitMegaByte);
0073     m_powerProperty->setUnit(KSysGuard::UnitWatt);
0074 }
0075 
0076 void LinuxNvidiaGpu::onDataReceived(const NvidiaSmiProcess::GpuData &data)
0077 {
0078     if (data.index != m_index) {
0079         return;
0080     }
0081 
0082     m_usageProperty->setValue(data.usage);
0083     m_usedVramProperty->setValue(data.memoryUsed);
0084     m_coreFrequencyProperty->setValue(data.coreFrequency);
0085     m_memoryFrequencyProperty->setValue(data.memoryFrequency);
0086     m_temperatureProperty->setValue(data.temperature);
0087     m_powerProperty->setValue(data.power);
0088 }