Blame src/components/infiniband/linux-infiniband.c

Packit 577717
/** 
Packit 577717
 * @file    linux-infiniband.c
Packit 577717
 * @author  Heike Jagode 
Packit 577717
 *          jagode@icl.utk.edu
Packit 577717
 * @author  Gabriel Marin
Packit 577717
 *          gmarin@eecs.utk.edu
Packit 577717
 *
Packit 577717
 * @ingroup papi_components
Packit 577717
 *
Packit 577717
 *
Packit 577717
 * Infiniband component 
Packit 577717
 * 
Packit 577717
 *
Packit 577717
 * @brief 
Packit 577717
 *  This file has the source code for a component that enables PAPI-C to access
Packit 577717
 *  the infiniband performance monitor through the Linux sysfs interface.
Packit 577717
 *  This code will dynamically create a native events table for all the events 
Packit 577717
 *  that can be accesed through the sysfs interface. The counters exported by 
Packit 577717
 *  this component cannot be reset programatically.
Packit 577717
 */
Packit 577717
Packit 577717
Packit 577717
/* Headers required by infiniband */
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <unistd.h>
Packit 577717
#include <errno.h>
Packit 577717
#include <ctype.h>
Packit 577717
#include <string.h>
Packit 577717
#include <dirent.h>
Packit 577717
#include <error.h>
Packit 577717
#include <time.h>
Packit 577717
#include "pscanf.h"
Packit 577717
Packit 577717
/* Headers required by PAPI */
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
Packit 577717
/*************************  DEFINES SECTION  ***********************************
Packit 577717
 *******************************************************************************/
Packit 577717
/* this number assumes that there will never be more events than indicated */
Packit 577717
#define INFINIBAND_MAX_COUNTERS 128
Packit 577717
Packit 577717
/** Structure that stores private information of each event */
Packit 577717
typedef struct infiniband_register
Packit 577717
{
Packit 577717
   /* This is used by the framework.It likes it to be !=0 to do somehting */
Packit 577717
   unsigned int selector;
Packit 577717
} infiniband_register_t;
Packit 577717
Packit 577717
/*
Packit 577717
 * The following structures mimic the ones used by other components. It is more
Packit 577717
 * convenient to use them like that as programming with PAPI makes specific
Packit 577717
 * assumptions for them.
Packit 577717
 */
Packit 577717
Packit 577717
typedef struct _ib_device_type
Packit 577717
{
Packit 577717
   char* dev_name;
Packit 577717
   int   dev_port;
Packit 577717
   struct _ib_device_type *next;
Packit 577717
} ib_device_t;
Packit 577717
Packit 577717
typedef struct _ib_counter_type
Packit 577717
{
Packit 577717
   char* ev_name;
Packit 577717
   char* ev_file_name;
Packit 577717
   ib_device_t* ev_device;
Packit 577717
   int extended;   // if this is an extended (64-bit) counter
Packit 577717
   struct _ib_counter_type *next;
Packit 577717
} ib_counter_t;
Packit 577717
Packit 577717
static const char *ib_dir_path = "/sys/class/infiniband";
Packit 577717
Packit 577717
/** This structure is used to build the table of events */
Packit 577717
typedef struct _infiniband_native_event_entry
Packit 577717
{
Packit 577717
   infiniband_register_t resources;
Packit 577717
   char *name;
Packit 577717
   char *description;
Packit 577717
   char* file_name;
Packit 577717
   ib_device_t* device;
Packit 577717
   int extended;   /* if this is an extended (64-bit) counter */
Packit 577717
} infiniband_native_event_entry_t;
Packit 577717
Packit 577717
Packit 577717
typedef struct _infiniband_control_state
Packit 577717
{
Packit 577717
   long long counts[INFINIBAND_MAX_COUNTERS];
Packit 577717
   int being_measured[INFINIBAND_MAX_COUNTERS];
Packit 577717
   /* all IB counters need difference, but use a flag for generality */
Packit 577717
   int need_difference[INFINIBAND_MAX_COUNTERS];
Packit 577717
   long long lastupdate;
Packit 577717
} infiniband_control_state_t;
Packit 577717
Packit 577717
Packit 577717
typedef struct _infiniband_context
Packit 577717
{
Packit 577717
   infiniband_control_state_t state;
Packit 577717
   long long start_value[INFINIBAND_MAX_COUNTERS];
Packit 577717
} infiniband_context_t;
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/*************************  GLOBALS SECTION  ***********************************
Packit 577717
 *******************************************************************************/
