File indexing completed on 2024-05-19 05:30:19

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 constexpr quint64 mbToBytes(quint64 mb) {
0014     return mb * 1024 * 1024;
0015 }
0016 
0017 LinuxNvidiaGpu::LinuxNvidiaGpu(const QString &id, const QString &name, udev_device *device)
0018     : GpuDevice(id, name)
0019     , m_device(device)
0020 {
0021     if (!s_smiProcess) {
0022         s_smiProcess = new NvidiaSmiProcess();
0023     }
0024 
0025     connect(s_smiProcess, &NvidiaSmiProcess::dataReceived, this, &LinuxNvidiaGpu::onDataReceived);
0026 }
0027 
0028 LinuxNvidiaGpu::~LinuxNvidiaGpu()
0029 {
0030     for (auto sensor : {m_usageProperty, m_totalVramProperty, m_usedVramProperty, m_temperatureProperty, m_coreFrequencyProperty, m_memoryFrequencyProperty}) {
0031         if (sensor->isSubscribed()) {
0032             LinuxNvidiaGpu::s_smiProcess->unref();
0033         }
0034     }
0035 }
0036 
0037 void LinuxNvidiaGpu::initialize()
0038 {
0039     GpuDevice::initialize();
0040 
0041     for (auto sensor : {m_usageProperty,
0042                         m_totalVramProperty,
0043                         m_usedVramProperty,
0044                         m_temperatureProperty,
0045                         m_coreFrequencyProperty,
0046                         m_memoryFrequencyProperty,
0047                         m_powerProperty}) {
0048         connect(sensor, &KSysGuard::SensorProperty::subscribedChanged, sensor, [sensor]() {
0049             if (sensor->isSubscribed()) {
0050                 LinuxNvidiaGpu::s_smiProcess->ref();
0051             } else {
0052                 LinuxNvidiaGpu::s_smiProcess->unref();
0053             }
0054         });
0055     }
0056 
0057     const auto queryResult = s_smiProcess->query();
0058     const auto sysName = QString::fromLocal8Bit(udev_device_get_sysname(m_device));
0059     auto it = std::find_if(queryResult.cbegin(), queryResult.cend(), [&sysName] (const NvidiaSmiProcess::GpuQueryResult &result) {
0060         return result.pciPath == sysName;
0061     });
0062     if (it == queryResult.cend()) {
0063         qWarning() << "Could not retrieve information for NVidia GPU" << sysName;
0064     } else {
0065         m_index = it - queryResult.cbegin();
0066         m_nameProperty->setValue(it->name);
0067         m_totalVramProperty->setValue(mbToBytes(it->totalMemory));
0068         m_usedVramProperty->setMax(mbToBytes(it->totalMemory));
0069         m_coreFrequencyProperty->setMax(it->maxCoreFrequency);
0070         m_memoryFrequencyProperty->setMax(it->maxMemoryFrequency);
0071         m_temperatureProperty->setMax(it->maxTemperature);
0072         m_powerProperty->setMax(it->maxPower);
0073     }
0074 
0075     m_powerProperty->setUnit(KSysGuard::UnitWatt);
0076 }
0077 
0078 void LinuxNvidiaGpu::onDataReceived(const NvidiaSmiProcess::GpuData &data)
0079 {
0080     if (data.index != m_index) {
0081         return;
0082     }
0083 
0084     m_usageProperty->setValue(data.usage);
0085     m_usedVramProperty->setValue(mbToBytes(data.memoryUsed));
0086     m_coreFrequencyProperty->setValue(data.coreFrequency);
0087     m_memoryFrequencyProperty->setValue(data.memoryFrequency);
0088     m_temperatureProperty->setValue(data.temperature);
0089     m_powerProperty->setValue(data.power);
0090 }
0091 
0092 #include "moc_LinuxNvidiaGpu.cpp"