Blame tools/fpgad/plugins/fpgad-vc/fpgad-vc.c

Packit 6639f8
// Copyright(c) 2019-2020, Intel Corporation
Packit 6639f8
//
Packit 6639f8
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 6639f8
// modification, are permitted provided that the following conditions are met:
Packit 6639f8
//
Packit 6639f8
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 6639f8
//   this list of conditions and the following disclaimer.
Packit 6639f8
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 6639f8
//   this list of conditions and the following disclaimer in the documentation
Packit 6639f8
//   and/or other materials provided with the distribution.
Packit 6639f8
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 6639f8
//   may be used to  endorse or promote  products derived  from this  software
Packit 6639f8
//   without specific prior written permission.
Packit 6639f8
//
Packit 6639f8
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 6639f8
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 6639f8
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 6639f8
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 6639f8
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 6639f8
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 6639f8
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 6639f8
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 6639f8
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 6639f8
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 6639f8
// POSSIBILITY OF SUCH DAMAGE.
Packit 6639f8
Packit 6639f8
#ifdef HAVE_CONFIG_H
Packit 6639f8
#include <config.h>
Packit 6639f8
#endif // HAVE_CONFIG_H
Packit 6639f8
Packit 6639f8
#include <glob.h>
Packit 6639f8
#include <json-c/json.h>
Packit 6639f8
Packit 6639f8
#include "fpgad/api/opae_events_api.h"
Packit 6639f8
#include "fpgad/api/device_monitoring.h"
Packit 6639f8
#include "fpgad/api/sysfs.h"
Packit 6639f8
Packit 6639f8
#ifdef LOG
Packit 6639f8
#undef LOG
Packit 6639f8
#endif
Packit 6639f8
#define LOG(format, ...) \
Packit 6639f8
log_printf("fpgad-vc: " format, ##__VA_ARGS__)
Packit 6639f8
Packit 6639f8
#define SYSFS_PATH_MAX 256
Packit 6639f8
Packit 6639f8
#define TRIM_LOG_MODULUS 20
Packit 6639f8
#define LOG_MOD(__r, __fmt, ...) \
Packit 6639f8
do { \
Packit 6639f8
\
Packit 6639f8
	++(__r); \
Packit 6639f8
	if (!((__r) % TRIM_LOG_MODULUS)) { \
Packit 6639f8
		log_printf("fpgad-vc: " __fmt, ##__VA_ARGS__); \
Packit 6639f8
	} \
Packit 6639f8
} while (0)
Packit 6639f8
Packit 6639f8
Packit 6639f8
typedef struct _vc_sensor {
Packit 6639f8
	fpga_object sensor_object;
Packit 6639f8
	char *name;
Packit 6639f8
	char *type;
Packit 6639f8
	uint64_t id;
Packit 6639f8
	fpga_object value_object;
Packit 6639f8
	uint64_t value;
Packit 6639f8
	uint64_t high_fatal;
Packit 6639f8
	uint64_t high_warn;
Packit 6639f8
	uint64_t low_fatal;
Packit 6639f8
	uint64_t low_warn;
Packit 6639f8
	uint32_t flags;
Packit 6639f8
#define FPGAD_SENSOR_VC_IGNORE           0x00000001
Packit 6639f8
#define FPGAD_SENSOR_VC_HIGH_FATAL_VALID 0x00000002
Packit 6639f8
#define FPGAD_SENSOR_VC_HIGH_WARN_VALID  0x00000004
Packit 6639f8
#define FPGAD_SENSOR_VC_LOW_FATAL_VALID  0x00000008
Packit 6639f8
#define FPGAD_SENSOR_VC_LOW_WARN_VALID   0x00000010
Packit 6639f8
	uint32_t read_errors;
Packit 6639f8
#define FPGAD_SENSOR_VC_MAX_READ_ERRORS  25
Packit 6639f8
} vc_sensor;
Packit 6639f8
Packit 6639f8
typedef struct _vc_config_sensor {
Packit 6639f8
	uint64_t id;
Packit 6639f8
	uint64_t high_fatal;
Packit 6639f8
	uint64_t high_warn;
Packit 6639f8
	uint64_t low_fatal;
Packit 6639f8
	uint64_t low_warn;
Packit 6639f8
	uint32_t flags;
Packit 6639f8
} vc_config_sensor;
Packit 6639f8
Packit 6639f8
#define MAX_VC_SENSORS 128
Packit 6639f8
typedef struct _vc_device {
Packit 6639f8
	fpgad_monitored_device *base_device;
Packit 6639f8
	fpga_object group_object;
Packit 6639f8
	vc_sensor sensors[MAX_VC_SENSORS];
Packit 6639f8
	uint32_t num_sensors;
Packit 6639f8
	uint64_t max_sensor_id;
Packit 6639f8
	uint8_t *state_tripped; // bit set
Packit 6639f8
	uint8_t *state_last;    // bit set
Packit 6639f8
	uint64_t tripped_count;
Packit 6639f8
	uint32_t num_config_sensors;
Packit 6639f8
	vc_config_sensor *config_sensors;
Packit 6639f8
	bool aer_disabled;
Packit 6639f8
	uint32_t previous_ecap_aer[2];
Packit 6639f8
} vc_device;
Packit 6639f8
Packit 6639f8
#define BIT_SET_MASK(__n)  (1 << ((__n) % 8))
Packit 6639f8
#define BIT_SET_INDEX(__n) ((__n) / 8)
Packit 6639f8
Packit 6639f8
#define BIT_SET_SET(__s, __n) \
Packit 6639f8
((__s)[BIT_SET_INDEX(__n)] |= BIT_SET_MASK(__n))
Packit 6639f8
Packit 6639f8
#define BIT_SET_CLR(__s, __n) \
Packit 6639f8
((__s)[BIT_SET_INDEX(__n)] &= ~BIT_SET_MASK(__n))
Packit 6639f8
Packit 6639f8
#define BIT_IS_SET(__s, __n) \
Packit 6639f8
((__s)[BIT_SET_INDEX(__n)] & BIT_SET_MASK(__n))
Packit 6639f8
Packit 6639f8
Packit 6639f8
#define HIGH_FATAL(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_HIGH_FATAL_VALID) && \
Packit 6639f8
 ((__sens)->value > (__sens)->high_fatal))
Packit 6639f8
Packit 6639f8
#define HIGH_WARN(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_HIGH_WARN_VALID) && \
Packit 6639f8
 ((__sens)->value > (__sens)->high_warn))
