Blame opae-libs/plugins/xfpga/metrics/metrics_max10.c

Packit 534379
// Copyright(c) 2018-2020, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
Packit 534379
Packit 534379
/**
Packit 534379
* \file metrics_max10.h
Packit 534379
* \brief fpga metrics max10 functions
Packit 534379
*/
Packit 534379
Packit 534379
#ifdef HAVE_CONFIG_H
Packit 534379
#include <config.h>
Packit 534379
#endif // HAVE_CONFIG_H
Packit 534379
Packit 534379
Packit 534379
#include <sys/types.h>
Packit 534379
#include <sys/stat.h>
Packit 534379
#include <string.h>
Packit 534379
#ifndef _WIN32
Packit 534379
#include <unistd.h>
Packit 534379
#else
Packit 534379
#include <io.h>
Packit 534379
#endif
Packit 534379
#include <fcntl.h>
Packit 534379
#include <stdlib.h>
Packit 534379
#include <string.h>
Packit 534379
#include <glob.h>
Packit 534379
Packit 534379
Packit 534379
#include "common_int.h"
Packit 534379
#include "metrics_int.h"
Packit 534379
#include "types_int.h"
Packit 534379
#include "sysfs_int.h"
Packit 534379
#include "opae/metrics.h"
Packit 534379
#include "metrics/vector.h"
Packit 534379
#include "xfpga.h"
Packit 534379
#include "metrics/metrics_metadata.h"
Packit 534379
#include "metrics/max10_metadata.h"
Packit 534379
Packit 534379
// Max10 Metric limits
Packit 534379
#define THERMAL_HIGH_LIMIT             300.00
Packit 534379
#define THERMAL_LOW_LIMIT              -273.00
Packit 534379
#define POWER_HIGH_LIMIT               1000.00
Packit 534379
#define POWER_LOW_LIMIT                0.00
Packit 534379
#define VOLTAMP_HIGH_LIMIT             500.00
Packit 534379
#define VOLTAMP_LOW_LIMIT              0.00
Packit 534379
Packit 534379
Packit 534379
fpga_result read_sensor_sysfs_file(const char *sysfs, const char *file,
Packit 534379
			void **buf, uint32_t *tot_bytes_ret)
Packit 534379
{
Packit 534379
	char sysfspath[SYSFS_PATH_MAX] = { 0, };
Packit 534379
	struct stat stats;
Packit 534379
	int fd = 0;
Packit 534379
	fpga_result res = FPGA_OK;
Packit 534379
Packit 534379
	if (sysfs == NULL ||
Packit 534379
		file == NULL ||
Packit 534379
		buf == NULL ||
Packit 534379
		tot_bytes_ret == NULL) {
Packit 534379
		OPAE_ERR("Invalid Input parameters");
Packit 534379
		return FPGA_INVALID_PARAM;
Packit 534379
	}
Packit 534379
	*buf = NULL;
Packit 534379
	*tot_bytes_ret = 0;
Packit 534379
Packit 534379
	snprintf(sysfspath, sizeof(sysfspath),
Packit 534379
		 "%s/%s", sysfs, file);
Packit 534379
Packit 534379
	glob_t pglob;
Packit 534379
	int gres = glob(sysfspath, GLOB_NOSORT, NULL, &pglob);
Packit 534379
	if ((gres) || (1 != pglob.gl_pathc)) {
Packit 534379
		globfree(&pglob);
Packit 534379
		return FPGA_NOT_FOUND;
Packit 534379
	}
Packit 534379
Packit 534379
	fd = open(pglob.gl_pathv[0], O_RDONLY);
Packit 534379
	globfree(&pglob);
Packit 534379
	if (fd < 0) {
Packit 534379
		return FPGA_NOT_FOUND;
Packit 534379
	}
Packit 534379
Packit 534379
	if (fstat(fd, &stats) != 0) {
Packit 534379
		close(fd);
Packit 534379
		return FPGA_NOT_FOUND;
Packit 534379
	}
Packit 534379
Packit 534379
	// fstat for a sysfs file is not accurate for the BMC
Packit 534379
	// Read the entire file into a temp buffer to get actual size of file
Packit 534379
	*buf = (void *)calloc(stats.st_size, 1);
Packit 534379
Packit 534379
	int32_t tot_bytes = 0;
Packit 534379
	int32_t bytes_read = 0;
Packit 534379
	do {
Packit 534379
		bytes_read = (int32_t)read(fd, *buf, stats.st_size);
Packit 534379
		if (bytes_read < 0) {
Packit 534379
			if (errno == EINTR) {
Packit 534379
				bytes_read = 1; // Fool the while loop
Packit 534379
				continue;
Packit 534379
			}
Packit 534379
		}
Packit 534379
		tot_bytes += bytes_read;
Packit 534379
	} while ((tot_bytes < stats.st_size) && (bytes_read > 0));
Packit 534379
Packit 534379
	close(fd);
Packit 534379
Packit 534379
	if ((tot_bytes > stats.st_size) || (bytes_read < 0)) {
Packit 534379
		res = FPGA_EXCEPTION;
Packit 534379
		free(*buf);
Packit 534379
		*buf = NULL;
Packit 534379
		goto out;
Packit 534379
	}
Packit 534379
Packit 534379
	*tot_bytes_ret = tot_bytes;
Packit 534379
Packit 534379
out:
Packit 534379
	return res;
Packit 534379
}
Packit 534379
Packit 534379
Packit 534379
fpga_result  enum_max10_metrics_info(struct _fpga_handle *_handle,
Packit 534379
							fpga_metric_vector *vector,
Packit 534379
							uint64_t *metric_num,
Packit 534379
							enum fpga_hw_type  hw_type)
