2
* Copyright © 2012-2013 Blue Brain Project, BBP/EPFL. All rights reserved.
3
* Copyright © 2012-2013 Inria. All rights reserved.
4
* See COPYING in top-level directory.
7
#include <private/autogen/config.h>
9
#include <hwloc/plugins.h>
11
/* private headers allowed for convenience because this plugin is built within hwloc */
12
#include <private/misc.h>
13
#include <private/debug.h>
18
#include <NVCtrl/NVCtrl.h>
19
#include <NVCtrl/NVCtrlLib.h>
21
#define HWLOC_GL_SERVER_MAX 10
22
#define HWLOC_GL_SCREEN_MAX 10
23
struct hwloc_gl_backend_data_s {
25
struct hwloc_gl_display_info_s {
27
unsigned port, device;
28
unsigned pcidomain, pcibus, pcidevice, pcifunc;
30
} display[HWLOC_GL_SERVER_MAX*HWLOC_GL_SCREEN_MAX];
34
hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
39
/* mark the number of display as 0 in case we fail below,
40
* so that we don't try again later.
44
for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) {
47
int opcode, event, error;
50
snprintf(displayName, sizeof(displayName), ":%u", i);
51
display = XOpenDisplay(displayName);
55
/* Check for NV-CONTROL extension (it's per server) */
56
if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) {
57
XCloseDisplay(display);
61
for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) {
62
struct hwloc_gl_display_info_s *info = &data->display[data->nr_display];
64
unsigned int *ptr_binary_data;
68
int nv_ctrl_pci_device;
69
int nv_ctrl_pci_domain;
73
/* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */
74
if (!XNVCTRLIsNvScreen(display, screen))
77
/* Gets the GPU number attached to the default screen. */
78
/* For further details, see the <NVCtrl/NVCtrlLib.h> */
79
err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0,
80
NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
81
(unsigned char **) &ptr_binary_data, &data_length);
85
gpu_number = ptr_binary_data[1];
86
free(ptr_binary_data);
88
#ifdef NV_CTRL_PCI_DOMAIN
89
/* Gets the ID's of the GPU defined by gpu_number
90
* For further details, see the <NVCtrl/NVCtrlLib.h> */
91
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
92
NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain);
96
nv_ctrl_pci_domain = 0;
99
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
100
NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus);
104
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
105
NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device);
109
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
110
NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func);
115
err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
116
NV_CTRL_STRING_PRODUCT_NAME, &productname);
118
snprintf(info->name, sizeof(info->name), ":%u.%u", i, j);
121
info->pcidomain = nv_ctrl_pci_domain;
122
info->pcibus = nv_ctrl_pci_bus;
123
info->pcidevice = nv_ctrl_pci_device;
124
info->pcifunc = nv_ctrl_pci_func;
125
info->productname = productname;
127
hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", info->name, productname,
128
nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func);
130
/* validate this device */
133
XCloseDisplay(display);
138
hwloc_gl_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
139
struct hwloc_obj *pcidev)
141
struct hwloc_topology *topology = backend->topology;
142
struct hwloc_gl_backend_data_s *data = backend->private_data;
145
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
148
if (!hwloc_topology_is_thissystem(topology)) {
149
hwloc_debug("%s", "\nno GL detection (not thissystem)\n");
153
if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
156
if (data->nr_display == (unsigned) -1) {
157
/* first call, lookup all display */
158
hwloc_gl_query_devices(data);
159
/* if it fails, data->nr_display = 0 so we won't do anything below and in next callbacks */
162
if (!data->nr_display)
163
/* found no display */
166
/* now the display array is ready to use */
168
for(i=0; i<data->nr_display; i++) {
169
struct hwloc_gl_display_info_s *info = &data->display[i];
172
if (info->pcidomain != pcidev->attr->pcidev.domain)
174
if (info->pcibus != pcidev->attr->pcidev.bus)
176
if (info->pcidevice != pcidev->attr->pcidev.dev)
178
if (info->pcifunc != pcidev->attr->pcidev.func)
181
osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1);
182
osdev->name = strdup(info->name);
183
osdev->logical_index = -1;
184
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
185
hwloc_obj_add_info(osdev, "Backend", "GL");
186
hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
187
if (info->productname)
188
hwloc_obj_add_info(osdev, "GPUModel", info->productname);
189
hwloc_insert_object_by_parent(topology, pcidev, osdev);
192
/* there may be others */
199
hwloc_gl_backend_disable(struct hwloc_backend *backend)
201
struct hwloc_gl_backend_data_s *data = backend->private_data;
203
if (data->nr_display != (unsigned) -1) { /* could be -1 if --no-io */
204
for(i=0; i<data->nr_display; i++) {
205
struct hwloc_gl_display_info_s *info = &data->display[i];
206
free(info->productname);
209
free(backend->private_data);
212
static struct hwloc_backend *
213
hwloc_gl_component_instantiate(struct hwloc_disc_component *component,
214
const void *_data1 __hwloc_attribute_unused,
215
const void *_data2 __hwloc_attribute_unused,
216
const void *_data3 __hwloc_attribute_unused)
218
struct hwloc_backend *backend;
219
struct hwloc_gl_backend_data_s *data;
221
if (hwloc_plugin_check_namespace(component->name, "hwloc_backend_alloc") < 0)
224
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
226
backend = hwloc_backend_alloc(component);
230
data = malloc(sizeof(*data));
235
/* the first callback will initialize those */
236
data->nr_display = (unsigned) -1; /* unknown yet */
238
backend->private_data = data;
239
backend->disable = hwloc_gl_backend_disable;
241
backend->notify_new_object = hwloc_gl_backend_notify_new_object;
245
static struct hwloc_disc_component hwloc_gl_disc_component = {
246
HWLOC_DISC_COMPONENT_TYPE_MISC,
248
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
249
hwloc_gl_component_instantiate,
254
#ifdef HWLOC_INSIDE_PLUGIN
255
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component;
258
const struct hwloc_component hwloc_gl_component = {
260
HWLOC_COMPONENT_TYPE_DISC,
262
&hwloc_gl_disc_component