X-Git-Url: https://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fnvidia.c;h=4c135d5a6a1b09e9bb959a08f7aa7e950f8e2c5b;hb=9f0b66b6c8beccb8b27225576453de3989c06cc7;hp=1e9ea4fa9d14512f2ef45a1ec8dbc7a4e578fda9;hpb=2b51051578ef29b031d0927388c4d62baa3c525e;p=psensor.git diff --git a/src/lib/nvidia.c b/src/lib/nvidia.c index 1e9ea4f..4c135d5 100644 --- a/src/lib/nvidia.c +++ b/src/lib/nvidia.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 jeanfi@gmail.com + * Copyright (C) 2010-2014 jeanfi@gmail.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -33,9 +33,7 @@ Display *display; -/* - Returns the temperature (Celcius) of a NVidia GPU. -*/ +/* Returns the temperature (Celsius) of a NVIDIA GPU. */ static int get_temp(struct psensor *sensor) { int temp; @@ -51,23 +49,143 @@ static int get_temp(struct psensor *sensor) if (res == True) return temp; - fprintf(stderr, _("ERROR: failed to retrieve nvidia temperature\n")); + log_debug(_("NVIDIA proprietary driver not used or cannot " + "retrieve NVIDIA GPU temperature.")); return 0; } -static struct psensor *create_sensor(int id, int values_len) +static double get_usage_att(char *atts, char *att) +{ + char *c, *key, *strv, *s; + size_t n; + double v; + + c = atts; + + v = UNKNOWN_DBL_VALUE; + while (*c) { + s = c; + n = 0; + while (*c) { + if (*c == '=') + break; + c++; + n++; + } + + key = strndup(s, n); + + if (*c) + c++; + + n = 0; + s = c; + while (*c) { + if (*c == ',') + break; + c++; + n++; + } + + strv = strndup(s, n); + if (!strcmp(key, att)) + v = atoi(strv); + + free(key); + free(strv); + + if (v != UNKNOWN_DBL_VALUE) + break; + + while (*c && (*c == ' ' || *c == ',')) + c++; + } + + return v; +} + +static int get_usage(struct psensor *sensor) +{ + char *temp; + Bool res; + + res = XNVCTRLQueryTargetStringAttribute(display, + NV_CTRL_TARGET_TYPE_GPU, + sensor->nvidia_id, + 0, + NV_CTRL_STRING_GPU_UTILIZATION, + &temp); + + if (res == True) { + if (sensor->type & SENSOR_TYPE_GRAPHICS) + return get_usage_att(temp, "graphics"); + else if (sensor->type & SENSOR_TYPE_VIDEO) + return get_usage_att(temp, "video"); + else if (sensor->type & SENSOR_TYPE_MEMORY) + return get_usage_att(temp, "memory"); + else if (sensor->type & SENSOR_TYPE_PCIE) + return get_usage_att(temp, "PCIe"); + } + + log_debug(_("NVIDIA proprietary driver not used or cannot " + "retrieve NVIDIA GPU usage.")); + return 0; +} + +static struct psensor *create_temp_sensor(int id, int values_len) { char name[200]; char *sid; struct psensor *s; + int t; sprintf(name, "GPU%d", id); - sid = malloc(strlen("nvidia") + 1 + strlen(name) + 1); - sprintf(sid, "nvidia %s", name); + sid = malloc(strlen("NVIDIA") + 1 + strlen(name) + 1); + sprintf(sid, "NVIDIA %s", name); + + t = SENSOR_TYPE_NVCTRL | SENSOR_TYPE_GPU | SENSOR_TYPE_TEMP; + + s = psensor_create(sid, + strdup(name), + strdup(_("NVIDIA GPU")), + t, + values_len); + + s->nvidia_id = id; + + return s; +} + +static struct psensor *create_usage_sensor(int id, + int subtype, + int values_len) +{ + char name[200]; + char *sid; + struct psensor *s; + int t; + + if (subtype & SENSOR_TYPE_GRAPHICS) + sprintf(name, "GPU%d graphics", id); + else if (subtype & SENSOR_TYPE_MEMORY) + sprintf(name, "GPU%d memory", id); + else if (subtype & SENSOR_TYPE_VIDEO) + sprintf(name, "GPU%d video", id); + else /* if (subtype & SENSOR_TYPE_PCIE) */ + sprintf(name, "GPU%d PCIe", id); + - s = psensor_create(sid, strdup(name), - SENSOR_TYPE_NVIDIA_TEMP, values_len); + sid = malloc(strlen("NVIDIA") + 1 + strlen(name) + 1); + sprintf(sid, "NVIDIA %s", name); + + t = SENSOR_TYPE_NVCTRL | SENSOR_TYPE_GPU | SENSOR_TYPE_USAGE | subtype; + + s = psensor_create(sid, + strdup(name), + strdup(_("NVIDIA GPU")), + t, + values_len); s->nvidia_id = id; @@ -76,9 +194,9 @@ static struct psensor *create_sensor(int id, int values_len) /* Opens connection to X server and returns the number - of NVidia GPUs. + of NVIDIA GPUs. - Return 0 if no NVidia gpus or cannot get information. + Return 0 if no NVIDIA gpus or cannot get information. */ static int init() { @@ -87,8 +205,7 @@ static int init() display = XOpenDisplay(NULL); if (!display) { - fprintf(stderr, - _("ERROR: Cannot open connection to X Server\n")); + log_err(_("Cannot open connection to X11 server.")); return 0; } @@ -96,7 +213,7 @@ static int init() XNVCTRLQueryTargetCount(display, NV_CTRL_TARGET_TYPE_GPU, &n)) return n; - fprintf(stderr, _("ERROR: Cannot retrieve NVidia information\n")); + log_err(_("Failed to retrieve NVIDIA information.")); return 0; } @@ -109,8 +226,12 @@ void nvidia_psensor_list_update(struct psensor **sensors) while (*ss) { s = *ss; - if (s->type == SENSOR_TYPE_NVIDIA_TEMP) - psensor_set_current_value(s, get_temp(s)); + if (s->type & SENSOR_TYPE_NVCTRL) { + if (s->type & SENSOR_TYPE_TEMP) + psensor_set_current_value(s, get_temp(s)); + else if (s->type & SENSOR_TYPE_USAGE) + psensor_set_current_value(s, get_usage(s)); + } ss++; } @@ -126,10 +247,32 @@ struct psensor **nvidia_psensor_list_add(struct psensor **sensors, ss = sensors; for (i = 0; i < n; i++) { - s = create_sensor(i, values_len); + s = create_temp_sensor(i, values_len); + tmp = psensor_list_add(ss, s); + if (ss != tmp) + free(ss); + ss = tmp; + s = create_usage_sensor(i, SENSOR_TYPE_GRAPHICS, values_len); tmp = psensor_list_add(ss, s); + if (ss != tmp) + free(ss); + ss = tmp; + s = create_usage_sensor(i, SENSOR_TYPE_VIDEO, values_len); + tmp = psensor_list_add(ss, s); + if (ss != tmp) + free(ss); + + ss = tmp; + s = create_usage_sensor(i, SENSOR_TYPE_MEMORY, values_len); + tmp = psensor_list_add(ss, s); + if (ss != tmp) + free(ss); + + ss = tmp; + s = create_usage_sensor(i, SENSOR_TYPE_PCIE, values_len); + tmp = psensor_list_add(ss, s); if (ss != tmp) free(ss);