Packit 534379
{
Packit 534379
	fpga_result result                             = FPGA_OK;
Packit 534379
	struct _fpga_token *_token                     = NULL;
Packit 534379
	size_t i                                       = 0;
Packit 534379
	char *tmp                                      = NULL;
Packit 534379
	uint32_t tot_bytes                             = 0;
Packit 534379
	enum fpga_metric_type metric_type              = FPGA_METRIC_TYPE_POWER;
Packit 534379
	char sysfspath[SYSFS_PATH_MAX]                 = { 0, };
Packit 534379
	char metrics_sysfs_path[SYSFS_PATH_MAX]        = { 0, };
Packit 534379
	char metric_name[SYSFS_PATH_MAX]               = { 0, };
Packit 534379
	char group_name[SYSFS_PATH_MAX]                = { 0, };
Packit 534379
	char group_sysfs[SYSFS_PATH_MAX]               = { 0, };
Packit 534379
	char qualifier_name[SYSFS_PATH_MAX]            = { 0, };
Packit 534379
	char metric_units[SYSFS_PATH_MAX]              = { 0, };
Packit 534379
	glob_t pglob;
Packit 534379
	size_t len;
Packit 534379
Packit 534379
	if (_handle == NULL ||
Packit 534379
		vector == NULL ||
Packit 534379
		metric_num == NULL) {
Packit 534379
		OPAE_ERR("Invalid Input parameters");
Packit 534379
		return FPGA_INVALID_PARAM;
Packit 534379
	}
Packit 534379
Packit 534379
	_token = (struct _fpga_token *)_handle->token;
Packit 534379
	if (_token == NULL) {
Packit 534379
		OPAE_ERR("Invalid token within handle");
Packit 534379
		return FPGA_INVALID_PARAM;
Packit 534379
	}
Packit 534379
Packit 534379
	// metrics group
Packit 534379
	if (snprintf(sysfspath, sizeof(sysfspath),
Packit 534379
		 "%s/%s", _token->sysfspath, MAX10_SYSFS_PATH) < 0) {
Packit 534379
		OPAE_ERR("snprintf failed");
Packit 534379
		return FPGA_EXCEPTION;
Packit 534379
	}
Packit 534379
Packit 534379
	int gres = glob(sysfspath, GLOB_NOSORT, NULL, &pglob);
Packit 534379
	if ((gres) || (1 != pglob.gl_pathc)) {
Packit 534379
		OPAE_ERR("Failed pattern match %s: %s", sysfspath, strerror(errno));
Packit 534379
		globfree(&pglob);
Packit 534379
		return FPGA_NOT_FOUND;
Packit 534379
	}
Packit 534379
Packit 534379
	len = strnlen(pglob.gl_pathv[0], sizeof(group_sysfs) - 1);
Packit 534379
	memcpy(group_sysfs, pglob.gl_pathv[0], len);
Packit 534379
	group_sysfs[len] = '\0';
Packit 534379
	globfree(&pglob);
Packit 534379
Packit 534379
	// Enum sensors
Packit 534379
	if (snprintf(sysfspath, sizeof(sysfspath),
Packit 534379
		 "%s/%s", _token->sysfspath, MAX10_SENSOR_SYSFS_PATH) < 0) {
Packit 534379
		OPAE_ERR("snprintf failed");
Packit 534379
		return FPGA_EXCEPTION;
Packit 534379
	}
Packit 534379
Packit 534379
	gres = glob(sysfspath, GLOB_NOSORT, NULL, &pglob);
Packit 534379
	if (gres) {
Packit 534379
		OPAE_ERR("Failed pattern match %s: %s", sysfspath, strerror(errno));
Packit 534379
		globfree(&pglob);
Packit 534379
		return FPGA_NOT_FOUND;
Packit 534379
	}
Packit 534379
Packit 534379
Packit 534379
	// for loop
Packit 534379
	for (i = 0; i < pglob.gl_pathc; i++) {
Packit 534379
Packit 534379
		// Sensor name
Packit 534379
		result = read_sensor_sysfs_file(pglob.gl_pathv[i], SENSOR_SYSFS_NAME, (void **)&tmp, &tot_bytes);
Packit 534379
		if (FPGA_OK != result || !tmp) {
Packit 534379
			if (tmp) {
Packit 534379
				free(tmp);
Packit 534379
			}
Packit 534379
			continue;
Packit 534379
		}
Packit 534379
Packit 534379
		memset(&metric_name, 0, sizeof(metric_name));
Packit 534379
Packit 534379
		len = strnlen(tmp, sizeof(metric_name) - 1);
Packit 534379
		memcpy(metric_name, tmp, len);
Packit 534379
		metric_name[len] = '\0';
Packit 534379
Packit 534379
		if (tmp) {
Packit 534379
			free(tmp);
Packit 534379
		}
Packit 534379
Packit 534379
		// Metrics typw
Packit 534379
		result = read_sensor_sysfs_file(pglob.gl_pathv[i], SENSOR_SYSFS_TYPE, (void **)&tmp, &tot_bytes);
Packit 534379
		if (FPGA_OK != result || !tmp) {
Packit 534379
			if (tmp) {
Packit 534379
				free(tmp);
Packit 534379
				continue;
Packit 534379
			}
Packit 534379
Packit 534379
		}
Packit 534379
Packit 534379
		// Metrics group name and qualifier name
Packit 534379
		if (tmp && (strstr(tmp, VOLTAGE) || strstr(tmp, CURRENT) || strstr(tmp, POWER))) {
Packit 534379
			metric_type = FPGA_METRIC_TYPE_POWER;
Packit 534379
Packit 534379
			// group name
Packit 534379
			len = strnlen(PWRMGMT, sizeof(group_name) - 1);
Packit 534379
			memcpy(group_name, PWRMGMT, len);
Packit 534379
			group_name[len] = '\0';
Packit 534379
Packit 534379
			//qualifier name
Packit 534379
			if (snprintf(qualifier_name, sizeof(qualifier_name),
Packit 534379
				 "%s:%s", PWRMGMT, metric_name) < 0) {
Packit 534379
				OPAE_ERR("snprintf failed");
Packit 534379
				result = FPGA_EXCEPTION;
Packit 534379
				if (tmp)
Packit 534379
					free(tmp);
Packit 534379
				goto out;
Packit 534379
			}
Packit 534379
Packit 534379
		} else if (tmp && strstr(tmp, TEMPERATURE)) {
Packit 534379
			metric_type = FPGA_METRIC_TYPE_THERMAL;
Packit 534379
Packit 534379
			// group name
Packit 534379
			len = strnlen(THERLGMT, sizeof(group_name) - 1);
Packit 534379
			memcpy(group_name, THERLGMT, len);
Packit 534379
			group_name[len] = '\0';
Packit 534379
Packit 534379
			//qualifier name
Packit 534379
			if (snprintf(qualifier_name, sizeof(qualifier_name),
Packit 534379
				 "%s:%s", THERLGMT, metric_name) < 0) {
Packit 534379
				OPAE_ERR("snprintf failed");
Packit 534379
				result = FPGA_EXCEPTION;
Packit 534379
				if (tmp)
Packit 534379
					free(tmp);
Packit 534379
				goto out;
Packit 534379
			}
Packit 534379
Packit 534379
		} else {
Packit 534379
			printf("FPGA_METRIC_TYPE_UNKNOWN \n");
Packit 534379
			metric_type = FPGA_METRIC_TYPE_UNKNOWN;
Packit 534379
		}
Packit 534379
Packit 534379
		if (tmp) {
Packit 534379
			free(tmp);
Packit 534379
		}
Packit 534379
Packit 534379
		// Metric Units
Packit 534379
		if (strstr(metric_name, POWER)) {
Packit 534379
Packit 534379
			len = strnlen(POWER_UNITS, sizeof(metric_units) - 1);
Packit 534379
			memcpy(metric_units, POWER_UNITS, len);
Packit 534379
			metric_units[len] = '\0';
Packit 534379
Packit 534379
		} else if (strstr(metric_name, VOLTAGE)) {
Packit 534379
Packit 534379
			len = strnlen(VOLTAGE_UNITS, sizeof(metric_units) - 1);
Packit 534379
			memcpy(metric_units, VOLTAGE_UNITS, len);
Packit 534379
			metric_units[len] = '\0';
Packit 534379
Packit 534379
		} else if (strstr(metric_name, CURRENT)) {
Packit 534379
Packit 534379
			len = strnlen(CURRENT_UNITS, sizeof(metric_units) - 1);
Packit 534379
			memcpy(metric_units, CURRENT_UNITS, len);
Packit 534379
			metric_units[len] = '\0';
Packit 534379
Packit 534379
		} else if (strstr(metric_name, TEMPERATURE)) {
Packit 534379
Packit 534379
			len = strnlen(TEMPERATURE_UNITS, sizeof(metric_units) - 1);
Packit 534379
			memcpy(metric_units, TEMPERATURE_UNITS, len);
Packit 534379
			metric_units[len] = '\0';
Packit 534379
Packit 534379
		} else if (strstr(metric_name, CLOCK)) {
Packit 534379
Packit 534379
			len = strnlen(CLOCK_UNITS, sizeof(metric_units) - 1);
Packit 534379
			memcpy(metric_units, CLOCK_UNITS, len);
Packit 534379
			metric_units[len] = '\0';
Packit 534379
Packit 534379
		} else {
Packit 534379
Packit 534379
			strncpy(metric_units, "N/A", 4);
Packit 534379
Packit 534379
		}
Packit 534379
Packit 534379
		// value sysfs path
Packit 534379
		snprintf(metrics_sysfs_path, sizeof(metrics_sysfs_path),
Packit 534379
			 "%s/%s", pglob.gl_pathv[i], SENSOR_SYSFS_VALUE);
Packit 534379
Packit 534379
		result = add_metric_vector(vector, *metric_num, qualifier_name,
Packit 534379
				group_name, group_sysfs, metric_name,
Packit 534379
				metrics_sysfs_path, metric_units,
Packit 534379
				FPGA_METRIC_DATATYPE_DOUBLE, metric_type, hw_type, 0);
Packit 534379
		if (result != FPGA_OK) {
Packit 534379
			OPAE_ERR("Failed to add metrics");
Packit 534379
			goto out;
Packit 534379
		}
Packit 534379
Packit 534379
		*metric_num = *metric_num + 1;
Packit 534379
Packit 534379
	} // end for loop
Packit 534379
Packit 534379
out:
Packit 534379
	globfree(&pglob);
Packit 534379
	return result;
Packit 534379
}
Packit 534379
Packit 534379
Packit 534379
Packit 534379
fpga_result read_max10_value(struct _fpga_enum_metric *_fpga_enum_metric,
Packit 534379
					double *dvalue)