Packit 577717
/* This table contains the component native events */
Packit 577717
static infiniband_native_event_entry_t *infiniband_native_events = 0;
Packit 577717
/* number of events in the table*/
Packit 577717
static int num_events = 0;
Packit 577717
Packit 577717
Packit 577717
papi_vector_t _infiniband_vector;
Packit 577717
Packit 577717
/******************************************************************************
Packit 577717
 ********  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT ********
Packit 577717
 *****************************************************************************/
Packit 577717
Packit 577717
static ib_device_t *root_device = 0;
Packit 577717
static ib_counter_t *root_counter = 0;
Packit 577717
Packit 577717
static char*
Packit 577717
make_ib_event_description(const char* input_str, int extended)
Packit 577717
{
Packit 577717
   int i, len;
Packit 577717
   char *desc = 0;
Packit 577717
   if (! input_str)
Packit 577717
      return (0);
Packit 577717
   
Packit 577717
   desc = (char*) papi_calloc(PAPI_MAX_STR_LEN, 1);
Packit 577717
   if (desc == 0) {
Packit 577717
      PAPIERROR("cannot allocate memory for event description");
Packit 577717
      return (0);
Packit 577717
   }
Packit 577717
   len = strlen(input_str);
Packit 577717
   
Packit 577717
   snprintf(desc, PAPI_MAX_STR_LEN, "%s (%s).",
Packit 577717
           input_str, (extended ? "free-running 64bit counter" :
Packit 577717
            "overflowing, auto-resetting counter"));
Packit 577717
   desc[0] = toupper(desc[0]);
Packit 577717
   for (i=0 ; i
Packit 577717
      if (desc[i] == '_')
Packit 577717
         desc[i] = ' ';
Packit 577717
   
Packit 577717
   return (desc);
Packit 577717
}
Packit 577717
Packit 577717
static ib_device_t*
Packit 577717
add_ib_device(const char* name, int port)
Packit 577717
{
Packit 577717
   ib_device_t *new_dev = (ib_device_t*) papi_calloc(sizeof(ib_device_t), 1);
Packit 577717
   if (new_dev == 0) {
Packit 577717
      PAPIERROR("cannot allocate memory for new IB device structure");
Packit 577717
      return (0);
Packit 577717
   }
Packit 577717
   
Packit 577717
   new_dev->dev_name = strdup(name);
Packit 577717
   new_dev->dev_port = port;
Packit 577717
   if (new_dev->dev_name==0)
Packit 577717
   {
Packit 577717
      PAPIERROR("cannot allocate memory for device internal fields");
Packit 577717
      papi_free(new_dev);
Packit 577717
      return (0);
Packit 577717
   }
Packit 577717
Packit 577717
   // prepend the new device to the device list
Packit 577717
   new_dev->next = root_device;
Packit 577717
   root_device = new_dev;
Packit 577717
   
Packit 577717
   return (new_dev);
Packit 577717
}
Packit 577717
Packit 577717
static ib_counter_t*
Packit 577717
add_ib_counter(const char* name, const char* file_name, int extended, ib_device_t *device)
Packit 577717
{
Packit 577717
   ib_counter_t *new_cnt = (ib_counter_t*) papi_calloc(sizeof(ib_counter_t), 1);
Packit 577717
   if (new_cnt == 0) {
Packit 577717
      PAPIERROR("cannot allocate memory for new IB counter structure");
Packit 577717
      return (0);
Packit 577717
   }
Packit 577717
   
Packit 577717
   new_cnt->ev_name = strdup(name);
Packit 577717
   new_cnt->ev_file_name = strdup(file_name);
Packit 577717
   new_cnt->extended = extended;
Packit 577717
   new_cnt->ev_device = device;
Packit 577717
   if (new_cnt->ev_name==0 || new_cnt->ev_file_name==0)
Packit 577717
   {
Packit 577717
      PAPIERROR("cannot allocate memory for counter internal fields");
Packit 577717
      papi_free(new_cnt);
Packit 577717
      return (0);
Packit 577717
   }
Packit 577717
Packit 577717
   // prepend the new counter to the counter list
Packit 577717
   new_cnt->next = root_counter;
Packit 577717
   root_counter = new_cnt;
Packit 577717
   
Packit 577717
   return (new_cnt);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
find_ib_device_events(ib_device_t *dev, int extended)
Packit 577717
{
Packit 577717
   int nevents = 0;
Packit 577717
   DIR *cnt_dir = NULL;
Packit 577717
   char counters_path[128];
Packit 577717
Packit 577717
   if ( extended ) {
Packit 577717
      /* mofed driver version <4.0 */
Packit 577717
      snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters%s", 
Packit 577717
             ib_dir_path, dev->dev_name, dev->dev_port, (extended?"_ext":""));
Packit 577717
   
Packit 577717
      cnt_dir = opendir(counters_path);
Packit 577717
      if (cnt_dir == NULL) {
Packit 577717
         /* directory counters_ext in sysfs fs has changed to hw_counters */
Packit 577717
         /* in 4.0 version of mofed driver */
Packit 577717
         SUBDBG("cannot open counters directory `%s'\n", counters_path);
Packit 577717
Packit 577717
         snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/%scounters", 
Packit 577717
                ib_dir_path, dev->dev_name, dev->dev_port, "hw_");
Packit 577717
   
Packit 577717
         cnt_dir = opendir(counters_path);
Packit 577717
      }
Packit 577717
   }
Packit 577717
   else {
Packit 577717
      snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters", 
Packit 577717
             ib_dir_path, dev->dev_name, dev->dev_port);
Packit 577717
      cnt_dir = opendir(counters_path);
Packit 577717
   }
