|
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 |
}
|