diff options
Diffstat (limited to 'src')
45 files changed, 2350 insertions, 817 deletions
diff --git a/src/Makefile b/src/Makefile index 7820829..aaa7876 100644 --- a/src/Makefile +++ b/src/Makefile @@ -139,9 +139,6 @@ endif LDFLAGS += $(XNVCTRL_LDFLAGS) -NVML_EXPERIMENTAL ?= -CFLAGS += $(if $(NVML_EXPERIMENTAL),-DNVML_EXPERIMENTAL) - # Some older Linux distributions do not have the dynamic library # libXxf86vm.so, though some newer Linux distributions do not have the diff --git a/src/command-line.c b/src/command-line.c index 69f065a..fb30054 100644 --- a/src/command-line.c +++ b/src/command-line.c @@ -49,7 +49,7 @@ static void print_version(void) { nv_msg(NULL, ""); nv_msg(NULL, NV_ID_STRING); - nv_msg(TAB, "The NVIDIA X Server Settings tool."); + nv_msg(TAB, "The NVIDIA Settings tool."); nv_msg(NULL, ""); nv_msg(TAB, "This program is used to configure the " "NVIDIA Linux graphics driver."); diff --git a/src/common-utils/msg.c b/src/common-utils/msg.c index 8a78530..70772a2 100644 --- a/src/common-utils/msg.c +++ b/src/common-utils/msg.c @@ -113,7 +113,7 @@ do { \ NV_VSNPRINTF(buf, fmt); \ format(stream, prefix, buf, whitespace); \ free (buf); \ -} while(0) +} while (0) /* diff --git a/src/common-utils/nvgetopt.c b/src/common-utils/nvgetopt.c index 286aee8..5ae3a14 100644 --- a/src/common-utils/nvgetopt.c +++ b/src/common-utils/nvgetopt.c @@ -189,7 +189,7 @@ int nvgetopt(int argc, if (a[0] == '-') a++; if (a[0] == '+') a++; - while(a[0]) { a[0] = a[1]; a++; } + while (a[0]) { a[0] = a[1]; a++; } /* * decrement argv_index so that we process this diff --git a/src/common-utils/nvpci-utils.c b/src/common-utils/nvpci-utils.c new file mode 100644 index 0000000..62946d2 --- /dev/null +++ b/src/common-utils/nvpci-utils.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nvpci-utils.h" + +/* + * libpciaccess stores the device class in bits 16-23, subclass in 8-15, and + * interface in bits 0-7 of dev->device_class. We care only about the class + * and subclass. + */ +const uint32_t PCI_CLASS_DISPLAY_VGA = 0x30000; +const uint32_t PCI_CLASS_SUBCLASS_MASK = 0xffff00; + +/* + * nvpci_find_gpu_by_vendor() - use libpciaccess to find all VGA and 3D PCI + * devices matching the passed-in vendor_id (which may be set to PCI_MATCH_ANY). + * The caller is responsible for calling pci_system_init() before using this + * function, and pci_system_cleanup() when libpciaccess is no longer needed. + */ +struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id) +{ + const struct pci_id_match match = { + .vendor_id = vendor_id, + .device_id = PCI_MATCH_ANY, + .subvendor_id = PCI_MATCH_ANY, + .subdevice_id = PCI_MATCH_ANY, + .device_class = PCI_CLASS_DISPLAY_VGA, + /* + * Ignore bit 1 of the subclass, to allow both 0x30000 (VGA controller) + * and 0x30200 (3D controller). + */ + .device_class_mask = PCI_CLASS_SUBCLASS_MASK & ~0x200, + }; + + return pci_id_match_iterator_create(&match); +} + +/* + * nvpci_dev_is_vga() - test whether the passed-in struct pci_device* has the + * VGA device class 0x0300 (and not 3D class 0x0302). + */ +int nvpci_dev_is_vga(struct pci_device *dev) +{ + return (dev->device_class & PCI_CLASS_SUBCLASS_MASK) == + PCI_CLASS_DISPLAY_VGA; +} diff --git a/src/common-utils/nvpci-utils.h b/src/common-utils/nvpci-utils.h new file mode 100644 index 0000000..9813e90 --- /dev/null +++ b/src/common-utils/nvpci-utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NVPCI_UTILS_H__ +#define __NVPCI_UTILS_H__ + +#include <pciaccess.h> + +#define NV_PCI_VENDOR_ID 0x10de + +struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id); +int nvpci_dev_is_vga(struct pci_device *dev); + +#endif /* __NVPCI_UTILS_H__ */ diff --git a/src/common-utils/src.mk b/src/common-utils/src.mk index 6dbed7a..bb1e1d3 100644 --- a/src/common-utils/src.mk +++ b/src/common-utils/src.mk @@ -1,5 +1,8 @@ # makefile fragment included by nvidia-xconfig, nvidia-settings, and nvidia-installer +# the including makefile should set this if the relevant program uses pciaccess +COMMON_UTILS_PCIACCESS ?= + COMMON_UTILS_SRC += nvgetopt.c COMMON_UTILS_SRC += common-utils.c COMMON_UTILS_SRC += msg.c @@ -9,6 +12,16 @@ COMMON_UTILS_EXTRA_DIST += common-utils.h COMMON_UTILS_EXTRA_DIST += msg.h COMMON_UTILS_EXTRA_DIST += src.mk +# only build nvpci-utils.c for programs that actually use libpciaccess, to +# prevent other programs from needing to set the right CFLAGS/LDFLAGS for code +# they won't use. Otherwise, just package it in the source tarball. +ifneq ($(COMMON_UTILS_PCIACCESS),) + COMMON_UTILS_SRC += nvpci-utils.c +else + COMMON_UTILS_EXTRA_DIST += nvpci-utils.c +endif +COMMON_UTILS_EXTRA_DIST += nvpci-utils.h + # gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC, # because it is not compiled into the utilities themselves, but used # when building the utility's gen-manpage-opts diff --git a/src/config-file.c b/src/config-file.c index ecf2227..8882641 100644 --- a/src/config-file.c +++ b/src/config-file.c @@ -19,7 +19,7 @@ /* * config-file.c - this source file contains functions for processing - * the NVIDIA X Server control panel configuration file. + * the NVIDIA Settings control panel configuration file. * * The configuration file is simply a newline-separated list of * attribute strings, where the syntax of an attribute string is @@ -260,7 +260,7 @@ int nv_write_config_file(const char *filename, const CtrlSystem *system, fprintf(stream, "# %s\n", filename); fprintf(stream, "#\n"); fprintf(stream, "# Configuration file for nvidia-settings - the NVIDIA " - "X Server Settings utility\n"); + "Settings utility\n"); /* NOTE: ctime(3) generates a new line */ diff --git a/src/gtk+-2.x/ctkappprofile.c b/src/gtk+-2.x/ctkappprofile.c index f42edc9..77dd503 100644 --- a/src/gtk+-2.x/ctkappprofile.c +++ b/src/gtk+-2.x/ctkappprofile.c @@ -42,6 +42,10 @@ #define STATUSBAR_UPDATE_WARNING "This will take effect after changes are saved." +#define SHARPEN_ENABLE_DEFAULT FALSE +#define SHARPEN_VALUE_DEFAULT 50 +#define SHARPEN_FILM_GRAIN_DEFAULT 17 + enum { RULE_FEATURE_PROCNAME, RULE_FEATURE_DSO, @@ -362,8 +366,13 @@ static GtkWidget *populate_registry_key_combo_callback(gpointer init_data) for (i = 0; i < json_array_size(key_docs); i++) { json_t *json_key_object = json_array_get(key_docs, i); json_t *json_name = json_object_get(json_key_object, "key"); + const gchar *key_name = json_string_value(json_name); + // The GLSharpen* variables have custom UI, so don't add them to the dropdown + if (!strncmp(key_name, "GLSharpen", 9)) { + continue; + } ctk_drop_down_menu_append_item(menu, - json_string_value(json_name), + key_name, i); } @@ -1382,6 +1391,18 @@ static gboolean profile_browse_button_clicked(GtkWidget *widget, gpointer user_d return FALSE; } +static void sharpen_enable_checkbox_toggled(GtkWidget *widget, + gpointer user_data) +{ + EditProfileDialog *dialog = (EditProfileDialog *)user_data; + gboolean sharpen_enable; + + sharpen_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + ctk_widget_set_visible(dialog->sharpen_value_box, sharpen_enable); + ctk_widget_set_visible(dialog->sharpen_film_grain_box, sharpen_enable); +} + static const char __rule_pattern_help[] = "In this section, you write the pattern that will be used to determine whether " "the settings in this rule will apply to a given application."; @@ -2348,12 +2369,47 @@ static gboolean append_setting(GtkTreeModel *model, return FALSE; } +static void edit_profile_dialog_update_sharpen_settings(EditProfileDialog *dialog) +{ + json_t *sharpen_enable_setting, *sharpen_value_setting, *sharpen_film_setting; + gboolean sharpen_enable; + int sharpen_value, sharpen_film; + + sharpen_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->sharpen_enable_check_button)); + + if (!sharpen_enable) { + return; + } + + sharpen_enable_setting = json_object(); + json_object_set_new(sharpen_enable_setting, "key", json_string("GLSharpenEnable")); + json_object_set_new(sharpen_enable_setting, "value", json_boolean(sharpen_enable)); + + json_array_append(dialog->settings, sharpen_enable_setting); + + sharpen_value_setting = json_object(); + json_object_set_new(sharpen_value_setting, "key", json_string("GLSharpenValue")); + sharpen_value = gtk_adjustment_get_value(GTK_ADJUSTMENT(dialog->sharpen_value_adjustment)); + json_object_set_new(sharpen_value_setting, "value", json_integer(sharpen_value)); + + json_array_append(dialog->settings, sharpen_value_setting); + + sharpen_film_setting = json_object(); + json_object_set_new(sharpen_film_setting, "key", json_string("GLSharpenIgnoreFilmGrain")); + sharpen_film = gtk_adjustment_get_value(GTK_ADJUSTMENT(dialog->sharpen_film_grain_adjustment)); + json_object_set_new(sharpen_film_setting, "value", json_integer(sharpen_film)); + + json_array_append(dialog->settings, sharpen_film_setting); +} + static void edit_profile_dialog_update_settings(EditProfileDialog *dialog) { json_array_clear(dialog->settings); gtk_tree_model_foreach(GTK_TREE_MODEL(dialog->settings_store), append_setting, (gpointer)dialog->settings); + + edit_profile_dialog_update_sharpen_settings(dialog); } static gboolean widget_get_visible(GtkWidget *widget) @@ -2974,6 +3030,11 @@ static EditProfileDialog *edit_profile_dialog_new(CtkAppProfile *ctk_app_profile GtkWidget *tree_view; GtkWidget *scroll_win; GtkWidget *button; + GtkWidget *sharpen_enable_checkbox; + GtkWidget *sharpen_value_slider; + GtkWidget *sharpen_film_slider; + GtkAdjustment *sharpen_value_adjustment; + GtkAdjustment *sharpen_film_adjustment; GList *toolbar_widget_items; ToolbarItemTemplate *edit_profile_settings_toolbar_items, *edit_profile_dialog_toolbar_items; @@ -2981,7 +3042,6 @@ static EditProfileDialog *edit_profile_dialog_new(CtkAppProfile *ctk_app_profile TreeViewColumnTemplate *settings_tree_view_columns; size_t num_settings_tree_view_columns; - dialog = malloc(sizeof(EditProfileDialog)); if (!dialog) { return NULL; @@ -3099,6 +3159,56 @@ static EditProfileDialog *edit_profile_dialog_new(CtkAppProfile *ctk_app_profile gtk_container_add(GTK_CONTAINER(scroll_win), tree_view); gtk_box_pack_start(GTK_BOX(main_vbox), scroll_win, TRUE, TRUE, 0); + hbox = gtk_hbox_new(FALSE, 5); + + label = gtk_label_new("Enable Sharpening"); + dialog->sharpen_enable_check_button = sharpen_enable_checkbox + = gtk_check_button_new(); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sharpen_enable_checkbox), + SHARPEN_ENABLE_DEFAULT); + + g_signal_connect(G_OBJECT(sharpen_enable_checkbox), "toggled", + G_CALLBACK(sharpen_enable_checkbox_toggled), + (gpointer)dialog); + + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), sharpen_enable_checkbox, TRUE, TRUE, 0); + + gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); + + dialog->sharpen_value_box = hbox = gtk_hbox_new(FALSE, 5); + label = gtk_label_new("Sharpening Amount"); + dialog->sharpen_value_adjustment = sharpen_value_adjustment + = GTK_ADJUSTMENT(gtk_adjustment_new(SHARPEN_VALUE_DEFAULT, 0, 100, 1, 1, 0.0)); + + dialog->sharpen_value_slider = sharpen_value_slider = + gtk_hscale_new(GTK_ADJUSTMENT(sharpen_value_adjustment)); + gtk_scale_set_draw_value(GTK_SCALE(sharpen_value_slider), TRUE); + gtk_scale_set_value_pos(GTK_SCALE(sharpen_value_slider), GTK_POS_TOP); + gtk_scale_set_digits(GTK_SCALE(sharpen_value_slider), 0); + + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), sharpen_value_slider, TRUE, TRUE, 0); + + gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); + + dialog->sharpen_film_grain_box = hbox = gtk_hbox_new(FALSE, 5); + label = gtk_label_new("Film Grain Reduction"); + dialog->sharpen_film_grain_adjustment = sharpen_film_adjustment = + GTK_ADJUSTMENT(gtk_adjustment_new(SHARPEN_FILM_GRAIN_DEFAULT, 0, 100, 1, 1, 0.0)); + + dialog->sharpen_film_grain_slider = sharpen_film_slider = + gtk_hscale_new(GTK_ADJUSTMENT(sharpen_film_adjustment)); + gtk_scale_set_draw_value(GTK_SCALE(sharpen_film_slider), TRUE); + gtk_scale_set_value_pos(GTK_SCALE(sharpen_film_slider), GTK_POS_TOP); + gtk_scale_set_digits(GTK_SCALE(sharpen_film_slider), 0); + + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), sharpen_film_slider, TRUE, TRUE, 0); + + gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); + dialog->setting_update_canceled = FALSE; ctk_statusbar_init(&dialog->error_statusbar); @@ -3400,6 +3510,50 @@ static gboolean profiles_tree_view_key_press_event(GtkWidget *widget, return FALSE; } +static gboolean check_sharpening_setting(EditProfileDialog *dialog, + GtkTreeModel *model, + GtkTreeIter *iter) +{ + json_t *setting; + json_t *value; + const char *key; + + gtk_tree_model_get(model, iter, SETTING_LIST_STORE_COL_SETTING, &setting, -1); + if (setting && setting->refcount == 0) { + return FALSE; + } + + key = json_string_value(json_object_get(setting, "key")); + value = json_object_get(setting, "value"); + + if (!strcmp(key, "GLSharpenEnable")) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->sharpen_enable_check_button), + json_is_true(value)); + return TRUE; + } else if (!strcmp(key, "GLSharpenValue") && json_is_integer(value)) { + gtk_adjustment_set_value(GTK_ADJUSTMENT(dialog->sharpen_value_adjustment), json_integer_value(value)); + return TRUE; + } else if (!strcmp(key, "GLSharpenIgnoreFilmGrain") && json_is_integer(value)) { + gtk_adjustment_set_value(GTK_ADJUSTMENT(dialog->sharpen_film_grain_adjustment), json_integer_value(value)); + return TRUE; + } + + return FALSE; +} + +static void edit_profile_dialog_load_sharpening_settings(EditProfileDialog *dialog) { + gint i, row_count; + GtkTreeModel *model = GTK_TREE_MODEL(dialog->settings_store); + GtkTreeIter iter; + row_count = gtk_tree_model_iter_n_children(model, NULL); + for (i = row_count - 1; i >= 0; i--) { + gtk_tree_model_iter_nth_child(model, &iter, NULL, i); + if (check_sharpening_setting(dialog, model, &iter)) { + gtk_list_store_remove(GTK_LIST_STORE(dialog->settings_store), &iter); + } + } +} + static void edit_profile_dialog_load_values(EditProfileDialog *dialog) { // window title @@ -3436,6 +3590,7 @@ static void edit_profile_dialog_load_values(EditProfileDialog *dialog) load_settings_from_profile(CTK_APP_PROFILE(dialog->parent), dialog->settings_store, dialog->name->str); + edit_profile_dialog_load_sharpening_settings(dialog); } else { gtk_list_store_clear(dialog->settings_store); } @@ -3445,6 +3600,7 @@ static void edit_profile_dialog_show(EditProfileDialog *dialog) { edit_profile_dialog_load_values(dialog); gtk_widget_show_all(dialog->top_window); + sharpen_enable_checkbox_toggled(dialog->sharpen_enable_check_button, dialog); // disable focusing to calling window until this window closed gtk_window_set_transient_for(GTK_WINDOW(dialog->top_window), diff --git a/src/gtk+-2.x/ctkappprofile.h b/src/gtk+-2.x/ctkappprofile.h index 3f59ca8..1627214 100644 --- a/src/gtk+-2.x/ctkappprofile.h +++ b/src/gtk+-2.x/ctkappprofile.h @@ -104,6 +104,14 @@ typedef struct _EditProfileDialog { GtkWidget *source_file_combo; + GtkWidget *sharpen_enable_check_button; + GtkWidget *sharpen_value_box; + GtkAdjustment *sharpen_value_adjustment; + GtkWidget *sharpen_value_slider; + GtkWidget *sharpen_film_grain_box; + GtkAdjustment *sharpen_film_grain_adjustment; + GtkWidget *sharpen_film_grain_slider; + GtkWidget *add_edit_profile_button; GtkWidget *registry_key_combo; diff --git a/src/gtk+-2.x/ctkbanner.c b/src/gtk+-2.x/ctkbanner.c index fe9d67a..b43af03 100644 --- a/src/gtk+-2.x/ctkbanner.c +++ b/src/gtk+-2.x/ctkbanner.c @@ -312,7 +312,8 @@ static gboolean ctk_banner_configure_event( needed_w = ctk_banner->artwork.w + ctk_banner->artwork_pad_x; needed_h = ctk_banner->artwork.h; - if ((ctk_banner->back.w >= needed_w) && + if (ctk_banner->artwork.pixbuf && + (ctk_banner->back.w >= needed_w) && (ctk_banner->back.h >= needed_h)) { w = ctk_banner->artwork.w; @@ -430,13 +431,13 @@ static GdkPixbuf* select_artwork(BannerArtworkType artwork, { BANNER_ARTWORK_X, FALSE, 16, PNG(x) }, { BANNER_ARTWORK_XVIDEO, FALSE, 16, PNG(xvideo) }, { BANNER_ARTWORK_SVP, FALSE, 16, PNG(svp_3dvp) }, - { BANNER_ARTWORK_INVALID, FALSE, 16, NULL, NULL }, + { BANNER_ARTWORK_BLANK, FALSE, 16, NULL, NULL }, #undef PNG }; int i; - for (i = 0; ArtworkTable[i].artwork != BANNER_ARTWORK_INVALID; i++) { + for (i = 0; ArtworkTable[i].artwork <= BANNER_ARTWORK_BLANK; i++) { if (ArtworkTable[i].artwork == artwork) { *tall = ArtworkTable[i].tall; *pad_x = ArtworkTable[i].pad_x; @@ -460,13 +461,10 @@ GtkWidget* ctk_banner_new(BannerArtworkType artwork) { GObject *object; CtkBanner *ctk_banner; - int tall, pad_x; + + int tall = 0, pad_x = 0; GdkPixbuf *pixbuf = select_artwork(artwork, &tall, &pad_x); - if (!pixbuf) { - return NULL; - } - object = g_object_new(CTK_TYPE_BANNER, NULL); ctk_banner = CTK_BANNER(object); @@ -525,10 +523,11 @@ GtkWidget* ctk_banner_new(BannerArtworkType artwork) /* load the artwork pixbuf */ - - ctk_banner->artwork.pixbuf = pixbuf; - ctk_banner->artwork.w = gdk_pixbuf_get_width(pixbuf); - ctk_banner->artwork.h = gdk_pixbuf_get_height(pixbuf); + if (pixbuf) { + ctk_banner->artwork.pixbuf = pixbuf; + ctk_banner->artwork.w = gdk_pixbuf_get_width(pixbuf); + ctk_banner->artwork.h = gdk_pixbuf_get_height(pixbuf); + } return GTK_WIDGET(object); } diff --git a/src/gtk+-2.x/ctkbanner.h b/src/gtk+-2.x/ctkbanner.h index 9d4dd4e..86ee0fd 100644 --- a/src/gtk+-2.x/ctkbanner.h +++ b/src/gtk+-2.x/ctkbanner.h @@ -66,7 +66,7 @@ typedef enum { BANNER_ARTWORK_X, BANNER_ARTWORK_XVIDEO, BANNER_ARTWORK_SVP, - BANNER_ARTWORK_INVALID + BANNER_ARTWORK_BLANK } BannerArtworkType; diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 40d82cc..578e543 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -499,6 +499,13 @@ static void register_layout_events(CtkDisplayConfig *ctk_object) CTK_EVENT_NAME(NV_CTRL_STRING_DELETE_METAMODE), G_CALLBACK(display_config_attribute_changed), (gpointer) ctk_object); + + if (screen->num_prime_displays > 0) { + g_signal_connect(G_OBJECT(screen->ctk_event), + CTK_EVENT_NAME(NV_CTRL_STRING_PRIME_OUTPUTS_DATA), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + } } } /* register_layout_events() */ diff --git a/src/gtk+-2.x/ctkecc.c b/src/gtk+-2.x/ctkecc.c index 591d2aa..82715a2 100644 --- a/src/gtk+-2.x/ctkecc.c +++ b/src/gtk+-2.x/ctkecc.c @@ -58,6 +58,22 @@ static const char *__aggregate_dbit_error_help = "Returns the number of double-bit ECC errors detected by the " "targeted GPU since the last counter reset."; +static const char *__detailed_sbit_error_help = +"Returns the number of single-bit ECC errors detected for the specified " +"memory location by the targeted GPU since the last system reboot."; + +static const char *__detailed_dbit_error_help = +"Returns the number of double-bit ECC errors detected for the specified " +"memory location by the targeted GPU since the last system reboot."; + +static const char *__detailed_aggregate_sbit_error_help = +"Returns the number of single-bit ECC errors detected for the specified " +"memory location by the targeted GPU since the last counter reset."; + +static const char *__detailed_aggregate_dbit_error_help = +"Returns the number of double-bit ECC errors detected for the specified " +"memory location by the targeted GPU since the last counter reset."; + static const char *__configuration_status_help = "Returns the current ECC configuration setting or specifies new " "settings. Changes to these settings do not take effect until the next " @@ -157,6 +173,135 @@ static GtkWidget *add_table_int_row(CtkConfig *ctk_config, GtkWidget *table, /* + * memory_location_label() - returns the proper name of the memory location + * specified. + */ +static const char *memory_location_label(const int index, int sram_value) +{ + if (index < 0 || index >= NVML_MEMORY_LOCATION_COUNT) { + return "Unknown"; + } + + /* + * NVML_MEMORY_LOCATION_DRAM and MNML_MEMORY_LOCATION_DEVICE_MEMORY share + * the same index value. _DRAM is only for Turing+ while _DEVICE_MEMORY is + * used preTuring. Since NVML_MEMORY_LOCATION_SRAM is also only used for + * Turing+, if that value is valid then this is Turing+ and we want the DRAM + * label. + */ + + if (index == NVML_MEMORY_LOCATION_DRAM && sram_value >= 0) { + return "DRAM"; + } + + switch (index) { + case NVML_MEMORY_LOCATION_L1_CACHE: + return "L1 Cache"; + case NVML_MEMORY_LOCATION_L2_CACHE: + return "L2 Cache"; + case NVML_MEMORY_LOCATION_DEVICE_MEMORY: + // See above for duplicate value NVML_MEMORY_LOCATION_DRAM + return "Device Memory"; + case NVML_MEMORY_LOCATION_REGISTER_FILE: + return "Register File"; + case NVML_MEMORY_LOCATION_TEXTURE_MEMORY: + return "Texture Memory"; + case NVML_MEMORY_LOCATION_TEXTURE_SHM: + return "Texture Shared"; + case NVML_MEMORY_LOCATION_CBU: + return "CBU"; + case NVML_MEMORY_LOCATION_SRAM: + return "SRAM"; + } + + return "Unknown"; +} + + + +/* + * update_detailed_widgets() - fills in or clears out the values for the + * detailed ECC information. + */ +static void update_detailed_widgets(CtkEccDetailedTableRow errors[], + gboolean vol, int *counts) +{ + int loc; + int value; + char s[32]; + GtkLabel *label; + for (loc = NVML_MEMORY_LOCATION_L1_CACHE; + loc < NVML_MEMORY_LOCATION_COUNT; + loc++) { + + if (!counts) { + value = -1; + } else { + value = counts[loc]; + } + + if (vol) { + errors[loc].vol_count_value = value; + label = GTK_LABEL(errors[loc].vol_count); + } else { + errors[loc].agg_count_value = value; + label = GTK_LABEL(errors[loc].agg_count); + } + + if (value < 0) { + gtk_label_set_text(label, "N/A"); + } else { + sprintf(s, "%d", value); + gtk_label_set_text(label, s); + } + } +} + + + +/* + * hide_unavailable_rows() - Hide a row in the table for a memory location if + * both the volatile and aggregate values are less than 0, i.e. not supported. + */ + +static void hide_unavailable_rows(CtkEcc *ctk_ecc) +{ + int loc; + gboolean show_row; + gboolean any_detailed_info = FALSE; + + for (loc = NVML_MEMORY_LOCATION_L1_CACHE; + loc < NVML_MEMORY_LOCATION_COUNT; + loc++) { + + show_row = (ctk_ecc->single_errors[loc].vol_count_value >= 0 || + ctk_ecc->single_errors[loc].agg_count_value >= 0); + ctk_widget_set_visible(ctk_ecc->single_errors[loc].err_type, show_row); + ctk_widget_set_visible(ctk_ecc->single_errors[loc].mem_type, show_row); + ctk_widget_set_visible(ctk_ecc->single_errors[loc].vol_count, + show_row); + ctk_widget_set_visible(ctk_ecc->single_errors[loc].agg_count, + show_row); + any_detailed_info |= show_row; + + show_row = (ctk_ecc->double_errors[loc].vol_count_value >= 0 || + ctk_ecc->double_errors[loc].agg_count_value >= 0); + ctk_widget_set_visible(ctk_ecc->double_errors[loc].err_type, show_row); + ctk_widget_set_visible(ctk_ecc->double_errors[loc].mem_type, show_row); + ctk_widget_set_visible(ctk_ecc->double_errors[loc].vol_count, + show_row); + ctk_widget_set_visible(ctk_ecc->double_errors[loc].agg_count, + show_row); + any_detailed_info |= show_row; + } + + ctk_widget_set_visible(ctk_ecc->detailed_table, any_detailed_info); + ctk_widget_set_visible(ctk_ecc->summary_table, !any_detailed_info); +} + + + +/* * update_ecc_info() - update ECC status and configuration */ @@ -167,6 +312,8 @@ static gboolean update_ecc_info(gpointer user_data) int64_t val; gboolean status; ReturnStatus ret; + unsigned char *cdata; + int *counts, len; if (!ctk_ecc->ecc_config_supported && !ctk_ecc->ecc_enabled ) { @@ -201,7 +348,18 @@ static gboolean update_ecc_info(gpointer user_data) /* Query ECC Errors */ - if (ctk_ecc->sbit_error) { + /* Detailed Single Bit Volatile */ + counts = NULL; + cdata = NULL; + ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT, + &cdata, &len); + if (ret == NvCtrlSuccess) { + counts = (int *)cdata; + } + update_detailed_widgets(ctk_ecc->single_errors, 1, counts); + + if (!counts && ctk_ecc->sbit_error) { ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS, &val); @@ -210,8 +368,21 @@ static gboolean update_ecc_info(gpointer user_data) } set_label_value(ctk_ecc->sbit_error, val); } + nvfree(cdata); + + /* Detailed Double Bit Volatile */ + counts = NULL; + cdata = NULL; + ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT, + &cdata, &len); + if (ret == NvCtrlSuccess) { + counts = (int *)cdata; + } + + update_detailed_widgets(ctk_ecc->double_errors, 1, counts); - if (ctk_ecc->dbit_error) { + if (!counts && ctk_ecc->dbit_error) { ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS, &val); @@ -220,8 +391,21 @@ static gboolean update_ecc_info(gpointer user_data) } set_label_value(ctk_ecc->dbit_error, val); } + nvfree(cdata); + + /* Detailed Single Bit Aggregate */ + counts = NULL; + cdata = NULL; + ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT_AGGREGATE, + &cdata, &len); + if (ret == NvCtrlSuccess) { + counts = (int *)cdata; + } + + update_detailed_widgets(ctk_ecc->single_errors, 0, counts); - if (ctk_ecc->aggregate_sbit_error) { + if (!counts && ctk_ecc->aggregate_sbit_error) { ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS, &val); @@ -230,8 +414,21 @@ static gboolean update_ecc_info(gpointer user_data) } set_label_value(ctk_ecc->aggregate_sbit_error, val); } + nvfree(cdata); + + /* Detailed Double Bit Aggregate */ + counts = NULL; + cdata = NULL; + ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE, + &cdata, &len); + if (ret == NvCtrlSuccess) { + counts = (int *)cdata; + } + + update_detailed_widgets(ctk_ecc->double_errors, 0, counts); - if (ctk_ecc->aggregate_dbit_error) { + if (!counts && ctk_ecc->aggregate_dbit_error) { ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS, &val); @@ -240,6 +437,9 @@ static gboolean update_ecc_info(gpointer user_data) } set_label_value(ctk_ecc->aggregate_dbit_error, val); } + nvfree(cdata); + + hide_unavailable_rows(ctk_ecc); return TRUE; } /* update_ecc_info() */ @@ -480,6 +680,99 @@ static void ecc_config_button_toggled(GtkWidget *widget, +/* + * pack_detailed_widgets() - helper function to create a row for detailed ECC + * data. + */ + +static void pack_detailed_widgets(CtkEcc *ctk_ecc, gboolean single, + int row, int loc) +{ + CtkConfig *ctk_config = ctk_ecc->ctk_config; + GtkWidget *widget_err = NULL; + GtkWidget *widget_mem = NULL; + int xpad = 12, ypad = 2; + + widget_mem = GTK_WIDGET(gtk_label_new(memory_location_label(loc, 0))); + if (single) { + widget_err = GTK_WIDGET(gtk_label_new("Single Bit")); + ctk_ecc->single_errors[loc].err_type = widget_err; + ctk_ecc->single_errors[loc].mem_type = widget_mem; + } else { + widget_err = GTK_WIDGET(gtk_label_new("Double Bit")); + ctk_ecc->double_errors[loc].err_type = widget_err; + ctk_ecc->double_errors[loc].mem_type = widget_mem; + } + + ctk_widget_set_halign_left(widget_err); + ctk_widget_set_halign_left(widget_mem); + + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), widget_err, 0, 1, + row, row + 1, GTK_FILL, GTK_FILL, xpad, ypad); + + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), widget_mem, 1, 2, + row, row + 1, GTK_FILL, GTK_FILL, xpad, ypad); + + if (single) { + ctk_config_set_tooltip(ctk_config, + ctk_ecc->single_errors[loc].vol_count, + __detailed_sbit_error_help); + ctk_config_set_tooltip(ctk_config, + ctk_ecc->single_errors[loc].agg_count, + __detailed_aggregate_sbit_error_help); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + ctk_ecc->single_errors[loc].vol_count, + 2, 3, row, row + 1, GTK_SHRINK, GTK_SHRINK, + xpad, ypad); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + ctk_ecc->single_errors[loc].agg_count, + 3, 4, row, row + 1, GTK_SHRINK, GTK_SHRINK, + xpad, ypad); + } else { + ctk_config_set_tooltip(ctk_config, + ctk_ecc->double_errors[loc].vol_count, + __detailed_dbit_error_help); + ctk_config_set_tooltip(ctk_config, + ctk_ecc->double_errors[loc].agg_count, + __detailed_aggregate_dbit_error_help); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + ctk_ecc->double_errors[loc].vol_count, + 2, 3, row, row + 1, GTK_SHRINK, GTK_SHRINK, + xpad, ypad); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + ctk_ecc->double_errors[loc].agg_count, + 3, 4, row, row + 1, GTK_SHRINK, GTK_SHRINK, + xpad, ypad); + } +} + + + +/* + * update_detailed_label_for_values() - Sets the label names for the + * detailed memory location labels. This need to be run after the first + * query for values so that it can propery set the labels for the + * memory locations available. + */ +static void update_detailed_label_for_values(CtkEcc *ctk_ecc) +{ + const char *loc_str; + + loc_str = memory_location_label(NVML_MEMORY_LOCATION_DRAM, + ctk_ecc->single_errors[NVML_MEMORY_LOCATION_SRAM].vol_count_value); + gtk_label_set_text( + GTK_LABEL(ctk_ecc->single_errors[NVML_MEMORY_LOCATION_DRAM].mem_type), + loc_str); + + loc_str = memory_location_label(NVML_MEMORY_LOCATION_DRAM, + ctk_ecc->double_errors[NVML_MEMORY_LOCATION_SRAM].vol_count_value); + gtk_label_set_text( + GTK_LABEL(ctk_ecc->double_errors[NVML_MEMORY_LOCATION_DRAM].mem_type), + loc_str); +} + + + GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, CtkConfig *ctk_config, CtkEvent *ctk_event) @@ -502,6 +795,8 @@ GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, ReturnStatus ret; gchar *ecc_enabled_string; gchar *str = NULL; + int loc; + gint xpad = 12, ypad = 2; /* make sure we have a handle */ @@ -635,34 +930,41 @@ GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); - table = gtk_table_new(1, 2, FALSE); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - /* ECC Status */ hbox2 = gtk_hbox_new(FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, row, row+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 5); label = gtk_label_new("ECC:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 5); eventbox = gtk_event_box_new(); - gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, row, row+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_box_pack_start(GTK_BOX(hbox2), eventbox, FALSE, FALSE, 5); label = gtk_label_new(ecc_enabled_string); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_container_add(GTK_CONTAINER(eventbox), label); ctk_config_set_tooltip(ctk_config, eventbox, __ecc_status_help); ctk_ecc->status = label; - - row += 3; - + + /* Add ECC Errors */ + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new("ECC Errors"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + hseparator = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); + + row = 0; + table = gtk_table_new(1, 2, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + if (sbit_error_available && dbit_error_available) { ctk_ecc->sbit_error = @@ -690,7 +992,79 @@ GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, "Aggregate Double-bit ECC Errors:", aggregate_dbit_error, row, ecc_enabled); } - + + ctk_ecc->summary_table = table; + + /* + * Create the structures needed for the Detailed ECC information table. + */ + + /* Initialize the widgets for the Detailed ECC counts */ + for (loc = NVML_MEMORY_LOCATION_L1_CACHE; + loc < NVML_MEMORY_LOCATION_COUNT; + loc++) { + ctk_ecc->single_errors[loc].vol_count = + GTK_WIDGET(gtk_label_new("N/A")); + ctk_ecc->single_errors[loc].agg_count = + GTK_WIDGET(gtk_label_new("N/A")); + ctk_ecc->double_errors[loc].vol_count = + GTK_WIDGET(gtk_label_new("N/A")); + ctk_ecc->double_errors[loc].agg_count = + GTK_WIDGET(gtk_label_new("N/A")); + } + + /* Create the detailed ECC table. Headers, labels, and pack the widgets */ + ctk_ecc->detailed_table = gtk_table_new(5, 4, FALSE); + + /* Header row */ + row = 0; + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + GTK_WIDGET(gtk_label_new("Error Type")), + 0, 1, row, row + 1, GTK_FILL, GTK_FILL, xpad, ypad); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + GTK_WIDGET(gtk_label_new("Memory Type")), + 1, 2, row, row + 1, GTK_FILL, GTK_FILL, xpad, ypad); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + GTK_WIDGET(gtk_label_new("Volatile")), + 2, 3, row, row + 1, GTK_SHRINK, GTK_SHRINK, xpad, ypad); + gtk_table_attach(GTK_TABLE(ctk_ecc->detailed_table), + GTK_WIDGET(gtk_label_new("Aggregate")), + 3, 4, row, row + 1, GTK_SHRINK, GTK_SHRINK, xpad, ypad); + + /* Start of the data rows, add the single bit error rows first */ + + row = 1; + + /* Single Bit */; + pack_detailed_widgets(ctk_ecc, TRUE, row++, + NVML_MEMORY_LOCATION_DEVICE_MEMORY); + for (loc = NVML_MEMORY_LOCATION_L1_CACHE; + loc < NVML_MEMORY_LOCATION_COUNT; + loc++, row++) { + if (loc == NVML_MEMORY_LOCATION_DEVICE_MEMORY) { + continue; + } + pack_detailed_widgets(ctk_ecc, TRUE, row, loc); + } + + /* Double Bit */ + pack_detailed_widgets(ctk_ecc, FALSE, row++, + NVML_MEMORY_LOCATION_DEVICE_MEMORY); + for (loc = NVML_MEMORY_LOCATION_L1_CACHE; + loc < NVML_MEMORY_LOCATION_COUNT; + loc++, row++) { + if (loc == NVML_MEMORY_LOCATION_DEVICE_MEMORY) { + continue; + } + pack_detailed_widgets(ctk_ecc, FALSE, row, loc); + } + + gtk_widget_set_sensitive(ctk_ecc->detailed_table, ecc_enabled); + + gtk_box_pack_start(GTK_BOX(vbox), ctk_ecc->detailed_table, + FALSE, FALSE, 0); + + /* ECC configuration settings */ hbox = gtk_hbox_new(FALSE, 0); @@ -783,6 +1157,7 @@ GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, gtk_widget_show_all(GTK_WIDGET(ctk_ecc)); update_ecc_info(ctk_ecc); + update_detailed_label_for_values(ctk_ecc); return GTK_WIDGET(ctk_ecc); } diff --git a/src/gtk+-2.x/ctkecc.h b/src/gtk+-2.x/ctkecc.h index 158cf16..424bb65 100644 --- a/src/gtk+-2.x/ctkecc.h +++ b/src/gtk+-2.x/ctkecc.h @@ -22,6 +22,7 @@ #include "ctkevent.h" #include "ctkconfig.h" +#include "nvml.h" G_BEGIN_DECLS @@ -46,6 +47,16 @@ G_BEGIN_DECLS typedef struct _CtkEcc CtkEcc; typedef struct _CtkEccClass CtkEccClass; +typedef struct _CtkEccDetailedTableRow +{ + GtkWidget *err_type; + GtkWidget *mem_type; + GtkWidget *vol_count; + GtkWidget *agg_count; + int vol_count_value; + int agg_count_value; +} CtkEccDetailedTableRow; + struct _CtkEcc { GtkVBox parent; @@ -62,6 +73,7 @@ struct _CtkEcc GtkWidget* clear_aggregate_button; GtkWidget* reset_default_config_button; GtkWidget* configuration_status; + GtkWidget* summary_table; gboolean ecc_enabled; gboolean ecc_configured; @@ -73,6 +85,9 @@ struct _CtkEcc gboolean ecc_config_supported; gboolean ecc_default_status; + GtkWidget* detailed_table; + CtkEccDetailedTableRow single_errors[NVML_MEMORY_LOCATION_COUNT]; + CtkEccDetailedTableRow double_errors[NVML_MEMORY_LOCATION_COUNT]; }; struct _CtkEccClass diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index 8308961..6178e55 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -243,7 +243,6 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class, MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_READING); MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_PROVIDER); MAKE_SIGNAL(NV_CTRL_THERMAL_SENSOR_TARGET); - MAKE_SIGNAL(NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS); MAKE_SIGNAL(NV_CTRL_GPU_PCIE_MAX_LINK_SPEED); MAKE_SIGNAL(NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL); MAKE_SIGNAL(NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE); @@ -386,7 +385,8 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class, MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU); #undef MAKE_BINARY_SIGNAL -#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU +#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != \ + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c index 05c5612..5e2f13e 100644 --- a/src/gtk+-2.x/ctkglx.c +++ b/src/gtk+-2.x/ctkglx.c @@ -1257,7 +1257,7 @@ GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table, ctk_help_title(b, &i, "Graphics Information Help"); ctk_help_para(b, &i, - "This page in the NVIDIA X Server Control Panel describes " + "This page in the NVIDIA Settings Control Panel describes " "information about graphics libraries available on this X " "screen." ); diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c index 99cb759..db0007d 100644 --- a/src/gtk+-2.x/ctkgpu.c +++ b/src/gtk+-2.x/ctkgpu.c @@ -96,7 +96,7 @@ void get_bus_type_str(CtrlTarget *ctrl_target, gchar **bus) gchar *bus_type_str, *bus_rate, *pcie_gen; bus_type = 0xffffffff; - bus_type_str = "Unknown"; + bus_type_str = NULL; ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_BUS_TYPE, &bus_type); if (ret == NvCtrlSuccess) { if (bus_type == NV_CTRL_BUS_TYPE_AGP) @@ -107,6 +107,8 @@ void get_bus_type_str(CtrlTarget *ctrl_target, gchar **bus) bus_type_str = "PCI Express"; else if (bus_type == NV_CTRL_BUS_TYPE_INTEGRATED) bus_type_str = "Integrated"; + else + bus_type_str = "Unknown"; } /* NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH */ @@ -228,8 +230,8 @@ GtkWidget* ctk_gpu_new(CtrlTarget *ctrl_target, ReturnStatus ret; gchar *screens; - gchar *displays; - gchar *tmp_str; + gchar *displays = NULL; + gchar *tmp_str = NULL; gchar *gpu_cores; gchar *memory_interface; gchar *bus = NULL; @@ -508,9 +510,11 @@ GtkWidget* ctk_gpu_new(CtrlTarget *ctrl_target, 0, 0.5, "VBIOS Version:", 0, 0.5, vbios_version); } - add_table_row(table, row++, - 0, 0.5, "Total Memory:", - 0, 0.5, video_ram); + if (video_ram) { + add_table_row(table, row++, + 0, 0.5, "Total Memory:", + 0, 0.5, video_ram); + } add_table_row(table, row++, 0, 0.5, "Total Dedicated Memory:", 0, 0.5, gpu_memory_text); @@ -548,9 +552,11 @@ GtkWidget* ctk_gpu_new(CtrlTarget *ctrl_target, /* spacing */ row += 3; - add_table_row(table, row++, - 0, 0.5, "Bus Type:", - 0, 0.5, bus); + if (bus) { + add_table_row(table, row++, + 0, 0.5, "Bus Type:", + 0, 0.5, bus); + } if ( pci_bus_id ) { add_table_row(table, row++, 0, 0.5, "Bus ID:", @@ -580,13 +586,17 @@ GtkWidget* ctk_gpu_new(CtrlTarget *ctrl_target, add_table_row(table, row++, 0, 0.5, "Maximum PCIe Link Width:", 0, 0.5, link_width_str); - add_table_row(table, row++, - 0, 0.5, "Maximum PCIe Link Speed:", - 0, 0.5, link_speed_str); - ctk_gpu->pcie_utilization_label = + if (link_speed_str) { add_table_row(table, row++, - 0, 0.5, "PCIe Bandwidth Utilization:", - 0, 0.5, NULL); + 0, 0.5, "Maximum PCIe Link Speed:", + 0, 0.5, link_speed_str); + } + if (entry.pcie_specified) { + ctk_gpu->pcie_utilization_label = + add_table_row(table, row++, + 0, 0.5, "PCIe Bandwidth Utilization:", + 0, 0.5, NULL); + } g_free(link_speed_str); g_free(link_width_str); @@ -595,19 +605,22 @@ GtkWidget* ctk_gpu_new(CtrlTarget *ctrl_target, } update_gpu_usage(ctk_gpu); - /* spacing */ - row += 3; - add_table_row(table, row++, - 0, 0, "X Screens:", - 0, 0, screens); - /* spacing */ - displays = make_display_device_list(ctrl_target); - row += 3; - ctk_gpu->displays = - add_table_row(table, row, - 0, 0, "Display Devices:", - 0, 0, displays); + if (ctrl_target->system->has_nv_control) { + /* spacing */ + row += 3; + add_table_row(table, row++, + 0, 0, "X Screens:", + 0, 0, screens); + /* spacing */ + displays = make_display_device_list(ctrl_target); + + row += 3; + ctk_gpu->displays = + add_table_row(table, row, + 0, 0, "Display Devices:", + 0, 0, displays); + } free(product_name); free(vbios_version); @@ -657,7 +670,7 @@ GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table, ctk_help_title(b, &i, "Graphics Card Information Help"); ctk_help_para(b, &i, "This page in the NVIDIA " - "X Server Control Panel describes basic " + "Settings Control Panel describes basic " "information about the Graphics Processing Unit " "(GPU)."); diff --git a/src/gtk+-2.x/ctkhelp.c b/src/gtk+-2.x/ctkhelp.c index 6a50461..ac4ce09 100644 --- a/src/gtk+-2.x/ctkhelp.c +++ b/src/gtk+-2.x/ctkhelp.c @@ -82,7 +82,7 @@ GtkWidget* ctk_help_new(GtkWidget *toggle_button, GtkTextTagTable *tag_table) ctk_help->toggle_button = toggle_button; gtk_window_set_title(GTK_WINDOW(ctk_help), - "NVIDIA X Server Settings Help"); + "NVIDIA Settings Help"); gtk_window_set_default_size(GTK_WINDOW(ctk_help), -1, 400); @@ -203,7 +203,7 @@ static GtkTextBuffer *create_default_help(CtkHelp *ctk_help) gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0); gtk_text_buffer_insert_with_tags_by_name - (buffer, &iter, "\nNVIDIA X Server Settings Help", -1, + (buffer, &iter, "\nNVIDIA Settings Help", -1, CTK_HELP_TITLE_TAG, NULL); gtk_text_buffer_insert(buffer, &iter, "\n\nThere is no help available " diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c index e8cc66b..c0bc8e6 100644 --- a/src/gtk+-2.x/ctkpowermizer.c +++ b/src/gtk+-2.x/ctkpowermizer.c @@ -81,13 +81,10 @@ static const char *__gpu_clock_freq_help = static const char *__memory_transfer_rate_freq_help = "This indicates the current Memory transfer rate."; -static const char *__processor_clock_freq_help = -"This indicates the current Processor Clock frequency."; - static const char *__performance_levels_table_help = "This indicates the Performance Levels available for the GPU. Each " "performance level is indicated by a Performance Level number, along with " -"the Graphics, Memory and Processor clocks for that level. The currently active " +"the Graphics and Memory clocks for that level. The currently active " "performance level is shown in regular text. All other performance " "levels are shown in gray. Note that multiple performance levels may share " "the same range of available clocks."; @@ -162,8 +159,6 @@ typedef struct { gboolean perf_level_specified; gint nvclock; gboolean nvclock_specified; - gint processorclock; - gboolean processorclock_specified; gint nvclockmin; gboolean nvclockmin_specified; gint nvclockmax; @@ -176,11 +171,6 @@ typedef struct { gint memtransferratemax; gint memtransferrateeditable; gboolean memtransferratemax_specified; - gint processorclockmin; - gboolean processorclockmin_specified; - gint processorclockmax; - gint processorclockeditable; - gboolean processorclockmax_specified; } perfModeEntry, * perfModeEntryPtr; @@ -213,17 +203,6 @@ static void apply_perf_mode_token(char *token, char *value, void *data) pEntry->memtransferratemax_specified = TRUE; } else if (!strcasecmp("memtransferrateeditable", token)) { pEntry->memtransferrateeditable = atoi(value); - } else if (!strcasecmp("processorclock", token)) { - pEntry->processorclock = atoi(value); - pEntry->processorclock_specified = TRUE; - } else if (!strcasecmp("processorclockmin", token)) { - pEntry->processorclockmin = atoi(value); - pEntry->processorclockmax_specified = TRUE; - } else if (!strcasecmp("processorclockmax", token)) { - pEntry->processorclockmax = atoi(value); - pEntry->processorclockmax_specified = TRUE; - } else if (!strcasecmp("processorclockeditable", token)) { - pEntry->nvclockeditable = atoi(value); } } @@ -659,9 +638,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, if (!ctk_powermizer->hasDecoupledClock && ((pEntry[index].nvclockmax != pEntry[index].nvclockmin) || (pEntry[index].memtransferratemax != - pEntry[index].memtransferratemin) || - (pEntry[index].processorclockmax != - pEntry[index].processorclockmin))) { + pEntry[index].memtransferratemin))) { ctk_powermizer->hasDecoupledClock = TRUE; } /* Set hasEditablePerfLevel flag to decide editable performance @@ -767,27 +744,6 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, col_idx += 4; } - if (ctk_powermizer->processor_clock) { - /* Processor clock */ - label = gtk_label_new("Processor Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+3, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Min"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - label = gtk_label_new("Max"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3, 1, 2, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - - /* Vertical separator */ - vsep = gtk_vseparator_new(); - gtk_table_attach(GTK_TABLE(table), vsep, col_idx+3, col_idx+4, - 0, row_idx, - GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0); - } } else { table = gtk_table_new(1, 4, FALSE); @@ -821,13 +777,6 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); col_idx++; } - - if (ctk_powermizer->processor_clock) { - label = gtk_label_new("Processor Clock"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } } /* Parse the perf levels and populate the table */ @@ -892,22 +841,6 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); col_idx +=4; } - if (ctk_powermizer->processor_clock) { - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmin); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmax); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } row_idx++; } else if ((pEntry[i].perf_level_specified) && (pEntry[i].nvclock_specified)) { @@ -951,15 +884,6 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); col_idx++; } - if (ctk_powermizer->processor_clock) { - g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclock); - label = gtk_label_new(tmp_str); - gtk_widget_set_sensitive(label, active); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, col_idx, col_idx+1, - row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - } row_idx++; } else { nv_warning_msg("Incomplete Perf Mode (perf=%d, nvclock=%d," @@ -1037,12 +961,6 @@ static gboolean update_powermizer_info(gpointer user_data) gtk_label_set_text(GTK_LABEL(ctk_powermizer->memory_transfer_rate), s); g_free(s); } - - if (ctk_powermizer->processor_clock && pEntry.processorclock_specified) { - s = g_strdup_printf("%d Mhz", pEntry.processorclock); - gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s); - g_free(s); - } } free(clock_string); @@ -1064,13 +982,15 @@ static gboolean update_powermizer_info(gpointer user_data) g_free(s); } - if (ctk_powermizer->pcie_gen_queriable) { + if (ctk_powermizer->link_width) { /* NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH */ s = get_pcie_link_width_string(ctrl_target, NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH); gtk_label_set_text(GTK_LABEL(ctk_powermizer->link_width), s); g_free(s); + } + if (ctk_powermizer->link_speed) { /* NV_CTRL_GPU_PCIE_MAX_LINK_SPEED */ s = get_pcie_link_speed_string(ctrl_target, NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED); @@ -1183,13 +1103,13 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, gint row = 0; gchar *s = NULL; gint tmp; - gboolean processor_clock_available = FALSE; gboolean power_source_available = FALSE; gboolean perf_level_available = FALSE; gboolean gpu_clock_available = FALSE; gboolean mem_transfer_rate_available = FALSE; gboolean adaptive_clock_state_available = FALSE; - gboolean pcie_gen_queriable = FALSE; + gboolean pcie_link_width_available = FALSE; + gboolean pcie_link_speed_available = FALSE; CtrlAttributeValidValues valid_modes; char *clock_string = NULL; perfModeEntry pEntry; @@ -1241,23 +1161,27 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, if (pEntry.memtransferrate_specified) { mem_transfer_rate_available = TRUE; } - if (pEntry.processorclock_specified) { - processor_clock_available = TRUE; - } } free(clock_string); /* NV_CTRL_GPU_PCIE_GENERATION */ - ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_PCIE_GENERATION, &tmp); + ret = NvCtrlGetAttribute(ctrl_target, + NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH, + &tmp); if (ret == NvCtrlSuccess) { - pcie_gen_queriable = TRUE; + pcie_link_width_available = TRUE; + } + + ret = NvCtrlGetAttribute(ctrl_target, + NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED, + &tmp); + if (ret == NvCtrlSuccess) { + pcie_link_speed_available = TRUE; } /* return early if query to attributes fail */ - if (!power_source_available && !perf_level_available && - !adaptive_clock_state_available && !gpu_clock_available && - !processor_clock_available && !pcie_gen_queriable) { + if (!perf_level_available && !gpu_clock_available) { return NULL; } /* create the CtkPowermizer object */ @@ -1267,7 +1191,6 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, ctk_powermizer = CTK_POWERMIZER(object); ctk_powermizer->ctrl_target = ctrl_target; ctk_powermizer->ctk_config = ctk_config; - ctk_powermizer->pcie_gen_queriable = pcie_gen_queriable; ctk_powermizer->hasDecoupledClock = FALSE; ctk_powermizer->hasEditablePerfLevel = FALSE; ctk_powermizer->editable_performance_levels_unified = FALSE; @@ -1384,24 +1307,6 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, } else { ctk_powermizer->memory_transfer_rate = NULL; } - /* Processor clock */ - if (processor_clock_available) { - /* spacing */ - row += 3; - ctk_powermizer->processor_clock = - add_table_row_with_help_text(table, ctk_config, - __processor_clock_freq_help, - row++, //row - 0, // column - 0.0f, - 0.5, - "Processor Clock:", - 0.0, - 0.5, - NULL); - } else { - ctk_powermizer->processor_clock = NULL; - } /* Power Source */ if (power_source_available) { /* spacing */ @@ -1420,10 +1325,13 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, } else { ctk_powermizer->power_source = NULL; } - /* Current PCIe Link Width */ - if (ctk_powermizer->pcie_gen_queriable) { + /* PCIe Gen Info block */ + if (pcie_link_width_available || pcie_link_speed_available) { /* spacing */ row += 3; + } + /* Current PCIe Link Width */ + if (pcie_link_width_available) { ctk_powermizer->link_width = add_table_row_with_help_text(table, ctk_config, __current_pcie_link_width_help, @@ -1436,7 +1344,11 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, 0.5, NULL); - /* Current PCIe Link Speed */ + } else { + ctk_powermizer->link_width = NULL; + } + /* Current PCIe Link Speed */ + if (pcie_link_speed_available) { ctk_powermizer->link_speed = add_table_row_with_help_text(table, ctk_config, __current_pcie_link_speed_help, @@ -1449,7 +1361,6 @@ GtkWidget* ctk_powermizer_new(CtrlTarget *ctrl_target, 0.5, NULL); } else { - ctk_powermizer->link_width = NULL; ctk_powermizer->link_speed = NULL; } @@ -1795,11 +1706,7 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table, if (ctk_powermizer->gpu_clock) { ctk_help_heading(b, &i, "Clock Frequencies"); - if (ctk_powermizer->memory_transfer_rate && - ctk_powermizer->processor_clock) { - s = "This indicates the GPU's current Graphics Clock, " - "Memory transfer rate and Processor Clock frequencies."; - } else if (ctk_powermizer->memory_transfer_rate) { + if (ctk_powermizer->memory_transfer_rate) { s = "This indicates the GPU's current Graphics Clock and " "Memory transfer rate."; } else { @@ -1813,9 +1720,11 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, "%s", __power_source_help); } - if (ctk_powermizer->pcie_gen_queriable) { + if (ctk_powermizer->link_width) { ctk_help_heading(b, &i, "Current PCIe link width"); ctk_help_para(b, &i, "%s", __current_pcie_link_width_help); + } + if (ctk_powermizer->link_speed) { ctk_help_heading(b, &i, "Current PCIe link speed"); ctk_help_para(b, &i, "%s", __current_pcie_link_speed_help); } diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h index 4260ad1..10712e0 100644 --- a/src/gtk+-2.x/ctkpowermizer.h +++ b/src/gtk+-2.x/ctkpowermizer.h @@ -55,7 +55,6 @@ struct _CtkPowermizer GtkWidget *adaptive_clock_status; GtkWidget *gpu_clock; GtkWidget *memory_transfer_rate; - GtkWidget *processor_clock; GtkWidget *power_source; GtkWidget *performance_level; GtkWidget *performance_table_hbox; @@ -78,7 +77,6 @@ struct _CtkPowermizer GtkWidget *link_width; GtkWidget *link_speed; - gboolean pcie_gen_queriable; }; struct _CtkPowermizerClass diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c index a452849..d186d5c 100644 --- a/src/gtk+-2.x/ctkscreen.c +++ b/src/gtk+-2.x/ctkscreen.c @@ -367,7 +367,7 @@ GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *table, ctk_help_title(b, &i, "X Screen Information Help"); ctk_help_para(b, &i, "This page in the NVIDIA " - "X Server Control Panel describes basic " + "Settings Control Panel describes basic " "information about the X Screen '%s'.", screen_name); diff --git a/src/gtk+-2.x/ctkserver.c b/src/gtk+-2.x/ctkserver.c index e4c21c1..1de17d4 100644 --- a/src/gtk+-2.x/ctkserver.c +++ b/src/gtk+-2.x/ctkserver.c @@ -247,21 +247,27 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, GtkWidget *hseparator; GtkWidget *table; - gchar *os; - gchar *arch; - gchar *driver_version; + CtrlTarget *gpu_target = NULL; + + gchar *os = NULL; + gchar *arch = NULL; + gchar *driver_version = NULL; + gchar *nvml_version = NULL; gchar *dname = NvCtrlGetDisplayName(ctrl_target); - gchar *display_name; - gchar *server_version; - gchar *vendor_str; - gchar *vendor_ver; - gchar *nv_control_server_version; - gchar *num_screens; + gchar *display_name = NULL; + gchar *server_version = NULL; + gchar *vendor_str = NULL; + gchar *vendor_ver = NULL; + gchar *nv_control_server_version = NULL; + gchar *num_screens = NULL; ReturnStatus ret; int tmp, os_val; int xinerama_enabled; + int row; + + gpu_target = NvCtrlGetDefaultTargetByType(ctrl_target->system, GPU_TARGET); /* * get the data that we will display below @@ -276,72 +282,85 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, xinerama_enabled = FALSE; } - /* NV_CTRL_OPERATING_SYSTEM */ + if (ctrl_target->system->has_nv_control) { - os_val = NV_CTRL_OPERATING_SYSTEM_LINUX; - ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_OPERATING_SYSTEM, &os_val); - os = NULL; - if (ret == NvCtrlSuccess) { - if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) os = "Linux"; - else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD"; - else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) os = "SunOS"; - } - if (!os) os = "Unknown"; - - /* NV_CTRL_ARCHITECTURE */ - - ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_ARCHITECTURE, &tmp); - arch = NULL; - if (ret == NvCtrlSuccess) { - switch (tmp) { - case NV_CTRL_ARCHITECTURE_X86: arch = "x86"; break; - case NV_CTRL_ARCHITECTURE_X86_64: arch = "x86_64"; break; - case NV_CTRL_ARCHITECTURE_IA64: arch = "ia64"; break; - case NV_CTRL_ARCHITECTURE_ARM: arch = "ARM"; break; - case NV_CTRL_ARCHITECTURE_AARCH64: arch = "AArch64"; break; - case NV_CTRL_ARCHITECTURE_PPC64LE: arch = "ppc64le"; break; + /* NV_CTRL_OPERATING_SYSTEM */ + + os_val = NV_CTRL_OPERATING_SYSTEM_LINUX; + ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_OPERATING_SYSTEM, &os_val); + os = NULL; + if (ret == NvCtrlSuccess) { + if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) os = "Linux"; + else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD"; + else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) os = "SunOS"; } + if (!os) os = "Unknown"; + + /* NV_CTRL_ARCHITECTURE */ + + ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_ARCHITECTURE, &tmp); + arch = NULL; + if (ret == NvCtrlSuccess) { + switch (tmp) { + case NV_CTRL_ARCHITECTURE_X86: arch = "x86"; break; + case NV_CTRL_ARCHITECTURE_X86_64: arch = "x86_64"; break; + case NV_CTRL_ARCHITECTURE_IA64: arch = "ia64"; break; + case NV_CTRL_ARCHITECTURE_ARM: arch = "ARM"; break; + case NV_CTRL_ARCHITECTURE_AARCH64: arch = "AArch64"; break; + case NV_CTRL_ARCHITECTURE_PPC64LE: arch = "ppc64le"; break; + } + } + if (!arch) arch = "Unknown"; + os = g_strdup_printf("%s-%s", os, arch); } - if (!arch) arch = "Unknown"; - os = g_strdup_printf("%s-%s", os, arch); /* NV_CTRL_STRING_NVIDIA_DRIVER_VERSION */ driver_version = get_nvidia_driver_version(ctrl_target); - /* Display Name */ + /* NV_CTRL_STRING_NVML_VERSION */ - display_name = nv_standardize_screen_name(dname, -2); + NvCtrlGetStringAttribute(gpu_target, + NV_CTRL_STRING_NVML_VERSION, + &nvml_version); - /* X Server Version */ + if (ctrl_target->system->has_nv_control) { - server_version = g_strdup_printf("%d.%d", - NvCtrlGetProtocolVersion(ctrl_target), - NvCtrlGetProtocolRevision(ctrl_target)); + /* Display Name */ - /* Server Vendor String */ + display_name = nv_standardize_screen_name(dname, -2); - vendor_str = g_strdup(NvCtrlGetServerVendor(ctrl_target)); + /* X Server Version */ - /* Server Vendor Version */ + server_version = g_strdup_printf("%d.%d", + NvCtrlGetProtocolVersion(ctrl_target), + NvCtrlGetProtocolRevision(ctrl_target)); - vendor_ver = get_server_vendor_version(ctrl_target); + /* Server Vendor String */ - /* NV_CTRL_STRING_NV_CONTROL_VERSION */ + vendor_str = g_strdup(NvCtrlGetServerVendor(ctrl_target)); - ret = NvCtrlGetStringAttribute(ctrl_target, - NV_CTRL_STRING_NV_CONTROL_VERSION, - &nv_control_server_version); - if (ret != NvCtrlSuccess) nv_control_server_version = NULL; + /* Server Vendor Version */ - /* # Logical X Screens */ + vendor_ver = get_server_vendor_version(ctrl_target); + + /* NV_CTRL_STRING_NV_CONTROL_VERSION */ + + ret = NvCtrlGetStringAttribute(ctrl_target, + NV_CTRL_STRING_NV_CONTROL_VERSION, + &nv_control_server_version); + if (ret != NvCtrlSuccess) nv_control_server_version = NULL; + + /* # Logical X Screens */ + + if (xinerama_enabled) { + num_screens = g_strdup_printf("%d (Xinerama)", + NvCtrlGetScreenCount(ctrl_target)); + } else { + num_screens = g_strdup_printf("%d", + NvCtrlGetScreenCount(ctrl_target)); + } - if (xinerama_enabled) { - num_screens = g_strdup_printf("%d (Xinerama)", - NvCtrlGetScreenCount(ctrl_target)); - } else { - num_screens = g_strdup_printf("%d", - NvCtrlGetScreenCount(ctrl_target)); } @@ -363,7 +382,7 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, } else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) { banner = ctk_banner_image_new(BANNER_ARTWORK_SOLARIS); } else { - banner = ctk_banner_image_new(BANNER_ARTWORK_PENGUIN); + banner = ctk_banner_image_new(BANNER_ARTWORK_BLANK); } gtk_box_pack_start(GTK_BOX(ctk_object), banner, FALSE, FALSE, 0); @@ -384,7 +403,7 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); - table = gtk_table_new(2, 2, FALSE); + table = gtk_table_new(3, 2, FALSE); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 3); @@ -392,47 +411,56 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, gtk_container_set_border_width(GTK_CONTAINER(table), 5); - add_table_row(table, 0, - 0, 0.5, "Operating System:", 0, 0.5, os); - add_table_row(table, 1, + row = 0; + if (os) { + add_table_row(table, row++, + 0, 0.5, "Operating System:", 0, 0.5, os); + } + add_table_row(table, row++, 0, 0.5, "NVIDIA Driver Version:", 0, 0.5, driver_version); + if (nvml_version) { + add_table_row(table, row++, + 0, 0.5, "NVML Version:", 0, 0.5, nvml_version); + } /* * This displays basic X Server information, including * version number, vendor information and the number of * X Screens. */ + if (ctrl_target->system->has_nv_control) { - hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new("X Server Information"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - hseparator = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - table = gtk_table_new(15, 2, FALSE); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); - gtk_table_set_row_spacings(GTK_TABLE(table), 3); - gtk_table_set_col_spacings(GTK_TABLE(table), 15); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); + label = gtk_label_new("X Server Information"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - add_table_row(table, 0, - 0, 0.5, "Display Name:", 0, 0.5, display_name); - /* separator */ - add_table_row(table, 4, - 0, 0.5, "Server Version Number:", 0, 0.5, server_version); - add_table_row(table, 5, - 0, 0.5, "Server Vendor String:", 0, 0.5, vendor_str); - add_table_row(table, 6, - 0, 0.5, "Server Vendor Version:", 0, 0.5, vendor_ver); - /* separator */ - add_table_row(table, 10, - 0, 0, "NV-CONTROL Version:", 0, 0, nv_control_server_version); - /* separator */ - add_table_row(table, 14, - 0, 0, "Screens:", 0, 0, num_screens); + hseparator = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); + + table = gtk_table_new(15, 2, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 15); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + + add_table_row(table, 0, + 0, 0.5, "Display Name:", 0, 0.5, display_name); + /* separator */ + add_table_row(table, 4, + 0, 0.5, "Server Version Number:", 0, 0.5, server_version); + add_table_row(table, 5, + 0, 0.5, "Server Vendor String:", 0, 0.5, vendor_str); + add_table_row(table, 6, + 0, 0.5, "Server Vendor Version:", 0, 0.5, vendor_ver); + /* separator */ + add_table_row(table, 10, + 0, 0, "NV-CONTROL Version:", 0, 0, nv_control_server_version); + /* separator */ + add_table_row(table, 14, + 0, 0, "Screens:", 0, 0, num_screens); + } /* print special trademark text for FreeBSD */ @@ -472,6 +500,7 @@ GtkWidget* ctk_server_new(CtrlTarget *ctrl_target, g_free(display_name); g_free(os); free(driver_version); + free(nvml_version); g_free(server_version); g_free(vendor_str); @@ -499,7 +528,7 @@ GtkTextBuffer *ctk_server_create_help(GtkTextTagTable *table, gtk_text_buffer_get_iter_at_offset(b, &i, 0); - ctk_help_title(b, &i, "X Server Information Help"); + ctk_help_title(b, &i, "System Information Help"); ctk_help_heading(b, &i, "Operating System"); ctk_help_para(b, &i, "This is the operating system on which the NVIDIA " diff --git a/src/gtk+-2.x/ctkthermal.c b/src/gtk+-2.x/ctkthermal.c index 48676fb..f32e0e8 100644 --- a/src/gtk+-2.x/ctkthermal.c +++ b/src/gtk+-2.x/ctkthermal.c @@ -101,9 +101,12 @@ static const char * __fan_id_help = static const char * __fan_rpm_help = "This shows the current GPU Fan Speed in rotations per minute (RPM)."; -static const char * __fan_speed_help = +static const char * __fan_current_speed_help = "This shows the current GPU Fan Speed level as a percentage."; +static const char * __fan_target_speed_help = +"This shows the target GPU Fan Speed level as a percentage."; + static const char * __fan_control_type_help = "Fan Type indicates if and how this fan may be controlled. Possible " "types are Variable, Toggle or Restricted. Variable fans can be " @@ -163,9 +166,12 @@ static gboolean update_cooler_info(gpointer user_data) gchar *tmp_str; CtkThermal *ctk_thermal; GtkWidget *table, *label, *eventbox; - gint ret; + gint ret, ret2; gint row_idx; /* Where to insert into the cooler info table */ - + gboolean cooler_extra_info = FALSE; + int num_cols = 2; + int current_speed_attr; + ctk_thermal = CTK_THERMAL(user_data); /* Since table cell management in GTK lacks, just remove and rebuild @@ -178,7 +184,17 @@ static gboolean update_cooler_info(gpointer user_data) /* Generate a new table */ - table = gtk_table_new(1, 5, FALSE); + ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[0].ctrl_target, + NV_CTRL_THERMAL_COOLER_CONTROL_TYPE, &cooler_type); + ret2 = NvCtrlGetAttribute(ctk_thermal->cooler_control[0].ctrl_target, + NV_CTRL_THERMAL_COOLER_TARGET, &cooler_target); + if (ret == NvCtrlSuccess && ret2 == NvCtrlSuccess) { + cooler_extra_info = TRUE; + ctk_thermal->thermal_cooler_extra_info_supported = cooler_extra_info; + num_cols = 5; + } + + table = gtk_table_new(1, num_cols, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); @@ -194,39 +210,51 @@ static gboolean update_cooler_info(gpointer user_data) gtk_container_add(GTK_CONTAINER(eventbox), label); ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_id_help); - label = gtk_label_new("Speed (RPM)"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); eventbox = gtk_event_box_new(); + if (cooler_extra_info) { + current_speed_attr = NV_CTRL_THERMAL_COOLER_SPEED; + label = gtk_label_new("Speed (RPM)"); + ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, + __fan_rpm_help); + } else { + current_speed_attr = NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL; + label = gtk_label_new("Current Speed (%)"); + ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, + __fan_current_speed_help); + } + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); gtk_container_add(GTK_CONTAINER(eventbox), label); - ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_rpm_help); - label = gtk_label_new("Speed (%)"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - eventbox = gtk_event_box_new(); - gtk_table_attach(GTK_TABLE(table), eventbox, 2, 3, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_container_add(GTK_CONTAINER(eventbox), label); - ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_speed_help); + if (cooler_extra_info) { + label = gtk_label_new("Target Speed (%)"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + eventbox = gtk_event_box_new(); + gtk_table_attach(GTK_TABLE(table), eventbox, 2, 3, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_container_add(GTK_CONTAINER(eventbox), label); + ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, + __fan_target_speed_help); - label = gtk_label_new("Control Type"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - eventbox = gtk_event_box_new(); - gtk_table_attach(GTK_TABLE(table), eventbox, 3, 4, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_container_add(GTK_CONTAINER(eventbox), label); - ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, - __fan_control_type_help); + label = gtk_label_new("Control Type"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + eventbox = gtk_event_box_new(); + gtk_table_attach(GTK_TABLE(table), eventbox, 3, 4, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_container_add(GTK_CONTAINER(eventbox), label); + ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, + __fan_control_type_help); - label = gtk_label_new("Cooling Target"); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - eventbox = gtk_event_box_new(); - gtk_table_attach(GTK_TABLE(table), eventbox, 4, 5, 0, 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - gtk_container_add(GTK_CONTAINER(eventbox), label); - ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, - __fan_cooling_target_help); + label = gtk_label_new("Cooling Target"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + eventbox = gtk_event_box_new(); + gtk_table_attach(GTK_TABLE(table), eventbox, 4, 5, 0, 1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + gtk_container_add(GTK_CONTAINER(eventbox), label); + ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, + __fan_cooling_target_help); + } /* Fill the cooler info */ for (i = 0; i < ctk_thermal->cooler_count; i++) { @@ -242,7 +270,7 @@ static gboolean update_cooler_info(gpointer user_data) free(tmp_str); ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, - NV_CTRL_THERMAL_COOLER_SPEED, + current_speed_attr, &speed); if (ret == NvCtrlSuccess) { tmp_str = g_strdup_printf("%d", speed); @@ -256,69 +284,79 @@ static gboolean update_cooler_info(gpointer user_data) GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); free(tmp_str); - ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, - NV_CTRL_THERMAL_COOLER_LEVEL, - &level); - if (ret != NvCtrlSuccess) { - /* cooler information no longer available */ - return FALSE; - } - tmp_str = g_strdup_printf("%d", level); - label = gtk_label_new(tmp_str); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - free(tmp_str); + if (cooler_extra_info) { + ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, + NV_CTRL_THERMAL_COOLER_LEVEL, + &level); + if (ret != NvCtrlSuccess) { + /* cooler information no longer available */ + return FALSE; + } + tmp_str = g_strdup_printf("%d", level); + label = gtk_label_new(tmp_str); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + free(tmp_str); - ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, - NV_CTRL_THERMAL_COOLER_CONTROL_TYPE, - &cooler_type); - if (ret != NvCtrlSuccess) { - /* cooler information no longer available */ - return FALSE; - } - if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_VARIABLE) { - tmp_str = g_strdup_printf("Variable"); - } else if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_TOGGLE) { - tmp_str = g_strdup_printf("Toggle"); - } else if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_NONE) { - tmp_str = g_strdup_printf("Restricted"); - } - label = gtk_label_new(tmp_str); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - free(tmp_str); + ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, + NV_CTRL_THERMAL_COOLER_CONTROL_TYPE, + &cooler_type); + if (ret != NvCtrlSuccess && ret != NvCtrlNotSupported) { + return FALSE; + } - ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, - NV_CTRL_THERMAL_COOLER_TARGET, - &cooler_target); - if (ret != NvCtrlSuccess) { - /* cooler information no longer available */ - return FALSE; - } - switch(cooler_target) { - case NV_CTRL_THERMAL_COOLER_TARGET_GPU: - tmp_str = g_strdup_printf("GPU"); - break; - case NV_CTRL_THERMAL_COOLER_TARGET_MEMORY: - tmp_str = g_strdup_printf("Memory"); - break; - case NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY: - tmp_str = g_strdup_printf("Power Supply"); - break; - case NV_CTRL_THERMAL_COOLER_TARGET_GPU_RELATED: - tmp_str = g_strdup_printf("GPU, Memory, and Power Supply"); - break; - default: - break; + if (ret == NvCtrlNotSupported) { + tmp_str = g_strdup_printf("Unknown"); + } else if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_VARIABLE) { + tmp_str = g_strdup_printf("Variable"); + } else if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_TOGGLE) { + tmp_str = g_strdup_printf("Toggle"); + } else if (cooler_type == NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_NONE) { + tmp_str = g_strdup_printf("Restricted"); + } + label = gtk_label_new(tmp_str); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + free(tmp_str); + + ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].ctrl_target, + NV_CTRL_THERMAL_COOLER_TARGET, + &cooler_target); + if (ret != NvCtrlSuccess && ret != NvCtrlNotSupported) { + return FALSE; + } + + if (ret == NvCtrlNotSupported) { + tmp_str = g_strdup_printf("Unknown"); + } else { + + switch(cooler_target) { + case NV_CTRL_THERMAL_COOLER_TARGET_GPU: + tmp_str = g_strdup_printf("GPU"); + break; + case NV_CTRL_THERMAL_COOLER_TARGET_MEMORY: + tmp_str = g_strdup_printf("Memory"); + break; + case NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY: + tmp_str = g_strdup_printf("Power Supply"); + break; + case NV_CTRL_THERMAL_COOLER_TARGET_GPU_RELATED: + tmp_str = g_strdup_printf("GPU, Memory, and Power Supply"); + break; + default: + break; + } + } + label = gtk_label_new(tmp_str); + gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); + gtk_table_attach(GTK_TABLE(table), label, 4, 5, row_idx, row_idx+1, + GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); + free(tmp_str); } - label = gtk_label_new(tmp_str); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(table), label, 4, 5, row_idx, row_idx+1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); - free(tmp_str); } + gtk_widget_show_all(table); /* X driver takes fraction of second to refresh newly set value */ @@ -1079,7 +1117,7 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, CtrlTarget *sensor_target; CtrlAttributeValidValues cooler_range; CtrlAttributeValidValues sensor_range; - gint trigger, core, ambient; + gint slowdown, core, ambient; gint upper; gchar *s; gint i, j; @@ -1094,7 +1132,6 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, Bool cooler_control_enabled; int cur_cooler_idx = 0; int cur_sensor_idx = 0; - int slowdown; Bool thermal_sensor_target_type_supported = FALSE; /* make sure we have a handle */ @@ -1127,21 +1164,21 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, /* thermal information unavailable */ return NULL; } + } - ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_MAX_CORE_THRESHOLD, - &upper); - if (ret != NvCtrlSuccess) { - /* thermal information unavailable */ - return NULL; - } + ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_SLOWDOWN_THRESHOLD, + &slowdown); + if (ret != NvCtrlSuccess) { + slowdown = 0; + } - ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_CORE_THRESHOLD, - &trigger); - if (ret != NvCtrlSuccess) { - /* thermal information unavailable */ - return NULL; - } + ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_SHUTDOWN_THRESHOLD, + &upper); + if (ret != NvCtrlSuccess) { + upper = slowdown; } + + /* Query the list of sensors attached to this GPU */ ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, @@ -1227,13 +1264,6 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, hsep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox1), hsep, TRUE, TRUE, 0); - ret = NvCtrlGetAttribute(ctk_thermal->ctrl_target, - NV_CTRL_GPU_SLOWDOWN_THRESHOLD, - &slowdown); - if (ret != NvCtrlSuccess) { - slowdown = 0; - } - if (ctk_thermal->sensor_count > 0) { ctk_thermal->sensor_info = (SensorInfoPtr) nvalloc(ctk_thermal->sensor_count * sizeof(SensorInfoRec)); @@ -1294,34 +1324,37 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, vbox1 = gtk_vbox_new(FALSE, 0); hbox1 = gtk_hbox_new(FALSE, 0); - frame = gtk_frame_new("Slowdown Threshold"); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox1), vbox1, FALSE, FALSE, 5); - gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0); - hbox2 = gtk_hbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(hbox2), FRAME_PADDING); - gtk_container_add(GTK_CONTAINER(frame), hbox2); + if (slowdown > 0) { + frame = gtk_frame_new("Slowdown Threshold"); + gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0); - label = gtk_label_new("Degrees: "); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + hbox2 = gtk_hbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox2), FRAME_PADDING); + gtk_container_add(GTK_CONTAINER(frame), hbox2); - eventbox = gtk_event_box_new(); - gtk_box_pack_start(GTK_BOX(hbox2), eventbox, FALSE, FALSE, 0); + label = gtk_label_new("Degrees: "); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - entry = gtk_entry_new(); - gtk_entry_set_max_length(GTK_ENTRY(entry), 5); - gtk_container_add(GTK_CONTAINER(eventbox), entry); - gtk_widget_set_sensitive(entry, FALSE); - gtk_entry_set_width_chars(GTK_ENTRY(entry), 5); + eventbox = gtk_event_box_new(); + gtk_box_pack_start(GTK_BOX(hbox2), eventbox, FALSE, FALSE, 0); - s = g_strdup_printf(" %d ", trigger); - gtk_entry_set_text(GTK_ENTRY(entry), s); - g_free(s); - ctk_config_set_tooltip(ctk_config, eventbox, __core_threshold_help); + entry = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(entry), 5); + gtk_container_add(GTK_CONTAINER(eventbox), entry); + gtk_widget_set_sensitive(entry, FALSE); + gtk_entry_set_width_chars(GTK_ENTRY(entry), 5); - label = gtk_label_new(" C"); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + s = g_strdup_printf(" %d ", slowdown); + gtk_entry_set_text(GTK_ENTRY(entry), s); + g_free(s); + ctk_config_set_tooltip(ctk_config, eventbox, __core_threshold_help); + + label = gtk_label_new(" C"); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + } /* GPU Core Temperature */ @@ -1376,7 +1409,7 @@ GtkWidget* ctk_thermal_new(CtrlTarget *ctrl_target, } /* GPU Core Temperature Gauge */ - + ctk_thermal->core_gauge = pack_gauge(hbox1, 25, upper, ctk_config, __temp_level_help); } @@ -1679,26 +1712,32 @@ next_help: ctk_help_heading(b, &i, "ID"); ctk_help_para(b, &i, "%s", __fan_id_help); - ctk_help_heading(b, &i, "Speed (RPM)"); - ctk_help_para(b, &i,"%s", __fan_rpm_help); + if (ctk_thermal->thermal_cooler_extra_info_supported) { + ctk_help_heading(b, &i, "Speed (RPM)"); + ctk_help_para(b, &i,"%s", __fan_rpm_help); - ctk_help_heading(b, &i, "Speed (%%)"); - ctk_help_para(b, &i, "%s", __fan_speed_help); + ctk_help_heading(b, &i, "Target Speed (%%)"); + ctk_help_para(b, &i, "%s", __fan_target_speed_help); - ctk_help_heading(b, &i, "Type"); - ctk_help_para(b, &i, "%s", __fan_control_type_help); + ctk_help_heading(b, &i, "Type"); + ctk_help_para(b, &i, "%s", __fan_control_type_help); - ctk_help_heading(b, &i, "Cooling Target"); - ctk_help_para(b, &i, "%s", __fan_cooling_target_help); + ctk_help_heading(b, &i, "Cooling Target"); + ctk_help_para(b, &i, "%s", __fan_cooling_target_help); - ctk_help_heading(b, &i, "Enable GPU Fan Settings"); - ctk_help_para(b, &i, "%s", __enable_button_help); + } else { + ctk_help_heading(b, &i, "Current Speed (%%)"); + ctk_help_para(b, &i,"%s", __fan_current_speed_help); + } if ( ctk_thermal->show_fan_control_frame ) { ctk_help_heading(b, &i, "Enable GPU Fan Settings"); + ctk_help_para(b, &i, "%s", __enable_button_help); + + ctk_help_heading(b, &i, "Apply"); ctk_help_para(b, &i, "%s", __apply_button_help); - ctk_help_heading(b, &i, "Enable GPU Fan Settings"); + ctk_help_heading(b, &i, "Reset Hardware Defaults"); ctk_help_para(b, &i, "%s", __reset_button_help); } done: diff --git a/src/gtk+-2.x/ctkthermal.h b/src/gtk+-2.x/ctkthermal.h index c3406e8..4c24c88 100644 --- a/src/gtk+-2.x/ctkthermal.h +++ b/src/gtk+-2.x/ctkthermal.h @@ -104,6 +104,7 @@ struct _CtkThermal int cooler_count; int sensor_count; gboolean thermal_sensor_target_type_supported; + gboolean thermal_cooler_extra_info_supported; }; struct _CtkThermalClass diff --git a/src/gtk+-2.x/ctkui.c b/src/gtk+-2.x/ctkui.c index 170ab8c..e8a3d9e 100644 --- a/src/gtk+-2.x/ctkui.c +++ b/src/gtk+-2.x/ctkui.c @@ -49,20 +49,6 @@ void ctk_main(ParsedAttribute *p, gtk_window_set_default_icon_list(list); window = ctk_window_new(p, conf, system); - if (!system->has_nv_control) { - GtkWidget *dlg; - dlg = gtk_message_dialog_new (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - "You do not appear to be using the NVIDIA " - "X driver. Please edit your X configuration " - "file (just run `nvidia-xconfig` " - "as root), and restart the X server."); - gtk_dialog_run(GTK_DIALOG(dlg)); - gtk_widget_destroy (dlg); - } - ctk_window_set_active_page(CTK_WINDOW(window), page); gtk_main(); diff --git a/src/gtk+-2.x/ctkutils.c b/src/gtk+-2.x/ctkutils.c index aa6b412..ad65e5f 100644 --- a/src/gtk+-2.x/ctkutils.c +++ b/src/gtk+-2.x/ctkutils.c @@ -67,6 +67,20 @@ gboolean ctk_widget_get_visible(GtkWidget *w) #endif } +void ctk_widget_set_visible(GtkWidget *w, gboolean visible) +{ +#ifdef CTK_GTK3 + /* GTK function added in 2.18 */ + gtk_widget_set_visible(w, visible); +#else + if (visible) { + gtk_widget_show(w); + } else { + gtk_widget_hide(w); + } +#endif +} + gboolean ctk_widget_is_drawable(GtkWidget *w) { #ifdef CTK_GTK3 @@ -323,6 +337,15 @@ void ctk_cell_renderer_set_alignment(GtkCellRenderer *renderer, #endif } +void ctk_widget_set_halign_left(GtkWidget *w) +{ +#ifdef CTK_GTK3 + gtk_widget_set_halign(w, GTK_ALIGN_START); +#else + g_object_set(w, "xalign", 0.0, NULL); +#endif +} + GtkWidget *ctk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action) @@ -457,9 +480,7 @@ gchar *get_pcie_link_speed_string(CtrlTarget *ctrl_target, int attribute) gchar *s = NULL; ret = NvCtrlGetAttribute(ctrl_target, attribute, &tmp); - if (ret != NvCtrlSuccess) { - s = g_strdup_printf("Unknown"); - } else { + if (ret == NvCtrlSuccess) { s = g_strdup_printf("%.1f GT/s", tmp/1000.0); } @@ -551,11 +572,11 @@ gchar* create_display_name_list_string(CtrlTarget *ctrl_target, ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, attr, (unsigned char **)(&pData), &len); - if (ret != NvCtrlSuccess) { - goto done; + if (ret == NvCtrlNotSupported) { + return NULL; } - for (i = 0; i < pData[0]; i++) { + for (i = 0; ret == NvCtrlSuccess && i < pData[0]; i++) { CtrlTarget *ctrl_other; int display_id = pData[i+1]; gchar *logName = NULL; @@ -601,8 +622,6 @@ gchar* create_display_name_list_string(CtrlTarget *ctrl_target, } } - done: - if (!displays) { displays = g_strdup("None"); } @@ -772,6 +791,10 @@ void ctk_empty_container(GtkWidget *container) GList *list; GList *node; + if (!container) { + return; + } + list = gtk_container_get_children(GTK_CONTAINER(container)); node = list; while (node) { diff --git a/src/gtk+-2.x/ctkutils.h b/src/gtk+-2.x/ctkutils.h index 92fa64b..6b7c3be 100644 --- a/src/gtk+-2.x/ctkutils.h +++ b/src/gtk+-2.x/ctkutils.h @@ -90,6 +90,7 @@ G_BEGIN_DECLS gboolean ctk_widget_is_sensitive(GtkWidget *w); gboolean ctk_widget_get_sensitive(GtkWidget *w); gboolean ctk_widget_get_visible(GtkWidget *w); +void ctk_widget_set_visible(GtkWidget *w, gboolean visible); gboolean ctk_widget_is_drawable(GtkWidget *w); GdkWindow *ctk_widget_get_window(GtkWidget *w); void ctk_widget_get_allocation(GtkWidget *w, GtkAllocation *a); @@ -110,6 +111,7 @@ void ctk_scrolled_window_add(GtkScrolledWindow *sw, GtkWidget *child); GtkWidget *ctk_statusbar_get_message_area(GtkStatusbar *statusbar); void ctk_cell_renderer_set_alignment(GtkCellRenderer *widget, gfloat x, gfloat y); +void ctk_widget_set_halign_left(GtkWidget *w); GtkWidget *ctk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action); diff --git a/src/gtk+-2.x/ctkvdpau.c b/src/gtk+-2.x/ctkvdpau.c index 3d07408..ff93ef8 100644 --- a/src/gtk+-2.x/ctkvdpau.c +++ b/src/gtk+-2.x/ctkvdpau.c @@ -229,6 +229,11 @@ static int queryBaseInfo(CtkVDPAU *ctk_vdpau, VdpDevice device, {"VP9", VDP_DECODER_PROFILE_VP9_PROFILE_2, 0x100}, {"VP9", VDP_DECODER_PROFILE_VP9_PROFILE_3, 0x100}, #endif +#ifdef VDP_DECODER_PROFILE_AV1_MAIN + {"AV1", VDP_DECODER_PROFILE_AV1_MAIN, 0x200}, + {"AV1", VDP_DECODER_PROFILE_AV1_HIGH, 0x200}, + {"AV1", VDP_DECODER_PROFILE_AV1_PROFESSIONAL, 0x200}, +#endif }; const size_t decoder_list_count = sizeof(decoder_list)/sizeof(Desc); @@ -577,6 +582,11 @@ static int queryDecoderCaps(CtkVDPAU *ctk_vdpau, VdpDevice device, {"VP9 PROFILE 2", VDP_DECODER_PROFILE_VP9_PROFILE_2, 0}, {"VP9 PROFILE 3", VDP_DECODER_PROFILE_VP9_PROFILE_3, 0}, #endif +#ifdef VDP_DECODER_PROFILE_AV1_MAIN + {"AV1 MAIN", VDP_DECODER_PROFILE_AV1_MAIN, 0}, + {"AV1 HIGH", VDP_DECODER_PROFILE_AV1_HIGH, 0}, + {"AV1 PROFESSIONAL", VDP_DECODER_PROFILE_AV1_PROFESSIONAL, 0}, +#endif }; const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(Desc); diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index 2d879ac..525796e 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -500,8 +500,9 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, GtkTextBuffer *help; CtrlTargetNode *node; - CtrlTarget *server_target = NULL; - CtrlTarget *ctrl_target = NULL; + CtrlTarget *default_x_target = NULL; + CtrlTarget *default_gpu_target = NULL; + CtrlTarget *ctrl_target; CtkEvent *ctk_event; CtkConfig *ctk_config; @@ -656,53 +657,56 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, ctk_window->page_viewer = hbox; ctk_window->page = NULL; + /* + * Create generic and specific default system targets. X Screen target + * will only exist if the X Server is available. In that case, the generic + * default target will be the default gpu target instead. + */ + default_x_target = NvCtrlGetDefaultTargetByType(system, X_SCREEN_TARGET); + default_gpu_target = NvCtrlGetDefaultTargetByType(system, GPU_TARGET); - /* X Server info & configuration */ + ctrl_target = default_x_target; + if (!ctrl_target) { + ctrl_target = default_gpu_target; + } - if (system->targets[X_SCREEN_TARGET]) { + /* System Information */ - GtkWidget *child; + if (ctrl_target) { - /* - * XXX For now, just use the first handle in the list - * to communicate with the X server for these two - * pages and the app profile page below. - */ + GtkWidget *child; - server_target = NvCtrlGetDefaultTargetByType(system, X_SCREEN_TARGET); - if (server_target) { + child = ctk_server_new(ctrl_target, ctk_config); + add_page(child, + ctk_server_create_help(tag_table, CTK_SERVER(child)), + ctk_window, NULL, NULL, "System Information", + NULL, NULL, NULL); + } - /* X Server information */ + /* X Server Display Configuration */ - child = ctk_server_new(server_target, ctk_config); - add_page(child, - ctk_server_create_help(tag_table, - CTK_SERVER(child)), - ctk_window, NULL, NULL, "X Server Information", - NULL, NULL, NULL); + if (default_x_target) { - /* X Server Display Configuration */ + GtkWidget *child; - child = ctk_display_config_new(server_target, ctk_config); - if (child) { - ctk_window->display_config_widget = child; - add_page(child, - ctk_display_config_create_help(tag_table, - CTK_DISPLAY_CONFIG(child)), - ctk_window, NULL, NULL, - "X Server Display Configuration", - NULL, ctk_display_config_selected, - ctk_display_config_unselected); - } + child = ctk_display_config_new(default_x_target, ctk_config); + if (child) { + ctk_window->display_config_widget = child; + add_page(child, + ctk_display_config_create_help(tag_table, + CTK_DISPLAY_CONFIG(child)), + ctk_window, NULL, NULL, + "X Server Display Configuration", + NULL, ctk_display_config_selected, + ctk_display_config_unselected); } } /* Platform Power Mode */ - ctrl_target = NvCtrlGetDefaultTargetByType(system, GPU_TARGET); - ctk_event = CTK_EVENT(ctk_event_new(ctrl_target)); - widget = ctk_powermode_new(ctrl_target, ctk_config, ctk_event); + ctk_event = CTK_EVENT(ctk_event_new(default_gpu_target)); + widget = ctk_powermode_new(default_gpu_target, ctk_config, ctk_event); if (widget) { help = ctk_powermode_create_help(tag_table, CTK_POWERMODE(widget)); add_page(widget, help, ctk_window, NULL, NULL, @@ -964,7 +968,7 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, } /* app profile configuration */ - widget = ctk_app_profile_new(server_target, ctk_config); + widget = ctk_app_profile_new(ctrl_target, ctk_config); if (widget) { add_page(widget, ctk_app_profile_create_help(CTK_APP_PROFILE(widget), tag_table), ctk_window, NULL, NULL, "Application Profiles", @@ -1019,7 +1023,7 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf, /* set the window title */ - gtk_window_set_title(GTK_WINDOW(object), "NVIDIA X Server Settings"); + gtk_window_set_title(GTK_WINDOW(object), "NVIDIA Settings"); gtk_widget_show_all(GTK_WIDGET(object)); diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 45adedd..5ff0f21 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -2846,8 +2846,7 @@ #define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_TRUE 1 /* - * NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS - Returns GPU's processor - * clock freqs. + * NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS - not supported */ #define NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS 359 /* RW-G */ @@ -4000,9 +3999,8 @@ * NV Clock and Memory Clock values. * Not all tokens will be reported on all GPUs, and additional tokens * may be added in the future. - * For backwards compatibility we still provide nvclock, memclock, and - * processorclock those are the same as nvclockmin, memclockmin and - * processorclockmin. + * For backwards compatibility we still provide nvclock and memclock; + * those are the same as nvclockmin and memclockmin. * * Note: These clock values take into account the offset * set by clients through NV_CTRL_GPU_NVCLOCK_OFFSET and @@ -4032,14 +4030,6 @@ * for the perf level * "memtransferrateeditable" integer - if the memory transfer rate is editable * for the perf level - * "processorclock" integer - the processor clocks (in MHz) - * for the perf level - * "processorclockmin" integer - the processor clocks min (in MHz) - * for the perf level - * "processorclockmax" integer - the processor clocks max (in MHz) - * for the perf level - * "processorclockeditable" integer - if the processor clock domain is editable - * for the perf level * * Example: * @@ -4105,11 +4095,8 @@ /* * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the - * associated NV Clock, Memory Clock and Processor Clock values. + * associated NV Clock and Memory Clock values. * - * Current valid tokens are "nvclock", "nvclockmin", "nvclockmax", - * "memclock", "memclockmin", "memclockmax", "processorclock", - * "processorclockmin" and "processorclockmax". * Not all tokens will be reported on all GPUs, and additional tokens * may be added in the future. * @@ -4140,14 +4127,6 @@ * for the perf level * "memtransferrateeditable" integer - if the memory transfer rate is editable * for the perf level - * "processorclock" integer - the processor clocks (in MHz) - * for the perf level - * "processorclockmin" integer - the processor clocks min (in MHz) - * for the perf level - * "processorclockmax" integer - the processor clocks max (in MHz) - * for the perf level - * "processorclockeditable" integer - if the processor clock domain is editable - * for the perf level * * Example: * @@ -4159,7 +4138,7 @@ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. */ -#define NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS 34 /* RW-G */ +#define NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS 34 /* R--G */ /* * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION - Returns the @@ -4758,8 +4737,24 @@ #define NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU 20 /* R--G */ +/* + * NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS - Returns volatile or aggregate + * detailed ECC error information of bit width specified. + * + * The format of the returned data is: + * + * 4 * n int number of ECC errors where n is equal to + NVML_MEMORY_LOCATION_COUNT. + * + * This attribute is queried through NVML. + */ +#define NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT 21 /* R--G */ +#define NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT 22 /* R--G */ +#define NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT_AGGREGATE 23 /* R--G */ +#define NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE 24 /* R--G */ + #define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE \ - NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU + NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE /**************************************************************************/ diff --git a/src/libXNVCtrl/utils.mk b/src/libXNVCtrl/utils.mk index dd68d48..2b15880 100644 --- a/src/libXNVCtrl/utils.mk +++ b/src/libXNVCtrl/utils.mk @@ -186,6 +186,8 @@ NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?= NV_GENERATED_HEADERS ?= +PCIACCESS_CFLAGS ?= +PCIACCESS_LDFLAGS ?= ############################################################################## # This makefile uses the $(eval) builtin function, which was added in @@ -380,6 +382,7 @@ BUILD_OBJECT_LIST_WITH_DIR = \ BUILD_OBJECT_LIST = \ $(call BUILD_OBJECT_LIST_WITH_DIR,$(1),$(OUTPUTDIR)) +$(call BUILD_OBJECT_LIST,nvpci-utils.c): CFLAGS += $(PCIACCESS_CFLAGS) ############################################################################## # function to generate a list of dependency files from their diff --git a/src/libXNVCtrl/version.mk b/src/libXNVCtrl/version.mk index 8e23d30..5e08b7b 100644 --- a/src/libXNVCtrl/version.mk +++ b/src/libXNVCtrl/version.mk @@ -1,4 +1,4 @@ -NVIDIA_VERSION = 495.46 +NVIDIA_VERSION = 510.39.01 # This file. VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST)) diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.c b/src/libXNVCtrlAttributes/NvCtrlAttributes.c index 73b8f41..661f77c 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.c @@ -596,6 +596,7 @@ ReturnStatus NvCtrlQueryTargetCount(const CtrlTarget *ctrl_target, int *val) { const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlMissingExtension; if (h == NULL) { return NvCtrlBadHandle; @@ -606,9 +607,9 @@ ReturnStatus NvCtrlQueryTargetCount(const CtrlTarget *ctrl_target, case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret = NvCtrlNvmlQueryTargetCount(ctrl_target, - target_type, - val); + ret = NvCtrlNvmlQueryTargetCount(ctrl_target, + target_type, + val); if ((ret != NvCtrlMissingExtension) && (ret != NvCtrlBadHandle) && (ret != NvCtrlNotSupported)) { @@ -621,6 +622,13 @@ ReturnStatus NvCtrlQueryTargetCount(const CtrlTarget *ctrl_target, case FRAMELOCK_TARGET: case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: case MUX_TARGET: + if (!h->nv) { + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; + } return NvCtrlNvControlQueryTargetCount(h, target_type, val); default: return NvCtrlBadHandle; @@ -674,6 +682,7 @@ ReturnStatus NvCtrlGetAttributePerms(const CtrlTarget *ctrl_target, CtrlAttributePerms *perms) { const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlError; if (h == NULL) { return NvCtrlBadHandle; @@ -688,6 +697,12 @@ ReturnStatus NvCtrlGetAttributePerms(const CtrlTarget *ctrl_target, case CTRL_ATTRIBUTE_TYPE_STRING: case CTRL_ATTRIBUTE_TYPE_BINARY_DATA: case CTRL_ATTRIBUTE_TYPE_STRING_OPERATION: + + ret = NvCtrlNvmlGetAttributePerms(h, attr_type, attr, perms); + + if (ret == NvCtrlSuccess || h->dpy == NULL) { + return ret; + } return NvCtrlNvControlGetAttributePerms(h, attr_type, attr, perms); case CTRL_ATTRIBUTE_TYPE_COLOR: @@ -760,18 +775,17 @@ ReturnStatus NvCtrlGetDisplayAttribute64(const CtrlTarget *ctrl_target, if (((attr >= 0) && (attr <= NV_CTRL_LAST_ATTRIBUTE)) || ((attr >= NV_CTRL_ATTR_NV_BASE) && (attr <= NV_CTRL_ATTR_NV_LAST_ATTRIBUTE))) { + ReturnStatus ret = NvCtrlMissingExtension; switch (h->target_type) { case GPU_TARGET: case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret = NvCtrlNvmlGetAttribute(ctrl_target, - attr, - val); - if ((ret != NvCtrlMissingExtension) && - (ret != NvCtrlBadHandle) && - (ret != NvCtrlNotSupported)) { + ret = NvCtrlNvmlGetAttribute(ctrl_target, + attr, + val); + if (ret == NvCtrlSuccess) { return ret; } } @@ -781,7 +795,13 @@ ReturnStatus NvCtrlGetDisplayAttribute64(const CtrlTarget *ctrl_target, case FRAMELOCK_TARGET: case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: case MUX_TARGET: - if (!h->nv) return NvCtrlMissingExtension; + if (!h->nv) { + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; + } return NvCtrlNvControlGetAttribute(h, display_mask, attr, val); default: return NvCtrlBadHandle; @@ -815,6 +835,7 @@ ReturnStatus NvCtrlSetDisplayAttribute(CtrlTarget *ctrl_target, int attr, int val) { NvCtrlAttributePrivateHandle *h = getPrivateHandle(ctrl_target); + ReturnStatus ret = NvCtrlMissingExtension; if (h == NULL) { return NvCtrlBadHandle; @@ -826,7 +847,6 @@ ReturnStatus NvCtrlSetDisplayAttribute(CtrlTarget *ctrl_target, case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret; ret = NvCtrlNvmlSetAttribute(ctrl_target, attr, display_mask, @@ -844,7 +864,11 @@ ReturnStatus NvCtrlSetDisplayAttribute(CtrlTarget *ctrl_target, case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: case MUX_TARGET: if (!h->nv) { - return NvCtrlMissingExtension; + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; } return NvCtrlNvControlSetAttribute(h, display_mask, attr, val); default: @@ -891,6 +915,7 @@ NvCtrlGetValidDisplayAttributeValues(const CtrlTarget *ctrl_target, CtrlAttributeValidValues *val) { const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlMissingExtension; if (h == NULL) { return NvCtrlBadHandle; @@ -902,13 +927,10 @@ NvCtrlGetValidDisplayAttributeValues(const CtrlTarget *ctrl_target, case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret; ret = NvCtrlNvmlGetValidAttributeValues(ctrl_target, attr, val); - if ((ret != NvCtrlMissingExtension) && - (ret != NvCtrlBadHandle) && - (ret != NvCtrlNotSupported)) { + if (ret == NvCtrlSuccess) { return ret; } } @@ -919,7 +941,11 @@ NvCtrlGetValidDisplayAttributeValues(const CtrlTarget *ctrl_target, case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: case MUX_TARGET: if (!h->nv) { - return NvCtrlMissingExtension; + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; } return NvCtrlNvControlGetValidAttributeValues(h, display_mask, attr, val); @@ -965,6 +991,7 @@ NvCtrlGetValidStringDisplayAttributeValues(const CtrlTarget *ctrl_target, CtrlAttributeValidValues *val) { const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlMissingExtension; if (h == NULL) { return NvCtrlBadHandle; @@ -976,13 +1003,10 @@ NvCtrlGetValidStringDisplayAttributeValues(const CtrlTarget *ctrl_target, case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret; ret = NvCtrlNvmlGetValidStringAttributeValues(ctrl_target, attr, val); - if ((ret != NvCtrlMissingExtension) && - (ret != NvCtrlBadHandle) && - (ret != NvCtrlNotSupported)) { + if (ret == NvCtrlSuccess) { return ret; } } @@ -993,7 +1017,11 @@ NvCtrlGetValidStringDisplayAttributeValues(const CtrlTarget *ctrl_target, case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: case MUX_TARGET: if (!h->nv) { - return NvCtrlMissingExtension; + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; } return NvCtrlNvControlGetValidStringDisplayAttributeValues( h, display_mask, attr, val); @@ -1174,6 +1202,7 @@ ReturnStatus NvCtrlGetBinaryAttribute(const CtrlTarget *ctrl_target, unsigned char **data, int *len) { const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlMissingExtension; if (h == NULL) { return NvCtrlBadHandle; @@ -1184,10 +1213,10 @@ ReturnStatus NvCtrlGetBinaryAttribute(const CtrlTarget *ctrl_target, case THERMAL_SENSOR_TARGET: case COOLER_TARGET: { - ReturnStatus ret = NvCtrlNvmlGetBinaryAttribute(ctrl_target, - attr, - data, - len); + ret = NvCtrlNvmlGetBinaryAttribute(ctrl_target, + attr, + data, + len); if ((ret != NvCtrlMissingExtension) && (ret != NvCtrlBadHandle) && (ret != NvCtrlNotSupported)) { @@ -1199,6 +1228,13 @@ ReturnStatus NvCtrlGetBinaryAttribute(const CtrlTarget *ctrl_target, case X_SCREEN_TARGET: case FRAMELOCK_TARGET: case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET: + if (!h->nv) { + /* + * If there is no connection to the X Driver, return the + * non-success value from the NVML query, if available. + */ + return ret; + } return NvCtrlNvControlGetBinaryAttribute(h, display_mask, attr, data, len); default: return NvCtrlBadHandle; @@ -1637,6 +1673,11 @@ NvCtrlEventHandle *NvCtrlGetEventHandle(const CtrlTarget *ctrl_target) return NULL; } + if (!h->dpy && !h->nv && h->nvml) { + /* We are running with NVML lib only. Events not yet supported.*/ + return NULL; + } + /* Look for the event handle */ evt_h = NULL; for (evt_hnode = __event_handles; diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.h b/src/libXNVCtrlAttributes/NvCtrlAttributes.h index f6f1f39..20b0dde 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributes.h +++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.h @@ -139,6 +139,7 @@ struct _CtrlSystem { char *display; /* string for XOpenDisplay */ Display *dpy; /* X display connection */ Bool has_nv_control; + Bool has_nvml; CtrlTargetNode *targets[MAX_TARGET_TYPES]; /* Shadows targetTypeTable */ CtrlTargetNode *physical_screens; @@ -574,6 +575,17 @@ typedef struct { #define NV_CTRL_STRING_XV_LAST_ATTRIBUTE (NV_CTRL_STRING_XV_VERSION) +/* + * Additional XVideo string attributes for NvCtrlGetStringDisplayAttribute(); + */ + +#define NV_CTRL_STRING_NVML_BASE (NV_CTRL_STRING_XV_LAST_ATTRIBUTE + 1) + +#define NV_CTRL_STRING_NVML_VERSION (NV_CTRL_STRING_NVML_BASE) + +#define NV_CTRL_STRING_NVML_LAST_ATTRIBUTE (NV_CTRL_STRING_NVML_VERSION) + + #define NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM 0x1 #define NV_CTRL_ATTRIBUTES_XF86VIDMODE_SUBSYSTEM 0x2 diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c index 4f5bce9..6cd46c2 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c @@ -41,7 +41,12 @@ NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h) NvCtrlNvControlAttributes *nv; int ret, major, minor, event, error; const CtrlTargetTypeInfo *targetTypeInfo; - + + if (!h->dpy) { + nv_warning_msg("NV-CONTROL Display not found."); + return NULL; + } + ret = XNVCTRLQueryExtension (h->dpy, &event, &error); if (ret != True) { nv_warning_msg("NV-CONTROL extension not found on this Display."); @@ -160,6 +165,11 @@ NvCtrlNvControlQueryTargetCount(const NvCtrlAttributePrivateHandle *h, return NvCtrlBadArgument; } + if (!h->dpy) { + nv_warning_msg("NV-CONTROL Display not found."); + return NvCtrlError; + } + ret = XNVCTRLQueryTargetCount(h->dpy, targetTypeInfo->nvctrl, val); return (ret) ? NvCtrlSuccess : NvCtrlError; @@ -174,6 +184,10 @@ ReturnStatus NvCtrlNvControlGetAttribute(const NvCtrlAttributePrivateHandle *h, int value_32; int major, minor; + if (!h->nv) { + return NvCtrlMissingExtension; + } + major = h->nv->major_version; minor = h->nv->minor_version; diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c b/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c index d39f635..7cec7c8 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c @@ -192,14 +192,29 @@ static Bool LoadNvml(NvCtrlNvmlAttributes *nvml) GET_SYMBOL_REQUIRED(deviceGetUUID, "nvmlDeviceGetUUID"); GET_SYMBOL_REQUIRED(deviceGetCount, "nvmlDeviceGetCount"); GET_SYMBOL_REQUIRED(deviceGetTemperature, "nvmlDeviceGetTemperature"); - GET_SYMBOL_REQUIRED(deviceGetFanSpeed, "nvmlDeviceGetFanSpeed"); GET_SYMBOL_REQUIRED(deviceGetName, "nvmlDeviceGetName"); GET_SYMBOL_REQUIRED(deviceGetVbiosVersion, "nvmlDeviceGetVbiosVersion"); GET_SYMBOL_REQUIRED(deviceGetMemoryInfo, "nvmlDeviceGetMemoryInfo"); GET_SYMBOL_REQUIRED(deviceGetPciInfo, "nvmlDeviceGetPciInfo"); + GET_SYMBOL_REQUIRED(deviceGetCurrPcieLinkWidth, "nvmlDeviceGetCurrPcieLinkWidth"); GET_SYMBOL_REQUIRED(deviceGetMaxPcieLinkGeneration, "nvmlDeviceGetMaxPcieLinkGeneration"); GET_SYMBOL_REQUIRED(deviceGetMaxPcieLinkWidth, "nvmlDeviceGetMaxPcieLinkWidth"); GET_SYMBOL_REQUIRED(deviceGetVirtualizationMode, "nvmlDeviceGetVirtualizationMode"); + GET_SYMBOL_REQUIRED(deviceGetUtilizationRates, "nvmlDeviceGetUtilizationRates"); + GET_SYMBOL_REQUIRED(deviceGetTemperatureThreshold, "nvmlDeviceGetTemperatureThreshold"); + GET_SYMBOL_REQUIRED(deviceGetFanSpeed_v2, "nvmlDeviceGetFanSpeed_v2"); + GET_SYMBOL_REQUIRED(systemGetDriverVersion, "nvmlSystemGetDriverVersion"); + GET_SYMBOL_REQUIRED(deviceGetEccMode, "nvmlDeviceGetEccMode"); + GET_SYMBOL_REQUIRED(deviceSetEccMode, "nvmlDeviceSetEccMode"); + GET_SYMBOL_REQUIRED(deviceGetTotalEccErrors, "nvmlDeviceGetTotalEccErrors"); + GET_SYMBOL_REQUIRED(deviceClearEccErrorCounts, "nvmlDeviceClearEccErrorCounts"); + GET_SYMBOL_REQUIRED(systemGetNVMLVersion, "nvmlSystemGetNVMLVersion"); + GET_SYMBOL_REQUIRED(deviceGetMemoryErrorCounter, "nvmlDeviceGetMemoryErrorCounter"); + GET_SYMBOL_REQUIRED(deviceGetNumGpuCores, "nvmlDeviceGetNumGpuCores"); + GET_SYMBOL_REQUIRED(deviceGetMemoryBusWidth, "nvmlDeviceGetMemoryBusWidth"); + GET_SYMBOL_REQUIRED(deviceGetIrqNum, "nvmlDeviceGetIrqNum"); + GET_SYMBOL_REQUIRED(deviceGetPowerSource, "nvmlDeviceGetPowerSource"); + GET_SYMBOL_REQUIRED(deviceGetNumFans, "nvmlDeviceGetNumFans"); #undef GET_SYMBOL_REQUIRED /* Do not fail with older drivers */ @@ -207,6 +222,7 @@ static Bool LoadNvml(NvCtrlNvmlAttributes *nvml) nvml->lib._proc = dlsym(nvml->lib.handle, _name); GET_SYMBOL_OPTIONAL(deviceGetGridLicensableFeatures, "nvmlDeviceGetGridLicensableFeatures_v4"); + GET_SYMBOL_OPTIONAL(deviceGetMemoryInfo_v2, "nvmlDeviceGetMemoryInfo_v2"); #undef GET_SYMBOL_OPTIONAL ret = nvml->lib.init(); @@ -243,8 +259,8 @@ static Bool matchNvCtrlWithNvmlIds(const NvCtrlNvmlAttributes *nvml, int nvctrlGpuCount = 0; /* Get the gpu count returned by NV-CONTROL. */ - if (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_GPU, - &nvctrlGpuCount)) { + if (h->nv && !XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_GPU, + &nvctrlGpuCount)) { return FALSE; } @@ -367,7 +383,7 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvmlReturn_t ret = nvml->lib.deviceGetHandleByIndex(devIdx, &device); if (ret == NVML_SUCCESS) { unsigned int temp; - unsigned int speed; + unsigned int fans; /* * XXX Currently, NVML only allows to get the GPU temperature so @@ -387,12 +403,7 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvml->sensorCount++; } - /* - * XXX NVML assumes at most 1 fan per GPU so check for - * nvmlDeviceGetFanSpeed success to figure out if that fan is - * available. - */ - ret = nvml->lib.deviceGetFanSpeed(device, &speed); + ret = nvml->lib.deviceGetNumFans(device, &fans); if (ret == NVML_SUCCESS) { if ((h->target_type == COOLER_TARGET) && (h->target_id == nvml->coolerCount)) { @@ -400,21 +411,20 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvml->deviceIdx = devIdx; } - nvml->coolerCountPerGPU[i] = 1; - nvml->coolerCount++; + nvml->coolerCountPerGPU[i] = fans; + nvml->coolerCount += fans; } } } /* - * NVML doesn't have support to handle more than 1 fan per GPU. Make sure - * total number of cooler probed by NVML are same as that of reported by - * NV-CONTROL, otherwise do not initialize NVML sub-system. + * Consistency check between X/NV-CONTROL and NVML. */ - if (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_COOLER, - &nvctrlCoolerCount) || - (nvctrlCoolerCount != nvml->coolerCount)) { - goto fail; + if (h->nv && + (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_COOLER, + &nvctrlCoolerCount) || + (nvctrlCoolerCount != nvml->coolerCount))) { + nv_warning_msg("Inconsistent number of fans detected."); } nvfree(nvctrlToNvmlId); @@ -495,10 +505,50 @@ ReturnStatus NvCtrlNvmlQueryTargetCount(const CtrlTarget *ctrl_target, /* - * Get NVML String Attribute Values + * Get NVML String Attribute Values that do not require a control target. */ -#ifdef NVML_EXPERIMENTAL +static ReturnStatus NvCtrlNvmlGetGeneralStringAttribute(const CtrlTarget *ctrl_target, + int attr, char **ptr) +{ + char res[MAX_NVML_STR_LEN]; + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + nvmlReturn_t ret; + *ptr = NULL; + + if ((h == NULL) || (h->nvml == NULL)) { + return NvCtrlBadHandle; + } + + switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + ret = h->nvml->lib.systemGetDriverVersion(res, MAX_NVML_STR_LEN); + break; + + case NV_CTRL_STRING_NVML_VERSION: + ret = h->nvml->lib.systemGetNVMLVersion(res, MAX_NVML_STR_LEN); + break; + + default: + /* This is expected to fall through silently. */ + return NvCtrlNotSupported; + } + + if (ret == NVML_SUCCESS) { + *ptr = strdup(res); + return NvCtrlSuccess; + } + + /* An NVML error occurred */ + printNvmlError(ret); + return NvCtrlNotSupported; +} + + + +/* + * Get NVML String Attribute Values + */ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_target, int attr, char **ptr) @@ -531,11 +581,33 @@ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_targe ret = nvml->lib.deviceGetUUID(device, res, MAX_NVML_STR_LEN); break; - case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_GPU_UTILIZATION: + { + nvmlUtilization_t util; + + if (ctrl_target->system->has_nv_control) { + /* + * Not all utilization types are currently available via + * NVML so, if accessible, get the rates from X. + */ + return NvCtrlNotSupported; + } + + ret = nvml->lib.deviceGetUtilizationRates(device, &util); + + if (ret != NVML_SUCCESS) { + break; + } + + snprintf(res, sizeof(res), + "graphics=%d, memory=%d", + util.gpu, util.memory); + + break; + } case NV_CTRL_STRING_SLI_MODE: case NV_CTRL_STRING_PERFORMANCE_MODES: case NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_STRING_GPU_UTILIZATION: case NV_CTRL_STRING_MULTIGPU_MODE: /* * XXX We'll eventually need to add support for this attributes @@ -562,22 +634,26 @@ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_targe return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, int attr, char **ptr) { + ReturnStatus ret; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* - * This shouldn't be reached for target types that are not handled through - * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up - * to date). + * Check for attributes that don't require a target, else continue to + * supported target types. */ - assert(TARGET_TYPE_IS_NVML_COMPATIBLE(NvCtrlGetTargetType(ctrl_target))); + ret = NvCtrlNvmlGetGeneralStringAttribute(ctrl_target, attr, ptr); + + if (ret == NvCtrlSuccess) { + return NvCtrlSuccess; + } switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: @@ -600,10 +676,6 @@ ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -612,7 +684,7 @@ ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, * Set NVML String Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlSetGPUStringAttribute(CtrlTarget *ctrl_target, int attr, const char *ptr) @@ -656,7 +728,7 @@ static ReturnStatus NvCtrlNvmlSetGPUStringAttribute(CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, int attr, const char *ptr) @@ -665,7 +737,6 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -695,10 +766,6 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -710,7 +777,7 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, int attr, int64_t *val) { - unsigned int res; + unsigned int res = 0; const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); const NvCtrlNvmlAttributes *nvml; nvmlDevice_t device; @@ -725,20 +792,35 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { -#ifdef NVML_EXPERIMENTAL case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: case NV_CTRL_USED_DEDICATED_GPU_MEMORY: { - nvmlMemory_t memory; - ret = nvml->lib.deviceGetMemoryInfo(device, &memory); - if (ret == NVML_SUCCESS) { - switch (attr) { - case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: - res = memory.total >> 20; // bytes --> MB - break; - case NV_CTRL_USED_DEDICATED_GPU_MEMORY: - res = memory.used >> 20; // bytes --> MB - break; + if (nvml->lib.deviceGetMemoryInfo_v2) { + nvmlMemory_v2_t memory; + memory.version = nvmlMemory_v2; + ret = nvml->lib.deviceGetMemoryInfo_v2(device, &memory); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + res = memory.total >> 20; // bytes --> MB + break; + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + res = memory.used >> 20; // bytes --> MB + break; + } + } + } else { + nvmlMemory_t memory; + ret = nvml->lib.deviceGetMemoryInfo(device, &memory); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + res = memory.total >> 20; // bytes --> MB + break; + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + res = memory.used >> 20; // bytes --> MB + break; + } } } } @@ -787,41 +869,127 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetMaxPcieLinkGeneration(device, &res); break; + case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: + ret = nvml->lib.deviceGetCurrPcieLinkWidth(device, &res); + break; case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: ret = nvml->lib.deviceGetMaxPcieLinkWidth(device, &res); break; -#else - case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: - case NV_CTRL_USED_DEDICATED_GPU_MEMORY: - case NV_CTRL_PCI_DOMAIN: - case NV_CTRL_PCI_BUS: - case NV_CTRL_PCI_DEVICE: - case NV_CTRL_PCI_FUNCTION: - case NV_CTRL_PCI_ID: - case NV_CTRL_GPU_PCIE_GENERATION: - case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: -#endif // NVML_EXPERIMENTAL + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + ret = nvml->lib.deviceGetTemperatureThreshold(device, + NVML_TEMPERATURE_THRESHOLD_SLOWDOWN ,&res); + break; + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + ret = nvml->lib.deviceGetTemperatureThreshold(device, + NVML_TEMPERATURE_THRESHOLD_SHUTDOWN ,&res); + break; + case NV_CTRL_GPU_CORE_TEMPERATURE: + ret = nvml->lib.deviceGetTemperature(device, + NVML_TEMPERATURE_GPU, + &res); + break; + + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + case NV_CTRL_GPU_ECC_SUPPORTED: + { + nvmlEnableState_t current, pending; + ret = nvml->lib.deviceGetEccMode(device, ¤t, &pending); + switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + res = (ret == NVML_SUCCESS) ? + NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_TRUE : + NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_FALSE; + break; + case NV_CTRL_GPU_ECC_SUPPORTED: + res = (ret == NVML_SUCCESS) ? + NV_CTRL_GPU_ECC_SUPPORTED_TRUE : + NV_CTRL_GPU_ECC_SUPPORTED_FALSE; + break; + } + } + break; + + case NV_CTRL_GPU_ECC_CONFIGURATION: + case NV_CTRL_GPU_ECC_STATUS: + { + nvmlEnableState_t current, pending; + ret = nvml->lib.deviceGetEccMode(device, ¤t, &pending); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_GPU_ECC_STATUS: + res = current; + break; + case NV_CTRL_GPU_ECC_CONFIGURATION: + res = pending; + break; + } + } + } + break; + + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + { + unsigned long long eccCounts; + nvmlEccCounterType_t counterType; + nvmlMemoryErrorType_t errorType; + switch (attr) { + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_CORRECTED; + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_CORRECTED; + counterType = NVML_AGGREGATE_ECC; + break; + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_UNCORRECTED; + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_UNCORRECTED; + counterType = NVML_AGGREGATE_ECC; + break; + } + + ret = nvml->lib.deviceGetTotalEccErrors(device, errorType, + counterType, &eccCounts); + if (ret == NVML_SUCCESS) { + if (val) { + *val = eccCounts; + } + return NvCtrlSuccess; + } + } + break; + + case NV_CTRL_GPU_CORES: + ret = nvml->lib.deviceGetNumGpuCores(device, &res); + break; + case NV_CTRL_GPU_MEMORY_BUS_WIDTH: + ret = nvml->lib.deviceGetMemoryBusWidth(device, &res); + break; + case NV_CTRL_IRQ: + ret = nvml->lib.deviceGetIrqNum(device, &res); + break; + case NV_CTRL_GPU_POWER_SOURCE: + assert(NV_CTRL_GPU_POWER_SOURCE_AC == NVML_POWER_SOURCE_AC); + assert(NV_CTRL_GPU_POWER_SOURCE_BATTERY == NVML_POWER_SOURCE_BATTERY); + ret = nvml->lib.deviceGetPowerSource(device, &res); + break; + + case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: case NV_CTRL_VIDEO_RAM: - case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: case NV_CTRL_BUS_TYPE: - case NV_CTRL_GPU_MEMORY_BUS_WIDTH: - case NV_CTRL_GPU_CORES: - case NV_CTRL_IRQ: case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: - case NV_CTRL_GPU_POWER_SOURCE: case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: case NV_CTRL_GPU_POWER_MIZER_MODE: case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: - case NV_CTRL_GPU_ECC_SUPPORTED: - case NV_CTRL_GPU_ECC_STATUS: - case NV_CTRL_GPU_ECC_CONFIGURATION: - case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: - case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: case NV_CTRL_ENABLED_DISPLAYS: case NV_CTRL_CONNECTED_DISPLAYS: case NV_CTRL_MAX_SCREEN_WIDTH: @@ -836,10 +1004,8 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, case NV_CTRL_ATTR_NV_MINOR_VERSION: case NV_CTRL_OPERATING_SYSTEM: case NV_CTRL_NO_SCANOUT: - case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_AMBIENT_TEMPERATURE: case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS: case NV_CTRL_VIDEO_ENCODER_UTILIZATION: case NV_CTRL_VIDEO_DECODER_UTILIZATION: case NV_CTRL_FRAMELOCK: @@ -886,14 +1052,16 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a GPU integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of GPU " - "(%d)", INT_ATTRIBUTE_NAME(attr), attr, - NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of GPU " + "(%d)", INT_ATTRIBUTE_NAME(attr), attr, + NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } if (ret == NVML_SUCCESS) { - *val = res; + if (val) { + *val = res; + } return NvCtrlSuccess; } } @@ -951,7 +1119,7 @@ static ReturnStatus NvCtrlNvmlGetGridLicensableFeatures(const CtrlTarget *ctrl_t return NvCtrlNotSupported; } -#ifdef NVML_EXPERIMENTAL + static int getThermalCoolerId(const NvCtrlAttributePrivateHandle *h, unsigned int thermalCoolerCount, @@ -1003,11 +1171,7 @@ static ReturnStatus NvCtrlNvmlGetThermalAttribute(const CtrlTarget *ctrl_target, if (ret == NVML_SUCCESS) { switch (attr) { case NV_CTRL_THERMAL_SENSOR_READING: - ret = nvml->lib.deviceGetTemperature(device, - NVML_TEMPERATURE_GPU, - &res); - break; - + case NV_CTRL_THERMAL_SENSOR_PROVIDER: case NV_CTRL_THERMAL_SENSOR_TARGET: /* @@ -1018,9 +1182,9 @@ static ReturnStatus NvCtrlNvmlGetThermalAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a sensor integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of " - "Thermal sensor (%d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of " + "Thermal sensor (%d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } @@ -1062,10 +1226,11 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_THERMAL_COOLER_LEVEL: - ret = nvml->lib.deviceGetFanSpeed(device, &res); + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + ret = nvml->lib.deviceGetFanSpeed_v2(device, coolerId, &res); break; + case NV_CTRL_THERMAL_COOLER_LEVEL: case NV_CTRL_THERMAL_COOLER_SPEED: case NV_CTRL_THERMAL_COOLER_CONTROL_TYPE: case NV_CTRL_THERMAL_COOLER_TARGET: @@ -1077,9 +1242,9 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a cooler integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Fan " - "(%d)", INT_ATTRIBUTE_NAME(attr), attr, - NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Fan " + "(%d)", INT_ATTRIBUTE_NAME(attr), attr, + NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } @@ -1093,7 +1258,8 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, printNvmlError(ret); return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + + ReturnStatus NvCtrlNvmlGetAttribute(const CtrlTarget *ctrl_target, int attr, int64_t *val) @@ -1112,18 +1278,12 @@ ReturnStatus NvCtrlNvmlGetAttribute(const CtrlTarget *ctrl_target, switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: return NvCtrlNvmlGetGPUAttribute(ctrl_target, attr, val); -#ifdef NVML_EXPERIMENTAL case THERMAL_SENSOR_TARGET: return NvCtrlNvmlGetThermalAttribute(ctrl_target, attr, val); case COOLER_TARGET: return NvCtrlNvmlGetCoolerAttribute(ctrl_target, attr, val); -#else - case THERMAL_SENSOR_TARGET: - case COOLER_TARGET: - return NvCtrlNotSupported; -#endif default: - return NvCtrlBadHandle; + return NvCtrlNotSupported; } } @@ -1155,7 +1315,7 @@ ReturnStatus NvCtrlNvmlGetGridLicenseAttributes(const CtrlTarget *ctrl_target, * Set NVML Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, int attr, int index, int val) @@ -1174,9 +1334,28 @@ static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION: + ret = nvml->lib.deviceSetEccMode(device, val); + break; + + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + { + nvmlEccCounterType_t counterType = 0; + switch (val) { + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_VOLATILE: + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_AGGREGATE: + counterType = NVML_AGGREGATE_ECC; + break; + } + ret = nvml->lib.deviceClearEccErrorCounts(device, + counterType); + } + break; + case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: case NV_CTRL_GPU_POWER_MIZER_MODE: - case NV_CTRL_GPU_ECC_CONFIGURATION: case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: case NV_CTRL_DITHERING: case NV_CTRL_DITHERING_MODE: @@ -1193,9 +1372,9 @@ static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, default: /* Did we forget to handle a GPU integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of GPU " - "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of GPU " + "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; } @@ -1244,9 +1423,9 @@ static ReturnStatus NvCtrlNvmlSetCoolerAttribute(CtrlTarget *ctrl_target, default: /* Did we forget to handle a cooler integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Fan " - "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Fan " + "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; } @@ -1260,7 +1439,7 @@ static ReturnStatus NvCtrlNvmlSetCoolerAttribute(CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, int index, int val) @@ -1269,7 +1448,6 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1283,9 +1461,9 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, case THERMAL_SENSOR_TARGET: /* Did we forget to handle a sensor integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Thermal " - "sensor (%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Thermal " + "sensor (%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; case COOLER_TARGET: @@ -1293,19 +1471,47 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } +static nvmlReturn_t getDeviceMemoryCounts(const CtrlTarget *ctrl_target, + const NvCtrlNvmlAttributes *nvml, + nvmlDevice_t device, + nvmlMemoryErrorType_t errorType, + nvmlEccCounterType_t counterType, + unsigned char **data, int *len) +{ + unsigned long long count; + int *counts = (int *) nvalloc(sizeof(int) * NVML_MEMORY_LOCATION_COUNT); + nvmlReturn_t ret, anySuccess = NVML_ERROR_NOT_SUPPORTED; + int i; + + for (i = NVML_MEMORY_LOCATION_L1_CACHE; + i < NVML_MEMORY_LOCATION_COUNT; + i++) { + + ret = nvml->lib.deviceGetMemoryErrorCounter(device, errorType, + counterType, i, &count); + if (ret == NVML_SUCCESS) { + anySuccess = NVML_SUCCESS; + counts[i] = (int) count; + } else { + counts[i] = -1; + } + } + + *data = (unsigned char *) counts; + *len = sizeof(int) * NVML_MEMORY_LOCATION_COUNT; + + return anySuccess; +} + /* * Get NVML Binary Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, @@ -1325,8 +1531,66 @@ NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU: + { + unsigned int *fan_data; + unsigned int count = 0; + int offset = 0; + int i = 0; + + ret = nvml->lib.deviceGetNumFans(device, &count); + if (ret != NVML_SUCCESS) { + return NvCtrlNotSupported; + } + + /* + * The format of the returned data is: + * + * int unsigned int number of COOLERS + * int * n unsigned int COOLER indices + */ + + *len = (count + 1) * sizeof(unsigned int); + fan_data = (unsigned int *) nvalloc(*len); + memset(fan_data, 0, *len); + *data = (unsigned char *) fan_data; + + /* Calculate global fan index offset for this GPU */ + for (i = 0; i < nvml->deviceIdx; i++) { + offset += nvml->coolerCountPerGPU[i]; + } + + fan_data[0] = count; + for (i = 0; i < count; i++) { + fan_data[i+1] = i + offset; + } + break; + } + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_CORRECTED, + NVML_VOLATILE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + NVML_VOLATILE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT_AGGREGATE: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_CORRECTED, + NVML_AGGREGATE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + NVML_AGGREGATE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU: case NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU: @@ -1356,7 +1620,7 @@ NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, @@ -1366,7 +1630,6 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1398,10 +1661,6 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -1410,28 +1669,31 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, * Get NVML Valid String Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUValidStringAttributeValues(int attr, CtrlAttributeValidValues *val) { switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: case NV_CTRL_STRING_PRODUCT_NAME: case NV_CTRL_STRING_VBIOS_VERSION: - case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_GPU_UUID: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING; + return NvCtrlSuccess; + case NV_CTRL_STRING_SLI_MODE: case NV_CTRL_STRING_PERFORMANCE_MODES: case NV_CTRL_STRING_MULTIGPU_MODE: case NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_STRING_GPU_UUID: case NV_CTRL_STRING_GPU_UTILIZATION: /* * XXX We'll eventually need to add support for this attributes. For * string attributes, NV-CONTROL only sets the attribute type * and permissions so no actual NVML call will be needed. */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not GPU-targeted */ @@ -1441,25 +1703,54 @@ NvCtrlNvmlGetGPUValidStringAttributeValues(int attr, return NvCtrlSuccess; } -#endif // NVML_EXPERIMENTAL + + +static ReturnStatus convertValidTypeToAttributeType(CtrlAttributeValidType val, + CtrlAttributeType *type) +{ + switch (val) { + case CTRL_ATTRIBUTE_VALID_TYPE_INTEGER: + case CTRL_ATTRIBUTE_VALID_TYPE_BOOL: + case CTRL_ATTRIBUTE_VALID_TYPE_BITMASK: + case CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER: + *type = CTRL_ATTRIBUTE_TYPE_INTEGER; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_STRING: + *type = CTRL_ATTRIBUTE_TYPE_STRING; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_STRING_OPERATION: + *type = CTRL_ATTRIBUTE_TYPE_STRING_OPERATION; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_BINARY_DATA: + *type = CTRL_ATTRIBUTE_TYPE_BINARY_DATA; + break; + default: + return NvCtrlAttributeNotAvailable; + } + + return NvCtrlSuccess; +} + + ReturnStatus NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, int attr, CtrlAttributeValidValues *val) { + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlAttributeNotAvailable; + CtrlAttributeType attr_type; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL - ReturnStatus ret; - /* - * This shouldn't be reached for target types that are not handled through - * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up - * to date). - */ - assert(TARGET_TYPE_IS_NVML_COMPATIBLE(NvCtrlGetTargetType(ctrl_target))); + if (val) { + memset(val, 0, sizeof(*val)); + } else { + return NvCtrlBadArgument; + } switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: @@ -1477,31 +1768,17 @@ NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, break; } - - /* - * XXX Did we forgot to handle this attribute? - REMOVE THIS after - * nvidia-settings NVML migration work is done - */ - if (ret == NvCtrlAttributeNotAvailable) { - const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); - ReturnStatus ret2; - - if (!h->nv) { - return NvCtrlMissingExtension; - } - - ret2 = NvCtrlNvControlGetValidStringDisplayAttributeValues(h, 0, attr, val); + if (ret == NvCtrlSuccess) { + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING; + } - assert(ret2 == NvCtrlAttributeNotAvailable); + ret = convertValidTypeToAttributeType(val->valid_type, &attr_type); - return ret2; + if (ret != NvCtrlSuccess) { + return ret; } - return ret; - -#else - return NvCtrlNotSupported; -#endif + return NvCtrlNvmlGetAttributePerms(h, attr_type, attr, &val->permissions); } @@ -1510,7 +1787,7 @@ NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, * Get NVML Valid Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, @@ -1527,10 +1804,11 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, nvml = h->nvml; + val->permissions.write = NV_FALSE; + ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_VIDEO_RAM: case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: case NV_CTRL_USED_DEDICATED_GPU_MEMORY: case NV_CTRL_PCI_DOMAIN: @@ -1539,27 +1817,46 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, case NV_CTRL_PCI_FUNCTION: case NV_CTRL_PCI_ID: case NV_CTRL_GPU_PCIE_GENERATION: - case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: - case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: - case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: - case NV_CTRL_BUS_TYPE: + case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_GPU_MEMORY_BUS_WIDTH: case NV_CTRL_GPU_CORES: case NV_CTRL_IRQ: - case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: case NV_CTRL_GPU_POWER_SOURCE: - case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: - case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: - case NV_CTRL_GPU_POWER_MIZER_MODE: - case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_INTEGER; + break; + case NV_CTRL_GPU_ECC_SUPPORTED: case NV_CTRL_GPU_ECC_STATUS: case NV_CTRL_GPU_ECC_CONFIGURATION: - case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BOOL; + break; + + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER; + break; + + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BITMASK; + break; + + case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: + case NV_CTRL_VIDEO_RAM: + case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: + case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: + case NV_CTRL_BUS_TYPE: + case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: + case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: + case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: + case NV_CTRL_GPU_POWER_MIZER_MODE: + case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: case NV_CTRL_ENABLED_DISPLAYS: case NV_CTRL_CONNECTED_DISPLAYS: case NV_CTRL_MAX_SCREEN_WIDTH: @@ -1574,10 +1871,8 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, case NV_CTRL_ATTR_NV_MINOR_VERSION: case NV_CTRL_OPERATING_SYSTEM: case NV_CTRL_NO_SCANOUT: - case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_AMBIENT_TEMPERATURE: case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS: case NV_CTRL_VIDEO_ENCODER_UTILIZATION: case NV_CTRL_VIDEO_DECODER_UTILIZATION: case NV_CTRL_FRAMELOCK: @@ -1599,7 +1894,7 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not GPU-targeted */ @@ -1613,7 +1908,7 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } static ReturnStatus @@ -1651,7 +1946,7 @@ NvCtrlNvmlGetThermalValidAttributeValues(const CtrlTarget *ctrl_target, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not sensor-targeted */ @@ -1665,7 +1960,7 @@ NvCtrlNvmlGetThermalValidAttributeValues(const CtrlTarget *ctrl_target, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } static ReturnStatus @@ -1696,6 +1991,13 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + /* Range as a percent */ + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_RANGE; + val->range.min = 0; + val->range.max = 100; + return NvCtrlSuccess; + case NV_CTRL_THERMAL_COOLER_LEVEL: case NV_CTRL_THERMAL_COOLER_SPEED: case NV_CTRL_THERMAL_COOLER_CONTROL_TYPE: @@ -1704,7 +2006,7 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not fan-targeted */ @@ -1718,22 +2020,24 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetValidAttributeValues(const CtrlTarget *ctrl_target, int attr, CtrlAttributeValidValues *val) { + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlAttributeNotAvailable; + CtrlAttributeType attr_type; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL - ReturnStatus ret; /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1764,30 +2068,136 @@ NvCtrlNvmlGetValidAttributeValues(const CtrlTarget *ctrl_target, ret = NvCtrlBadHandle; } - - /* - * XXX Did we forgot to handle this attribute? - REMOVE THIS after - * nvidia-settings NVML migration work is done - */ - if (ret == NvCtrlAttributeNotAvailable) { - const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); - ReturnStatus ret2; + if (ret != NvCtrlSuccess) { + return ret; + } - if (!h->nv) { - return NvCtrlMissingExtension; - } + ret = convertValidTypeToAttributeType(val->valid_type, &attr_type); + + if (ret != NvCtrlSuccess) { + return ret; + } + + return NvCtrlNvmlGetAttributePerms(h, attr_type, attr, &val->permissions); +} + +static ReturnStatus NvCtrlNvmlGetIntegerAttributePerms(int attr, + CtrlAttributePerms *perms) +{ + /* Set write permissions */ + switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION: + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + perms->write = NV_TRUE; + break; + default: + perms->write = NV_FALSE; + } + + /* Valid target and read permissions */ + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + case NV_CTRL_PCI_DOMAIN: + case NV_CTRL_PCI_BUS: + case NV_CTRL_PCI_DEVICE: + case NV_CTRL_PCI_FUNCTION: + case NV_CTRL_PCI_ID: + case NV_CTRL_GPU_PCIE_GENERATION: + case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: + case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + case NV_CTRL_GPU_CORE_TEMPERATURE: + case NV_CTRL_GPU_MEMORY_BUS_WIDTH: + case NV_CTRL_GPU_CORES: + case NV_CTRL_IRQ: + case NV_CTRL_GPU_POWER_SOURCE: + /* CTRL_ATTRIBUTE_VALID_TYPE_BOOL */ + case NV_CTRL_GPU_ECC_SUPPORTED: + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + case NV_CTRL_GPU_ECC_STATUS: + case NV_CTRL_GPU_ECC_CONFIGURATION: + /* CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER */ + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + perms->read = NV_TRUE; + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + break; - ret2 = NvCtrlNvControlGetValidAttributeValues(h, 0, attr, val); + /* GPU_TARGET non-readable attribute */ + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + perms->read = NV_FALSE; + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + break; - assert(ret2 == NvCtrlAttributeNotAvailable); + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + perms->valid_targets = CTRL_TARGET_PERM_BIT(COOLER_TARGET); + perms->read = NV_TRUE; + break; - return ret2; + default: + perms->valid_targets = 0; + perms->read = NV_FALSE; + return NvCtrlNotSupported; + } + + return NvCtrlSuccess; +} + +static ReturnStatus NvCtrlNvmlGetStringAttributePerms(int attr, + CtrlAttributePerms *perms) +{ + perms->write = NV_FALSE; + + switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_PRODUCT_NAME: + case NV_CTRL_STRING_VBIOS_VERSION: + case NV_CTRL_STRING_GPU_UUID: + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + perms->read = NV_TRUE; + break; + default: + perms->valid_targets = 0; + perms->read = NV_FALSE; + return NvCtrlNotSupported; + } + return NvCtrlSuccess; +} + + +ReturnStatus +NvCtrlNvmlGetAttributePerms(const NvCtrlAttributePrivateHandle *h, + CtrlAttributeType attr_type, int attr, + CtrlAttributePerms *perms) +{ + ReturnStatus ret = NvCtrlSuccess; + + if (!h->nvml) { + return NvCtrlBadArgument; + } + + switch (attr_type) { + case CTRL_ATTRIBUTE_TYPE_INTEGER: + ret = NvCtrlNvmlGetIntegerAttributePerms(attr, perms); + break; + + case CTRL_ATTRIBUTE_TYPE_STRING: + ret = NvCtrlNvmlGetStringAttributePerms(attr, perms); + break; + + case CTRL_ATTRIBUTE_TYPE_BINARY_DATA: + return NvCtrlBadArgument; + break; + + default: + return NvCtrlBadArgument; } return ret; -#else - return NvCtrlNotSupported; -#endif } diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h index 1ce590f..d93e207 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h @@ -170,15 +170,31 @@ struct __NvCtrlNvmlAttributes { typeof(nvmlDeviceGetUUID) (*deviceGetUUID); typeof(nvmlDeviceGetCount) (*deviceGetCount); typeof(nvmlDeviceGetTemperature) (*deviceGetTemperature); - typeof(nvmlDeviceGetFanSpeed) (*deviceGetFanSpeed); typeof(nvmlDeviceGetName) (*deviceGetName); typeof(nvmlDeviceGetVbiosVersion) (*deviceGetVbiosVersion); typeof(nvmlDeviceGetMemoryInfo) (*deviceGetMemoryInfo); + typeof(nvmlDeviceGetMemoryInfo_v2) (*deviceGetMemoryInfo_v2); typeof(nvmlDeviceGetPciInfo) (*deviceGetPciInfo); + typeof(nvmlDeviceGetCurrPcieLinkWidth) (*deviceGetCurrPcieLinkWidth); typeof(nvmlDeviceGetMaxPcieLinkGeneration) (*deviceGetMaxPcieLinkGeneration); typeof(nvmlDeviceGetMaxPcieLinkWidth) (*deviceGetMaxPcieLinkWidth); typeof(nvmlDeviceGetVirtualizationMode) (*deviceGetVirtualizationMode); typeof(nvmlDeviceGetGridLicensableFeatures_v4) (*deviceGetGridLicensableFeatures); + typeof(nvmlDeviceGetUtilizationRates) (*deviceGetUtilizationRates); + typeof(nvmlDeviceGetTemperatureThreshold) (*deviceGetTemperatureThreshold); + typeof(nvmlDeviceGetFanSpeed_v2) (*deviceGetFanSpeed_v2); + typeof(nvmlSystemGetDriverVersion) (*systemGetDriverVersion); + typeof(nvmlDeviceGetEccMode) (*deviceGetEccMode); + typeof(nvmlDeviceSetEccMode) (*deviceSetEccMode); + typeof(nvmlDeviceGetTotalEccErrors) (*deviceGetTotalEccErrors); + typeof(nvmlDeviceClearEccErrorCounts) (*deviceClearEccErrorCounts); + typeof(nvmlDeviceGetMemoryErrorCounter) (*deviceGetMemoryErrorCounter); + typeof(nvmlSystemGetNVMLVersion) (*systemGetNVMLVersion); + typeof(nvmlDeviceGetNumGpuCores) (*deviceGetNumGpuCores); + typeof(nvmlDeviceGetMemoryBusWidth) (*deviceGetMemoryBusWidth); + typeof(nvmlDeviceGetIrqNum) (*deviceGetIrqNum); + typeof(nvmlDeviceGetPowerSource) (*deviceGetPowerSource); + typeof(nvmlDeviceGetNumFans) (*deviceGetNumFans); } lib; @@ -457,4 +473,9 @@ NvCtrlNvmlGetValidAttributeValues(const CtrlTarget *ctrl_target, int attr, CtrlAttributeValidValues *val); +ReturnStatus +NvCtrlNvmlGetAttributePerms(const NvCtrlAttributePrivateHandle *, + CtrlAttributeType, int, + CtrlAttributePerms *); + #endif /* __NVCTRL_ATTRIBUTES_PRIVATE__ */ diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesUtils.c b/src/libXNVCtrlAttributes/NvCtrlAttributesUtils.c index 5acb7c3..111b24c 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesUtils.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesUtils.c @@ -505,7 +505,9 @@ static void add_target_relationships(CtrlTarget *target, status = NvCtrlGetBinaryAttribute(target, 0, attr, (unsigned char **)(&pData), &len); if ((status != NvCtrlSuccess) || !pData) { - nv_error_msg("Error querying target relations"); + if (status != NvCtrlNotSupported) { + nv_error_msg("Error querying target relations"); + } return; } @@ -673,7 +675,7 @@ static CtrlTarget *nv_alloc_ctrl_target(CtrlSystem *system, * not being specified in xorg.conf, it can cause errors down the line. */ - if (target_type == GPU_TARGET) { + if (target_type == GPU_TARGET && t->system->has_nv_control) { /* NV_CTRL_DEPTH_30_ALLOWED expected to succeed for any valid device */ status = NvCtrlGetAttribute(t, NV_CTRL_DEPTH_30_ALLOWED, &d); if (status != NvCtrlSuccess) { @@ -733,7 +735,7 @@ static CtrlTarget *nv_alloc_ctrl_target(CtrlSystem *system, * (framelock), we just assign this to 0. */ - if (targetTypeInfo->uses_display_devices) { + if (targetTypeInfo->uses_display_devices && system->has_nv_control) { status = NvCtrlGetAttribute(t, NV_CTRL_ENABLED_DISPLAYS, &d); @@ -817,6 +819,16 @@ static Bool is_nvcontrol_protocol_valid(const CtrlTarget *ctrl_target, } +static const char *get_display_name(CtrlSystem *system) +{ + if (system->has_nv_control) { + return XDisplayName(system->display); + } else { + return system->display; + } +} + + static Bool load_system_info(CtrlSystem *system, const char *display) { ReturnStatus status; @@ -826,6 +838,8 @@ static Bool load_system_info(CtrlSystem *system, const char *display) int unused; int *pData = NULL; const CtrlTargetTypeInfo *targetTypeInfo; + int subsystems = NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | + NV_CTRL_ATTRIBUTES_NVML_SUBSYSTEM; if (!system) { return FALSE; @@ -841,19 +855,19 @@ static Bool load_system_info(CtrlSystem *system, const char *display) system->dpy = XOpenDisplay(system->display); if (system->dpy == NULL) { - nv_error_msg("Unable to find display on any available system"); - return FALSE; + /* If it fails, just use NVML */ + subsystems = NV_CTRL_ATTRIBUTES_NVML_SUBSYSTEM; + } else { + system->has_nv_control = + XNVCTRLQueryExtension(system->dpy, &unused, &unused); } - system->has_nv_control = - XNVCTRLQueryExtension(system->dpy, &unused, &unused); - /* Try to initialize the NVML library */ - nvmlQueryTarget = nv_alloc_ctrl_target(system, GPU_TARGET, 0, - NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | - NV_CTRL_ATTRIBUTES_NVML_SUBSYSTEM); + nvmlQueryTarget = nv_alloc_ctrl_target(system, GPU_TARGET, 0, subsystems); - if (nvmlQueryTarget == NULL) { + system->has_nvml = (nvmlQueryTarget != NULL); + + if (system->has_nvml == FALSE) { nv_error_msg("Unable to load info from any available system"); return FALSE; } @@ -888,7 +902,9 @@ static Bool load_system_info(CtrlSystem *system, const char *display) status = NvCtrlQueryTargetCount(nvmlQueryTarget, target_type, &val); - target_count = val; + if (status == NvCtrlSuccess) { + target_count = val; + } } else if ((h != NULL) && (h->nvml != NULL) && @@ -950,7 +966,7 @@ static Bool load_system_info(CtrlSystem *system, const char *display) nv_warning_msg("Unable to determine number of NVIDIA " "%ss on '%s'.", targetTypeInfo->name, - XDisplayName(system->display)); + get_display_name(system)); val = 0; } @@ -1026,7 +1042,7 @@ static Bool load_system_info(CtrlSystem *system, const char *display) if (status != NvCtrlSuccess) { nv_warning_msg("Unable to determine number of NVIDIA %ss on '%s'.", - targetTypeInfo->name, XDisplayName(system->display)); + targetTypeInfo->name, get_display_name(system)); val = 0; } diff --git a/src/nvidia-settings.c b/src/nvidia-settings.c index 75a5a28..da4cab8 100644 --- a/src/nvidia-settings.c +++ b/src/nvidia-settings.c @@ -367,7 +367,7 @@ int main(int argc, char **argv) system = NvCtrlGetSystem(op->ctrl_display, &systems); - if (!system || !system->dpy) { + if (!system) { return 1; } @@ -114,15 +114,19 @@ extern "C" { #define nvmlEventSetWait nvmlEventSetWait_v2 #define nvmlDeviceGetAttributes nvmlDeviceGetAttributes_v2 #define nvmlComputeInstanceGetInfo nvmlComputeInstanceGetInfo_v2 - #define nvmlDeviceGetComputeRunningProcesses nvmlDeviceGetComputeRunningProcesses_v2 - #define nvmlDeviceGetGraphicsRunningProcesses nvmlDeviceGetGraphicsRunningProcesses_v2 - #define nvmlDeviceGetMPSComputeRunningProcesses nvmlDeviceGetMPSComputeRunningProcesses_v2 + #define nvmlDeviceGetComputeRunningProcesses nvmlDeviceGetComputeRunningProcesses_v3 + #define nvmlDeviceGetGraphicsRunningProcesses nvmlDeviceGetGraphicsRunningProcesses_v3 + #define nvmlDeviceGetMPSComputeRunningProcesses nvmlDeviceGetMPSComputeRunningProcesses_v3 #define nvmlBlacklistDeviceInfo_t nvmlExcludedDeviceInfo_t #define nvmlGetBlacklistDeviceCount nvmlGetExcludedDeviceCount #define nvmlGetBlacklistDeviceInfoByIndex nvmlGetExcludedDeviceInfoByIndex #define nvmlDeviceGetGpuInstancePossiblePlacements nvmlDeviceGetGpuInstancePossiblePlacements_v2 + #define nvmlVgpuInstanceGetLicenseInfo nvmlVgpuInstanceGetLicenseInfo_v2 #endif // #ifndef NVML_NO_UNVERSIONED_FUNC_DEFS +#define NVML_STRUCT_VERSION(data, ver) (unsigned int)(sizeof(nvml ## data ## _v ## ver ## _t) | \ + (ver << 24U)) + /***************************************************************************************************/ /** @defgroup nvmlDeviceStructs Device Structs * @{ @@ -208,16 +212,35 @@ typedef struct nvmlUtilization_st } nvmlUtilization_t; /** - * Memory allocation information for a device. + * Memory allocation information for a device (v1). + * The total amount is equal to the sum of the amounts of free and used memory. */ typedef struct nvmlMemory_st { - unsigned long long total; //!< Total installed FB memory (in bytes) - unsigned long long free; //!< Unallocated FB memory (in bytes) - unsigned long long used; //!< Allocated FB memory (in bytes). Note that the driver/GPU always sets aside a small amount of memory for bookkeeping + unsigned long long total; //!< Total physical device memory (in bytes) + unsigned long long free; //!< Unallocated device memory (in bytes) + unsigned long long used; //!< Sum of Reserved and Allocated device memory (in bytes). + //!< Note that the driver/GPU always sets aside a small amount of memory for bookkeeping } nvmlMemory_t; /** + * Memory allocation information for a device (v2). + * + * Version 2 adds versioning for the struct and the amount of system-reserved memory as an output. + * @note The \ref nvmlMemory_v2_t.used amount also includes the \ref nvmlMemory_v2_t.reserved amount. + */ +typedef struct nvmlMemory_v2_st +{ + unsigned int version; //!< Structure format version (must be 2) + unsigned long long total; //!< Total physical device memory (in bytes) + unsigned long long reserved; //!< Device memory (in bytes) reserved for system use (driver or firmware) + unsigned long long free; //!< Unallocated device memory (in bytes) + unsigned long long used; //!< Allocated device memory (in bytes). Note that the driver/GPU always sets aside a small amount of memory for bookkeeping +} nvmlMemory_v2_t; + +#define nvmlMemory_v2 NVML_STRUCT_VERSION(Memory, 2) + +/** * BAR1 Memory allocation Information for a device */ typedef struct nvmlBAR1Memory_st @@ -242,6 +265,22 @@ typedef struct nvmlProcessInfo_v1_st /** * Information about running compute processes on the GPU */ +typedef struct nvmlProcessInfo_v2_st +{ + unsigned int pid; //!< Process ID + unsigned long long usedGpuMemory; //!< Amount of used GPU memory in bytes. + //! Under WDDM, \ref NVML_VALUE_NOT_AVAILABLE is always reported + //! because Windows KMD manages all the memory and not the NVIDIA driver + unsigned int gpuInstanceId; //!< If MIG is enabled, stores a valid GPU instance ID. gpuInstanceId is set to + // 0xFFFFFFFF otherwise. + unsigned int computeInstanceId; //!< If MIG is enabled, stores a valid compute instance ID. computeInstanceId is set to + // 0xFFFFFFFF otherwise. +} nvmlProcessInfo_v2_t; + +/** + * Information about running compute processes on the GPU + * Version 2 adds versioning for the struct and the conf compute protected memory in output. + */ typedef struct nvmlProcessInfo_st { unsigned int pid; //!< Process ID @@ -567,23 +606,24 @@ typedef enum nvmlEnableState_enum * */ typedef enum nvmlBrandType_enum { - NVML_BRAND_UNKNOWN = 0, - NVML_BRAND_QUADRO = 1, - NVML_BRAND_TESLA = 2, - NVML_BRAND_NVS = 3, - NVML_BRAND_GRID = 4, // Deprecated from API reporting. Keeping definition for backward compatibility. - NVML_BRAND_GEFORCE = 5, - NVML_BRAND_TITAN = 6, - NVML_BRAND_NVIDIA_VAPPS = 7, // NVIDIA Virtual Applications - NVML_BRAND_NVIDIA_VPC = 8, // NVIDIA Virtual PC - NVML_BRAND_NVIDIA_VCS = 9, // NVIDIA Virtual Compute Server - NVML_BRAND_NVIDIA_VWS = 10, // NVIDIA RTX Virtual Workstation - NVML_BRAND_NVIDIA_VGAMING = 11, // NVIDIA vGaming - NVML_BRAND_QUADRO_RTX = 12, - NVML_BRAND_NVIDIA_RTX = 13, - NVML_BRAND_NVIDIA = 14, - NVML_BRAND_GEFORCE_RTX = 15, // Unused - NVML_BRAND_TITAN_RTX = 16, // Unused + NVML_BRAND_UNKNOWN = 0, + NVML_BRAND_QUADRO = 1, + NVML_BRAND_TESLA = 2, + NVML_BRAND_NVS = 3, + NVML_BRAND_GRID = 4, // Deprecated from API reporting. Keeping definition for backward compatibility. + NVML_BRAND_GEFORCE = 5, + NVML_BRAND_TITAN = 6, + NVML_BRAND_NVIDIA_VAPPS = 7, // NVIDIA Virtual Applications + NVML_BRAND_NVIDIA_VPC = 8, // NVIDIA Virtual PC + NVML_BRAND_NVIDIA_VCS = 9, // NVIDIA Virtual Compute Server + NVML_BRAND_NVIDIA_VWS = 10, // NVIDIA RTX Virtual Workstation + NVML_BRAND_NVIDIA_CLOUD_GAMING = 11, // NVIDIA Cloud Gaming + NVML_BRAND_NVIDIA_VGAMING = NVML_BRAND_NVIDIA_CLOUD_GAMING, // Deprecated from API reporting. Keeping definition for backward compatibility. + NVML_BRAND_QUADRO_RTX = 12, + NVML_BRAND_NVIDIA_RTX = 13, + NVML_BRAND_NVIDIA = 14, + NVML_BRAND_GEFORCE_RTX = 15, // Unused + NVML_BRAND_TITAN_RTX = 16, // Unused // Keep this last NVML_BRAND_COUNT @@ -1093,10 +1133,21 @@ typedef struct nvmlVgpuLicenseExpiry_st unsigned char status; //!< License expiry status } nvmlVgpuLicenseExpiry_t; +/** + * vGPU license state + */ +#define NVML_GRID_LICENSE_STATE_UNKNOWN 0 //!< Unknown state +#define NVML_GRID_LICENSE_STATE_UNINITIALIZED 1 //!< Uninitialized state +#define NVML_GRID_LICENSE_STATE_UNLICENSED_UNRESTRICTED 2 //!< Unlicensed unrestricted state +#define NVML_GRID_LICENSE_STATE_UNLICENSED_RESTRICTED 3 //!< Unlicensed restricted state +#define NVML_GRID_LICENSE_STATE_UNLICENSED 4 //!< Unlicensed state +#define NVML_GRID_LICENSE_STATE_LICENSED 5 //!< Licensed state + typedef struct nvmlVgpuLicenseInfo_st { unsigned char isLicensed; //!< License status nvmlVgpuLicenseExpiry_t licenseExpiry; //!< License expiry information + unsigned int currentState; //!< Current license state } nvmlVgpuLicenseInfo_t; /** @@ -1175,6 +1226,30 @@ typedef unsigned int nvmlDeviceArchitecture_t; typedef unsigned int nvmlBusType_t; +/** + * Device Power Source + */ +#define NVML_POWER_SOURCE_AC 0x00000000 +#define NVML_POWER_SOURCE_BATTERY 0x00000001 + +typedef unsigned int nvmlPowerSource_t; + +/* + * Device PCIE link Max Speed + */ +#define NVML_PCIE_LINK_MAX_SPEED_INVALID 0x00000000 +#define NVML_PCIE_LINK_MAX_SPEED_2500MBPS 0x00000001 +#define NVML_PCIE_LINK_MAX_SPEED_5000MBPS 0x00000002 +#define NVML_PCIE_LINK_MAX_SPEED_8000MBPS 0x00000003 +#define NVML_PCIE_LINK_MAX_SPEED_16000MBPS 0x00000004 +#define NVML_PCIE_LINK_MAX_SPEED_32000MBPS 0x00000005 + +/* + * Adaptive clocking status + */ +#define NVML_ADAPTIVE_CLOCKING_INFO_STATUS_DISABLED 0x00000000 +#define NVML_ADAPTIVE_CLOCKING_INFO_STATUS_ENABLED 0x00000001 + /** @} */ /** @} */ @@ -3610,6 +3685,24 @@ nvmlReturn_t DECLDIR nvmlDeviceGetFanSpeed(nvmlDevice_t device, unsigned int *sp nvmlReturn_t DECLDIR nvmlDeviceGetFanSpeed_v2(nvmlDevice_t device, unsigned int fan, unsigned int * speed); /** + * Retrieves the number of fans on the device. + * + * For all discrete products with dedicated fans. + * + * @param device The identifier of the target device + * @param numFans The number of fans + * + * @return + * - \ref NVML_SUCCESS if \a fan number query was successful + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a numFans is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have a fan + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNumFans(nvmlDevice_t device, unsigned int *numFans); + +/** * Retrieves the current temperature readings for the device, in degrees C. * * For all products. @@ -3940,7 +4033,8 @@ nvmlReturn_t DECLDIR nvmlDeviceGetEnforcedPowerLimit(nvmlDevice_t device, unsign nvmlReturn_t DECLDIR nvmlDeviceGetGpuOperationMode(nvmlDevice_t device, nvmlGpuOperationMode_t *current, nvmlGpuOperationMode_t *pending); /** - * Retrieves the amount of used, free and total memory available on the device, in bytes. + * Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. + * The reserved amount is supported on version 2 only. * * For all products. * @@ -3950,11 +4044,13 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuOperationMode(nvmlDevice_t device, nvmlGpuO * Under Linux and Windows TCC, the reported amount of used memory is equal to the sum of memory allocated * by all active channels on the device. * - * See \ref nvmlMemory_t for details on available memory info. + * See \ref nvmlMemory_v2_t for details on available memory info. * * @note In MIG mode, if device handle is provided, the API returns aggregate * information, only if the caller has appropriate privileges. Per-instance * information can be queried by using specific MIG device handles. + * + * @note nvmlDeviceGetMemoryInfo_v2 adds additional memory information. * * @param device The identifier of the target device * @param memory Reference in which to return the memory information @@ -3968,6 +4064,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuOperationMode(nvmlDevice_t device, nvmlGpuO * - \ref NVML_ERROR_UNKNOWN on any unexpected error */ nvmlReturn_t DECLDIR nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t *memory); +nvmlReturn_t DECLDIR nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t *memory); /** * Retrieves the current compute mode for the device. @@ -4491,7 +4588,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetBridgeChipInfo(nvmlDevice_t device, nvmlBridge * * @see \ref nvmlSystemGetProcessName */ -nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses_v3(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); /** * Get information about processes with a graphics context on a device @@ -4516,8 +4613,6 @@ nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses_v2(nvmlDevice_t device * Querying per-instance information using MIG device handles is not supported if the device is in vGPU Host virtualization mode. * * @param device The device handle or MIG device handle -#else - * @param device The device handle * @param infoCount Reference in which to provide the \a infos array size, and * to return the number of returned elements * @param infos Reference in which to return the process information @@ -4536,7 +4631,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses_v2(nvmlDevice_t device * * @see \ref nvmlSystemGetProcessName */ -nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses_v3(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); /** * Get information about processes with a MPS compute context on a device @@ -4579,7 +4674,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses_v2(nvmlDevice_t devic * * @see \ref nvmlSystemGetProcessName */ -nvmlReturn_t DECLDIR nvmlDeviceGetMPSComputeRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetMPSComputeRunningProcesses_v3(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); /** * Check if the GPU devices are on the same physical board. @@ -4742,6 +4837,86 @@ nvmlReturn_t DECLDIR nvmlDeviceGetViolationStatus(nvmlDevice_t device, nvmlPerfP nvmlReturn_t DECLDIR nvmlDeviceGetIrqNum(nvmlDevice_t device, unsigned int *irqNum); /** + * Gets the device's core count + * + * @param device The identifier of the target device + * @param numCores The number of cores for the specified device + * + * @return + * - \ref NVML_SUCCESS if Gpu core count is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a numCores is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int *numCores); + +/** + * Gets the devices power source + * + * @param device The identifier of the target device + * @param powerSource The power source of the device + * + * @return + * - \ref NVML_SUCCESS if the current power source was successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a powerSource is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerSource(nvmlDevice_t device, nvmlPowerSource_t *powerSource); + +/** + * Gets the device's memory bus width + * + * @param device The identifier of the target device + * @param maxSpeed The devices's memory bus width + * + * @return + * - \ref NVML_SUCCESS if the memory bus width is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a busWidth is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMemoryBusWidth(nvmlDevice_t device, unsigned int *busWidth); + +/** + * Gets the device's PCIE Max Link speed in MBPS + * + * @param device The identifier of the target device + * @param maxSpeed The devices's PCIE Max Link speed in MBPS + * + * @return + * - \ref NVML_SUCCESS if Pcie Max Link Speed is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a maxSpeed is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPcieLinkMaxSpeed(nvmlDevice_t device, unsigned int *maxSpeed); + +/** + * Gets the device's Adaptive Clock status + * + * @param device The identifier of the target device + * @param adaptiveClockStatus The current adaptive clocking status + * + * @return + * - \ref NVML_SUCCESS if the current adaptive clocking status is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a adaptiveClockStatus is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAdaptiveClockInfoStatus(nvmlDevice_t device, unsigned int *adaptiveClockStatus); + +/** * @} */ @@ -6635,7 +6810,7 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetVmDriverVersion(nvmlVgpuInstance_t vgpuI nvmlReturn_t DECLDIR nvmlVgpuInstanceGetFbUsage(nvmlVgpuInstance_t vgpuInstance, unsigned long long *fbUsage); /** - * @deprecated Use \ref nvmlVgpuInstanceGetLicenseInfo. + * @deprecated Use \ref nvmlVgpuInstanceGetLicenseInfo_v2. * * Retrieve the current licensing state of the vGPU instance. * @@ -6862,6 +7037,26 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetFBCSessions(nvmlVgpuInstance_t vgpuInsta */ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetGpuInstanceId(nvmlVgpuInstance_t vgpuInstance, unsigned int *gpuInstanceId); +/** +* Retrieves the PCI Id of the given vGPU Instance i.e. the PCI Id of the GPU as seen inside the VM. +* +* The vGPU PCI id is returned as "00000000:00:00.0" if NVIDIA driver is not installed on the vGPU instance. +* +* @param vgpuInstance Identifier of the target vGPU instance +* @param vgpuPciId Caller-supplied buffer to return vGPU PCI Id string +* @param length Size of the vgpuPciId buffer +* +* @return +* - \ref NVML_SUCCESS if vGPU PCI Id is sucessfully retrieved +* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized +* - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is 0, or \a vgpuPciId is NULL +* - \ref NVML_ERROR_NOT_FOUND if \a vgpuInstance does not match a valid active vGPU instance on the system +* - \ref NVML_ERROR_DRIVER_NOT_LOADED if NVIDIA driver is not running on the vGPU instance +* - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small, \a length is set to required length +* - \ref NVML_ERROR_UNKNOWN on any unexpected error +*/ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetGpuPciId(nvmlVgpuInstance_t vgpuInstance, char *vgpuPciId, unsigned int *length); + /** @} */ /***************************************************************************************************/ @@ -7325,7 +7520,7 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceClearAccountingPids(nvmlVgpuInstance_t vgpu * - \ref NVML_ERROR_DRIVER_NOT_LOADED if NVIDIA driver is not running on the vGPU instance * - \ref NVML_ERROR_UNKNOWN on any unexpected error */ -nvmlReturn_t DECLDIR nvmlVgpuInstanceGetLicenseInfo(nvmlVgpuInstance_t vgpuInstance, nvmlVgpuLicenseInfo_t *licenseInfo); +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetLicenseInfo_v2(nvmlVgpuInstance_t vgpuInstance, nvmlVgpuLicenseInfo_t *licenseInfo); /** @} */ /***************************************************************************************************/ @@ -7414,10 +7609,13 @@ nvmlReturn_t DECLDIR nvmlGetExcludedDeviceInfoByIndex(unsigned int index, nvmlEx typedef struct nvmlGpuInstancePlacement_st { - unsigned int start; - unsigned int size; + unsigned int start; //!< Index of first occupied memory slice + unsigned int size; //!< Number of memory slices occupied } nvmlGpuInstancePlacement_t; +/** + * GPU instance profile information. + */ typedef struct nvmlGpuInstanceProfileInfo_st { unsigned int id; //!< Unique profile ID within the device @@ -7433,6 +7631,36 @@ typedef struct nvmlGpuInstanceProfileInfo_st unsigned long long memorySizeMB; //!< Memory size in MBytes } nvmlGpuInstanceProfileInfo_t; +/** + * GPU instance profile information (v2). + * + * Version 2 adds the \ref nvmlGpuInstanceProfileInfo_v2_t.version field + * to the start of the structure, and the \ref nvmlGpuInstanceProfileInfo_v2_t.name + * field to the end. This structure is not backwards-compatible with + * \ref nvmlGpuInstanceProfileInfo_t. + */ +typedef struct nvmlGpuInstanceProfileInfo_v2_st +{ + unsigned int version; //!< Structure version identifier (set to \ref nvmlGpuInstanceProfileInfo_v2) + unsigned int id; //!< Unique profile ID within the device + unsigned int isP2pSupported; //!< Peer-to-Peer support + unsigned int sliceCount; //!< GPU Slice count + unsigned int instanceCount; //!< GPU instance count + unsigned int multiprocessorCount; //!< Streaming Multiprocessor count + unsigned int copyEngineCount; //!< Copy Engine count + unsigned int decoderCount; //!< Decoder Engine count + unsigned int encoderCount; //!< Encoder Engine count + unsigned int jpegCount; //!< JPEG Engine count + unsigned int ofaCount; //!< OFA Engine count + unsigned long long memorySizeMB; //!< Memory size in MBytes + char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE]; //!< Profile name +} nvmlGpuInstanceProfileInfo_v2_t; + +/** + * Version identifier value for \ref nvmlGpuInstanceProfileInfo_v2_t.version. + */ +#define nvmlGpuInstanceProfileInfo_v2 NVML_STRUCT_VERSION(GpuInstanceProfileInfo, 2) + typedef struct nvmlGpuInstanceInfo_st { nvmlDevice_t device; //!< Parent device @@ -7463,10 +7691,13 @@ typedef struct nvmlGpuInstance_st* nvmlGpuInstance_t; typedef struct nvmlComputeInstancePlacement_st { - unsigned int start; - unsigned int size; + unsigned int start; //!< Index of first occupied compute slice + unsigned int size; //!< Number of compute slices occupied } nvmlComputeInstancePlacement_t; +/** + * Compute instance profile information. + */ typedef struct nvmlComputeInstanceProfileInfo_st { unsigned int id; //!< Unique profile ID within the GPU instance @@ -7480,13 +7711,41 @@ typedef struct nvmlComputeInstanceProfileInfo_st unsigned int sharedOfaCount; //!< Shared OFA Engine count } nvmlComputeInstanceProfileInfo_t; +/** + * Compute instance profile information (v2). + * + * Version 2 adds the \ref nvmlComputeInstanceProfileInfo_v2_t.version field + * to the start of the structure, and the \ref nvmlComputeInstanceProfileInfo_v2_t.name + * field to the end. This structure is not backwards-compatible with + * \ref nvmlComputeInstanceProfileInfo_t. + */ +typedef struct nvmlComputeInstanceProfileInfo_v2_st +{ + unsigned int version; //!< Structure version identifier (set to \ref nvmlComputeInstanceProfileInfo_v2) + unsigned int id; //!< Unique profile ID within the GPU instance + unsigned int sliceCount; //!< GPU Slice count + unsigned int instanceCount; //!< Compute instance count + unsigned int multiprocessorCount; //!< Streaming Multiprocessor count + unsigned int sharedCopyEngineCount; //!< Shared Copy Engine count + unsigned int sharedDecoderCount; //!< Shared Decoder Engine count + unsigned int sharedEncoderCount; //!< Shared Encoder Engine count + unsigned int sharedJpegCount; //!< Shared JPEG Engine count + unsigned int sharedOfaCount; //!< Shared OFA Engine count + char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE]; //!< Profile name +} nvmlComputeInstanceProfileInfo_v2_t; + +/** + * Version identifier value for \ref nvmlComputeInstanceProfileInfo_v2_t.version. + */ +#define nvmlComputeInstanceProfileInfo_v2 NVML_STRUCT_VERSION(ComputeInstanceProfileInfo, 2) + typedef struct nvmlComputeInstanceInfo_st { nvmlDevice_t device; //!< Parent device nvmlGpuInstance_t gpuInstance; //!< Parent GPU instance unsigned int id; //!< Unique instance ID within the GPU instance unsigned int profileId; //!< Unique profile ID within the GPU instance - nvmlComputeInstancePlacement_t placement; //!< Placement for this instance within the GPU instance's slice range {0, sliceCount} + nvmlComputeInstancePlacement_t placement; //!< Placement for this instance within the GPU instance's compute slice range {0, sliceCount} } nvmlComputeInstanceInfo_t; typedef struct nvmlComputeInstance_st* nvmlComputeInstance_t; @@ -7555,7 +7814,6 @@ nvmlReturn_t DECLDIR nvmlDeviceGetMigMode(nvmlDevice_t device, unsigned int *cur * * For Ampere &tm; or newer fully supported devices. * Supported on Linux only. - * Requires privileged user. * * @param device The identifier of the target device * @param profile One of the NVML_GPU_INSTANCE_PROFILE_* @@ -7572,10 +7830,43 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstanceProfileInfo(nvmlDevice_t device, un nvmlGpuInstanceProfileInfo_t *info); /** + * Versioned wrapper around \ref nvmlDeviceGetGpuInstanceProfileInfo that accepts a versioned + * \ref nvmlGpuInstanceProfileInfo_v2_t or later output structure. + * + * @note The caller must set the \ref nvmlGpuInstanceProfileInfo_v2_t.version field to the + * appropriate version prior to calling this function. For example: + * \code + * nvmlGpuInstanceProfileInfo_v2_t profileInfo = + * { .version = nvmlGpuInstanceProfileInfo_v2 }; + * nvmlReturn_t result = nvmlDeviceGetGpuInstanceProfileInfoV(device, + * profile, + * &profileInfo); + * \endcode + * + * For Ampere &tm; or newer fully supported devices. + * Supported on Linux only. + * + * @param device The identifier of the target device + * @param profile One of the NVML_GPU_INSTANCE_PROFILE_* + * @param info Returns detailed profile information + * + * @return + * - \ref NVML_SUCCESS Upon success + * - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT If \a device, \a profile, \a info, or \a info->version are invalid + * - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't have MIG mode enabled or \a profile isn't supported + * - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation + */ +nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstanceProfileInfoV(nvmlDevice_t device, unsigned int profile, + nvmlGpuInstanceProfileInfo_v2_t *info); + +/** * Get GPU instance placements. * * A placement represents the location of a GPU instance within a device. This API only returns all the possible * placements for the given profile. + * A created GPU instance occupies memory slices described by its placement. Creation of new GPU instance will + * fail if there is overlap with the already occupied memory slices. * * For Ampere &tm; or newer fully supported devices. * Supported on Linux only. @@ -7762,7 +8053,6 @@ nvmlReturn_t DECLDIR nvmlGpuInstanceGetInfo(nvmlGpuInstance_t gpuInstance, nvmlG * * For Ampere &tm; or newer fully supported devices. * Supported on Linux only. - * Requires privileged user. * * @param gpuInstance The identifier of the target GPU instance * @param profile One of the NVML_COMPUTE_INSTANCE_PROFILE_* @@ -7781,6 +8071,40 @@ nvmlReturn_t DECLDIR nvmlGpuInstanceGetComputeInstanceProfileInfo(nvmlGpuInstanc nvmlComputeInstanceProfileInfo_t *info); /** + * Versioned wrapper around \ref nvmlGpuInstanceGetComputeInstanceProfileInfo that accepts a versioned + * \ref nvmlComputeInstanceProfileInfo_v2_t or later output structure. + * + * @note The caller must set the \ref nvmlGpuInstanceProfileInfo_v2_t.version field to the + * appropriate version prior to calling this function. For example: + * \code + * nvmlComputeInstanceProfileInfo_v2_t profileInfo = + * { .version = nvmlComputeInstanceProfileInfo_v2 }; + * nvmlReturn_t result = nvmlGpuInstanceGetComputeInstanceProfileInfoV(gpuInstance, + * profile, + * engProfile, + * &profileInfo); + * \endcode + * + * For Ampere &tm; or newer fully supported devices. + * Supported on Linux only. + * + * @param gpuInstance The identifier of the target GPU instance + * @param profile One of the NVML_COMPUTE_INSTANCE_PROFILE_* + * @param engProfile One of the NVML_COMPUTE_INSTANCE_ENGINE_PROFILE_* + * @param info Returns detailed profile information + * + * @return + * - \ref NVML_SUCCESS Upon success + * - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT If \a gpuInstance, \a profile, \a engProfile, \a info, or \a info->version are invalid + * - \ref NVML_ERROR_NOT_SUPPORTED If \a profile isn't supported + * - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation + */ +nvmlReturn_t DECLDIR nvmlGpuInstanceGetComputeInstanceProfileInfoV(nvmlGpuInstance_t gpuInstance, unsigned int profile, + unsigned int engProfile, + nvmlComputeInstanceProfileInfo_v2_t *info); + +/** * Get compute instance profile capacity. * * For Ampere &tm; or newer fully supported devices. @@ -8077,9 +8401,13 @@ nvmlReturn_t DECLDIR nvmlEventSetWait(nvmlEventSet_t set, nvmlEventData_t * data nvmlReturn_t DECLDIR nvmlDeviceGetAttributes(nvmlDevice_t device, nvmlDeviceAttributes_t *attributes); nvmlReturn_t DECLDIR nvmlComputeInstanceGetInfo(nvmlComputeInstance_t computeInstance, nvmlComputeInstanceInfo_t *info); nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v1_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v2_t *infos); nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v1_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v2_t *infos); nvmlReturn_t DECLDIR nvmlDeviceGetMPSComputeRunningProcesses(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v1_t *infos); +nvmlReturn_t DECLDIR nvmlDeviceGetMPSComputeRunningProcesses_v2(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_v2_t *infos); nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstancePossiblePlacements(nvmlDevice_t device, unsigned int profileId, nvmlGpuInstancePlacement_t *placements, unsigned int *count); +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetLicenseInfo(nvmlVgpuInstance_t vgpuInstance, nvmlVgpuLicenseInfo_t *licenseInfo); #endif // #ifdef NVML_NO_UNVERSIONED_FUNC_DEFS #if defined(NVML_NO_UNVERSIONED_FUNC_DEFS) @@ -8104,6 +8432,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstancePossiblePlacements(nvmlDevice_t dev #undef nvmlGetBlacklistDeviceCount #undef nvmlGetBlacklistDeviceInfoByIndex #undef nvmlDeviceGetGpuInstancePossiblePlacements +#undef nvmlVgpuInstanceGetLicenseInfo #endif #ifdef __cplusplus diff --git a/src/option-table.h b/src/option-table.h index d8109de..fd6ff56 100644 --- a/src/option-table.h +++ b/src/option-table.h @@ -181,7 +181,7 @@ static const NVGetoptOption __options[] = { TAB "--page=\"GPU 0 - (Quadro 6000), PowerMizer\"\n" "\n" "The first page with a name matching the &PAGE& argument will be used. " - "By default, the \"X Server Information\" page is displayed." }, + "By default, the \"System Information\" page is displayed." }, { "list-targets-only", 'L', NVGETOPT_HELP_ALWAYS, NULL, "When performing an attribute query (from the '--query' command line " diff --git a/src/parse.c b/src/parse.c index b505b53..abf6f10 100644 --- a/src/parse.c +++ b/src/parse.c @@ -67,7 +67,7 @@ const AttributeTableEntry attributeTable[] = { */ /* Version information */ - { "OperatingSystem", NV_CTRL_OPERATING_SYSTEM, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "The operating system on which the X server is running. 0-Linux, 1-FreeBSD, 2-SunOS." }, + { "OperatingSystem", NV_CTRL_OPERATING_SYSTEM, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "The operating system on which the NVIDIA driver is running. 0-Linux, 1-FreeBSD, 2-SunOS." }, { "NvidiaDriverVersion", NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, STR_ATTR, {0,0,0,1,0}, {}, "The NVIDIA X driver version." }, { "NvControlVersion", NV_CTRL_STRING_NV_CONTROL_VERSION, STR_ATTR, {0,0,0,1,0}, {}, "The NV-CONTROL X driver extension version." }, { "GLXServerVersion", NV_CTRL_STRING_GLX_SERVER_VERSION, STR_ATTR, {0,0,0,1,0}, {}, "The GLX X server extension version." }, @@ -161,7 +161,6 @@ const AttributeTableEntry attributeTable[] = { { "GPUDefault2DClockFreqs", NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,1,0,0,0,0} }, "NOT SUPPORTED." }, { "GPUDefault3DClockFreqs", NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,1,0,0,0,0} }, "NOT SUPPORTED." }, { "GPUCurrentClockFreqs", NV_CTRL_GPU_CURRENT_CLOCK_FREQS, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,1,0,0,0,0} }, "Returns the current GPU and memory clocks of the graphics device driving the X screen." }, - { "GPUCurrentProcessorClockFreqs", NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "Returns the current processor clock of the graphics device driving the X screen." }, { "BusRate", NV_CTRL_BUS_RATE, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "If the device is on an AGP bus, then BusRate returns the configured AGP rate. If the device is on a PCI Express bus, then this attribute returns the width of the physical link." }, { "PCIDomain", NV_CTRL_PCI_DOMAIN, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "Returns the PCI domain number for the specified device." }, { "PCIBus", NV_CTRL_PCI_BUS, INT_ATTR, {0,0,0,1,0}, { .int_flags = {0,0,0,0,0,0,0} }, "Returns the PCI bus number for the specified device." }, diff --git a/src/query-assign.c b/src/query-assign.c index ef4fadf..ec5d389 100644 --- a/src/query-assign.c +++ b/src/query-assign.c @@ -601,7 +601,7 @@ static int resolve_attribute_targets(ParsedAttribute *p, CtrlSystem *system, const char *whence) { CtrlAttributePerms perms; - CtrlTarget *ctrl_target; + CtrlTarget *ctrl_target = NULL; ReturnStatus status; int ret = NV_PARSER_STATUS_SUCCESS; int i; @@ -614,7 +614,13 @@ static int resolve_attribute_targets(ParsedAttribute *p, CtrlSystem *system, return NV_PARSER_STATUS_BAD_ARGUMENT; } - ctrl_target = NvCtrlGetDefaultTarget(system); + if (system->has_nvml) { + ctrl_target = NvCtrlGetDefaultTargetByType(system, GPU_TARGET); + } + if (!ctrl_target) { + ctrl_target = NvCtrlGetDefaultTarget(system); + } + if (ctrl_target == NULL) { return NV_PARSER_STATUS_TARGET_SPEC_NO_TARGETS; } @@ -1441,7 +1447,8 @@ static int query_all(const Options *op, const char *display_name, goto exit_bit_loop; } - if (status != NvCtrlSuccess) { + if (status != NvCtrlSuccess && + status != NvCtrlMissingExtension) { nv_error_msg("Error while querying valid values for " "attribute '%s' on %s (%s).", a->name, t->name, @@ -1749,7 +1756,11 @@ static int query_all_targets(const char *display_name, const int target_type, /* build the standard X server name */ - str = nv_standardize_screen_name(XDisplayName(system->display), -2); + if (system->has_nv_control) { + str = nv_standardize_screen_name(XDisplayName(system->display), -2); + } else { + str = strdup(system->display); + } /* warn if we don't have any of the target type */ @@ -2134,7 +2145,7 @@ int nv_process_parsed_attribute(const Options *op, /* if we don't have a Display connection, abort now */ - if (system == NULL || system->dpy == NULL) { + if (system == NULL) { nv_error_msg("Unable to %s attribute %s specified %s (no Display " "connection).", assign ? "assign" : "query", a->name, whence); diff --git a/src/version.mk b/src/version.mk index 8e23d30..5e08b7b 100644 --- a/src/version.mk +++ b/src/version.mk @@ -1,4 +1,4 @@ -NVIDIA_VERSION = 495.46 +NVIDIA_VERSION = 510.39.01 # This file. VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST)) |