Packit 577717
   
Packit 577717
   if (cnt_dir == NULL) {
Packit 577717
      SUBDBG("cannot open counters directory `%s'\n", counters_path);
Packit 577717
      goto out;
Packit 577717
   }
Packit 577717
   
Packit 577717
   struct dirent *ev_ent;
Packit 577717
   /* iterate over all the events */
Packit 577717
   while ((ev_ent = readdir(cnt_dir)) != NULL) {
Packit 577717
      char *ev_name = ev_ent->d_name;
Packit 577717
      long long value = -1;
Packit 577717
      char event_path[160];
Packit 577717
      char counter_name[80];
Packit 577717
Packit 577717
      if (ev_name[0] == '.')
Packit 577717
         continue;
Packit 577717
Packit 577717
      /* Check that we can read an integer from the counter file */
Packit 577717
      snprintf(event_path, sizeof(event_path), "%s/%s", counters_path, ev_name);
Packit 577717
      if (pscanf(event_path, "%lld", &value) != 1) {
Packit 577717
        SUBDBG("cannot read value for event '%s'\n", ev_name);
Packit 577717
        continue;
Packit 577717
      }
Packit 577717
Packit 577717
      /* Create new counter */
Packit 577717
      snprintf(counter_name, sizeof(counter_name), "%s_%d%s:%s", 
Packit 577717
            dev->dev_name, dev->dev_port, (extended?"_ext":""), ev_name);
Packit 577717
      if (add_ib_counter(counter_name, ev_name, extended, dev))
Packit 577717
      {
Packit 577717
         SUBDBG("Added new counter `%s'\n", counter_name);
Packit 577717
         nevents += 1;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
 out:
Packit 577717
  if (cnt_dir != NULL)
Packit 577717
    closedir(cnt_dir);
Packit 577717
Packit 577717
  return (nevents);
Packit 577717
}
Packit 577717
Packit 577717
static int 
Packit 577717
find_ib_devices() 
Packit 577717
{
Packit 577717
  DIR *ib_dir = NULL;
Packit 577717
  int result = PAPI_OK;
Packit 577717
  num_events = 0;
Packit 577717
Packit 577717
  ib_dir = opendir(ib_dir_path);
Packit 577717
  if (ib_dir == NULL) {
Packit 577717
     SUBDBG("cannot open `%s'\n", ib_dir_path);
Packit 577717
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
Packit 577717
                 "Infiniband sysfs interface not found", PAPI_MAX_STR_LEN);
Packit 577717
     result = PAPI_ENOSUPP;
Packit 577717
     goto out;
Packit 577717
  }
Packit 577717
Packit 577717
  struct dirent *hca_ent;
Packit 577717
  while ((hca_ent = readdir(ib_dir)) != NULL) {
Packit 577717
     char *hca = hca_ent->d_name;
Packit 577717
     char ports_path[80];
Packit 577717
     DIR *ports_dir = NULL;
Packit 577717
Packit 577717
     if (hca[0] == '.')
Packit 577717
        goto next_hca;
Packit 577717
Packit 577717
     snprintf(ports_path, sizeof(ports_path), "%s/%s/ports", ib_dir_path, hca);
Packit 577717
     ports_dir = opendir(ports_path);
Packit 577717
     if (ports_dir == NULL) {
Packit 577717
        SUBDBG("cannot open `%s'\n", ports_path);
Packit 577717
        goto next_hca;
Packit 577717
     }
Packit 577717
Packit 577717
     struct dirent *port_ent;
Packit 577717
     while ((port_ent = readdir(ports_dir)) != NULL) {
Packit 577717
        int port = atoi(port_ent->d_name);
Packit 577717
        if (port <= 0)
Packit 577717
           continue;
Packit 577717
Packit 577717
        /* Check that port is active. .../HCA/ports/PORT/state should read "4: ACTIVE." */
Packit 577717
        int state = -1;
Packit 577717
        char state_path[80];
Packit 577717
        snprintf(state_path, sizeof(state_path), "%s/%s/ports/%d/state", ib_dir_path, hca, port);
Packit 577717
        if (pscanf(state_path, "%d", &state) != 1) {
Packit 577717
           SUBDBG("cannot read state of IB HCA `%s' port %d\n", hca, port);
Packit 577717
           continue;
Packit 577717
        }
Packit 577717
Packit 577717
        if (state != 4) {
Packit 577717
           SUBDBG("skipping inactive IB HCA `%s', port %d, state %d\n", hca, port, state);
Packit 577717
           continue;
Packit 577717
        }
Packit 577717
Packit 577717
        /* Create dev name (HCA/PORT) and get stats for dev. */
Packit 577717
        SUBDBG("Found IB device `%s', port %d\n", hca, port);
Packit 577717
        ib_device_t *dev = add_ib_device(hca, port);
Packit 577717
        if (!dev)
Packit 577717
           continue;
Packit 577717
        // do we want to check for short counters only if no extended counters found?
Packit 577717
        num_events += find_ib_device_events(dev, 1);  // check if we have extended (64bit) counters
Packit 577717
        num_events += find_ib_device_events(dev, 0);  // check also for short counters
Packit 577717
     }
Packit 577717
Packit 577717
   next_hca:
Packit 577717
      if (ports_dir != NULL)
Packit 577717
         closedir(ports_dir);
Packit 577717
   }
Packit 577717
Packit 577717
   if (root_device == 0)  // no active devices found
Packit 577717
   {
Packit 577717
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
Packit 577717
                 "No active Infiniband ports found", PAPI_MAX_STR_LEN);
Packit 577717
     result = PAPI_ENOIMPL;
Packit 577717
   } else if (num_events == 0)
