This source file includes following definitions.
- hwloc_gl_discover
- hwloc_gl_component_instantiate
- hwloc_gl_component_init
1
2
3
4
5
6
7 #include <private/autogen/config.h>
8 #include <hwloc.h>
9 #include <hwloc/plugins.h>
10
11
12 #include <private/misc.h>
13 #include <private/debug.h>
14
15 #include <stdarg.h>
16 #include <errno.h>
17 #include <X11/Xlib.h>
18 #include <NVCtrl/NVCtrl.h>
19 #include <NVCtrl/NVCtrlLib.h>
20
21 #define HWLOC_GL_SERVER_MAX 10
22 #define HWLOC_GL_SCREEN_MAX 10
23
24 static int
25 hwloc_gl_discover(struct hwloc_backend *backend)
26 {
27 struct hwloc_topology *topology = backend->topology;
28 enum hwloc_type_filter_e filter;
29 unsigned i;
30 int err;
31
32 hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
33 if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
34 return 0;
35
36 for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) {
37 Display* display;
38 char displayName[10];
39 int opcode, event, error;
40 unsigned j;
41
42
43 snprintf(displayName, sizeof(displayName), ":%u", i);
44 display = XOpenDisplay(displayName);
45 if (!display)
46 continue;
47
48
49 if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) {
50 XCloseDisplay(display);
51 continue;
52 }
53
54 for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) {
55 hwloc_obj_t osdev, parent;
56 const int screen = (int)j;
57 unsigned int *ptr_binary_data;
58 int data_length;
59 int gpu_number;
60 int nv_ctrl_pci_bus;
61 int nv_ctrl_pci_device;
62 int nv_ctrl_pci_domain;
63 int nv_ctrl_pci_func;
64 char *productname;
65 char name[64];
66
67
68 if (!XNVCTRLIsNvScreen(display, screen))
69 continue;
70
71
72
73 err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0,
74 NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
75 (unsigned char **) &ptr_binary_data, &data_length);
76 if (!err)
77 continue;
78
79 gpu_number = (int)ptr_binary_data[1];
80 free(ptr_binary_data);
81
82 #ifdef NV_CTRL_PCI_DOMAIN
83
84
85 err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
86 NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain);
87 if (!err)
88 continue;
89 #else
90 nv_ctrl_pci_domain = 0;
91 #endif
92
93 err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
94 NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus);
95 if (!err)
96 continue;
97
98 err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
99 NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device);
100 if (!err)
101 continue;
102
103 err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
104 NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func);
105 if (!err)
106 continue;
107
108 productname = NULL;
109 err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
110 NV_CTRL_STRING_PRODUCT_NAME, &productname);
111
112 snprintf(name, sizeof(name), ":%u.%u", i, j);
113
114 osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, HWLOC_UNKNOWN_INDEX);
115 osdev->name = strdup(name);
116 osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
117 hwloc_obj_add_info(osdev, "Backend", "GL");
118 hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
119 if (productname)
120 hwloc_obj_add_info(osdev, "GPUModel", productname);
121
122 parent = hwloc_pcidisc_find_by_busid(topology, (unsigned)nv_ctrl_pci_domain, (unsigned)nv_ctrl_pci_bus, (unsigned)nv_ctrl_pci_device, (unsigned)nv_ctrl_pci_func);
123 if (!parent)
124 parent = hwloc_pcidisc_find_busid_parent(topology, (unsigned)nv_ctrl_pci_domain, (unsigned)nv_ctrl_pci_bus, (unsigned)nv_ctrl_pci_device, (unsigned)nv_ctrl_pci_func);
125 if (!parent)
126 parent = hwloc_get_root_obj(topology);
127
128 hwloc_insert_object_by_parent(topology, parent, osdev);
129
130 hwloc_debug("GL device %s (product %s) on PCI %04x:%02x:%02x.%01x\n",
131 name, productname,
132 (unsigned) nv_ctrl_pci_domain, (unsigned) nv_ctrl_pci_bus, (unsigned) nv_ctrl_pci_device, (unsigned) nv_ctrl_pci_func);
133 }
134 XCloseDisplay(display);
135 }
136
137 return 0;
138 }
139
140 static struct hwloc_backend *
141 hwloc_gl_component_instantiate(struct hwloc_disc_component *component,
142 const void *_data1 __hwloc_attribute_unused,
143 const void *_data2 __hwloc_attribute_unused,
144 const void *_data3 __hwloc_attribute_unused)
145 {
146 struct hwloc_backend *backend;
147
148 backend = hwloc_backend_alloc(component);
149 if (!backend)
150 return NULL;
151 backend->discover = hwloc_gl_discover;
152 return backend;
153 }
154
155 static struct hwloc_disc_component hwloc_gl_disc_component = {
156 HWLOC_DISC_COMPONENT_TYPE_MISC,
157 "gl",
158 HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
159 hwloc_gl_component_instantiate,
160 10,
161 1,
162 NULL
163 };
164
165 static int
166 hwloc_gl_component_init(unsigned long flags)
167 {
168 if (flags)
169 return -1;
170 if (hwloc_plugin_check_namespace("gl", "hwloc_backend_alloc") < 0)
171 return -1;
172 return 0;
173 }
174
175 #ifdef HWLOC_INSIDE_PLUGIN
176 HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component;
177 #endif
178
179 const struct hwloc_component hwloc_gl_component = {
180 HWLOC_COMPONENT_ABI,
181 hwloc_gl_component_init, NULL,
182 HWLOC_COMPONENT_TYPE_DISC,
183 0,
184 &hwloc_gl_disc_component
185 };