~ubuntu-branches/ubuntu/vivid/mpich/vivid-proposed

« back to all changes in this revision

Viewing changes to src/pm/hydra/tools/topo/hwloc/hwloc/src/topology-gl.c

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2014-04-01 20:24:20 UTC
  • mfrom: (5.2.4 sid)
  • Revision ID: package-import@ubuntu.com-20140401202420-t5ey1ia2klt5dkq3
Tags: 3.1-4
* [c3e3398] Disable test_primitives, which is unreliable on some platforms.
            (Closes: #743047)
* [265a699] Add minimal autotest.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
5
 */
 
6
 
 
7
#include <private/autogen/config.h>
 
8
#include <hwloc.h>
 
9
#include <hwloc/plugins.h>
 
10
 
 
11
/* private headers allowed for convenience because this plugin is built within hwloc */
 
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
struct hwloc_gl_backend_data_s {
 
24
  unsigned nr_display;
 
25
  struct hwloc_gl_display_info_s {
 
26
    char name[10];
 
27
    unsigned port, device;
 
28
    unsigned pcidomain, pcibus, pcidevice, pcifunc;
 
29
    char *productname;
 
30
  } display[HWLOC_GL_SERVER_MAX*HWLOC_GL_SCREEN_MAX];
 
31
};
 
32
 
 
33
static void
 
34
hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
 
35
{
 
36
  int err;
 
37
  unsigned i,j;
 
38
 
 
39
  /* mark the number of display as 0 in case we fail below,
 
40
   * so that we don't try again later.
 
41
   */
 
42
  data->nr_display = 0;
 
43
 
 
44
  for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) {
 
45
    Display* display;
 
46
    char displayName[10];
 
47
    int opcode, event, error;
 
48
 
 
49
    /* open X server */
 
50
    snprintf(displayName, sizeof(displayName), ":%u", i);
 
51
    display = XOpenDisplay(displayName);
 
52
    if (!display)
 
53
      continue;
 
54
 
 
55
    /* Check for NV-CONTROL extension (it's per server) */
 
56
    if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) {
 
57
      XCloseDisplay(display);
 
58
      continue;
 
59
    }
 
60
 
 
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];
 
63
      const int screen = j;
 
64
      unsigned int *ptr_binary_data;
 
65
      int data_length;
 
66
      int gpu_number;
 
67
      int nv_ctrl_pci_bus;
 
68
      int nv_ctrl_pci_device;
 
69
      int nv_ctrl_pci_domain;
 
70
      int nv_ctrl_pci_func;
 
71
      char *productname;
 
72
 
 
73
      /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */
 
74
      if (!XNVCTRLIsNvScreen(display, screen))
 
75
        continue;
 
76
 
 
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);
 
82
      if (!err)
 
83
        continue;
 
84
 
 
85
      gpu_number = ptr_binary_data[1];
 
86
      free(ptr_binary_data);
 
87
 
 
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);
 
93
      if (!err)
 
94
        continue;
 
95
#else
 
96
      nv_ctrl_pci_domain = 0;
 
97
#endif
 
98
 
 
99
      err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
 
100
                                        NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus);
 
101
      if (!err)
 
102
        continue;
 
103
 
 
104
      err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
 
105
                                        NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device);
 
106
      if (!err)
 
107
        continue;
 
108
 
 
109
      err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
 
110
                                        NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func);
 
111
      if (!err)
 
112
        continue;
 
113
 
 
114
      productname = NULL;
 
115
      err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
 
116
                                              NV_CTRL_STRING_PRODUCT_NAME, &productname);
 
117
 
 
118
      snprintf(info->name, sizeof(info->name), ":%u.%u", i, j);
 
119
      info->port = i;
 
120
      info->device = 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;
 
126
 
 
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);
 
129
 
 
130
      /* validate this device */
 
131
      data->nr_display++;
 
132
    }
 
133
    XCloseDisplay(display);
 