Packit 577717
   {
Packit 577717
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
Packit 577717
                 "No supported Infiniband events found", PAPI_MAX_STR_LEN);
Packit 577717
     result = PAPI_ENOIMPL;
Packit 577717
   } else
Packit 577717
   {
Packit 577717
      // Events are stored in a linked list, in reverse order than how I found them
Packit 577717
      // Revert them again, so that they are in finding order, not that it matters.
Packit 577717
      int i = num_events - 1;
Packit 577717
      // now allocate memory to store the counters into the native table
Packit 577717
      infiniband_native_events = (infiniband_native_event_entry_t*)
Packit 577717
           papi_calloc(num_events, sizeof(infiniband_native_event_entry_t));
Packit 577717
      ib_counter_t *iter = root_counter;
Packit 577717
      while (iter != 0)
Packit 577717
      {
Packit 577717
         infiniband_native_events[i].name = iter->ev_name;
Packit 577717
         infiniband_native_events[i].file_name = iter->ev_file_name;
Packit 577717
         infiniband_native_events[i].device = iter->ev_device;
Packit 577717
         infiniband_native_events[i].extended = iter->extended;
Packit 577717
         infiniband_native_events[i].resources.selector = i + 1;
Packit 577717
         infiniband_native_events[i].description = 
Packit 577717
                  make_ib_event_description(iter->ev_file_name, iter->extended);
Packit 577717
         
Packit 577717
         ib_counter_t *tmp = iter;
Packit 577717
         iter = iter->next;
Packit 577717
         papi_free(tmp);
Packit 577717
         -- i;
Packit 577717
      }
Packit 577717
      root_counter = 0;
Packit 577717
   }