Packit 6639f8
Packit 6639f8
#define HIGH_NORMAL(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_HIGH_WARN_VALID) && \
Packit 6639f8
 ((__sens)->value <= (__sens)->high_warn))
Packit 6639f8
Packit 6639f8
#define LOW_FATAL(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_LOW_FATAL_VALID) && \
Packit 6639f8
 ((__sens)->value < (__sens)->low_fatal))
Packit 6639f8
Packit 6639f8
#define LOW_WARN(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_LOW_WARN_VALID) && \
Packit 6639f8
 ((__sens)->value < (__sens)->low_warn))
Packit 6639f8
Packit 6639f8
#define LOW_NORMAL(__sens) \
Packit 6639f8
(((__sens)->flags & FPGAD_SENSOR_VC_LOW_WARN_VALID) && \
Packit 6639f8
 ((__sens)->value >= (__sens)->low_warn))
Packit 6639f8
Packit 6639f8
STATIC bool vc_threads_running = true;
Packit 6639f8
Packit 6639f8
STATIC void stop_vc_threads(void)
Packit 6639f8
{
Packit 6639f8
	vc_threads_running = false;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC void vc_destroy_sensor(vc_sensor *sensor)
Packit 6639f8
{
Packit 6639f8
	fpgaDestroyObject(&sensor->sensor_object);
Packit 6639f8
	if (sensor->name) {
Packit 6639f8
		free(sensor->name);
Packit 6639f8
		sensor->name = NULL;
Packit 6639f8
	}
Packit 6639f8
	if (sensor->type) {
Packit 6639f8
		free(sensor->type);
Packit 6639f8
		sensor->type = NULL;
Packit 6639f8
	}
Packit 6639f8
	if (sensor->value_object) {
Packit 6639f8
		fpgaDestroyObject(&sensor->value_object);
Packit 6639f8
		sensor->value_object = NULL;
Packit 6639f8
	}
Packit 6639f8
	sensor->flags = 0;
Packit 6639f8
	sensor->read_errors = 0;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC void vc_destroy_sensors(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	uint32_t i;
Packit 6639f8
Packit 6639f8
	for (i = 0 ; i < vc->num_sensors ; ++i) {
Packit 6639f8
		vc_destroy_sensor(&vc->sensors[i]);
Packit 6639f8
	}
Packit 6639f8
	vc->num_sensors = 0;
Packit 6639f8
	vc->max_sensor_id = 0;
Packit 6639f8
Packit 6639f8
	if (vc->group_object) {
Packit 6639f8
		fpgaDestroyObject(&vc->group_object);
Packit 6639f8
		vc->group_object = NULL;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (vc->state_tripped) {
Packit 6639f8
		free(vc->state_tripped);
Packit 6639f8
		vc->state_tripped = NULL;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (vc->state_last) {
Packit 6639f8
		free(vc->state_last);
Packit 6639f8
		vc->state_last = NULL;
Packit 6639f8
	}
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC void vc_destroy_device(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	vc_destroy_sensors(vc);
Packit 6639f8
	if (vc->config_sensors) {
Packit 6639f8
		free(vc->config_sensors);
Packit 6639f8
		vc->config_sensors = NULL;
Packit 6639f8
		vc->num_config_sensors = 0;
Packit 6639f8
	}
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_sensor_get_string(vc_sensor *sensor,
Packit 6639f8
					const char *obj_name,
Packit 6639f8
					char **name)
Packit 6639f8
{
Packit 6639f8
	fpga_result res;
Packit 6639f8
	fpga_object obj = NULL;
Packit 6639f8
	char buf[SYSFS_PATH_MAX] = { 0, };
Packit 6639f8
	uint32_t len = 0;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectGetObject(sensor->sensor_object,
Packit 6639f8
				  obj_name,
Packit 6639f8
				  &obj,
Packit 6639f8
				  0);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectGetSize(obj, &len, 0);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		goto out_free_obj;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectRead(obj, (uint8_t *)buf, 0, len, 0);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		goto out_free_obj;
Packit 6639f8
Packit 6639f8
	if (buf[len-1] == '\n')
Packit 6639f8
		buf[len-1] = '\0';
Packit 6639f8
Packit 6639f8
	*name = cstr_dup((const char *)buf);
Packit 6639f8
	if (!(*name))
Packit 6639f8
		res = FPGA_NO_MEMORY;
Packit 6639f8
Packit 6639f8
out_free_obj:
Packit 6639f8
	fpgaDestroyObject(&obj);
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_sensor_get_u64(vc_sensor *sensor,
Packit 6639f8
				     const char *obj_name,
Packit 6639f8
				     uint64_t *value)
Packit 6639f8
{
Packit 6639f8
	fpga_result res;
Packit 6639f8
	fpga_object obj = NULL;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectGetObject(sensor->sensor_object,
Packit 6639f8
				  obj_name,
Packit 6639f8
				  &obj,
Packit 6639f8
				  0);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectRead64(obj, value, 0);
Packit 6639f8
Packit 6639f8
	fpgaDestroyObject(&obj);
Packit 6639f8
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
// The percentage by which we adjust the power trip
Packit 6639f8
// points so that we catch anomolies before the hw does.
Packit 6639f8
#define VC_PERCENT_ADJUST_PWR 5
Packit 6639f8
// The number of degrees by which we adjust the
Packit 6639f8
// temperature trip points so that we catch anomolies
Packit 6639f8
// before the hw does.
Packit 6639f8
#define VC_DEGREES_ADJUST_TEMP 5
Packit 6639f8
STATIC fpga_result vc_sensor_get(vc_device *vc, vc_sensor *s)
Packit 6639f8
{
Packit 6639f8
	fpga_result res;
Packit 6639f8
	bool is_temperature;
Packit 6639f8
	int indicator = -1;
Packit 6639f8
	vc_config_sensor *cfg_sensor = NULL;
Packit 6639f8
	uint32_t i;
Packit 6639f8
Packit 6639f8
	if (s->name) {
Packit 6639f8
		free(s->name);
Packit 6639f8
		s->name = NULL;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (s->type) {
Packit 6639f8
		free(s->type);
Packit 6639f8
		s->type = NULL;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_string(s, "name", &s->name);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_string(s, "type", &s->type);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_u64(s, "id", &s->id);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectRead64(s->value_object, &s->value, 0);
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	indicator = strcmp(s->type, "Temperature");
Packit 6639f8
	is_temperature = (indicator == 0);
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_u64(s, "high_fatal", &s->high_fatal);
Packit 6639f8
	if (res == FPGA_OK) {
Packit 6639f8
		s->flags |= FPGAD_SENSOR_VC_HIGH_FATAL_VALID;
Packit 6639f8
		if (is_temperature)
Packit 6639f8
			s->high_fatal -= VC_DEGREES_ADJUST_TEMP;
Packit 6639f8
		else
Packit 6639f8
			s->high_fatal -=
Packit 6639f8
				(s->high_fatal * VC_PERCENT_ADJUST_PWR) / 100;
Packit 6639f8
	} else
Packit 6639f8
		s->flags &= ~FPGAD_SENSOR_VC_HIGH_FATAL_VALID;
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_u64(s, "high_warn", &s->high_warn);
Packit 6639f8
	if (res == FPGA_OK)
Packit 6639f8
		s->flags |= FPGAD_SENSOR_VC_HIGH_WARN_VALID;
Packit 6639f8
	else
Packit 6639f8
		s->flags &= ~FPGAD_SENSOR_VC_HIGH_WARN_VALID;
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_u64(s, "low_fatal", &s->low_fatal);
Packit 6639f8
	if (res == FPGA_OK) {
Packit 6639f8
		s->flags |= FPGAD_SENSOR_VC_LOW_FATAL_VALID;
Packit 6639f8
		if (is_temperature)
Packit 6639f8
			s->low_fatal += VC_DEGREES_ADJUST_TEMP;
Packit 6639f8
		else
Packit 6639f8
			s->low_fatal +=
Packit 6639f8
				(s->low_fatal * VC_PERCENT_ADJUST_PWR) / 100;
Packit 6639f8
	} else
Packit 6639f8
		s->flags &= ~FPGAD_SENSOR_VC_LOW_FATAL_VALID;
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get_u64(s, "low_warn", &s->low_warn);
Packit 6639f8
	if (res == FPGA_OK)
Packit 6639f8
		s->flags |= FPGAD_SENSOR_VC_LOW_WARN_VALID;
Packit 6639f8
	else
Packit 6639f8
		s->flags &= ~FPGAD_SENSOR_VC_LOW_WARN_VALID;
Packit 6639f8
Packit 6639f8
	/* Do we have a user override (via the config) for
Packit 6639f8
	 * this sensor? If so, then honor it.
Packit 6639f8
	 */
Packit 6639f8
	for (i = 0 ; i < vc->num_config_sensors ; ++i) {
Packit 6639f8
		if (vc->config_sensors[i].flags &
Packit 6639f8
		    FPGAD_SENSOR_VC_IGNORE)
Packit 6639f8
			continue;
Packit 6639f8
		if (vc->config_sensors[i].id == s->id) {
Packit 6639f8
			cfg_sensor = &vc->config_sensors[i];
Packit 6639f8
			break;
Packit 6639f8
		}
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (cfg_sensor) {
Packit 6639f8
Packit 6639f8
		if (cfg_sensor->flags & FPGAD_SENSOR_VC_HIGH_FATAL_VALID) {
Packit 6639f8
			// Cap the sensor at the adjusted max
Packit 6639f8
			// allowed by the hardware.
Packit 6639f8
			if ((s->flags & FPGAD_SENSOR_VC_HIGH_FATAL_VALID) &&
Packit 6639f8
			    (cfg_sensor->high_fatal > s->high_fatal))
Packit 6639f8
				/* nothing */ ;
Packit 6639f8
			else
Packit 6639f8
				s->high_fatal = cfg_sensor->high_fatal;
Packit 6639f8
Packit 6639f8
			s->flags |= FPGAD_SENSOR_VC_HIGH_FATAL_VALID;
Packit 6639f8
		} else
Packit 6639f8
			s->flags &= ~FPGAD_SENSOR_VC_HIGH_FATAL_VALID;
Packit 6639f8
Packit 6639f8
		if (cfg_sensor->flags & FPGAD_SENSOR_VC_HIGH_WARN_VALID) {
Packit 6639f8
Packit 6639f8
			if ((s->flags & FPGAD_SENSOR_VC_HIGH_WARN_VALID) &&
Packit 6639f8
			    (cfg_sensor->high_warn > s->high_warn))
Packit 6639f8
				/* nothing */ ;
Packit 6639f8
			else
Packit 6639f8
				s->high_warn = cfg_sensor->high_warn;
Packit 6639f8
Packit 6639f8
			s->flags |= FPGAD_SENSOR_VC_HIGH_WARN_VALID;
Packit 6639f8
		} else
Packit 6639f8
			s->flags &= ~FPGAD_SENSOR_VC_HIGH_WARN_VALID;
Packit 6639f8
Packit 6639f8
		if (cfg_sensor->flags & FPGAD_SENSOR_VC_LOW_FATAL_VALID) {
Packit 6639f8
Packit 6639f8
			if ((s->flags & FPGAD_SENSOR_VC_LOW_FATAL_VALID) &&
Packit 6639f8
			    (cfg_sensor->low_fatal < s->low_fatal))
Packit 6639f8
				/* nothing */ ;
Packit 6639f8
			else
Packit 6639f8
				s->low_fatal = cfg_sensor->low_fatal;
Packit 6639f8
Packit 6639f8
			s->flags |= FPGAD_SENSOR_VC_LOW_FATAL_VALID;
Packit 6639f8
		} else
Packit 6639f8
			s->flags &= ~FPGAD_SENSOR_VC_LOW_FATAL_VALID;
Packit 6639f8
Packit 6639f8
		if (cfg_sensor->flags & FPGAD_SENSOR_VC_LOW_WARN_VALID) {
Packit 6639f8
Packit 6639f8
			if ((s->flags & FPGAD_SENSOR_VC_LOW_WARN_VALID) &&
Packit 6639f8
			    (cfg_sensor->low_warn < s->low_warn))
Packit 6639f8
				/* nothing */ ;
Packit 6639f8
			else
Packit 6639f8
				s->low_warn = cfg_sensor->low_warn;
Packit 6639f8
Packit 6639f8
			s->flags |= FPGAD_SENSOR_VC_LOW_WARN_VALID;
Packit 6639f8
		} else
Packit 6639f8
			s->flags &= ~FPGAD_SENSOR_VC_LOW_WARN_VALID;
Packit 6639f8
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	return FPGA_OK;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_enum_sensor(vc_device *vc,
Packit 6639f8
				  const char *name)
Packit 6639f8
{
Packit 6639f8
	fpga_result res;
Packit 6639f8
	vc_sensor *s;
Packit 6639f8
Packit 6639f8
	if (vc->num_sensors == MAX_VC_SENSORS) {
Packit 6639f8
		LOG("exceeded max number of sensors.\n");
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	s = &vc->sensors[vc->num_sensors];
Packit 6639f8
Packit 6639f8
	res = fpgaObjectGetObject(vc->group_object,
Packit 6639f8
				  name,
Packit 6639f8
				  &s->sensor_object,
Packit 6639f8
				  0);
Packit 6639f8
Packit 6639f8
	if (res != FPGA_OK)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	res = fpgaObjectGetObject(s->sensor_object,
Packit 6639f8
				  "value",
Packit 6639f8
				  &s->value_object,
Packit 6639f8
				  0);
Packit 6639f8
Packit 6639f8
	if (res != FPGA_OK) {
Packit 6639f8
		LOG("failed to get value object for %s.\n", name);
Packit 6639f8
		fpgaDestroyObject(&s->sensor_object);
Packit 6639f8
		return res;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	res = vc_sensor_get(vc, s);
Packit 6639f8
	if (res == FPGA_OK)
Packit 6639f8
		++vc->num_sensors;
Packit 6639f8
	else {
Packit 6639f8
		LOG("warning: sensor attribute enumeration failed.\n");
Packit 6639f8
		vc_destroy_sensor(s);
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_enum_sensors(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	fpga_result res;
Packit 6639f8
	char name[SYSFS_PATH_MAX];
Packit 6639f8
	int i;
Packit 6639f8
Packit 6639f8
	res = fpgaTokenGetObject(vc->base_device->token,
Packit 6639f8
				 "spi-altera.*.auto/spi_master/spi*/spi*.*",
Packit 6639f8
				 &vc->group_object,
Packit 6639f8
				 FPGA_OBJECT_GLOB);
Packit 6639f8
	if (res)
Packit 6639f8
		return res;
Packit 6639f8
Packit 6639f8
	for (i = 0 ; i < MAX_VC_SENSORS ; ++i) {
Packit 6639f8
		snprintf(name, sizeof(name), "sensor%d", i);
Packit 6639f8
		vc_enum_sensor(vc, name);
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (vc->num_sensors > 0) {
Packit 6639f8
		vc_sensor *s = &vc->sensors[vc->num_sensors - 1];
Packit 6639f8
Packit 6639f8
		vc->max_sensor_id = s->id;
Packit 6639f8
Packit 6639f8
		vc->state_tripped = calloc((vc->max_sensor_id + 7) / 8, 1);
Packit 6639f8
		vc->state_last = calloc((vc->max_sensor_id + 7) / 8, 1);
Packit 6639f8
Packit 6639f8
		return (vc->state_tripped && vc->state_last) ?
Packit 6639f8
			FPGA_OK : FPGA_NO_MEMORY;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	return FPGA_NOT_FOUND;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_disable_aer(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	fpga_token token;
Packit 6639f8
	fpga_result res;
Packit 6639f8
	fpga_properties prop = NULL;
Packit 6639f8
	char path[PATH_MAX];
Packit 6639f8
	char rlpath[PATH_MAX];
Packit 6639f8
	char *p;
Packit 6639f8
	char cmd[256];
Packit 6639f8
	char output[256];
Packit 6639f8
	FILE *fp;
Packit 6639f8
	size_t sz;
Packit 6639f8
Packit 6639f8
	uint16_t seg = 0;
Packit 6639f8
	uint8_t bus = 0;
Packit 6639f8
	uint8_t dev = 0;
Packit 6639f8
	uint8_t fn = 0;
Packit 6639f8
Packit 6639f8
	token = vc->base_device->token;
Packit 6639f8
Packit 6639f8
	res = fpgaGetProperties(token, &prop);
Packit 6639f8
	if (res != FPGA_OK) {
Packit 6639f8
		LOG("failed to get fpga properties.\n");
Packit 6639f8
		return res;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if ((fpgaPropertiesGetSegment(prop, &seg) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetBus(prop, &bus) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetDevice(prop, &dev) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetFunction(prop, &fn) != FPGA_OK)) {
Packit 6639f8
		LOG("failed to get PCI attributes.\n");
Packit 6639f8
		fpgaDestroyProperties(&prop);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	fpgaDestroyProperties(&prop);
Packit 6639f8
Packit 6639f8
	snprintf(path, sizeof(path),
Packit 6639f8
			"/sys/bus/pci/devices/%04x:%02x:%02x.%d",
Packit 6639f8
			(int)seg, (int)bus, (int)dev, (int)fn);
Packit 6639f8
Packit 6639f8
	memset(rlpath, 0, sizeof(rlpath));
Packit 6639f8
Packit 6639f8
	if (readlink(path, rlpath, sizeof(rlpath)) < 0) {
Packit 6639f8
		LOG("readlink \"%s\" failed.\n", path);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	// (rlpath)
Packit 6639f8
	//                    1111111111
Packit 6639f8
	//          01234567890123456789
Packit 6639f8
	// ../../../devices/pci0000:ae/0000:ae:00.0/0000:af:00.0/
Packit 6639f8
	// 0000:b0:09.0/0000:b2:00.0
Packit 6639f8
Packit 6639f8
	p = strstr(rlpath, "devices/pci");
Packit 6639f8
Packit 6639f8
	p += 19;
Packit 6639f8
	*(p + 12) = '\0';
Packit 6639f8
Packit 6639f8
	// Save the current ECAP_AER values.
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x08.L", p);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to read ECAP_AER+0x08 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	sz = fread(output, 1, sizeof(output), fp);
Packit 6639f8
Packit 6639f8
	if (sz >= sizeof(output))
Packit 6639f8
		sz = sizeof(output) - 1;
Packit 6639f8
	output[sz] = '\0';
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	vc->previous_ecap_aer[0] = strtoul(output, NULL, 16);
Packit 6639f8
Packit 6639f8
	LOG("saving previous ECAP_AER+0x08 value 0x%08x for %s\n",
Packit 6639f8
	    vc->previous_ecap_aer[0], p);
Packit 6639f8
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x14.L", p);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to read ECAP_AER+0x14 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	sz = fread(output, 1, sizeof(output), fp);
Packit 6639f8
Packit 6639f8
	if (sz >= sizeof(output))
Packit 6639f8
		sz = sizeof(output) - 1;
Packit 6639f8
	output[sz] = '\0';
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	vc->previous_ecap_aer[1] = strtoul(output, NULL, 16);
Packit 6639f8
Packit 6639f8
	LOG("saving previous ECAP_AER+0x14 value 0x%08x for %s\n",
Packit 6639f8
	    vc->previous_ecap_aer[1], p);
Packit 6639f8
Packit 6639f8
Packit 6639f8
	// Disable AER.
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x08.L=0xffffffff", p);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to write ECAP_AER+0x08 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x14.L=0xffffffff", p);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to write ECAP_AER+0x14 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	return FPGA_OK;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC fpga_result vc_enable_aer(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	fpga_token token;
Packit 6639f8
	fpga_result res;
Packit 6639f8
	fpga_properties prop = NULL;
Packit 6639f8
	char path[PATH_MAX];
Packit 6639f8
	char rlpath[PATH_MAX];
Packit 6639f8
	char *p;
Packit 6639f8
	char cmd[256];
Packit 6639f8
	FILE *fp;
Packit 6639f8
Packit 6639f8
	uint16_t seg = 0;
Packit 6639f8
	uint8_t bus = 0;
Packit 6639f8
	uint8_t dev = 0;
Packit 6639f8
	uint8_t fn = 0;
Packit 6639f8
Packit 6639f8
	token = vc->base_device->token;
Packit 6639f8
Packit 6639f8
	res = fpgaGetProperties(token, &prop);
Packit 6639f8
	if (res != FPGA_OK) {
Packit 6639f8
		LOG("failed to get fpga properties.\n");
Packit 6639f8
		return res;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if ((fpgaPropertiesGetSegment(prop, &seg) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetBus(prop, &bus) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetDevice(prop, &dev) != FPGA_OK) ||
Packit 6639f8
	    (fpgaPropertiesGetFunction(prop, &fn) != FPGA_OK)) {
Packit 6639f8
		LOG("failed to get PCI attributes.\n");
Packit 6639f8
		fpgaDestroyProperties(&prop);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	fpgaDestroyProperties(&prop);
Packit 6639f8
Packit 6639f8
	snprintf(path, sizeof(path),
Packit 6639f8
			"/sys/bus/pci/devices/%04x:%02x:%02x.%d",
Packit 6639f8
			(int)seg, (int)bus, (int)dev, (int)fn);
Packit 6639f8
Packit 6639f8
	memset(rlpath, 0, sizeof(rlpath));
Packit 6639f8
Packit 6639f8
	if (readlink(path, rlpath, sizeof(rlpath)) < 0) {
Packit 6639f8
		LOG("readlink \"%s\" failed.\n", path);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	// (rlpath)
Packit 6639f8
	//                    1111111111
Packit 6639f8
	//          01234567890123456789
Packit 6639f8
	// ../../../devices/pci0000:ae/0000:ae:00.0/0000:af:00.0/
Packit 6639f8
	// 0000:b0:09.0/0000:b2:00.0
Packit 6639f8
Packit 6639f8
	p = strstr(rlpath, "devices/pci");
Packit 6639f8
Packit 6639f8
	p += 19;
Packit 6639f8
	*(p + 12) = '\0';
Packit 6639f8
Packit 6639f8
	// Write the saved ECAP_AER values to enable AER.
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x08.L=0x%08x",
Packit 6639f8
		      p, vc->previous_ecap_aer[0]);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to write ECAP_AER+0x08 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	LOG("restored previous ECAP_AER+0x08 value 0x%08x for %s\n",
Packit 6639f8
	    vc->previous_ecap_aer[0], p);
Packit 6639f8
Packit 6639f8
Packit 6639f8
	snprintf(cmd, sizeof(cmd),
Packit 6639f8
		      "setpci -s %s ECAP_AER+0x14.L=0x%08x",
Packit 6639f8
		      p, vc->previous_ecap_aer[1]);
Packit 6639f8
Packit 6639f8
	fp = popen(cmd, "r");
Packit 6639f8
	if (!fp) {
Packit 6639f8
		LOG("failed to write ECAP_AER+0x14 for %s\n", p);
Packit 6639f8
		return FPGA_EXCEPTION;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	pclose(fp);
Packit 6639f8
Packit 6639f8
	LOG("restored previous ECAP_AER+0x14 value 0x%08x for %s\n",
Packit 6639f8
	    vc->previous_ecap_aer[1], p);
Packit 6639f8
Packit 6639f8
	return FPGA_OK;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC bool vc_monitor_sensors(vc_device *vc)
Packit 6639f8
{
Packit 6639f8
	uint32_t i;
Packit 6639f8
	uint32_t monitoring = 0;
Packit 6639f8
	bool negative_trans = false;
Packit 6639f8
	bool res = true;
Packit 6639f8
Packit 6639f8
	for (i = 0 ; i < vc->num_sensors ; ++i) {
Packit 6639f8
		vc_sensor *s = &vc->sensors[i];
Packit 6639f8
Packit 6639f8
		if (s->flags & FPGAD_SENSOR_VC_IGNORE)
Packit 6639f8
			continue;
Packit 6639f8
Packit 6639f8
		if (s->flags & (FPGAD_SENSOR_VC_HIGH_WARN_VALID|
Packit 6639f8
				FPGAD_SENSOR_VC_LOW_WARN_VALID))
Packit 6639f8
			++monitoring;
Packit 6639f8
Packit 6639f8
		if (fpgaObjectRead64(s->value_object,
Packit 6639f8
				     &s->value,
Packit 6639f8
				     FPGA_OBJECT_SYNC) != FPGA_OK) {
Packit 6639f8
			if (++s->read_errors >=
Packit 6639f8
				FPGAD_SENSOR_VC_MAX_READ_ERRORS)
Packit 6639f8
				s->flags |= FPGAD_SENSOR_VC_IGNORE;
Packit 6639f8
			continue;
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (HIGH_WARN(s) || LOW_WARN(s)) {
Packit 6639f8
			opae_api_send_EVENT_POWER_THERMAL(vc->base_device);
Packit 6639f8
			BIT_SET_SET(vc->state_tripped, s->id);
Packit 6639f8
			if (!BIT_IS_SET(vc->state_last, s->id)) {
Packit 6639f8
				LOG("sensor '%s' warning.\n", s->name);
Packit 6639f8
				if (!vc->aer_disabled) {
Packit 6639f8
					if (FPGA_OK == vc_disable_aer(vc))
Packit 6639f8
						vc->aer_disabled = true;
Packit 6639f8
				}
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (HIGH_NORMAL(s) || LOW_NORMAL(s)) {
Packit 6639f8
			if (BIT_IS_SET(vc->state_last, s->id)) {
Packit 6639f8
				negative_trans = true;
Packit 6639f8
				LOG("sensor '%s' back to normal.\n", s->name);
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (BIT_IS_SET(vc->state_last, s->id) &&
Packit 6639f8
		    BIT_IS_SET(vc->state_tripped, s->id)) {
Packit 6639f8
			LOG_MOD(vc->tripped_count,
Packit 6639f8
				"sensor '%s' still tripped.\n", s->name);
Packit 6639f8
		}
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (negative_trans) {
Packit 6639f8
		for (i = 0 ; i < vc->num_sensors ; ++i) {
Packit 6639f8
			if (BIT_IS_SET(vc->state_tripped, vc->sensors[i].id))
Packit 6639f8
				break;
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (i == vc->num_sensors) {
Packit 6639f8
			// no remaining tripped sensors
Packit 6639f8
			vc->tripped_count = 0;
Packit 6639f8
			if (vc->aer_disabled) {
Packit 6639f8
				if (FPGA_OK == vc_enable_aer(vc))
Packit 6639f8
					vc->aer_disabled = false;
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	/*
Packit 6639f8
	** Are we still monitoring any sensor that has a valid
Packit 6639f8
	** high/low warn threshold? If not, then this fn should
Packit 6639f8
	** return false so that we wait for sensor enumeration
Packit 6639f8
	** in the caller. It's possible that we're ignoring all
Packit 6639f8
	** of the sensors because they became unavailable due to
Packit 6639f8
	** driver removal, eg.
Packit 6639f8
	*/
Packit 6639f8
	if (!monitoring)
Packit 6639f8
		res = false;
Packit 6639f8
Packit 6639f8
	for (i = 0 ; i < vc->num_sensors ; ++i) {
Packit 6639f8
		vc_sensor *s = &vc->sensors[i];
Packit 6639f8
		if (BIT_IS_SET(vc->state_tripped, s->id))
Packit 6639f8
			BIT_SET_SET(vc->state_last, s->id);
Packit 6639f8
		else
Packit 6639f8
			BIT_SET_CLR(vc->state_last, s->id);
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	memset(vc->state_tripped, 0, (vc->max_sensor_id + 7) / 8);
Packit 6639f8
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC int cool_down = 30;
Packit 6639f8
Packit 6639f8
STATIC void *monitor_fme_vc_thread(void *arg)
Packit 6639f8
{
Packit 6639f8
	fpgad_monitored_device *d =
Packit 6639f8
		(fpgad_monitored_device *)arg;
Packit 6639f8
Packit 6639f8
	vc_device *vc = (vc_device *)d->thread_context;
Packit 6639f8
Packit 6639f8
	uint32_t enum_retries = 0;
Packit 6639f8
	uint8_t *save_state_last = NULL;
Packit 6639f8
Packit 6639f8
	while (vc_threads_running) {
Packit 6639f8
Packit 6639f8
		while (vc_enum_sensors(vc) != FPGA_OK) {
Packit 6639f8
			LOG_MOD(enum_retries, "waiting to enumerate sensors.\n");
Packit 6639f8
			if (!vc_threads_running)
Packit 6639f8
				return NULL;
Packit 6639f8
			sleep(1);
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (save_state_last) {
Packit 6639f8
			free(vc->state_last);
Packit 6639f8
			vc->state_last = save_state_last;
Packit 6639f8
			save_state_last = NULL;
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		while (vc_monitor_sensors(vc)) {
Packit 6639f8
			usleep(d->config->poll_interval_usec);
Packit 6639f8
Packit 6639f8
			if (!vc_threads_running) {
Packit 6639f8
				vc_destroy_sensors(vc);
Packit 6639f8
				return NULL;
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		save_state_last = vc->state_last;
Packit 6639f8
		vc->state_last = NULL;
Packit 6639f8
Packit 6639f8
		vc_destroy_sensors(vc);
Packit 6639f8
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	return NULL;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
STATIC int vc_parse_config(vc_device *vc, const char *cfg)
Packit 6639f8
{
Packit 6639f8
	json_object *root;
Packit 6639f8
	enum json_tokener_error j_err = json_tokener_success;
Packit 6639f8
	json_object *j_cool_down = NULL;
Packit 6639f8
	json_object *j_config_sensors_enabled = NULL;
Packit 6639f8
	json_object *j_sensors = NULL;
Packit 6639f8
	int res = 1;
Packit 6639f8
	int sensor_entries;
Packit 6639f8
	int i;
Packit 6639f8
Packit 6639f8
	root = json_tokener_parse_verbose(cfg, &j_err);
Packit 6639f8
	if (!root) {
Packit 6639f8
		LOG("error parsing config: %s\n",
Packit 6639f8
		    json_tokener_error_desc(j_err));
Packit 6639f8
		return 1;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_object_get_ex(root,
Packit 6639f8
				       "cool-down",
Packit 6639f8
				       &j_cool_down)) {
Packit 6639f8
		LOG("failed to find cool-down key in config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_is_type(j_cool_down, json_type_int)) {
Packit 6639f8
		LOG("cool-down key not integer.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	cool_down = json_object_get_int(j_cool_down);
Packit 6639f8
	if (cool_down < 0)
Packit 6639f8
		cool_down = 30;
Packit 6639f8
Packit 6639f8
	LOG("set cool-down period to %d seconds.\n", cool_down);
Packit 6639f8
Packit 6639f8
	res = 0;
Packit 6639f8
Packit 6639f8
	if (!json_object_object_get_ex(root,
Packit 6639f8
				       "config-sensors-enabled",
Packit 6639f8
				       &j_config_sensors_enabled)) {
Packit 6639f8
		LOG("failed to find config-sensors-enabled key in config.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_is_type(j_config_sensors_enabled, json_type_boolean)) {
Packit 6639f8
		LOG("config-sensors-enabled key not Boolean.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_get_boolean(j_config_sensors_enabled)) {
Packit 6639f8
		LOG("config-sensors-enabled key set to false.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_object_get_ex(root,
Packit 6639f8
				       "sensors",
Packit 6639f8
				       &j_sensors)) {
Packit 6639f8
		LOG("failed to find sensors key in config.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	if (!json_object_is_type(j_sensors, json_type_array)) {
Packit 6639f8
		LOG("sensors key not array.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	sensor_entries = json_object_array_length(j_sensors);
Packit 6639f8
	if (!sensor_entries) {
Packit 6639f8
		LOG("sensors key is empty array.\n"
Packit 6639f8
		    "Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	vc->config_sensors = calloc(sensor_entries, sizeof(vc_config_sensor));
Packit 6639f8
	if (!vc->config_sensors) {
Packit 6639f8
		LOG("calloc failed. Skipping user sensor config.\n");
Packit 6639f8
		goto out_put;
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	vc->num_config_sensors = (uint32_t)sensor_entries;
Packit 6639f8
Packit 6639f8
	for (i = 0 ; i < sensor_entries ; ++i) {
Packit 6639f8
		json_object *j_sensor_sub_i = json_object_array_get_idx(j_sensors, i);
Packit 6639f8
		json_object *j_id;
Packit 6639f8
		json_object *j_high_fatal;
Packit 6639f8
		json_object *j_high_warn;
Packit 6639f8
		json_object *j_low_fatal;
Packit 6639f8
		json_object *j_low_warn;
Packit 6639f8
Packit 6639f8
		if (!json_object_object_get_ex(j_sensor_sub_i,
Packit 6639f8
					       "id",
Packit 6639f8
					       &j_id)) {
Packit 6639f8
			LOG("failed to find id key in config sensors[%d].\n"
Packit 6639f8
			    "Skipping entry %d.\n", i, i);
Packit 6639f8
			vc->config_sensors[i].id = MAX_VC_SENSORS;
Packit 6639f8
			vc->config_sensors[i].flags = FPGAD_SENSOR_VC_IGNORE;
Packit 6639f8
			continue;
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (!json_object_is_type(j_id, json_type_int)) {
Packit 6639f8
			LOG("sensors[%d].id key not int.\n"
Packit 6639f8
			    "Skipping entry %d.\n", i, i);
Packit 6639f8
			vc->config_sensors[i].id = MAX_VC_SENSORS;
Packit 6639f8
			vc->config_sensors[i].flags = FPGAD_SENSOR_VC_IGNORE;
Packit 6639f8
			continue;
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		vc->config_sensors[i].id = json_object_get_int(j_id);
Packit 6639f8
Packit 6639f8
		if (json_object_object_get_ex(j_sensor_sub_i,
Packit 6639f8
					      "high-fatal",
Packit 6639f8
					      &j_high_fatal)) {
Packit 6639f8
			if (json_object_is_type(j_high_fatal,
Packit 6639f8
						json_type_double)) {
Packit 6639f8
				vc->config_sensors[i].high_fatal =
Packit 6639f8
				(uint64_t)(json_object_get_double(j_high_fatal)
Packit 6639f8
					* 1000.0);
Packit 6639f8
				vc->config_sensors[i].flags |=
Packit 6639f8
					FPGAD_SENSOR_VC_HIGH_FATAL_VALID;
Packit 6639f8
				LOG("user sensor%u high-fatal: %f\n",
Packit 6639f8
				    vc->config_sensors[i].id,
Packit 6639f8
				    json_object_get_double(j_high_fatal));
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (json_object_object_get_ex(j_sensor_sub_i,
Packit 6639f8
					      "high-warn",
Packit 6639f8
					      &j_high_warn)) {
Packit 6639f8
			if (json_object_is_type(j_high_warn,
Packit 6639f8
						json_type_double)) {
Packit 6639f8
				vc->config_sensors[i].high_warn =
Packit 6639f8
				(uint64_t)(json_object_get_double(j_high_warn)
Packit 6639f8
					* 1000.0);
Packit 6639f8
				vc->config_sensors[i].flags |=
Packit 6639f8
					FPGAD_SENSOR_VC_HIGH_WARN_VALID;
Packit 6639f8
				LOG("user sensor%u high-warn: %f\n",
Packit 6639f8
				    vc->config_sensors[i].id,
Packit 6639f8
				    json_object_get_double(j_high_warn));
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (json_object_object_get_ex(j_sensor_sub_i,
Packit 6639f8
					      "low-fatal",
Packit 6639f8
					      &j_low_fatal)) {
Packit 6639f8
			if (json_object_is_type(j_low_fatal,
Packit 6639f8
						json_type_double)) {
Packit 6639f8
				vc->config_sensors[i].low_fatal =
Packit 6639f8
				(uint64_t)(json_object_get_double(j_low_fatal)
Packit 6639f8
					* 1000.0);
Packit 6639f8
				vc->config_sensors[i].flags |=
Packit 6639f8
					FPGAD_SENSOR_VC_LOW_FATAL_VALID;
Packit 6639f8
				LOG("user sensor%u low-fatal: %f\n",
Packit 6639f8
				    vc->config_sensors[i].id,
Packit 6639f8
				    json_object_get_double(j_low_fatal));
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
		if (json_object_object_get_ex(j_sensor_sub_i,
Packit 6639f8
					      "low-warn",
Packit 6639f8
					      &j_low_warn)) {
Packit 6639f8
			if (json_object_is_type(j_low_warn,
Packit 6639f8
						json_type_double)) {
Packit 6639f8
				vc->config_sensors[i].low_warn =
Packit 6639f8
				(uint64_t)(json_object_get_double(j_low_warn)
Packit 6639f8
					* 1000.0);
Packit 6639f8
				vc->config_sensors[i].flags |=
Packit 6639f8
					FPGAD_SENSOR_VC_LOW_WARN_VALID;
Packit 6639f8
				LOG("user sensor%u low-warn: %f\n",
Packit 6639f8
				    vc->config_sensors[i].id,
Packit 6639f8
				    json_object_get_double(j_low_warn));
Packit 6639f8
			}
Packit 6639f8
		}
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
out_put:
Packit 6639f8
	json_object_put(root);
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
int fpgad_plugin_configure(fpgad_monitored_device *d,
Packit 6639f8
			   const char *cfg)
Packit 6639f8
{
Packit 6639f8
	int res = 1;
Packit 6639f8
	vc_device *vc;
Packit 6639f8
Packit 6639f8
	vc_threads_running = true;
Packit 6639f8
Packit 6639f8
	d->type = FPGAD_PLUGIN_TYPE_THREAD;
Packit 6639f8
Packit 6639f8
	if (d->object_type == FPGA_DEVICE) {
Packit 6639f8
Packit 6639f8
		d->thread_fn = monitor_fme_vc_thread;
Packit 6639f8
		d->thread_stop_fn = stop_vc_threads;
Packit 6639f8
Packit 6639f8
		vc = calloc(1, sizeof(vc_device));
Packit 6639f8
		if (!vc)
Packit 6639f8
			return res;
Packit 6639f8
Packit 6639f8
		vc->base_device = d;
Packit 6639f8
		d->thread_context = vc;
Packit 6639f8
Packit 6639f8
		LOG("monitoring vid=0x%04x did=0x%04x (%s)\n",
Packit 6639f8
			d->supported->vendor_id,
Packit 6639f8
			d->supported->device_id,
Packit 6639f8
			d->object_type == FPGA_ACCELERATOR ?
Packit 6639f8
			"accelerator" : "device");
Packit 6639f8
Packit 6639f8
		res = vc_parse_config(vc, cfg);
Packit 6639f8
		if (res) {
Packit 6639f8
			free(vc);
Packit 6639f8
		}
Packit 6639f8
Packit 6639f8
	}
Packit 6639f8
Packit 6639f8
	// Not currently monitoring the Port device
Packit 6639f8
Packit 6639f8
	return res;
Packit 6639f8
}
Packit 6639f8
Packit 6639f8
void fpgad_plugin_destroy(fpgad_monitored_device *d)
Packit 6639f8
{
Packit 6639f8
	LOG("stop monitoring vid=0x%04x did=0x%04x (%s)\n",
Packit 6639f8
			d->supported->vendor_id,
Packit 6639f8
			d->supported->device_id,
Packit 6639f8
			d->object_type == FPGA_ACCELERATOR ?
Packit 6639f8
			"accelerator" : "device");
Packit 6639f8
Packit 6639f8
	if (d->thread_context) {
Packit 6639f8
		vc_destroy_device((vc_device *)d->thread_context);
Packit 6639f8
		free(d->thread_context);
Packit 6639f8
		d->thread_context = NULL;
Packit 6639f8
	}
Packit 6639f8
}