2018-05-12 16:03:00 +00:00
|
|
|
|
/*
|
2009-07-28 21:44:22 +00:00
|
|
|
|
*
|
|
|
|
|
* Conky, a system monitor, based on torsmo
|
2008-06-03 20:46:15 +00:00
|
|
|
|
*
|
|
|
|
|
* Any original torsmo code is licensed under the BSD license
|
|
|
|
|
*
|
|
|
|
|
* All code written since the fork of torsmo is licensed under the GPL
|
|
|
|
|
*
|
|
|
|
|
* Please see COPYING for details
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2008 Markus Meissner
|
2021-02-27 15:14:19 +00:00
|
|
|
|
* Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al.
|
2008-06-03 20:46:15 +00:00
|
|
|
|
* (see AUTHORS)
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
/*
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2015-12-09 17:38:20 +00:00
|
|
|
|
* Author:
|
|
|
|
|
* Fonic <fonic.maxxim@live.com>
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2018-12-23 17:55:14 +00:00
|
|
|
|
* Things to do:
|
2015-12-09 17:38:20 +00:00
|
|
|
|
* - Move decoding of GPU/MEM freqs to print_nvidia_value() using QUERY_SPECIAL
|
|
|
|
|
* so that all quirks are located there
|
|
|
|
|
* - Implement nvs->print_type to allow control over how the value is printed
|
|
|
|
|
* (int, float, temperature...)
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2015-12-09 17:38:20 +00:00
|
|
|
|
* Showcase (conky.conf):
|
|
|
|
|
* --==| NVIDIA | ==--
|
2021-01-24 00:41:22 +00:00
|
|
|
|
* GPU ${nvidia gpufreq [target_id]}MHz (${nvidia gpufreqmin
|
|
|
|
|
* [target_id]}-${nvidia gpufreqmax [target_id]}MHz) MEM ${nvidia memfreq
|
|
|
|
|
* [target_id]}MHz (${nvidia memfreqmin [target_id]}-${nvidia memfreqmax
|
|
|
|
|
* [target_id]}MHz) MTR ${nvidia mtrfreq [target_id]}MHz (${nvidia mtrfreqmin
|
|
|
|
|
* [target_id]}-${nvidia mtrfreqmax [target_id]}MHz) PERF Level ${nvidia
|
|
|
|
|
* perflevel [target_id]} (${nvidia perflevelmin [target_id]}-${nvidia
|
|
|
|
|
* perflevelmax [target_id]}), Mode: ${nvidia perfmode [target_id]} VRAM
|
|
|
|
|
* ${nvidia memutil [target_id]}% (${nvidia memused [target_id]}MB/${nvidia
|
|
|
|
|
* memtotal [target_id]}MB) LOAD GPU ${nvidia gpuutil [target_id]}%, RAM
|
|
|
|
|
* ${nvidia membwutil [target_id]}%, VIDEO ${nvidia videoutil [target_id]}%,
|
|
|
|
|
* PCIe ${nvidia pcieutil [target_id]}% TEMP GPU ${nvidia gputemp
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* [target_id]}°C (${nvidia gputempthreshold [target_id]}°C max.), SYS ${nvidia
|
2021-01-24 00:41:22 +00:00
|
|
|
|
* ambienttemp [target_id]}°C FAN ${nvidia fanspeed [target_id]} RPM
|
|
|
|
|
* (${nvidia fanlevel [target_id]}%)
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2019-09-19 05:50:20 +00:00
|
|
|
|
* Miscellaneous:
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* OPENGL ${nvidia imagequality [target_id]}
|
|
|
|
|
* GPU ${nvidia modelname [target_id]}
|
|
|
|
|
* DRIVER ${nvidia driverversion [target_id]}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2016-05-03 12:03:45 +00:00
|
|
|
|
* --==| NVIDIA Bars |==--
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* LOAD ${nvidiabar [height][,width] gpuutil [target_id]}
|
|
|
|
|
* VRAM ${nvidiabar [height][,width] memutil [target_id]}
|
|
|
|
|
* RAM ${nvidiabar [height][,width] membwutil [target_id]}
|
|
|
|
|
* VIDEO ${nvidiabar [height][,width] videoutil [target_id]}
|
|
|
|
|
* PCIe ${nvidiabar [height][,width] pcieutil [target_id]}
|
|
|
|
|
* Fan ${nvidiabar [height][,width] fanlevel [target_id]}
|
|
|
|
|
* TEMP ${nvidiabar [height][,width] gputemp [target_id]}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2018-01-19 14:04:23 +00:00
|
|
|
|
* --==| NVIDIA Gauge |==--
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* LOAD ${nvidiagauge [height][,width] gpuutil [target_id]}
|
|
|
|
|
* VRAM ${nvidiagauge [height][,width] memutil [target_id]}
|
|
|
|
|
* RAM ${nvidiagauge [height][,width] membwutil [target_id]}
|
|
|
|
|
* VIDEO ${nvidiagauge [height][,width] videoutil [target_id]}
|
|
|
|
|
* PCIe ${nvidiagauge [height][,width] pcieutil [target_id]}
|
|
|
|
|
* Fan ${nvidiagauge [height][,width] fanlevel [target_id]}
|
|
|
|
|
* TEMP ${nvidiagauge [height][,width] gputemp [target_id]}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
*
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* --==| NVIDIA Graph |==-- (target_id is not optional in this case)
|
2018-05-12 16:03:00 +00:00
|
|
|
|
* LOAD ${nvidiagraph gpuutil [height][,width] [gradient color 1] [gradient
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* color 2] [scale] [-t] [-l] target_id} VRAM ${nvidiagraph memutil
|
2018-05-12 16:03:00 +00:00
|
|
|
|
* [height][,width] [gradient color 1] [gradient color 2] [scale] [-t] [-l]
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* target_id} RAM ${nvidiagraph membwutil [height][,width] [gradient color 1]
|
|
|
|
|
* [gradient color 2] [scale] [-t] [-l] target_id} VIDEO ${nvidiagraph videoutil
|
2018-05-12 16:03:00 +00:00
|
|
|
|
* [height][,width] [gradient color 1] [gradient color 2] [scale] [-t] [-l]
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* target_id} PCIe ${nvidiagraph pcieutil [height][,width] [gradient color 1]
|
|
|
|
|
* [gradient color 2] [scale] [-t] [-l] target_id} Fan ${nvidiagraph fanlevel
|
2018-05-12 16:03:00 +00:00
|
|
|
|
* [height][,width] [gradient color 1] [gradient color 2] [scale] [-t] [-l]
|
2020-09-25 19:46:33 +00:00
|
|
|
|
* target_id} TEMP ${nvidiagraph gputemp [height][,width] [gradient color 1]
|
|
|
|
|
* [gradient color 2] [scale] [-t] [-l] target_id}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
#include "nvidia.h"
|
2018-12-09 14:16:46 +00:00
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
#include "NVCtrl/NVCtrl.h"
|
|
|
|
|
#include "NVCtrl/NVCtrlLib.h"
|
2009-10-03 14:14:23 +00:00
|
|
|
|
#include "conky.h"
|
|
|
|
|
#include "logging.h"
|
|
|
|
|
#include "temphelper.h"
|
2009-11-16 21:54:30 +00:00
|
|
|
|
#include "x11.h"
|
2009-02-18 05:10:15 +00:00
|
|
|
|
|
2022-10-14 02:17:14 +00:00
|
|
|
|
#include <memory>
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
// Separators for nvidia string parsing
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// (sample: "perf=0, nvclock=324, nvclockmin=324, nvclockmax=324 ; perf=1,
|
|
|
|
|
// nvclock=549, nvclockmin=549, nvclockmax=549")
|
2015-12-09 17:38:20 +00:00
|
|
|
|
#define NV_KVPAIR_SEPARATORS ", ;"
|
|
|
|
|
#define NV_KEYVAL_SEPARATORS "="
|
|
|
|
|
|
|
|
|
|
// Module arguments
|
2018-05-12 16:03:00 +00:00
|
|
|
|
const char *translate_module_argument[] = {
|
|
|
|
|
"temp", // Temperatures
|
|
|
|
|
"gputemp", "threshold", "gputempthreshold", "ambient", "ambienttemp",
|
|
|
|
|
|
|
|
|
|
"gpufreq", // GPU frequency
|
|
|
|
|
"gpufreqcur", "gpufreqmin", "gpufreqmax",
|
|
|
|
|
|
|
|
|
|
"memfreq", // Memory frequency
|
|
|
|
|
"memfreqcur", "memfreqmin", "memfreqmax",
|
|
|
|
|
|
|
|
|
|
"mtrfreq", // Memory transfer rate frequency
|
|
|
|
|
"mtrfreqcur", "mtrfreqmin", "mtrfreqmax",
|
|
|
|
|
|
|
|
|
|
"perflevel", // Performance levels
|
|
|
|
|
"perflevelcur", "perflevelmin", "perflevelmax", "perfmode",
|
|
|
|
|
|
|
|
|
|
"gpuutil", // Load/utilization
|
|
|
|
|
"membwutil", // NOTE: this is the memory _bandwidth_ utilization, not the
|
|
|
|
|
// percentage of used/available memory!
|
|
|
|
|
"videoutil", "pcieutil",
|
|
|
|
|
|
|
|
|
|
"mem", // RAM statistics
|
|
|
|
|
"memused", "memfree", "memavail", "memmax", "memtotal", "memutil",
|
|
|
|
|
"memperc",
|
|
|
|
|
|
|
|
|
|
"fanspeed", // Fan/cooler
|
|
|
|
|
"fanlevel",
|
|
|
|
|
|
|
|
|
|
"imagequality", // Miscellaneous
|
2019-09-19 05:50:20 +00:00
|
|
|
|
"modelname", "driverversion"};
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
|
|
|
|
// Enum for module arguments
|
|
|
|
|
typedef enum _ARG_ID {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
ARG_TEMP,
|
|
|
|
|
ARG_GPU_TEMP,
|
|
|
|
|
ARG_THRESHOLD,
|
|
|
|
|
ARG_GPU_TEMP_THRESHOLD,
|
|
|
|
|
ARG_AMBIENT,
|
|
|
|
|
ARG_AMBIENT_TEMP,
|
|
|
|
|
|
|
|
|
|
ARG_GPU_FREQ,
|
|
|
|
|
ARG_GPU_FREQ_CUR,
|
|
|
|
|
ARG_GPU_FREQ_MIN,
|
|
|
|
|
ARG_GPU_FREQ_MAX,
|
|
|
|
|
|
|
|
|
|
ARG_MEM_FREQ,
|
|
|
|
|
ARG_MEM_FREQ_CUR,
|
|
|
|
|
ARG_MEM_FREQ_MIN,
|
|
|
|
|
ARG_MEM_FREQ_MAX,
|
|
|
|
|
|
|
|
|
|
ARG_MTR_FREQ,
|
|
|
|
|
ARG_MTR_FREQ_CUR,
|
|
|
|
|
ARG_MTR_FREQ_MIN,
|
|
|
|
|
ARG_MTR_FREQ_MAX,
|
|
|
|
|
|
|
|
|
|
ARG_PERF_LEVEL,
|
|
|
|
|
ARG_PERF_LEVEL_CUR,
|
|
|
|
|
ARG_PERF_LEVEL_MIN,
|
|
|
|
|
ARG_PERF_LEVEL_MAX,
|
|
|
|
|
ARG_PERF_MODE,
|
|
|
|
|
|
|
|
|
|
ARG_GPU_UTIL,
|
|
|
|
|
ARG_MEM_BW_UTIL,
|
|
|
|
|
ARG_VIDEO_UTIL,
|
|
|
|
|
ARG_PCIE_UTIL,
|
|
|
|
|
|
|
|
|
|
ARG_MEM,
|
|
|
|
|
ARG_MEM_USED,
|
|
|
|
|
ARG_MEM_FREE,
|
|
|
|
|
ARG_MEM_AVAIL,
|
|
|
|
|
ARG_MEM_MAX,
|
|
|
|
|
ARG_MEM_TOTAL,
|
|
|
|
|
ARG_MEM_UTIL,
|
|
|
|
|
ARG_MEM_PERC,
|
|
|
|
|
|
|
|
|
|
ARG_FAN_SPEED,
|
|
|
|
|
ARG_FAN_LEVEL,
|
|
|
|
|
|
|
|
|
|
ARG_IMAGEQUALITY,
|
|
|
|
|
ARG_MODEL_NAME,
|
2019-09-19 05:50:20 +00:00
|
|
|
|
ARG_DRIVER_VERSION,
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
ARG_UNKNOWN
|
2015-12-09 17:38:20 +00:00
|
|
|
|
} ARG_ID;
|
|
|
|
|
|
|
|
|
|
// Nvidia query targets
|
|
|
|
|
const int translate_nvidia_target[] = {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
NV_CTRL_TARGET_TYPE_X_SCREEN,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_GPU,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_FRAMELOCK,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_VCSC,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_GVI,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_COOLER,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_THERMAL_SENSOR,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER,
|
|
|
|
|
NV_CTRL_TARGET_TYPE_DISPLAY,
|
2015-12-09 17:38:20 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Enum for nvidia query targets
|
|
|
|
|
typedef enum _TARGET_ID {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
TARGET_SCREEN,
|
|
|
|
|
TARGET_GPU,
|
|
|
|
|
TARGET_FRAMELOCK,
|
|
|
|
|
TARGET_VCSC,
|
|
|
|
|
TARGET_GVI,
|
|
|
|
|
TARGET_COOLER,
|
|
|
|
|
TARGET_THERMAL,
|
|
|
|
|
TARGET_3DVISION,
|
|
|
|
|
TARGET_DISPLAY
|
2015-12-09 17:38:20 +00:00
|
|
|
|
} TARGET_ID;
|
|
|
|
|
|
|
|
|
|
// Nvidia query attributes
|
|
|
|
|
const int translate_nvidia_attribute[] = {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
NV_CTRL_GPU_CORE_TEMPERATURE,
|
|
|
|
|
NV_CTRL_GPU_CORE_THRESHOLD,
|
|
|
|
|
NV_CTRL_AMBIENT_TEMPERATURE,
|
|
|
|
|
|
|
|
|
|
NV_CTRL_GPU_CURRENT_CLOCK_FREQS,
|
|
|
|
|
NV_CTRL_GPU_CURRENT_CLOCK_FREQS,
|
|
|
|
|
NV_CTRL_STRING_PERFORMANCE_MODES,
|
|
|
|
|
NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS,
|
|
|
|
|
NV_CTRL_GPU_POWER_MIZER_MODE,
|
|
|
|
|
|
|
|
|
|
NV_CTRL_STRING_GPU_UTILIZATION,
|
|
|
|
|
|
|
|
|
|
NV_CTRL_USED_DEDICATED_GPU_MEMORY,
|
|
|
|
|
0,
|
|
|
|
|
NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY, // NOTE: NV_CTRL_TOTAL_GPU_MEMORY would
|
|
|
|
|
// be better, but returns KB instead of
|
|
|
|
|
// MB
|
|
|
|
|
0,
|
|
|
|
|
|
|
|
|
|
NV_CTRL_THERMAL_COOLER_SPEED,
|
|
|
|
|
NV_CTRL_THERMAL_COOLER_LEVEL,
|
|
|
|
|
|
|
|
|
|
NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL,
|
|
|
|
|
NV_CTRL_IMAGE_SETTINGS,
|
2019-09-19 05:50:20 +00:00
|
|
|
|
|
|
|
|
|
NV_CTRL_STRING_PRODUCT_NAME,
|
|
|
|
|
NV_CTRL_STRING_NVIDIA_DRIVER_VERSION,
|
2015-12-09 17:38:20 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Enum for nvidia query attributes
|
|
|
|
|
typedef enum _ATTR_ID {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
ATTR_GPU_TEMP,
|
|
|
|
|
ATTR_GPU_TEMP_THRESHOLD,
|
|
|
|
|
ATTR_AMBIENT_TEMP,
|
2018-01-19 14:04:23 +00:00
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
ATTR_GPU_FREQ,
|
|
|
|
|
ATTR_MEM_FREQ,
|
|
|
|
|
ATTR_PERFMODES_STRING,
|
|
|
|
|
ATTR_FREQS_STRING,
|
|
|
|
|
ATTR_PERF_MODE,
|
|
|
|
|
|
|
|
|
|
ATTR_UTILS_STRING,
|
|
|
|
|
|
|
|
|
|
ATTR_MEM_USED,
|
|
|
|
|
ATTR_MEM_FREE,
|
|
|
|
|
ATTR_MEM_TOTAL,
|
|
|
|
|
ATTR_MEM_UTIL,
|
|
|
|
|
|
|
|
|
|
ATTR_FAN_SPEED,
|
|
|
|
|
ATTR_FAN_LEVEL,
|
|
|
|
|
|
|
|
|
|
ATTR_PERF_LEVEL,
|
|
|
|
|
ATTR_IMAGE_QUALITY,
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
ATTR_MODEL_NAME,
|
2019-09-19 05:50:20 +00:00
|
|
|
|
ATTR_DRIVER_VERSION,
|
2018-05-12 16:03:00 +00:00
|
|
|
|
} ATTR_ID;
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
|
|
|
|
// Enum for query type
|
2009-10-03 14:14:23 +00:00
|
|
|
|
typedef enum _QUERY_ID {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
QUERY_VALUE,
|
|
|
|
|
QUERY_STRING,
|
|
|
|
|
QUERY_STRING_VALUE,
|
|
|
|
|
QUERY_SPECIAL
|
2009-10-03 14:14:23 +00:00
|
|
|
|
} QUERY_ID;
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
// Enum for string token search mode
|
|
|
|
|
typedef enum _SEARCH_ID {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
SEARCH_FIRST,
|
|
|
|
|
SEARCH_LAST,
|
|
|
|
|
SEARCH_MIN,
|
|
|
|
|
SEARCH_MAX
|
2015-12-09 17:38:20 +00:00
|
|
|
|
} SEARCH_ID;
|
|
|
|
|
|
2016-06-24 18:05:17 +00:00
|
|
|
|
// Translate special_type into command string
|
2018-05-12 16:03:00 +00:00
|
|
|
|
const char *translate_nvidia_special_type[] = {
|
|
|
|
|
"nvidia", // NONSPECIAL
|
|
|
|
|
"", // HORIZONTAL_LINE
|
|
|
|
|
"", // STIPPLED_HR
|
|
|
|
|
"nvidiabar", // BAR
|
|
|
|
|
"", // FG
|
|
|
|
|
"", // BG
|
|
|
|
|
"", // OUTLINE
|
|
|
|
|
"", // ALIGNR
|
|
|
|
|
"", // ALIGNC
|
|
|
|
|
"nvidiagague", // GAUGE
|
|
|
|
|
"nvidiagraph", // GRAPH
|
|
|
|
|
"", // OFFSET
|
|
|
|
|
"", // VOFFSET
|
2021-01-29 23:25:58 +00:00
|
|
|
|
"", // SAVE_COORDINATES
|
2018-05-12 16:03:00 +00:00
|
|
|
|
"", // FONT
|
|
|
|
|
"", // GOTO
|
|
|
|
|
"" // TAB
|
2016-06-24 18:05:17 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
// Global struct to keep track of queries
|
2018-12-23 17:55:14 +00:00
|
|
|
|
class nvidia_s {
|
|
|
|
|
public:
|
|
|
|
|
nvidia_s()
|
|
|
|
|
: command(0),
|
|
|
|
|
arg(0),
|
|
|
|
|
query(QUERY_VALUE),
|
|
|
|
|
target(TARGET_SCREEN),
|
|
|
|
|
attribute(ATTR_GPU_TEMP),
|
|
|
|
|
token(0),
|
|
|
|
|
search(SEARCH_FIRST),
|
2022-01-10 09:04:07 +00:00
|
|
|
|
target_id(0),
|
|
|
|
|
is_percentage(false) {}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
const char *command;
|
|
|
|
|
const char *arg;
|
|
|
|
|
QUERY_ID query;
|
|
|
|
|
TARGET_ID target;
|
|
|
|
|
ATTR_ID attribute;
|
|
|
|
|
char *token;
|
|
|
|
|
SEARCH_ID search;
|
|
|
|
|
// added new field for GPU id
|
2020-09-25 19:46:33 +00:00
|
|
|
|
int target_id;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
bool is_percentage;
|
2018-01-19 14:04:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Cache by value
|
2018-01-19 14:04:23 +00:00
|
|
|
|
struct nvidia_c_value {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
int memtotal = -1;
|
|
|
|
|
int gputempthreshold = -1;
|
2018-01-19 14:04:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Cache by string
|
2018-01-19 14:04:23 +00:00
|
|
|
|
struct nvidia_c_string {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
int nvclockmin = -1;
|
|
|
|
|
int nvclockmax = -1;
|
|
|
|
|
int memclockmin = -1;
|
|
|
|
|
int memclockmax = -1;
|
|
|
|
|
int memTransferRatemin = -1;
|
|
|
|
|
int memTransferRatemax = -1;
|
|
|
|
|
int perfmin = -1;
|
|
|
|
|
int perfmax = -1;
|
2009-10-03 14:14:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
2018-01-19 14:04:23 +00:00
|
|
|
|
// Maximum number of GPU connected:
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// For cache default value: choosed a model of direct access to array instead of
|
|
|
|
|
// list for speed improvement value based on the incoming quad Naples tech
|
|
|
|
|
// having 256 PCIe lanes available
|
|
|
|
|
const int MAXNUMGPU = 64;
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
2010-08-21 12:13:07 +00:00
|
|
|
|
namespace {
|
2022-10-14 02:17:14 +00:00
|
|
|
|
|
|
|
|
|
// Deleter for nv display to use with std::unique_ptr
|
2022-12-24 14:44:03 +00:00
|
|
|
|
void close_nvdisplay(Display *dp) { XCloseDisplay(dp); }
|
2022-10-14 02:17:14 +00:00
|
|
|
|
|
|
|
|
|
using unique_display_t = std::unique_ptr<Display, decltype(&close_nvdisplay)>;
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
class nvidia_display_setting
|
|
|
|
|
: public conky::simple_config_setting<std::string> {
|
|
|
|
|
typedef conky::simple_config_setting<std::string> Base;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual void lua_setter(lua::state &l, bool init);
|
|
|
|
|
virtual void cleanup(lua::state &l);
|
|
|
|
|
|
2022-01-30 12:43:43 +00:00
|
|
|
|
std::string nvdisplay;
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
public:
|
|
|
|
|
nvidia_display_setting() : Base("nvidia_display", std::string(), false) {}
|
2022-10-14 02:17:14 +00:00
|
|
|
|
virtual unique_display_t get_nvdisplay();
|
2018-05-12 16:03:00 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void nvidia_display_setting::lua_setter(lua::state &l, bool init) {
|
|
|
|
|
lua::stack_sentry s(l, -2);
|
|
|
|
|
|
|
|
|
|
Base::lua_setter(l, init);
|
|
|
|
|
|
2022-01-30 12:43:43 +00:00
|
|
|
|
nvdisplay = do_convert(l, -1).first;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
++s;
|
2018-12-23 17:55:14 +00:00
|
|
|
|
} // namespace
|
2010-08-21 12:13:07 +00:00
|
|
|
|
|
2022-10-14 02:17:14 +00:00
|
|
|
|
unique_display_t nvidia_display_setting::get_nvdisplay() {
|
2022-01-30 12:43:43 +00:00
|
|
|
|
if (!nvdisplay.empty()) {
|
2022-10-14 02:17:14 +00:00
|
|
|
|
unique_display_t nvd(XOpenDisplay(nvdisplay.c_str()), &close_nvdisplay);
|
|
|
|
|
if (!nvd) {
|
2022-01-30 12:43:43 +00:00
|
|
|
|
NORM_ERR(nullptr, NULL, "can't open nvidia display: %s",
|
|
|
|
|
XDisplayName(nvdisplay.c_str()));
|
|
|
|
|
}
|
|
|
|
|
return nvd;
|
|
|
|
|
}
|
2022-10-14 02:17:14 +00:00
|
|
|
|
return unique_display_t(nullptr, &close_nvdisplay);
|
2022-01-30 12:43:43 +00:00
|
|
|
|
} // namespace
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
void nvidia_display_setting::cleanup(lua::state &l) {
|
|
|
|
|
lua::stack_sentry s(l, -1);
|
|
|
|
|
|
|
|
|
|
l.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvidia_display_setting nvidia_display;
|
|
|
|
|
} // namespace
|
2016-05-03 12:03:45 +00:00
|
|
|
|
|
2016-06-24 18:05:17 +00:00
|
|
|
|
// Evaluate module parameters and prepare query
|
2018-05-12 16:03:00 +00:00
|
|
|
|
int set_nvidia_query(struct text_object *obj, const char *arg,
|
|
|
|
|
unsigned int special_type) {
|
2018-12-23 17:55:14 +00:00
|
|
|
|
nvidia_s *nvs;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
int aid;
|
|
|
|
|
int ilen;
|
|
|
|
|
|
|
|
|
|
// Initialize global struct
|
2018-12-23 17:55:14 +00:00
|
|
|
|
nvs = new nvidia_s();
|
|
|
|
|
obj->data.opaque = nvs;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Added new parameter parsing GPU_ID as 0,1,2,..
|
|
|
|
|
// if no GPU_ID parameter then default to 0
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id = 0;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
char *strbuf = strdup(arg);
|
|
|
|
|
char *p = strrchr(strbuf, ' ');
|
|
|
|
|
if (p && *(p + 1)) {
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id = atoi(p + 1);
|
|
|
|
|
if ((nvs->target_id > 0) || !strcmp(p + 1, "0")) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
ilen = strlen(strbuf);
|
|
|
|
|
ilen = ilen - strlen(p);
|
|
|
|
|
strbuf[ilen] = 0;
|
|
|
|
|
arg = strbuf;
|
2018-01-19 14:04:23 +00:00
|
|
|
|
}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the value is negative it is set to 0
|
2020-09-25 19:46:33 +00:00
|
|
|
|
if (nvs->target_id < 0) nvs->target_id = 0;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Extract arguments for nvidiabar, etc, and run set_nvidia_query
|
|
|
|
|
switch (special_type) {
|
|
|
|
|
case BAR:
|
|
|
|
|
arg = scan_bar(obj, arg, 100);
|
|
|
|
|
break;
|
2023-03-06 00:25:56 +00:00
|
|
|
|
case GRAPH: {
|
|
|
|
|
auto [buf, skip] = scan_command(arg);
|
|
|
|
|
scan_graph(obj, arg + skip, 100);
|
|
|
|
|
arg = buf;
|
|
|
|
|
} break;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
case GAUGE:
|
|
|
|
|
arg = scan_gauge(obj, arg, 100);
|
|
|
|
|
break;
|
2018-12-23 17:55:14 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return error if no argument
|
|
|
|
|
// (sometimes scan_graph gets excited and eats the whole string!
|
2018-12-23 17:55:14 +00:00
|
|
|
|
if (!arg) {
|
|
|
|
|
free_and_zero(strbuf);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Translate parameter to id
|
|
|
|
|
for (aid = 0; aid < ARG_UNKNOWN; aid++) {
|
|
|
|
|
if (strcmp(arg, translate_module_argument[aid]) == 0) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// free the string buffer after arg is not anymore needed
|
2018-12-23 17:55:14 +00:00
|
|
|
|
if (strbuf != nullptr) free_and_zero(strbuf);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Save pointers to the arg and command strings for debugging and printing
|
|
|
|
|
nvs->arg = translate_module_argument[aid];
|
|
|
|
|
nvs->command = translate_nvidia_special_type[special_type];
|
|
|
|
|
|
|
|
|
|
// Evaluate parameter
|
|
|
|
|
switch (aid) {
|
|
|
|
|
case ARG_TEMP: // GPU temperature
|
|
|
|
|
case ARG_GPU_TEMP:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_GPU_TEMP;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_THRESHOLD: // GPU temperature threshold
|
|
|
|
|
case ARG_GPU_TEMP_THRESHOLD:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_GPU_TEMP_THRESHOLD;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_AMBIENT: // Ambient temperature
|
|
|
|
|
case ARG_AMBIENT_TEMP:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_AMBIENT_TEMP;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_GPU_FREQ: // Current GPU clock
|
|
|
|
|
case ARG_GPU_FREQ_CUR:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_GPU_FREQ;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_GPU_FREQ_MIN: // Minimum GPU clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"nvclockmin";
|
|
|
|
|
nvs->search = SEARCH_MIN;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_GPU_FREQ_MAX: // Maximum GPU clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"nvclockmax";
|
|
|
|
|
nvs->search = SEARCH_MAX;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_MEM_FREQ: // Current memory clock
|
|
|
|
|
case ARG_MEM_FREQ_CUR:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MEM_FREQ;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_FREQ_MIN: // Minimum memory clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"memclockmin";
|
|
|
|
|
nvs->search = SEARCH_MIN;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_FREQ_MAX: // Maximum memory clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"memclockmax";
|
|
|
|
|
nvs->search = SEARCH_MAX;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_MTR_FREQ: // Current memory transfer rate clock
|
|
|
|
|
case ARG_MTR_FREQ_CUR:
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_FREQS_STRING;
|
|
|
|
|
nvs->token = (char *)"memTransferRate";
|
|
|
|
|
nvs->search = SEARCH_FIRST;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MTR_FREQ_MIN: // Minimum memory transfer rate clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"memTransferRatemin";
|
|
|
|
|
nvs->search = SEARCH_MIN;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MTR_FREQ_MAX: // Maximum memory transfer rate clock
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"memTransferRatemax";
|
|
|
|
|
nvs->search = SEARCH_MAX;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_PERF_LEVEL: // Current performance level
|
|
|
|
|
case ARG_PERF_LEVEL_CUR:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERF_LEVEL;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_PERF_LEVEL_MIN: // Lowest performance level
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"perf";
|
|
|
|
|
nvs->search = SEARCH_MIN;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_PERF_LEVEL_MAX: // Highest performance level
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERFMODES_STRING;
|
|
|
|
|
nvs->token = (char *)"perf";
|
|
|
|
|
nvs->search = SEARCH_MAX;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_PERF_MODE: // Performance mode
|
|
|
|
|
nvs->query = QUERY_SPECIAL;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_PERF_MODE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_GPU_UTIL: // GPU utilization %
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_UTILS_STRING;
|
|
|
|
|
nvs->token = (char *)"graphics";
|
|
|
|
|
nvs->search = SEARCH_FIRST;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_BW_UTIL: // Memory bandwidth utilization %
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_UTILS_STRING;
|
|
|
|
|
nvs->token = (char *)"memory";
|
|
|
|
|
nvs->search = SEARCH_FIRST;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ARG_VIDEO_UTIL: // Video engine utilization %
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_UTILS_STRING;
|
|
|
|
|
nvs->token = (char *)"video";
|
|
|
|
|
nvs->search = SEARCH_FIRST;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ARG_PCIE_UTIL: // PCIe bandwidth utilization %
|
|
|
|
|
nvs->query = QUERY_STRING_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_UTILS_STRING;
|
|
|
|
|
nvs->token = (char *)"PCIe";
|
|
|
|
|
nvs->search = SEARCH_FIRST;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_MEM: // Amount of used memory
|
|
|
|
|
case ARG_MEM_USED:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MEM_USED;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_FREE: // Amount of free memory
|
|
|
|
|
case ARG_MEM_AVAIL:
|
|
|
|
|
nvs->query = QUERY_SPECIAL;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MEM_FREE;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_MAX: // Total amount of memory
|
|
|
|
|
case ARG_MEM_TOTAL:
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MEM_TOTAL;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_MEM_UTIL: // Memory utilization %
|
|
|
|
|
case ARG_MEM_PERC:
|
|
|
|
|
nvs->query = QUERY_SPECIAL;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MEM_UTIL;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_FAN_SPEED: // Fan speed
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_COOLER;
|
|
|
|
|
nvs->attribute = ATTR_FAN_SPEED;
|
|
|
|
|
break;
|
|
|
|
|
case ARG_FAN_LEVEL: // Fan level %
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_COOLER;
|
|
|
|
|
nvs->attribute = ATTR_FAN_LEVEL;
|
2022-01-10 09:04:07 +00:00
|
|
|
|
nvs->is_percentage = true;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_IMAGEQUALITY: // Image quality
|
|
|
|
|
nvs->query = QUERY_VALUE;
|
|
|
|
|
nvs->target = TARGET_SCREEN;
|
|
|
|
|
nvs->attribute = ATTR_IMAGE_QUALITY;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARG_MODEL_NAME:
|
|
|
|
|
nvs->query = QUERY_STRING;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_MODEL_NAME;
|
|
|
|
|
break;
|
|
|
|
|
|
2019-09-19 05:50:20 +00:00
|
|
|
|
case ARG_DRIVER_VERSION:
|
|
|
|
|
nvs->query = QUERY_STRING;
|
|
|
|
|
nvs->target = TARGET_GPU;
|
|
|
|
|
nvs->attribute = ATTR_DRIVER_VERSION;
|
|
|
|
|
break;
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
default: // Unknown/invalid argument
|
|
|
|
|
// Error printed by core.cc
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2008-08-03 13:27:00 +00:00
|
|
|
|
}
|
2009-10-03 14:14:23 +00:00
|
|
|
|
|
2018-01-19 14:04:23 +00:00
|
|
|
|
// Return the amount of targets present or raise error)
|
2018-05-12 16:03:00 +00:00
|
|
|
|
static inline int get_nvidia_target_count(Display *dpy, TARGET_ID tid) {
|
|
|
|
|
int num_tgts;
|
|
|
|
|
if (!XNVCTRLQueryTargetCount(dpy, translate_nvidia_target[tid], &num_tgts)) {
|
|
|
|
|
num_tgts = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-10 01:14:08 +00:00
|
|
|
|
if (num_tgts < 1 && tid == TARGET_GPU) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Print error and exit if there's no NVIDIA's GPU
|
2018-12-10 01:14:08 +00:00
|
|
|
|
NORM_ERR(nullptr, NULL,
|
2018-05-12 16:03:00 +00:00
|
|
|
|
"%s:"
|
|
|
|
|
"\n Trying to query Nvidia target failed (using the "
|
2020-12-31 08:09:23 +00:00
|
|
|
|
"proprietary drivers)."
|
2018-05-12 16:03:00 +00:00
|
|
|
|
"\n Are you sure they are installed correctly and a "
|
|
|
|
|
"Nvidia GPU is in use?"
|
|
|
|
|
"\n (display: %d,Nvidia target_count: %d)",
|
|
|
|
|
__func__, dpy, num_tgts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return num_tgts;
|
2016-06-24 18:05:17 +00:00
|
|
|
|
}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
static int cache_nvidia_value(TARGET_ID tid, ATTR_ID aid, Display *dpy,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
int *value, int gid, const char *arg) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
static nvidia_c_value ac_value[MAXNUMGPU];
|
|
|
|
|
|
|
|
|
|
if (aid == ATTR_MEM_TOTAL) {
|
|
|
|
|
if (ac_value[gid].memtotal < 0) {
|
|
|
|
|
if (!dpy || !XNVCTRLQueryTargetAttribute(
|
|
|
|
|
dpy, translate_nvidia_target[tid], gid, 0,
|
|
|
|
|
translate_nvidia_attribute[aid], value)) {
|
|
|
|
|
NORM_ERR(
|
2018-12-10 01:14:08 +00:00
|
|
|
|
"%s: Something went wrong running nvidia query (arg: %s tid: %d, "
|
|
|
|
|
"aid: %d)",
|
|
|
|
|
__func__, arg, tid, aid);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ac_value[gid].memtotal = *value;
|
|
|
|
|
} else {
|
|
|
|
|
*value = ac_value[gid].memtotal;
|
|
|
|
|
}
|
|
|
|
|
} else if (aid == ATTR_GPU_TEMP_THRESHOLD) {
|
|
|
|
|
if (ac_value[gid].gputempthreshold < 0) {
|
|
|
|
|
if (!dpy || !XNVCTRLQueryTargetAttribute(
|
|
|
|
|
dpy, translate_nvidia_target[tid], gid, 0,
|
|
|
|
|
translate_nvidia_attribute[aid], value)) {
|
|
|
|
|
NORM_ERR(
|
2018-12-10 01:14:08 +00:00
|
|
|
|
"%s: Something went wrong running nvidia query (arg: %s, tid: "
|
|
|
|
|
"%d, aid: %d)",
|
|
|
|
|
__func__, arg, tid, aid);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ac_value[gid].gputempthreshold = *value;
|
|
|
|
|
} else {
|
|
|
|
|
*value = ac_value[gid].gputempthreshold;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2016-12-04 15:13:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
// Retrieve attribute value via nvidia interface
|
2018-12-10 01:14:08 +00:00
|
|
|
|
static int get_nvidia_value(TARGET_ID tid, ATTR_ID aid, int gid,
|
|
|
|
|
const char *arg) {
|
2022-10-14 02:17:14 +00:00
|
|
|
|
auto nvdpy = nvidia_display.get_nvdisplay();
|
2022-12-24 14:44:03 +00:00
|
|
|
|
Display *dpy = nvdpy ? nvdpy.get() : display;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
int value;
|
|
|
|
|
|
|
|
|
|
// Check if the aid is cacheable
|
|
|
|
|
if (aid == ATTR_MEM_TOTAL || aid == ATTR_GPU_TEMP_THRESHOLD) {
|
2018-12-10 01:14:08 +00:00
|
|
|
|
if (cache_nvidia_value(tid, aid, dpy, &value, gid, arg)) { return -1; }
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// If not, then query it
|
|
|
|
|
} else {
|
|
|
|
|
if (!dpy ||
|
|
|
|
|
!XNVCTRLQueryTargetAttribute(dpy, translate_nvidia_target[tid], gid, 0,
|
|
|
|
|
translate_nvidia_attribute[aid], &value)) {
|
|
|
|
|
NORM_ERR(
|
2018-12-10 01:14:08 +00:00
|
|
|
|
"%s: Something went wrong running nvidia query (arg: %s, tid: %d, "
|
|
|
|
|
"aid: %d)",
|
|
|
|
|
__func__, arg, tid, aid);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Unpack clock values (see NVCtrl.h for details)
|
|
|
|
|
if (aid == ATTR_GPU_FREQ) return value >> 16;
|
|
|
|
|
if (aid == ATTR_MEM_FREQ) return value & 0xFFFF;
|
|
|
|
|
|
|
|
|
|
// Return value
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
|
|
|
|
// Retrieve attribute string via nvidia interface
|
2018-12-10 01:14:08 +00:00
|
|
|
|
static char *get_nvidia_string(TARGET_ID tid, ATTR_ID aid, int gid,
|
|
|
|
|
const char *arg) {
|
2022-10-14 02:17:14 +00:00
|
|
|
|
auto nvdpy = nvidia_display.get_nvdisplay();
|
2022-12-24 14:44:03 +00:00
|
|
|
|
Display *dpy = nvdpy ? nvdpy.get() : display;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
// Query nvidia interface
|
|
|
|
|
if (!dpy || !XNVCTRLQueryTargetStringAttribute(
|
|
|
|
|
dpy, translate_nvidia_target[tid], gid, 0,
|
|
|
|
|
translate_nvidia_attribute[aid], &str)) {
|
|
|
|
|
NORM_ERR(
|
2018-12-10 01:14:08 +00:00
|
|
|
|
"%s: Something went wrong running nvidia string query (arg, tid: %d, "
|
|
|
|
|
"aid: "
|
2018-05-12 16:03:00 +00:00
|
|
|
|
"%d, GPU %d)",
|
2018-12-10 01:14:08 +00:00
|
|
|
|
__func__, arg, tid, aid, gid);
|
2018-05-12 23:26:31 +00:00
|
|
|
|
return nullptr;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
return str;
|
2015-12-09 17:38:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-23 18:35:04 +00:00
|
|
|
|
void cache_nvidia_string_value_update(nvidia_c_string *ac_string, char *token,
|
|
|
|
|
SEARCH_ID search, int *value, int gid) {
|
|
|
|
|
if (strcmp(token, (char *)"nvclockmin") == 0 &&
|
|
|
|
|
ac_string[gid].nvclockmin < 0) {
|
|
|
|
|
ac_string[gid].nvclockmin = *value;
|
|
|
|
|
} else if (strcmp(token, (char *)"nvclockmax") == 0 &&
|
|
|
|
|
ac_string[gid].nvclockmax < 0) {
|
|
|
|
|
ac_string[gid].nvclockmax = *value;
|
|
|
|
|
} else if (strcmp(token, (char *)"memclockmin") == 0 &&
|
|
|
|
|
ac_string[gid].memclockmin < 0) {
|
|
|
|
|
ac_string[gid].memclockmin = *value;
|
|
|
|
|
} else if (strcmp(token, (char *)"memclockmax") == 0 &&
|
|
|
|
|
ac_string[gid].memclockmax < 0) {
|
|
|
|
|
ac_string[gid].memclockmax = *value;
|
|
|
|
|
} else if (strcmp(token, (char *)"memTransferRatemin") == 0 &&
|
|
|
|
|
ac_string[gid].memTransferRatemin < 0) {
|
|
|
|
|
ac_string[gid].memTransferRatemin = *value;
|
|
|
|
|
} else if (strcmp(token, (char *)"memTransferRatemax") == 0 &&
|
|
|
|
|
ac_string[gid].memTransferRatemax < 0) {
|
|
|
|
|
ac_string[gid].memTransferRatemax = *value;
|
|
|
|
|
|
|
|
|
|
} else if (strcmp(token, (char *)"perf") == 0 &&
|
|
|
|
|
ac_string[gid].memTransferRatemax < 0) {
|
|
|
|
|
if (search == SEARCH_MIN) {
|
|
|
|
|
ac_string[gid].perfmin = *value;
|
|
|
|
|
} else if (search == SEARCH_MAX) {
|
|
|
|
|
ac_string[gid].perfmax = *value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void cache_nvidia_string_value_noupdate(nvidia_c_string *ac_string, char *token,
|
|
|
|
|
SEARCH_ID search, int *value, int gid) {
|
|
|
|
|
if (strcmp(token, (char *)"nvclockmin") == 0) {
|
|
|
|
|
*value = ac_string[gid].nvclockmin;
|
|
|
|
|
} else if (strcmp(token, (char *)"nvclockmax") == 0) {
|
|
|
|
|
*value = ac_string[gid].nvclockmax;
|
|
|
|
|
} else if (strcmp(token, (char *)"memclockmin") == 0) {
|
|
|
|
|
*value = ac_string[gid].memclockmin;
|
|
|
|
|
} else if (strcmp(token, (char *)"memclockmax") == 0) {
|
|
|
|
|
*value = ac_string[gid].memclockmax;
|
|
|
|
|
} else if (strcmp(token, (char *)"memTransferRatemin") == 0) {
|
|
|
|
|
*value = ac_string[gid].memTransferRatemin;
|
|
|
|
|
} else if (strcmp(token, (char *)"memTransferRatemax") == 0) {
|
|
|
|
|
*value = ac_string[gid].memTransferRatemax;
|
|
|
|
|
|
|
|
|
|
} else if (strcmp(token, (char *)"perf") == 0) {
|
|
|
|
|
if (search == SEARCH_MIN) {
|
|
|
|
|
*value = ac_string[gid].perfmin;
|
|
|
|
|
} else if (search == SEARCH_MAX) {
|
|
|
|
|
*value = ac_string[gid].perfmax;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
static int cache_nvidia_string_value(TARGET_ID tid, ATTR_ID aid, char *token,
|
|
|
|
|
SEARCH_ID search, int *value, int update,
|
|
|
|
|
int gid) {
|
|
|
|
|
static nvidia_c_string ac_string[MAXNUMGPU];
|
2018-12-23 16:37:19 +00:00
|
|
|
|
(void)tid;
|
|
|
|
|
(void)aid;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
if (update) {
|
2018-12-23 18:35:04 +00:00
|
|
|
|
cache_nvidia_string_value_update(ac_string, token, search, value, gid);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
} else {
|
2018-12-23 18:35:04 +00:00
|
|
|
|
cache_nvidia_string_value_noupdate(ac_string, token, search, value, gid);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2016-12-04 15:13:57 +00:00
|
|
|
|
}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
|
|
|
|
// Retrieve token value from nvidia string
|
2018-05-12 16:03:00 +00:00
|
|
|
|
static int get_nvidia_string_value(TARGET_ID tid, ATTR_ID aid, char *token,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
SEARCH_ID search, int gid, const char *arg) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
char *str;
|
2018-12-23 17:55:14 +00:00
|
|
|
|
char *kvp;
|
|
|
|
|
char *key;
|
|
|
|
|
char *val;
|
|
|
|
|
char *saveptr1;
|
|
|
|
|
char *saveptr2;
|
|
|
|
|
int temp;
|
|
|
|
|
int value = -1;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Checks if the value is cacheable and is already loaded
|
|
|
|
|
cache_nvidia_string_value(tid, aid, token, search, &value, 0, gid);
|
2018-12-10 01:14:08 +00:00
|
|
|
|
if (value != -1) { return value; }
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Get string via nvidia interface
|
2018-12-10 01:14:08 +00:00
|
|
|
|
str = get_nvidia_string(tid, aid, gid, arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Split string into 'key=value' substrings, split substring
|
|
|
|
|
// into key and value, from value, check if token was found,
|
|
|
|
|
// convert value to int, evaluate value according to specified
|
|
|
|
|
// token search mode
|
|
|
|
|
kvp = strtok_r(str, NV_KVPAIR_SEPARATORS, &saveptr1);
|
|
|
|
|
while (kvp) {
|
|
|
|
|
key = strtok_r(kvp, NV_KEYVAL_SEPARATORS, &saveptr2);
|
2018-05-12 23:26:31 +00:00
|
|
|
|
val = strtok_r(nullptr, NV_KEYVAL_SEPARATORS, &saveptr2);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
if (key && val && (strcmp(token, key) == 0)) {
|
2018-05-12 23:26:31 +00:00
|
|
|
|
temp = (int)strtol(val, nullptr, 0);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
if (search == SEARCH_FIRST) {
|
|
|
|
|
value = temp;
|
|
|
|
|
break;
|
|
|
|
|
} else if (search == SEARCH_LAST) {
|
|
|
|
|
value = temp;
|
|
|
|
|
} else if (search == SEARCH_MIN) {
|
|
|
|
|
if ((value == -1) || (temp < value)) value = temp;
|
|
|
|
|
} else if (search == SEARCH_MAX) {
|
|
|
|
|
if (temp > value) value = temp;
|
|
|
|
|
} else {
|
|
|
|
|
value = -1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-12 23:26:31 +00:00
|
|
|
|
kvp = strtok_r(nullptr, NV_KVPAIR_SEPARATORS, &saveptr1);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-23 18:35:04 +00:00
|
|
|
|
// This call updated the cache for the cacheable values
|
2018-05-12 16:03:00 +00:00
|
|
|
|
cache_nvidia_string_value(tid, aid, token, search, &value, 1, gid);
|
|
|
|
|
|
|
|
|
|
// Free string, return value
|
2018-12-23 18:35:04 +00:00
|
|
|
|
free_and_zero(str);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
return value;
|
2015-12-09 17:38:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-24 00:41:22 +00:00
|
|
|
|
bool validate_target_id(Display *dpy, int target_id, ATTR_ID attribute) {
|
2020-09-25 19:46:33 +00:00
|
|
|
|
// num_GPU and num_COOLER calculated only once based on the physical target
|
|
|
|
|
static int num_GPU = get_nvidia_target_count(dpy, TARGET_GPU) - 1;
|
|
|
|
|
static int num_COOLER = get_nvidia_target_count(dpy, TARGET_COOLER) - 1;
|
|
|
|
|
|
|
|
|
|
if (target_id < 0) return false;
|
|
|
|
|
switch (attribute) {
|
|
|
|
|
case ATTR_FAN_LEVEL:
|
|
|
|
|
case ATTR_FAN_SPEED:
|
|
|
|
|
if (target_id > num_COOLER) return false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (target_id > num_GPU) return false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-09 17:38:20 +00:00
|
|
|
|
// Perform query and print result
|
2018-12-10 01:14:08 +00:00
|
|
|
|
void print_nvidia_value(struct text_object *obj, char *p,
|
|
|
|
|
unsigned int p_max_size) {
|
2018-12-23 17:55:14 +00:00
|
|
|
|
nvidia_s *nvs = static_cast<nvidia_s *>(obj->data.opaque);
|
2018-12-23 18:35:04 +00:00
|
|
|
|
int value;
|
|
|
|
|
int temp1;
|
|
|
|
|
int temp2;
|
|
|
|
|
int result;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
char *str;
|
2018-12-10 01:14:08 +00:00
|
|
|
|
int event_base;
|
|
|
|
|
int error_base;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
2022-10-14 02:17:14 +00:00
|
|
|
|
auto nvdpy = nvidia_display.get_nvdisplay();
|
2022-12-24 14:44:03 +00:00
|
|
|
|
Display *dpy = nvdpy ? nvdpy.get() : display;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
2018-12-10 01:14:08 +00:00
|
|
|
|
if (!dpy) {
|
|
|
|
|
NORM_ERR("%s: no display set (try setting nvidia_display)", __func__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!XNVCTRLQueryExtension(dpy, &event_base, &error_base)) {
|
|
|
|
|
NORM_ERR("%s: NV-CONTROL X extension not present", __func__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Assume failure
|
|
|
|
|
value = -1;
|
2018-05-12 23:26:31 +00:00
|
|
|
|
str = nullptr;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
2020-09-25 19:46:33 +00:00
|
|
|
|
// Perform query if the query exists and isnt stupid
|
2021-01-24 00:41:22 +00:00
|
|
|
|
if (nvs != nullptr &&
|
|
|
|
|
validate_target_id(dpy, nvs->target_id, nvs->attribute)) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Execute switch by query type
|
|
|
|
|
switch (nvs->query) {
|
|
|
|
|
case QUERY_VALUE:
|
2020-09-25 19:46:33 +00:00
|
|
|
|
value = get_nvidia_value(nvs->target, nvs->attribute, nvs->target_id,
|
2021-01-24 00:41:22 +00:00
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case QUERY_STRING:
|
2020-09-25 19:46:33 +00:00
|
|
|
|
str = get_nvidia_string(nvs->target, nvs->attribute, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case QUERY_STRING_VALUE:
|
|
|
|
|
value = get_nvidia_string_value(nvs->target, nvs->attribute, nvs->token,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->search, nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case QUERY_SPECIAL:
|
|
|
|
|
switch (nvs->attribute) {
|
|
|
|
|
case ATTR_PERF_MODE:
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, nvs->attribute,
|
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
switch (temp1) {
|
|
|
|
|
case NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE:
|
2018-12-23 18:35:04 +00:00
|
|
|
|
result = asprintf(&str, "Adaptive");
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE:
|
2018-12-23 18:35:04 +00:00
|
|
|
|
result = asprintf(&str, "Max. Perf.");
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case NV_CTRL_GPU_POWER_MIZER_MODE_AUTO:
|
2018-12-23 18:35:04 +00:00
|
|
|
|
result = asprintf(&str, "Auto");
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE:
|
2018-12-23 18:35:04 +00:00
|
|
|
|
result = asprintf(&str, "Consistent");
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2018-12-23 18:35:04 +00:00
|
|
|
|
result = asprintf(&str, "Unknown (%d)", value);
|
|
|
|
|
break;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
2018-12-23 18:35:04 +00:00
|
|
|
|
if (result < 0) { str = nullptr; }
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ATTR_MEM_FREE:
|
2020-09-25 19:46:33 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_MEM_USED, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_MEM_TOTAL,
|
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = temp2 - temp1;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_MEM_UTIL:
|
2020-09-25 19:46:33 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_MEM_USED, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_MEM_TOTAL,
|
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
2018-12-23 16:37:19 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2018-12-23 18:35:04 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print result
|
|
|
|
|
if (value != -1) {
|
2022-01-10 09:04:07 +00:00
|
|
|
|
if (nvs->is_percentage) {
|
|
|
|
|
percent_print(p, p_max_size, value);
|
2022-10-05 00:14:02 +00:00
|
|
|
|
} else {
|
2022-01-10 09:04:07 +00:00
|
|
|
|
snprintf(p, p_max_size, "%d", value);
|
|
|
|
|
}
|
2018-05-12 23:26:31 +00:00
|
|
|
|
} else if (str != nullptr) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
snprintf(p, p_max_size, "%s", str);
|
2018-12-23 18:35:04 +00:00
|
|
|
|
free_and_zero(str);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
} else {
|
2018-08-02 15:15:16 +00:00
|
|
|
|
snprintf(p, p_max_size, "%s", "N/A");
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
2009-10-03 14:14:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-03 12:03:45 +00:00
|
|
|
|
double get_nvidia_barval(struct text_object *obj) {
|
2018-12-23 18:35:04 +00:00
|
|
|
|
nvidia_s *nvs = static_cast<nvidia_s *>(obj->data.opaque);
|
|
|
|
|
int temp1;
|
|
|
|
|
int temp2;
|
2018-05-12 16:03:00 +00:00
|
|
|
|
double value;
|
2020-09-25 19:46:33 +00:00
|
|
|
|
int event_base;
|
|
|
|
|
int error_base;
|
|
|
|
|
|
2022-10-14 02:17:14 +00:00
|
|
|
|
auto nvdpy = nvidia_display.get_nvdisplay();
|
2022-12-24 14:44:03 +00:00
|
|
|
|
Display *dpy = nvdpy ? nvdpy.get() : display;
|
2020-09-25 19:46:33 +00:00
|
|
|
|
|
|
|
|
|
if (!dpy) {
|
|
|
|
|
NORM_ERR("%s: no display set (try setting nvidia_display)", __func__);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!XNVCTRLQueryExtension(dpy, &event_base, &error_base)) {
|
|
|
|
|
NORM_ERR("%s: NV-CONTROL X extension not present", __func__);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-05-12 16:03:00 +00:00
|
|
|
|
|
|
|
|
|
// Assume failure
|
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
|
|
// Convert query_result to a percentage using ((val-min)÷(max-min)×100)+0.5 if
|
|
|
|
|
// needed.
|
2021-01-24 00:41:22 +00:00
|
|
|
|
if (nvs != nullptr &&
|
|
|
|
|
validate_target_id(dpy, nvs->target_id, nvs->attribute)) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
switch (nvs->attribute) {
|
|
|
|
|
case ATTR_UTILS_STRING: // one of the percentage utils (gpuutil,
|
|
|
|
|
// membwutil, videoutil and pcieutil)
|
2018-12-10 01:14:08 +00:00
|
|
|
|
value =
|
|
|
|
|
get_nvidia_string_value(nvs->target, ATTR_UTILS_STRING, nvs->token,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->search, nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ATTR_MEM_UTIL: // memutil
|
|
|
|
|
case ATTR_MEM_USED:
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_MEM_USED, nvs->target_id,
|
|
|
|
|
nvs->arg);
|
2020-09-25 19:46:33 +00:00
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_MEM_TOTAL, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_MEM_FREE: // memfree
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_MEM_USED, nvs->target_id,
|
|
|
|
|
nvs->arg);
|
2020-09-25 19:46:33 +00:00
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_MEM_TOTAL, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = temp2 - temp1;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_FAN_SPEED: // fanspeed: Warn user we are using fanlevel
|
|
|
|
|
NORM_ERR(
|
|
|
|
|
"%s: invalid argument specified: '%s' (using 'fanlevel' instead).",
|
|
|
|
|
nvs->command, nvs->arg);
|
2018-12-23 16:37:19 +00:00
|
|
|
|
/* falls through */
|
2018-05-12 16:03:00 +00:00
|
|
|
|
case ATTR_FAN_LEVEL: // fanlevel
|
2020-09-25 19:46:33 +00:00
|
|
|
|
value = get_nvidia_value(nvs->target, ATTR_FAN_LEVEL, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case ATTR_GPU_TEMP: // gputemp (calculate out of gputempthreshold)
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_GPU_TEMP, nvs->target_id,
|
|
|
|
|
nvs->arg);
|
2018-12-10 01:14:08 +00:00
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_GPU_TEMP_THRESHOLD,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_AMBIENT_TEMP: // ambienttemp (calculate out of gputempthreshold
|
|
|
|
|
// for consistency)
|
2020-09-25 19:46:33 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_AMBIENT_TEMP, nvs->target_id,
|
2018-12-10 01:14:08 +00:00
|
|
|
|
nvs->arg);
|
|
|
|
|
temp2 = get_nvidia_value(nvs->target, ATTR_GPU_TEMP_THRESHOLD,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_GPU_FREQ: // gpufreq (calculate out of gpufreqmax)
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_GPU_FREQ, nvs->target_id,
|
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
temp2 = get_nvidia_string_value(nvs->target, ATTR_PERFMODES_STRING,
|
|
|
|
|
(char *)"nvclockmax", SEARCH_MAX,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_MEM_FREQ: // memfreq (calculate out of memfreqmax)
|
2021-01-24 00:41:22 +00:00
|
|
|
|
temp1 = get_nvidia_value(nvs->target, ATTR_MEM_FREQ, nvs->target_id,
|
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
temp2 = get_nvidia_string_value(nvs->target, ATTR_PERFMODES_STRING,
|
|
|
|
|
(char *)"memclockmax", SEARCH_MAX,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_FREQS_STRING: // mtrfreq (calculate out of memfreqmax)
|
2018-12-23 16:37:19 +00:00
|
|
|
|
if (strcmp(nvs->token, "memTransferRate") != 0) {
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Just in case error for silly devs
|
2023-05-05 01:24:55 +00:00
|
|
|
|
CRIT_ERR(
|
|
|
|
|
"%s: attribute is 'ATTR_FREQS_STRING' but token is not "
|
|
|
|
|
"\"memTransferRate\" (arg: '%s')",
|
|
|
|
|
nvs->command, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-12-10 01:14:08 +00:00
|
|
|
|
temp1 =
|
|
|
|
|
get_nvidia_string_value(nvs->target, ATTR_FREQS_STRING, nvs->token,
|
2020-09-25 19:46:33 +00:00
|
|
|
|
SEARCH_MAX, nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
temp2 = get_nvidia_string_value(nvs->target, ATTR_PERFMODES_STRING,
|
|
|
|
|
(char *)"memTransferRatemax",
|
2020-09-25 19:46:33 +00:00
|
|
|
|
SEARCH_MAX, nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
if (temp2 > temp1) temp1 = temp2; // extra safe here
|
|
|
|
|
value = ((float)temp1 * 100 / (float)temp2) + 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case ATTR_IMAGE_QUALITY: // imagequality
|
2021-01-24 00:41:22 +00:00
|
|
|
|
value = get_nvidia_value(nvs->target, ATTR_IMAGE_QUALITY,
|
|
|
|
|
nvs->target_id, nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: // Throw error if unsupported args are used
|
2023-05-05 01:24:55 +00:00
|
|
|
|
CRIT_ERR("%s: invalid argument specified: '%s'", nvs->command,
|
|
|
|
|
nvs->arg);
|
2018-05-12 16:03:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-05-03 12:03:45 +00:00
|
|
|
|
|
2018-05-12 16:03:00 +00:00
|
|
|
|
// Return the percentage
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2015-12-09 17:38:20 +00:00
|
|
|
|
|
|
|
|
|
// Cleanup
|
2018-12-23 17:55:14 +00:00
|
|
|
|
void free_nvidia(struct text_object *obj) {
|
|
|
|
|
nvidia_s *nvs = static_cast<nvidia_s *>(obj->data.opaque);
|
|
|
|
|
delete nvs;
|
|
|
|
|
obj->data.opaque = nullptr;
|
|
|
|
|
}
|