Packit 577717
   
Packit 577717
   out:
Packit 577717
      if (ib_dir != NULL)
Packit 577717
         closedir(ib_dir);
Packit 577717
    
Packit 577717
   return (result);
Packit 577717
}
Packit 577717
Packit 577717
static long long
Packit 577717
read_ib_counter_value(int index)
Packit 577717
{
Packit 577717
   char ev_file[128];
Packit 577717
   char counters_path[128];
Packit 577717
   DIR *cnt_dir = NULL;
Packit 577717
   long long value = 0ll;
Packit 577717
   infiniband_native_event_entry_t *iter = &infiniband_native_events[index];
Packit 577717
   
Packit 577717
   if ( iter->extended ) {
Packit 577717
      /* mofed driver version <4.0 */
Packit 577717
      snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters%s",
Packit 577717
             ib_dir_path, iter->device->dev_name, iter->device->dev_port, "_ext");
Packit 577717
   
Packit 577717
      cnt_dir = opendir(counters_path);
Packit 577717
      if (cnt_dir == NULL) {
Packit 577717
         /* directory counters_ext in sysfs fs has changed to hw_counters */
Packit 577717
         /* in 4.0 version of mofed driver */
Packit 577717
         snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/%scounters",
Packit 577717
                ib_dir_path, iter->device->dev_name, iter->device->dev_port, "hw_");
Packit 577717
   
Packit 577717
         cnt_dir = opendir(counters_path);
Packit 577717
      }
Packit 577717
   }
Packit 577717
   else {
Packit 577717
      snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters",
Packit 577717
             ib_dir_path, iter->device->dev_name, iter->device->dev_port );
Packit 577717
      cnt_dir = opendir(counters_path);
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   if (cnt_dir != NULL)
Packit 577717
      closedir(cnt_dir);
Packit 577717
Packit 577717
 
Packit 577717
   snprintf(ev_file, sizeof(ev_file), "%s/%s",
Packit 577717
           counters_path, iter->file_name);
Packit 577717
Packit 577717
   if (pscanf(ev_file, "%lld", &value) != 1) {
Packit 577717
      PAPIERROR("cannot read value for counter '%s'\n", iter->name);
Packit 577717
   } else
Packit 577717
   {
Packit 577717
      SUBDBG("Counter '%s': %lld\n", iter->name, value);
Packit 577717
   }
Packit 577717
   return (value);
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
deallocate_infiniband_resources()
Packit 577717
{
Packit 577717
   int i;
Packit 577717
   
Packit 577717
   if (infiniband_native_events)
Packit 577717
   {
Packit 577717
      for (i=0 ; i
Packit 577717
         if (infiniband_native_events[i].name)
Packit 577717
            free(infiniband_native_events[i].name);
Packit 577717
         if (infiniband_native_events[i].file_name)
Packit 577717
            free(infiniband_native_events[i].file_name);
Packit 577717
         if (infiniband_native_events[i].description)
Packit 577717
            papi_free(infiniband_native_events[i].description);
Packit 577717
      }
Packit 577717
      papi_free(infiniband_native_events);
Packit 577717
   }
Packit 577717
   
Packit 577717
   ib_device_t *iter = root_device;
Packit 577717
   while (iter != 0) 
Packit 577717
   {
Packit 577717
      if (iter->dev_name)
Packit 577717
         free(iter->dev_name);
Packit 577717
   
Packit 577717
      ib_device_t *tmp = iter;
Packit 577717
      iter = iter->next;
Packit 577717
      papi_free(tmp);
Packit 577717
   }
Packit 577717
   root_device = 0;
Packit 577717
}
Packit 577717
Packit 577717
/*****************************************************************************
Packit 577717
 *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
Packit 577717
 *****************************************************************************/
