linux-infiniband.c File Reference

This file has the source code for a component that enables PAPI-C to access the infiniband performance monitor through the Linux sysfs interface. This code will dynamically create a native events table for all the events that can be accesed through the sysfs interface. The counters exported by this component cannot be reset programatically. More...

Include dependency graph for linux-infiniband.c:

Go to the source code of this file.

Data Structures

struct  infiniband_register_t
struct  ib_device_t
struct  ib_counter_t
struct  infiniband_native_event_entry_t
struct  infiniband_control_state_t
struct  infiniband_context_t

Defines

#define INFINIBAND_MAX_COUNTERS   128

Functions

static char * make_ib_event_description (const char *input_str, int extended)
static ib_device_tadd_ib_device (const char *name, int port)
static ib_counter_tadd_ib_counter (const char *name, const char *file_name, int extended, ib_device_t *device)
static int find_ib_device_events (ib_device_t *dev, int extended)
static int find_ib_devices ()
static long long read_ib_counter_value (int index)
static void deallocate_infiniband_resources ()
static int _infiniband_init_thread (hwd_context_t *ctx)
static int _infiniband_init_component (int cidx)
static int _infiniband_init_control_state (hwd_control_state_t *ctl)
static int _infiniband_start (hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _infiniband_stop (hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _infiniband_read (hwd_context_t *ctx, hwd_control_state_t *ctl, long_long **events, int flags)
static int _infiniband_shutdown_component (void)
static int _infiniband_shutdown_thread (hwd_context_t *ctx)
static int _infiniband_ctl (hwd_context_t *ctx, int code, _papi_int_option_t *option)
static int _infiniband_update_control_state (hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int _infiniband_set_domain (hwd_control_state_t *ctl, int domain)
static int _infiniband_reset (hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _infiniband_ntv_enum_events (unsigned int *EventCode, int modifier)
static int _infiniband_ntv_code_to_name (unsigned int EventCode, char *name, int len)
static int _infiniband_ntv_code_to_descr (unsigned int EventCode, char *name, int len)
static int _infiniband_ntv_code_to_info (unsigned int EventCode, PAPI_event_info_t *info)

Variables

static const char * ib_dir_path = "/sys/class/infiniband"
static
infiniband_native_event_entry_t
infiniband_native_events = 0
static int num_events = 0
papi_vector_t _infiniband_vector
static ib_device_troot_device = 0
static ib_counter_troot_counter = 0

Detailed Description

This file has the source code for a component that enables PAPI-C to access hardware monitoring counters for InfiniBand devices through the OFED library. Since a new interface was introduced with OFED version 1.4 (released Dec 2008), the current InfiniBand component does not support OFED versions < 1.4.

Author:
Gabriel Marin gmarin@eecs.utk.edu

Infiniband component

Author:
Heike Jagode (in collaboration with Michael Kluge, TU Dresden) jagode@eecs.utk.edu

InfiniBand component

Tested version of OFED: 1.4

Definition in file linux-infiniband.c.


Define Documentation

#define INFINIBAND_MAX_COUNTERS   128

Definition at line 42 of file linux-infiniband.c.


Function Documentation

static int _infiniband_ctl ( hwd_context_t ctx,
int  code,
_papi_int_option_t option 
) [static]

Definition at line 577 of file linux-infiniband.c.

00578 {
00579    ( void ) ctx;
00580    ( void ) code;
00581    ( void ) option;
00582    return PAPI_OK;
00583 }

static int _infiniband_init_component ( int  cidx  )  [static]

Definition at line 433 of file linux-infiniband.c.

00434 {
00435    /* discover Infiniband devices and available events */
00436    int result = find_ib_devices();
00437    
00438    if (result != PAPI_OK)  // we couldn't initialize the component
00439    {
00440       // deallocate any eventually allocated memory
00441       deallocate_infiniband_resources();
00442    }
00443     
00444    _infiniband_vector.cmp_info.num_native_events = num_events;
00445 
00446    _infiniband_vector.cmp_info.num_cntrs = num_events;
00447    _infiniband_vector.cmp_info.num_mpx_cntrs = num_events;
00448 
00449 
00450    /* Export the component id */
00451    _infiniband_vector.cmp_info.CmpIdx = cidx;
00452 
00453    return (result);
00454 }

Here is the call graph for this function:

static int _infiniband_init_control_state ( hwd_control_state_t ctl  )  [static]

Definition at line 462 of file linux-infiniband.c.

00463 {
00464    infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
00465    int i;
00466 
00467    for (i=0 ; i<INFINIBAND_MAX_COUNTERS ; ++i) {
00468       control->being_measured[i] = 0;
00469    }
00470 
00471    return PAPI_OK;
00472 }

static int _infiniband_init_thread ( hwd_context_t ctx  )  [static]

Definition at line 421 of file linux-infiniband.c.

00422 {
00423    (void) ctx;
00424    return PAPI_OK;
00425 }

static int _infiniband_ntv_code_to_descr ( unsigned int  EventCode,
char *  name,
int  len 
) [static]

Definition at line 707 of file linux-infiniband.c.

00708 {
00709    int index = EventCode;
00710 
00711    if (index>=0 && index<num_events) {
00712       strncpy(name, infiniband_native_events[index].description, len);
00713    }
00714    return PAPI_OK;
00715 }

static int _infiniband_ntv_code_to_info ( unsigned int  EventCode,
PAPI_event_info_t info 
) [static]

Definition at line 718 of file linux-infiniband.c.

00719 {
00720    int index = EventCode;
00721 
00722    if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT; 
00723 
00724    if (infiniband_native_events[index].name)
00725    {
00726       unsigned int len = strlen(infiniband_native_events[index].name);
00727       if (len > sizeof(info->symbol)-1) len = sizeof(info->symbol)-1;
00728       strncpy(info->symbol, infiniband_native_events[index].name, len);
00729       info->symbol[len] = '\0';
00730    }
00731    if (infiniband_native_events[index].description)
00732    {
00733       unsigned int len = strlen(infiniband_native_events[index].description);
00734       if (len > sizeof(info->long_descr)-1) len = sizeof(info->long_descr)-1;
00735       strncpy(info->long_descr, infiniband_native_events[index].description, len);
00736       info->long_descr[len] = '\0';
00737    }
00738 
00739    strncpy(info->units, "\0", 1);
00740        /* infiniband_native_events[index].units, sizeof(info->units)); */
00741 
00742 /*   info->data_type = infiniband_native_events[index].return_type;
00743  */
00744    return PAPI_OK;
00745 }

static int _infiniband_ntv_code_to_name ( unsigned int  EventCode,
char *  name,
int  len 
) [static]

Definition at line 692 of file linux-infiniband.c.

00693 {
00694    int index = EventCode;
00695 
00696    if (index>=0 && index<num_events) {
00697       strncpy( name, infiniband_native_events[index].name, len );
00698    }
00699 
00700    return PAPI_OK;
00701 }

static int _infiniband_ntv_enum_events ( unsigned int *  EventCode,
int  modifier 
) [static]

Definition at line 660 of file linux-infiniband.c.

00661 {
00662    switch (modifier) {
00663       case PAPI_ENUM_FIRST:
00664          if (num_events == 0)
00665             return (PAPI_ENOEVNT);
00666             
00667          *EventCode = 0;
00668          return PAPI_OK;
00669 
00670       case PAPI_ENUM_EVENTS:
00671       {
00672          int index = *EventCode & PAPI_NATIVE_AND_MASK;
00673 
00674          if (index < num_events - 1) {
00675             *EventCode = *EventCode + 1;
00676             return PAPI_OK;
00677          } else
00678             return PAPI_ENOEVNT;
00679 
00680          break;
00681       }
00682       default:
00683          return PAPI_EINVAL;
00684    }
00685    return PAPI_EINVAL;
00686 }

static int _infiniband_read ( hwd_context_t ctx,
hwd_control_state_t ctl,
long_long **  events,
int  flags 
) [static]

Definition at line 540 of file linux-infiniband.c.

00542 {
00543    ( void ) flags;
00544     
00545    _infiniband_stop(ctx, ctl);  /* we cannot actually stop the counters */
00546    /* Pass back a pointer to our results */
00547    *events = ((infiniband_control_state_t*) ctl)->counts;
00548    
00549    return PAPI_OK;
00550 }

Here is the call graph for this function:

static int _infiniband_reset ( hwd_context_t ctx,
hwd_control_state_t ctl 
) [static]

Definition at line 648 of file linux-infiniband.c.

00649 {
00650    (void) ctx;
00651    (void) ctl;
00652    return PAPI_OK;
00653 }

static int _infiniband_set_domain ( hwd_control_state_t ctl,
int  domain 
) [static]

Definition at line 623 of file linux-infiniband.c.

00624 {
00625    int found = 0;
00626    (void) ctl;
00627     
00628    if (PAPI_DOM_USER & domain)
00629       found = 1;
00630 
00631    if (PAPI_DOM_KERNEL & domain)
00632       found = 1;
00633 
00634    if (PAPI_DOM_OTHER & domain)
00635       found = 1;
00636 
00637    if (!found)
00638       return (PAPI_EINVAL);
00639 
00640    return (PAPI_OK);
00641 }

static int _infiniband_shutdown_component ( void   )  [static]

Definition at line 554 of file linux-infiniband.c.

00555 {
00556    /* Cleanup resources used by this component before leaving */
00557    deallocate_infiniband_resources();
00558    
00559    return PAPI_OK;
00560 }

Here is the call graph for this function:

static int _infiniband_shutdown_thread ( hwd_context_t ctx  )  [static]

Definition at line 563 of file linux-infiniband.c.

00564 {
00565    ( void ) ctx;
00566 
00567    return PAPI_OK;
00568 }

static int _infiniband_start ( hwd_context_t ctx,
hwd_control_state_t ctl 
) [static]

Definition at line 478 of file linux-infiniband.c.

00479 {
00480    infiniband_context_t* context = (infiniband_context_t*) ctx;
00481    infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
00482    long long now = PAPI_get_real_usec();
00483    int i;
00484 
00485    for (i=0 ; i<INFINIBAND_MAX_COUNTERS ; ++i) {
00486       if (control->being_measured[i] && control->need_difference[i]) {
00487          context->start_value[i] = read_ib_counter_value(i);
00488       }
00489    }
00490    control->lastupdate = now;
00491 
00492    return PAPI_OK;
00493 }

Here is the call graph for this function:

static int _infiniband_stop ( hwd_context_t ctx,
hwd_control_state_t ctl 
) [static]

Definition at line 500 of file linux-infiniband.c.

00501 {
00502    infiniband_context_t* context = (infiniband_context_t*) ctx;
00503    infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
00504    long long now = PAPI_get_real_usec();
00505    int i;
00506    long long temp;
00507 
00508    for (i=0 ; i<INFINIBAND_MAX_COUNTERS ; ++i) {
00509       if (control->being_measured[i])
00510       {
00511          temp = read_ib_counter_value(i);
00512          if (context->start_value[i] && control->need_difference[i]) {
00513             /* Must subtract values, but check for wraparound. 
00514              * We cannot even detect all wraparound cases. Using the short,
00515              * auto-resetting IB counters is error prone.
00516              */
00517             if (temp < context->start_value[i]) {
00518                SUBDBG("Wraparound!\nstart:\t%#016x\ttemp:\t%#016x",
00519                         (unsigned)context->start_value[i], (unsigned)temp);
00520                /* The counters auto-reset. I cannot even adjust them to 
00521                 * account for a simple wraparound. 
00522                 * Just use the current reading of the counter, which is useless.
00523                 */
00524             } else
00525                temp -= context->start_value[i];
00526          }
00527          control->counts[i] = temp;
00528       }
00529    }
00530    control->lastupdate = now;
00531 
00532    return PAPI_OK;
00533 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int _infiniband_update_control_state ( hwd_control_state_t ctl,
NativeInfo_t native,
int  count,
hwd_context_t ctx 
) [static]

Definition at line 587 of file linux-infiniband.c.

00591 {
00592    int i, index;
00593    ( void ) ctx;
00594     
00595    infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
00596    
00597    for (i=0 ; i<INFINIBAND_MAX_COUNTERS ; ++i) {
00598       control->being_measured[i] = 0;
00599    }
00600    
00601    for (i=0 ; i<count ; ++i) {
00602       index = native[i].ni_event & PAPI_NATIVE_AND_MASK;
00603       native[i].ni_position =
00604                   infiniband_native_events[index].resources.selector - 1;
00605       control->being_measured[index] = 1;
00606       control->need_difference[index] = 1;
00607    }
00608    return PAPI_OK;
00609 }

static ib_counter_t* add_ib_counter ( const char *  name,
const char *  file_name,
int  extended,
ib_device_t device 
) [static]

Definition at line 174 of file linux-infiniband.c.

00175 {
00176    ib_counter_t *new_cnt = (ib_counter_t*) papi_calloc(sizeof(ib_counter_t), 1);
00177    if (new_cnt == 0) {
00178       PAPIERROR("cannot allocate memory for new IB counter structure");
00179       return (0);
00180    }
00181    
00182    new_cnt->ev_name = strdup(name);
00183    new_cnt->ev_file_name = strdup(file_name);
00184    new_cnt->extended = extended;
00185    new_cnt->ev_device = device;
00186    if (new_cnt->ev_name==0 || new_cnt->ev_file_name==0)
00187    {
00188       PAPIERROR("cannot allocate memory for counter internal fields");
00189       papi_free(new_cnt);
00190       return (0);
00191    }
00192 
00193    // prepend the new counter to the counter list
00194    new_cnt->next = root_counter;
00195    root_counter = new_cnt;
00196    
00197    return (new_cnt);
00198 }

Here is the call graph for this function:

Here is the caller graph for this function:

static ib_device_t* add_ib_device ( const char *  name,
int  port 
) [static]

Definition at line 149 of file linux-infiniband.c.

00150 {
00151    ib_device_t *new_dev = (ib_device_t*) papi_calloc(sizeof(ib_device_t), 1);
00152    if (new_dev == 0) {
00153       PAPIERROR("cannot allocate memory for new IB device structure");
00154       return (0);
00155    }
00156    
00157    new_dev->dev_name = strdup(name);
00158    new_dev->dev_port = port;
00159    if (new_dev->dev_name==0)
00160    {
00161       PAPIERROR("cannot allocate memory for device internal fields");
00162       papi_free(new_dev);
00163       return (0);
00164    }
00165 
00166    // prepend the new device to the device list
00167    new_dev->next = root_device;
00168    root_device = new_dev;
00169    
00170    return (new_dev);
00171 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void deallocate_infiniband_resources (  )  [static]

Definition at line 383 of file linux-infiniband.c.

00384 {
00385    int i;
00386    
00387    if (infiniband_native_events)
00388    {
00389       for (i=0 ; i<num_events ; ++i) {
00390          if (infiniband_native_events[i].name)
00391             free(infiniband_native_events[i].name);
00392          if (infiniband_native_events[i].file_name)
00393             free(infiniband_native_events[i].file_name);
00394          if (infiniband_native_events[i].description)
00395             papi_free(infiniband_native_events[i].description);
00396       }
00397       papi_free(infiniband_native_events);
00398    }
00399    
00400    ib_device_t *iter = root_device;
00401    while (iter != 0) 
00402    {
00403       if (iter->dev_name)
00404          free(iter->dev_name);
00405    
00406       ib_device_t *tmp = iter;
00407       iter = iter->next;
00408       papi_free(tmp);
00409    }
00410    root_device = 0;
00411 }

Here is the caller graph for this function:

static int find_ib_device_events ( ib_device_t dev,
int  extended 
) [static]

Definition at line 202 of file linux-infiniband.c.

00203 {
00204    int nevents = 0;
00205    DIR *cnt_dir = NULL;
00206    char counters_path[128];
00207    snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters%s", 
00208           ib_dir_path, dev->dev_name, dev->dev_port, (extended?"_ext":""));
00209    
00210    cnt_dir = opendir(counters_path);
00211    if (cnt_dir == NULL) {
00212       SUBDBG("cannot open counters directory `%s'\n", counters_path);
00213       goto out;
00214    }
00215    
00216    struct dirent *ev_ent;
00217    /* iterate over all the events */
00218    while ((ev_ent = readdir(cnt_dir)) != NULL) {
00219       char *ev_name = ev_ent->d_name;
00220       long long value = -1;
00221       char event_path[160];
00222       char counter_name[80];
00223 
00224       if (ev_name[0] == '.')
00225          continue;
00226 
00227       /* Check that we can read an integer from the counter file */
00228       snprintf(event_path, sizeof(event_path), "%s/%s", counters_path, ev_name);
00229       if (pscanf(event_path, "%lld", &value) != 1) {
00230         SUBDBG("cannot read value for event '%s'\n", ev_name);
00231         continue;
00232       }
00233 
00234       /* Create new counter */
00235       snprintf(counter_name, sizeof(counter_name), "%s_%d%s:%s", 
00236             dev->dev_name, dev->dev_port, (extended?"_ext":""), ev_name);
00237       if (add_ib_counter(counter_name, ev_name, extended, dev))
00238       {
00239          SUBDBG("Added new counter `%s'\n", counter_name);
00240          nevents += 1;
00241       }
00242    }
00243 
00244  out:
00245   if (cnt_dir != NULL)
00246     closedir(cnt_dir);
00247 
00248   return (nevents);
00249 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int find_ib_devices (  )  [static]

Definition at line 252 of file linux-infiniband.c.

00253 {
00254   DIR *ib_dir = NULL;
00255   int result = PAPI_OK;
00256   num_events = 0;
00257 
00258   ib_dir = opendir(ib_dir_path);
00259   if (ib_dir == NULL) {
00260      SUBDBG("cannot open `%s'\n", ib_dir_path);
00261      strncpy(_infiniband_vector.cmp_info.disabled_reason,
00262                  "Infiniband sysfs interface not found", PAPI_MAX_STR_LEN);
00263      result = PAPI_ENOSUPP;
00264      goto out;
00265   }
00266 
00267   struct dirent *hca_ent;
00268   while ((hca_ent = readdir(ib_dir)) != NULL) {
00269      char *hca = hca_ent->d_name;
00270      char ports_path[80];
00271      DIR *ports_dir = NULL;
00272 
00273      if (hca[0] == '.')
00274         goto next_hca;
00275 
00276      snprintf(ports_path, sizeof(ports_path), "%s/%s/ports", ib_dir_path, hca);
00277      ports_dir = opendir(ports_path);
00278      if (ports_dir == NULL) {
00279         SUBDBG("cannot open `%s'\n", ports_path);
00280         goto next_hca;
00281      }
00282 
00283      struct dirent *port_ent;
00284      while ((port_ent = readdir(ports_dir)) != NULL) {
00285         int port = atoi(port_ent->d_name);
00286         if (port <= 0)
00287            continue;
00288 
00289         /* Check that port is active. .../HCA/ports/PORT/state should read "4: ACTIVE." */
00290         int state = -1;
00291         char state_path[80];
00292         snprintf(state_path, sizeof(state_path), "%s/%s/ports/%d/state", ib_dir_path, hca, port);
00293         if (pscanf(state_path, "%d", &state) != 1) {
00294            SUBDBG("cannot read state of IB HCA `%s' port %d\n", hca, port);
00295            continue;
00296         }
00297 
00298         if (state != 4) {
00299            SUBDBG("skipping inactive IB HCA `%s', port %d, state %d\n", hca, port, state);
00300            continue;
00301         }
00302 
00303         /* Create dev name (HCA/PORT) and get stats for dev. */
00304         SUBDBG("Found IB device `%s', port %d\n", hca, port);
00305         ib_device_t *dev = add_ib_device(hca, port);
00306         if (!dev)
00307            continue;
00308         // do we want to check for short counters only if no extended counters found?
00309         num_events += find_ib_device_events(dev, 1);  // check if we have extended (64bit) counters
00310         num_events += find_ib_device_events(dev, 0);  // check also for short counters
00311      }
00312 
00313    next_hca:
00314       if (ports_dir != NULL)
00315          closedir(ports_dir);
00316    }
00317 
00318    if (root_device == 0)  // no active devices found
00319    {
00320      strncpy(_infiniband_vector.cmp_info.disabled_reason,
00321                  "No active Infiniband ports found", PAPI_MAX_STR_LEN);
00322      result = PAPI_ENOIMPL;
00323    } else if (num_events == 0)
00324    {
00325      strncpy(_infiniband_vector.cmp_info.disabled_reason,
00326                  "No supported Infiniband events found", PAPI_MAX_STR_LEN);
00327      result = PAPI_ENOIMPL;
00328    } else
00329    {
00330       // Events are stored in a linked list, in reverse order than how I found them
00331       // Revert them again, so that they are in finding order, not that it matters.
00332       int i = num_events - 1;
00333       // now allocate memory to store the counters into the native table
00334       infiniband_native_events = (infiniband_native_event_entry_t*)
00335            papi_calloc(sizeof(infiniband_native_event_entry_t), num_events);
00336       ib_counter_t *iter = root_counter;
00337       while (iter != 0)
00338       {
00339          infiniband_native_events[i].name = iter->ev_name;
00340          infiniband_native_events[i].file_name = iter->ev_file_name;
00341          infiniband_native_events[i].device = iter->ev_device;
00342          infiniband_native_events[i].extended = iter->extended;
00343          infiniband_native_events[i].resources.selector = i + 1;
00344          infiniband_native_events[i].description = 
00345                   make_ib_event_description(iter->ev_file_name, iter->extended);
00346          
00347          ib_counter_t *tmp = iter;
00348          iter = iter->next;
00349          papi_free(tmp);
00350          -- i;
00351       }
00352       root_counter = 0;
00353    }
00354    
00355    out:
00356       if (ib_dir != NULL)
00357          closedir(ib_dir);
00358     
00359    return (result);
00360 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char* make_ib_event_description ( const char *  input_str,
int  extended 
) [static]

Definition at line 123 of file linux-infiniband.c.

00124 {
00125    int i, len;
00126    char *desc = 0;
00127    if (! input_str)
00128       return (0);
00129    
00130    desc = (char*) papi_calloc(PAPI_MAX_STR_LEN, 1);
00131    if (desc == 0) {
00132       PAPIERROR("cannot allocate memory for event description");
00133       return (0);
00134    }
00135    len = strlen(input_str);
00136    
00137    snprintf(desc, PAPI_MAX_STR_LEN, "%s (%s).",
00138            input_str, (extended ? "free-running 64bit counter" :
00139             "overflowing, auto-resetting counter"));
00140    desc[0] = toupper(desc[0]);
00141    for (i=0 ; i<len ; ++i)
00142       if (desc[i] == '_')
00143          desc[i] = ' ';
00144    
00145    return (desc);
00146 }

Here is the call graph for this function:

Here is the caller graph for this function:

static long long read_ib_counter_value ( int  index  )  [static]

Definition at line 363 of file linux-infiniband.c.

00364 {
00365    char ev_file[128];
00366    long long value = 0ll;
00367    infiniband_native_event_entry_t *iter = &infiniband_native_events[index];
00368    snprintf(ev_file, sizeof(ev_file), "%s/%s/ports/%d/counters%s/%s",
00369            ib_dir_path, iter->device->dev_name,
00370            iter->device->dev_port, (iter->extended?"_ext":""),
00371            iter->file_name);
00372 
00373    if (pscanf(ev_file, "%lld", &value) != 1) {
00374       PAPIERROR("cannot read value for counter '%s'\n", iter->name);
00375    } else
00376    {
00377       SUBDBG("Counter '%s': %lld\n", iter->name, value);
00378    }
00379    return (value);
00380 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 113 of file linux-infiniband.c.

const char* ib_dir_path = "/sys/class/infiniband" [static]

Definition at line 73 of file linux-infiniband.c.

Definition at line 108 of file linux-infiniband.c.

int num_events = 0 [static]

Definition at line 110 of file linux-infiniband.c.

ib_counter_t* root_counter = 0 [static]

Definition at line 120 of file linux-infiniband.c.

ib_device_t* root_device = 0 [static]

Definition at line 119 of file linux-infiniband.c.


Generated on 8 Sep 2016 for PAPI by  doxygen 1.6.1