Packit 534379
{
Packit 534379
	fpga_result result     = FPGA_OK;
Packit 534379
	uint64_t value         = 0;
Packit 534379
Packit 534379
	if (_fpga_enum_metric == NULL ||
Packit 534379
		dvalue == NULL) {
Packit 534379
		OPAE_ERR("Invalid Input Parameters");
Packit 534379
		return FPGA_INVALID_PARAM;
Packit 534379
	}
Packit 534379
Packit 534379
	result = sysfs_read_u64(_fpga_enum_metric->metric_sysfs, &value);
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		OPAE_MSG("Failed to read Metrics values");
Packit 534379
		return result;
Packit 534379
	}
Packit 534379
Packit 534379
	*dvalue = ((double)value / MILLI);
Packit 534379
Packit 534379
	// Check for limits
Packit 534379
	if (strstr(_fpga_enum_metric->metric_name, POWER)) {
Packit 534379
Packit 534379
		if (*dvalue  < POWER_LOW_LIMIT || *dvalue  > POWER_HIGH_LIMIT)
Packit 534379
			result = FPGA_EXCEPTION;
Packit 534379
Packit 534379
	} else if (strstr(_fpga_enum_metric->metric_name, VOLTAGE)) {
Packit 534379
Packit 534379
		if (*dvalue < VOLTAMP_LOW_LIMIT || *dvalue > VOLTAMP_HIGH_LIMIT)
Packit 534379
			result = FPGA_EXCEPTION;
Packit 534379
Packit 534379
	} else if (strstr(_fpga_enum_metric->metric_name, CURRENT)) {
Packit 534379
Packit 534379
		if (*dvalue < VOLTAMP_LOW_LIMIT || *dvalue > VOLTAMP_HIGH_LIMIT)
Packit 534379
			result = FPGA_EXCEPTION;
Packit 534379
Packit 534379
	} else if (strstr(_fpga_enum_metric->metric_name, TEMPERATURE)) {
Packit 534379
Packit 534379
		if (*dvalue < THERMAL_LOW_LIMIT || *dvalue > THERMAL_HIGH_LIMIT)
Packit 534379
			result = FPGA_EXCEPTION;
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	return result;
Packit 534379
}