Packit 577717
Packit 577717
/*
Packit 577717
 * This is called whenever a thread is initialized
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_init_thread( hwd_context_t *ctx )
Packit 577717
{
Packit 577717
   (void) ctx;
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* Initialize hardware counters, setup the function vector table
Packit 577717
 * and get hardware information, this routine is called when the 
Packit 577717
 * PAPI process is initialized (IE PAPI_library_init)
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_init_component( int cidx )
Packit 577717
{
Packit 577717
   /* discover Infiniband devices and available events */
Packit 577717
   int result = find_ib_devices();
Packit 577717
   
Packit 577717
   if (result != PAPI_OK)  // we couldn't initialize the component
Packit 577717
   {
Packit 577717
      // deallocate any eventually allocated memory
Packit 577717
      deallocate_infiniband_resources();
Packit 577717
   }
Packit 577717
    
Packit 577717
   _infiniband_vector.cmp_info.num_native_events = num_events;
Packit 577717
Packit 577717
   _infiniband_vector.cmp_info.num_cntrs = num_events;
Packit 577717
   _infiniband_vector.cmp_info.num_mpx_cntrs = num_events;
Packit 577717
Packit 577717
Packit 577717
   /* Export the component id */
Packit 577717
   _infiniband_vector.cmp_info.CmpIdx = cidx;
Packit 577717
Packit 577717
   return (result);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 * Control of counters (Reading/Writing/Starting/Stopping/Setup)
Packit 577717
 * functions
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_init_control_state( hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
Packit 577717
   int i;
Packit 577717
Packit 577717
   for (i=0 ; i
Packit 577717
      control->being_measured[i] = 0;
Packit 577717
   }
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   infiniband_context_t* context = (infiniband_context_t*) ctx;
Packit 577717
   infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
Packit 577717
   long long now = PAPI_get_real_usec();
Packit 577717
   int i;
Packit 577717
Packit 577717
   for (i=0 ; i
Packit 577717
      if (control->being_measured[i] && control->need_difference[i]) {
Packit 577717
         context->start_value[i] = read_ib_counter_value(i);
Packit 577717
      }
Packit 577717
   }
Packit 577717
   control->lastupdate = now;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   infiniband_context_t* context = (infiniband_context_t*) ctx;
Packit 577717
   infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
Packit 577717
   long long now = PAPI_get_real_usec();
Packit 577717
   int i;
Packit 577717
   long long temp;
Packit 577717
Packit 577717
   for (i=0 ; i
Packit 577717
      if (control->being_measured[i])
Packit 577717
      {
Packit 577717
         temp = read_ib_counter_value(i);
Packit 577717
         if (context->start_value[i] && control->need_difference[i]) {
Packit 577717
            /* Must subtract values, but check for wraparound. 
Packit 577717
             * We cannot even detect all wraparound cases. Using the short,
Packit 577717
             * auto-resetting IB counters is error prone.
Packit 577717
             */
Packit 577717
            if (temp < context->start_value[i]) {
Packit 577717
               SUBDBG("Wraparound!\nstart:\t%#016x\ttemp:\t%#016x",
Packit 577717
                        (unsigned)context->start_value[i], (unsigned)temp);
Packit 577717
               /* The counters auto-reset. I cannot even adjust them to 
Packit 577717
                * account for a simple wraparound. 
Packit 577717
                * Just use the current reading of the counter, which is useless.
Packit 577717
                */
Packit 577717
            } else
Packit 577717
               temp -= context->start_value[i];
Packit 577717
         }
Packit 577717
         control->counts[i] = temp;
Packit 577717
      }
Packit 577717
   }
Packit 577717
   control->lastupdate = now;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
Packit 577717
		 long_long ** events, int flags )
