diff options
Diffstat (limited to 'hardinfo/gpu_util.c')
-rw-r--r-- | hardinfo/gpu_util.c | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/hardinfo/gpu_util.c b/hardinfo/gpu_util.c deleted file mode 100644 index 29f6c77e..00000000 --- a/hardinfo/gpu_util.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * HardInfo - Displays System Information - * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br> - * This file - * Copyright (C) 2018 Burt P. <pburt0@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 published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "hardinfo.h" -#include "gpu_util.h" -#include "nice_name.h" -#include "cpu_util.h" /* for EMPIFNULL() */ - -nvgpu *nvgpu_new() { - return g_new0(nvgpu, 1); -} - -void nvgpu_free(nvgpu *s) { - if (s) { - free(s->model); - free(s->bios_version); - free(s->uuid); - } -} - -static char *_line_value(char *line, const char *prefix) { - if (g_str_has_prefix(g_strstrip(line), prefix)) { - line += strlen(prefix) + 1; - return g_strstrip(line); - } else - return NULL; -} - -static gboolean nv_fill_procfs_info(gpud *s) { - gchar *data, *p, *l, *next_nl; - gchar *pci_loc = pci_address_str(s->pci_dev->domain, s->pci_dev->bus, s->pci_dev->device, s->pci_dev->function); - gchar *nvi_file = g_strdup_printf("/proc/driver/nvidia/gpus/%s/information", pci_loc); - - g_file_get_contents(nvi_file, &data, NULL, NULL); - g_free(pci_loc); - g_free(nvi_file); - - if (data) { - s->nv_info = nvgpu_new(); - p = data; - while(next_nl = strchr(p, '\n')) { - strend(p, '\n'); - g_strstrip(p); - if (l = _line_value(p, "Model")) { - s->nv_info->model = g_strdup(l); - goto nv_details_next; - } - if (l = _line_value(p, "GPU UUID")) { - s->nv_info->uuid = g_strdup(l); - goto nv_details_next; - } - if (l = _line_value(p, "Video BIOS")) { - s->nv_info->bios_version = g_strdup(l); - goto nv_details_next; - } - - /* TODO: more details */ - - nv_details_next: - p = next_nl + 1; - } - g_free(data); - return TRUE; - } - return FALSE; -} - -static void intel_fill_freq(gpud *s) { - gchar path[256] = ""; - gchar *min_mhz = NULL, *max_mhz = NULL; - if (s->sysfs_drm_path) { - snprintf(path, 255, "%s/%s/gt_min_freq_mhz", s->sysfs_drm_path, s->id); - g_file_get_contents(path, &min_mhz, NULL, NULL); - snprintf(path, 255, "%s/%s/gt_max_freq_mhz", s->sysfs_drm_path, s->id); - g_file_get_contents(path, &max_mhz, NULL, NULL); - - if (min_mhz) - s->khz_min = atoi(min_mhz) * 1000; - if (max_mhz) - s->khz_max = atoi(max_mhz) * 1000; - - g_free(min_mhz); - g_free(max_mhz); - } -} - -static void amdgpu_parse_dpmclk(gchar *path, int *min, int *max) { - gchar *data = NULL, *p, *next_nl; - int sp, i, clk; - - *min = -1; - *max = -1; - - g_file_get_contents(path, &data, NULL, NULL); - if (data) { - p = data; - - while(next_nl = strchr(p, '\n')) { - strend(p, '\n'); - sp = sscanf(p, "%d: %dMhz", &i, &clk); - - if (sp == 2) { - if (clk > 0) { - if (*min < 0 || clk < *min) - *min = clk; - if (clk > *max) - *max = clk; - } - } - - p = next_nl + 1; - } - } - g_free(data); -} - -static void amdgpu_fill_freq(gpud *s) { - gchar path[256] = ""; - int clk_min = -1, clk_max = -1, mem_clk_min = -1, mem_clk_max = -1; - - if (s->sysfs_drm_path) { - /* core */ - snprintf(path, 255, "%s/%s/device/pp_dpm_sclk", s->sysfs_drm_path, s->id); - amdgpu_parse_dpmclk(path, &clk_min, &clk_max); - - if (clk_max > 0) - s->khz_max = clk_max * 1000; - if (clk_min > 0) - s->khz_min = clk_min * 1000; - - /* memory */ - snprintf(path, 255, "%s/%s/device/pp_dpm_mclk", s->sysfs_drm_path, s->id); - amdgpu_parse_dpmclk(path, &mem_clk_min, &mem_clk_max); - - if (mem_clk_max > 0) - s->mem_khz_max = mem_clk_max * 1000; - if (mem_clk_min > 0) - s->mem_khz_min = mem_clk_min * 1000; - } -} - -gpud *gpud_new() { - return g_new0(gpud, 1); -} - -void gpud_free(gpud *s) { - if (s) { - free(s->id); - free(s->nice_name); - free(s->vendor_str); - free(s->device_str); - free(s->location); - free(s->drm_dev); - free(s->sysfs_drm_path); - free(s->dt_compat); - g_free(s->dt_opp); - pcid_free(s->pci_dev); - nvgpu_free(s->nv_info); - g_free(s); - } -} - -void gpud_list_free(gpud *s) { - gpud *n; - while(s != NULL) { - n = s->next; - gpud_free(s); - s = n; - } -} - -/* returns number of items after append */ -static int gpud_list_append(gpud *l, gpud *n) { - int c = 0; - while(l != NULL) { - c++; - if (l->next == NULL) { - if (n != NULL) { - l->next = n; - c++; - } - break; - } - l = l->next; - } - return c; -} - -int gpud_list_count(gpud *s) { - return gpud_list_append(s, NULL); -} - -/* TODO: In the future, when there is more vendor specific information available in - * the gpu struct, then more precise names can be given to each gpu */ -static void make_nice_name(gpud *s) { - - /* NV information available */ - if (s->nv_info && s->nv_info->model) { - s->nice_name = g_strdup_printf("%s %s", "NVIDIA", s->nv_info->model); - return; - } - - static const char unk_v[] = "Unknown"; /* do not... */ - static const char unk_d[] = "Device"; /* ...translate */ - const char *vendor_str = s->vendor_str; - const char *device_str = s->device_str; - if (!vendor_str) - vendor_str = unk_v; - if (!device_str) - device_str = unk_d; - - /* try and a get a "short name" for the vendor */ - vendor_str = vendor_get_shortest_name(vendor_str); - - if (strstr(vendor_str, "Intel")) { - gchar *device_str_clean = strdup(device_str); - nice_name_intel_gpu_device(device_str_clean); - s->nice_name = g_strdup_printf("%s %s", vendor_str, device_str_clean); - g_free(device_str_clean); - } else if (strstr(vendor_str, "AMD")) { - /* AMD PCI strings are crazy stupid because they use the exact same - * chip and device id for a zillion "different products" */ - char *full_name = strdup(device_str); - /* Try and shorten it to the chip code name only, at least */ - char *b = strchr(full_name, '['); - if (b) *b = '\0'; - s->nice_name = g_strdup_printf("%s %s", "AMD/ATI", g_strstrip(full_name)); - free(full_name); - } else { - /* nothing nicer */ - s->nice_name = g_strdup_printf("%s %s", vendor_str, device_str); - } - -} - -/* Look for this kind of thing: - * * /soc/gpu - * * /gpu@ff300000 - * - * Usually a gpu dt node will have ./name = "gpu" - */ -static gchar *dt_find_gpu(dtr *dt, char *np) { - gchar *dir_path, *dt_path, *ret; - gchar *ftmp, *ntmp; - const gchar *fn; - GDir *dir; - dtr_obj *obj; - - /* consider self */ - obj = dtr_obj_read(dt, np); - dt_path = dtr_obj_path(obj); - ntmp = strstr(dt_path, "/gpu"); - if (ntmp) { - /* was found in node name */ - if ( strchr(ntmp+1, '/') == NULL) { - ftmp = ntmp + 4; - /* should either be NULL or @ */ - if (*ftmp == '\0' || *ftmp == '@') - return g_strdup(dt_path); - } - } - - /* search children ... */ - dir_path = g_strdup_printf("%s/%s", dtr_base_path(dt), np); - dir = g_dir_open(dir_path, 0 , NULL); - if (dir) { - while((fn = g_dir_read_name(dir)) != NULL) { - ftmp = g_strdup_printf("%s/%s", dir_path, fn); - if ( g_file_test(ftmp, G_FILE_TEST_IS_DIR) ) { - if (strcmp(np, "/") == 0) - ntmp = g_strdup_printf("/%s", fn); - else - ntmp = g_strdup_printf("%s/%s", np, fn); - ret = dt_find_gpu(dt, ntmp); - g_free(ntmp); - if (ret != NULL) { - g_free(ftmp); - g_dir_close(dir); - return ret; - } - } - g_free(ftmp); - } - g_dir_close(dir); - } - - return NULL; -} - -gpud *dt_soc_gpu() { - static const char std_soc_gpu_drm_path[] = "/sys/devices/platform/soc/soc:gpu/drm"; - - /* compatible contains a list of compatible hardware, so be careful - * with matching order. - * ex: "ti,omap3-beagleboard-xm", "ti,omap3450", "ti,omap3"; - * matches "omap3 family" first. - * ex: "brcm,bcm2837", "brcm,bcm2836"; - * would match 2836 when it is a 2837. - */ - const struct { - char *search_str; - char *vendor; - char *soc; - } dt_compat_searches[] = { - { "brcm,bcm2837-vc4", "Broadcom", "VideoCore IV" }, - { "brcm,bcm2836-vc4", "Broadcom", "VideoCore IV" }, - { "brcm,bcm2835-vc4", "Broadcom", "VideoCore IV" }, - { "arm,mali-450", "ARM", "Mali 450" }, - { "arm,mali", "ARM", "Mali family" }, - { NULL, NULL, NULL } - }; - char tmp_path[256] = ""; - char *dt_gpu_path = NULL; - char *compat = NULL; - char *vendor = NULL, *device = NULL; - int i; - - gpud *gpu = NULL; - - dtr *dt = dtr_new(NULL); - if (!dtr_was_found(dt)) - goto dt_gpu_end; - - dt_gpu_path = dt_find_gpu(dt, "/"); - - if (dt_gpu_path == NULL) - goto dt_gpu_end; - - snprintf(tmp_path, 255, "%s/compatible", dt_gpu_path); - compat = dtr_get_string(tmp_path, 1); - - if (compat == NULL) - goto dt_gpu_end; - - gpu = gpud_new(); - - i = 0; - while(dt_compat_searches[i].search_str != NULL) { - if (strstr(compat, dt_compat_searches[i].search_str) != NULL) { - vendor = dt_compat_searches[i].vendor; - device = dt_compat_searches[i].soc; - break; - } - i++; - } - - gpu->dt_compat = compat; - gpu->dt_vendor = vendor; - gpu->dt_device = device; - gpu->dt_path = dt_gpu_path; - snprintf(tmp_path, 255, "%s/status", dt_gpu_path); - gpu->dt_status = dtr_get_string(tmp_path, 1); - snprintf(tmp_path, 255, "%s/name", dt_gpu_path); - gpu->dt_name = dtr_get_string(tmp_path, 1); - gpu->dt_opp = dtr_get_opp_range(dt, dt_gpu_path); - if (gpu->dt_opp) { - gpu->khz_max = gpu->dt_opp->khz_max; - gpu->khz_min = gpu->dt_opp->khz_min; - } - EMPIFNULL(gpu->dt_name); - EMPIFNULL(gpu->dt_status); - - gpu->id = strdup("dt-soc-gpu"); - gpu->location = strdup("SOC"); - - if (access(std_soc_gpu_drm_path, F_OK) != -1) - gpu->sysfs_drm_path = strdup(std_soc_gpu_drm_path); - if (vendor) gpu->vendor_str = strdup(vendor); - if (device) gpu->device_str = strdup(device); - make_nice_name(gpu); - - -dt_gpu_end: - dtr_free(dt); - return gpu; -} - -gpud *gpu_get_device_list() { - int cn = 0; - gpud *list = NULL; - -/* Can we just ask DRM someway? ... */ - /* TODO: yes. /sys/class/drm/card* */ - -/* Try PCI ... */ - pcid_list pci_list = pci_get_device_list(0x300,0x3ff); - GSList *l = pci_list; - - if (l) { - while(l) { - pcid *curr = (pcid*)l->data; - char *pci_loc = NULL; - gpud *new_gpu = gpud_new(); - new_gpu->pci_dev = curr; - - pci_loc = pci_address_str(curr->domain, curr->bus, curr->device, curr->function); - - int len; - char drm_id[512] = "", card_id[64] = ""; - char *drm_dev = NULL; - gchar *drm_path = - g_strdup_printf("/dev/dri/by-path/pci-%s-card", pci_loc); - memset(drm_id, 0, 512); - if ((len = readlink(drm_path, drm_id, sizeof(drm_id)-1)) != -1) - drm_id[len] = '\0'; - g_free(drm_path); - - if (strlen(drm_id) != 0) { - /* drm has the card */ - drm_dev = strstr(drm_id, "card"); - if (drm_dev) - snprintf(card_id, 64, "%s", drm_dev); - } - - if (strlen(card_id) == 0) { - /* fallback to our own counter */ - snprintf(card_id, 64, "pci-dc%d", cn); - cn++; - } - - if (drm_dev) - new_gpu->drm_dev = strdup(drm_dev); - - char *sysfs_path_candidate = g_strdup_printf("%s/%s/drm", SYSFS_PCI_ROOT, pci_loc); - if (access(sysfs_path_candidate, F_OK) != -1) { - new_gpu->sysfs_drm_path = sysfs_path_candidate; - } else - free(sysfs_path_candidate); - new_gpu->location = g_strdup_printf("PCI/%s", pci_loc); - new_gpu->id = strdup(card_id); - if (curr->vendor_id_str) new_gpu->vendor_str = strdup(curr->vendor_id_str); - if (curr->device_id_str) new_gpu->device_str = strdup(curr->device_id_str); - nv_fill_procfs_info(new_gpu); - intel_fill_freq(new_gpu); - amdgpu_fill_freq(new_gpu); - make_nice_name(new_gpu); - if (list == NULL) - list = new_gpu; - else - gpud_list_append(list, new_gpu); - - free(pci_loc); - l=l->next; - } - - /* don't pcid_list_free(pci_list); They will be freed by gpud_free() */ - g_slist_free(pci_list); /* just the linking data */ - return list; - } - -/* Try Device Tree ... */ - list = dt_soc_gpu(); - if (list) return list; - -/* Try other things ... */ - - return list; -} - - |