134
  }
 
135
}
 
136
 
 
137
static int
 
138
hwloc_gl_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
 
139
                                   struct hwloc_obj *pcidev)
 
140
{
 
141
  struct hwloc_topology *topology = backend->topology;
 
142
  struct hwloc_gl_backend_data_s *data = backend->private_data;
 
143
  unsigned i, res;
 
144
 
 
145
  if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
 
146
    return 0;
 
147
 
 
148
  if (!hwloc_topology_is_thissystem(topology)) {
 
149
    hwloc_debug("%s", "\nno GL detection (not thissystem)\n");
 
150
    return 0;
 
151
  }
 
152
 
 
153
  if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
 
154
    return 0;
 
155
 
 
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 */
 
160
  }
 
161
 
 
162
  if (!data->nr_display)
 
163
    /* found no display */
 
164
    return 0;
 
165
 
 
166
  /* now the display array is ready to use */
 
167
  res = 0;
 
168
  for(i=0; i<data->nr_display; i++) {
 
169
    struct hwloc_gl_display_info_s *info = &data->display[i];
 
170
    hwloc_obj_t osdev;
 
171
 
 
172
    if (info->pcidomain != pcidev->attr->pcidev.domain)
 
173
      continue;
 
174
    if (info->pcibus != pcidev->attr->pcidev.bus)
 
175
      continue;
 
176
    if (info->pcidevice != pcidev->attr->pcidev.dev)
 
177
      continue;
 
178
    if (info->pcifunc != pcidev->attr->pcidev.func)
 
179
      continue;
 
180
 
 
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);
 
190
 
 
191
    res++;
 
192
    /* there may be others */
 
193
  }
 
194
 
 
195
  return res;
 
196
}
 
197
 
 
198
static void
 
199
hwloc_gl_backend_disable(struct hwloc_backend *backend)
 
200
{
 
201
  struct hwloc_gl_backend_data_s *data = backend->private_data;
 
202
  unsigned i;
 
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);
 
207
    }
 
208
  }
 
209
  free(backend->private_data);
 
210
}
 
211
 
 
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)
 
217
{
 
218
  struct hwloc_backend *backend;
 
219
  struct hwloc_gl_backend_data_s *data;
 
220
 
 
221
  if (hwloc_plugin_check_namespace(component->name, "hwloc_backend_alloc") < 0)
 
222
    return NULL;
 
223
 
 
224
  /* thissystem may not be fully initialized yet, we'll check flags in discover() */
 
225
 
 
226
  backend = hwloc_backend_alloc(component);
 
227
  if (!backend)
 
228
    return NULL;
 
229
 
 
230
  data = malloc(sizeof(*data));
 
231
  if (!data) {
 
232
    free(backend);
 
233
    return NULL;
 
234
  }
 
235
  /* the first callback will initialize those */
 
236
  data->nr_display = (unsigned) -1; /* unknown yet */
 
237
 
 
238
  backend->private_data = data;
 
239
  backend->disable = hwloc_gl_backend_disable;
 
240
 
 
241
  backend->notify_new_object = hwloc_gl_backend_notify_new_object;
 
242
  return backend;
 
243
}
 
244
 
 
245
static struct hwloc_disc_component hwloc_gl_disc_component = {
 
246
  HWLOC_DISC_COMPONENT_TYPE_MISC,
 
247
  "gl",
 
248
  HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
 
249
  hwloc_gl_component_instantiate,
 
250
  10, /* after pci */
 
251
  NULL
 
252
};
 
253
 
 
254
#ifdef HWLOC_INSIDE_PLUGIN
 
255
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component;
 
256
#endif
 
257
 
 
258
const struct hwloc_component hwloc_gl_component = {
 
259
  HWLOC_COMPONENT_ABI,
 
260
  HWLOC_COMPONENT_TYPE_DISC,
 
261
  0,
 
262
  &hwloc_gl_disc_component
 
263
};