Packit 577717
{
Packit 577717
   ( void ) flags;
Packit 577717
    
Packit 577717
   _infiniband_stop(ctx, ctl);  /* we cannot actually stop the counters */
Packit 577717
   /* Pass back a pointer to our results */
Packit 577717
   *events = ((infiniband_control_state_t*) ctl)->counts;
Packit 577717
   
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
_infiniband_shutdown_component( void )
Packit 577717
{
Packit 577717
   /* Cleanup resources used by this component before leaving */
Packit 577717
   deallocate_infiniband_resources();
Packit 577717
   
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_infiniband_shutdown_thread( hwd_context_t *ctx )
Packit 577717
{
Packit 577717
   ( void ) ctx;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/* This function sets various options in the component
Packit 577717
 * The valid codes being passed in are PAPI_SET_DEFDOM,
Packit 577717
 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
Packit 577717
{
Packit 577717
   ( void ) ctx;
Packit 577717
   ( void ) code;
Packit 577717
   ( void ) option;
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
_infiniband_update_control_state( hwd_control_state_t *ctl,
Packit 577717
				 NativeInfo_t * native, 
Packit 577717
				 int count,
Packit 577717
				 hwd_context_t *ctx )
Packit 577717
{
Packit 577717
   int i, index;
Packit 577717
   ( void ) ctx;
Packit 577717
    
Packit 577717
   infiniband_control_state_t* control = (infiniband_control_state_t*) ctl;
Packit 577717
   
Packit 577717
   for (i=0 ; i
Packit 577717
      control->being_measured[i] = 0;
Packit 577717
   }
Packit 577717
   
Packit 577717
   for (i=0 ; i
Packit 577717
      index = native[i].ni_event & PAPI_NATIVE_AND_MASK;
Packit 577717
      native[i].ni_position =
Packit 577717
                  infiniband_native_events[index].resources.selector - 1;
Packit 577717
      control->being_measured[index] = 1;
Packit 577717
      control->need_difference[index] = 1;
Packit 577717
   }
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 * This function has to set the bits needed to count different domains
Packit 577717
 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
Packit 577717
 * By default return PAPI_EINVAL if none of those are specified
Packit 577717
 * and PAPI_OK with success
Packit 577717
 * PAPI_DOM_USER is only user context is counted
Packit 577717
 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
Packit 577717
 * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
Packit 577717
 * PAPI_DOM_ALL   is all of the domains
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_set_domain( hwd_control_state_t *ctl, int domain )
Packit 577717
{
Packit 577717
   int found = 0;
Packit 577717
   (void) ctl;
Packit 577717
	
Packit 577717
   if (PAPI_DOM_USER & domain)
Packit 577717
      found = 1;
Packit 577717
Packit 577717
   if (PAPI_DOM_KERNEL & domain)
Packit 577717
      found = 1;
Packit 577717
Packit 577717
   if (PAPI_DOM_OTHER & domain)
Packit 577717
      found = 1;
Packit 577717
Packit 577717
   if (!found)
Packit 577717
      return (PAPI_EINVAL);
Packit 577717
Packit 577717
   return (PAPI_OK);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 * Cannot reset the counters using the sysfs interface.
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   (void) ctx;
Packit 577717
   (void) ctl;
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 * Native Event functions
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_ntv_enum_events( unsigned int *EventCode, int modifier )
Packit 577717
{
Packit 577717
   switch (modifier) {
Packit 577717
      case PAPI_ENUM_FIRST:
Packit 577717
         if (num_events == 0)
Packit 577717
            return (PAPI_ENOEVNT);
Packit 577717
            
Packit 577717
         *EventCode = 0;
Packit 577717
         return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_ENUM_EVENTS:
Packit 577717
      {
Packit 577717
         int index = *EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
         if (index < num_events - 1) {
Packit 577717
            *EventCode = *EventCode + 1;
Packit 577717
            return PAPI_OK;
Packit 577717
         } else
Packit 577717
            return PAPI_ENOEVNT;
Packit 577717
Packit 577717
         break;
Packit 577717
      }
Packit 577717
      default:
Packit 577717
         return PAPI_EINVAL;
Packit 577717
   }
Packit 577717
   return PAPI_EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_ntv_code_to_name( unsigned int EventCode, char *name, int len )
Packit 577717
{
Packit 577717
   int index = EventCode;
Packit 577717
Packit 577717
   if (index>=0 && index
Packit 577717
      strncpy( name, infiniband_native_events[index].name, len );
Packit 577717
   }
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
static int
Packit 577717
_infiniband_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
Packit 577717
{
Packit 577717
   int index = EventCode;
Packit 577717
Packit 577717
   if (index>=0 && index
Packit 577717
      strncpy(name, infiniband_native_events[index].description, len);
Packit 577717
   }
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_infiniband_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Packit 577717
{
Packit 577717
   int index = EventCode;
Packit 577717
Packit 577717
   if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT; 
Packit 577717
Packit 577717
   if (infiniband_native_events[index].name)
Packit 577717
   {
Packit 577717
      unsigned int len = strlen(infiniband_native_events[index].name);
Packit 577717
      if (len > sizeof(info->symbol)-1) len = sizeof(info->symbol)-1;
Packit 577717
      strncpy(info->symbol, infiniband_native_events[index].name, len);
Packit 577717
      info->symbol[len] = '\0';
Packit 577717
   }
Packit 577717
   if (infiniband_native_events[index].description)
Packit 577717
   {
Packit 577717
      unsigned int len = strlen(infiniband_native_events[index].description);
Packit 577717
      if (len > sizeof(info->long_descr)-1) len = sizeof(info->long_descr)-1;
Packit 577717
      strncpy(info->long_descr, infiniband_native_events[index].description, len);
Packit 577717
      info->long_descr[len] = '\0';
Packit 577717
   }
Packit 577717
Packit 577717
   strncpy(info->units, "\0", 1);
Packit 577717
       /* infiniband_native_events[index].units, sizeof(info->units)); */
Packit 577717
Packit 577717
/*   info->data_type = infiniband_native_events[index].return_type;
Packit 577717
 */
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
 *
Packit 577717
 */
Packit 577717
papi_vector_t _infiniband_vector = {
Packit 577717
   .cmp_info = {
Packit 577717
        /* component information (unspecified values are initialized to 0) */
Packit 577717
	.name = "infiniband",
Packit 577717
	.short_name = "infiniband",
Packit 577717
	.version = "5.3.0",
Packit 577717
	.description = "Linux Infiniband statistics using the sysfs interface",
Packit 577717
	.num_mpx_cntrs = INFINIBAND_MAX_COUNTERS,
Packit 577717
	.num_cntrs = INFINIBAND_MAX_COUNTERS,
Packit 577717
	.default_domain = PAPI_DOM_USER | PAPI_DOM_KERNEL,
Packit 577717
	.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
Packit 577717
	.default_granularity = PAPI_GRN_SYS,
Packit 577717
	.available_granularities = PAPI_GRN_SYS,
Packit 577717
	.hardware_intr_sig = PAPI_INT_SIGNAL,
Packit 577717
Packit 577717
	/* component specific cmp_info initializations */
Packit 577717
	.fast_real_timer = 0,
Packit 577717
	.fast_virtual_timer = 0,
Packit 577717
	.attach = 0,
Packit 577717
	.attach_must_ptrace = 0,
Packit 577717
  },
Packit 577717
Packit 577717
        /* sizes of framework-opaque component-private structures */
Packit 577717
	.size = {
Packit 577717
	   .context = sizeof (infiniband_context_t),
Packit 577717
	   .control_state = sizeof (infiniband_control_state_t),
Packit 577717
	   .reg_value = sizeof (infiniband_register_t),
Packit 577717
	   /* .reg_alloc = sizeof (infiniband_reg_alloc_t), */
Packit 577717
  },
Packit 577717
	/* function pointers in this component */
Packit 577717
     .init_thread =          _infiniband_init_thread,
Packit 577717
     .init_component =       _infiniband_init_component,
Packit 577717
     .init_control_state =   _infiniband_init_control_state,
Packit 577717
     .start =                _infiniband_start,
Packit 577717
     .stop =                 _infiniband_stop,
Packit 577717
     .read =                 _infiniband_read,
Packit 577717
     .shutdown_thread =      _infiniband_shutdown_thread,
Packit 577717
     .shutdown_component =   _infiniband_shutdown_component,
Packit 577717
     .ctl =                  _infiniband_ctl,
Packit 577717
     .update_control_state = _infiniband_update_control_state,
Packit 577717
     .set_domain =           _infiniband_set_domain,
Packit 577717
     .reset =                _infiniband_reset,
Packit 577717
	
Packit 577717
     .ntv_enum_events =      _infiniband_ntv_enum_events,
Packit 577717
     .ntv_code_to_name =     _infiniband_ntv_code_to_name,
Packit 577717
     .ntv_code_to_descr =    _infiniband_ntv_code_to_descr,
Packit 577717
     .ntv_code_to_info =     _infiniband_ntv_code_to_info,
Packit 577717
};