|
Packit |
534379 |
// Copyright(c) 2017-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 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <config.h>
|
|
Packit |
534379 |
#endif // HAVE_CONFIG_H
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifndef _GNU_SOURCE
|
|
Packit |
534379 |
#define _GNU_SOURCE
|
|
Packit |
534379 |
#endif // _GNU_SOURCE
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <string.h>
|
|
Packit |
534379 |
#include <sys/socket.h>
|
|
Packit |
534379 |
#include <sys/un.h>
|
|
Packit |
534379 |
#include <sys/eventfd.h>
|
|
Packit |
534379 |
#include <errno.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <opae/properties.h>
|
|
Packit |
534379 |
#include "xfpga.h"
|
|
Packit |
534379 |
#include "common_int.h"
|
|
Packit |
534379 |
#include "opae_drv.h"
|
|
Packit |
534379 |
#include "types_int.h"
|
|
Packit |
534379 |
#include "intel-fpga.h"
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#define EVENT_SOCKET_NAME "/tmp/fpga_event_socket"
|
|
Packit |
534379 |
#define EVENT_SOCKET_NAME_LEN 23
|
|
Packit |
534379 |
|
|
Packit |
534379 |
enum request_type { REGISTER_EVENT = 0, UNREGISTER_EVENT = 1 };
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct event_request {
|
|
Packit |
534379 |
enum request_type type;
|
|
Packit |
534379 |
fpga_event_type event;
|
|
Packit |
534379 |
uint64_t object_id;
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result send_event_request(int conn_socket, int fd,
|
|
Packit |
534379 |
struct event_request *req)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct msghdr mh;
|
|
Packit |
534379 |
struct cmsghdr *cmh;
|
|
Packit |
534379 |
struct iovec iov[1];
|
|
Packit |
534379 |
char buf[CMSG_SPACE(sizeof(int))];
|
|
Packit |
534379 |
ssize_t n;
|
|
Packit |
534379 |
int *fd_ptr;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* set up ancillary data message header */
|
|
Packit |
534379 |
iov[0].iov_base = req;
|
|
Packit |
534379 |
iov[0].iov_len = sizeof(*req);
|
|
Packit |
534379 |
memset(buf, 0, sizeof(buf));
|
|
Packit |
534379 |
mh.msg_name = NULL;
|
|
Packit |
534379 |
mh.msg_namelen = 0;
|
|
Packit |
534379 |
mh.msg_iov = iov;
|
|
Packit |
534379 |
mh.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
|
|
Packit |
534379 |
mh.msg_control = buf;
|
|
Packit |
534379 |
mh.msg_controllen = CMSG_LEN(sizeof(int));
|
|
Packit |
534379 |
mh.msg_flags = 0;
|
|
Packit |
534379 |
cmh = CMSG_FIRSTHDR(&mh);
|
|
Packit |
534379 |
cmh->cmsg_len = CMSG_LEN(sizeof(int));
|
|
Packit |
534379 |
cmh->cmsg_level = SOL_SOCKET;
|
|
Packit |
534379 |
cmh->cmsg_type = SCM_RIGHTS;
|
|
Packit |
534379 |
fd_ptr = (int *)CMSG_DATA(cmh);
|
|
Packit |
534379 |
*fd_ptr = fd;
|
|
Packit |
534379 |
/* send ancillary data */
|
|
Packit |
534379 |
n = sendmsg(conn_socket, &mh, 0);
|
|
Packit |
534379 |
if (n < 0) {
|
|
Packit |
534379 |
OPAE_ERR("sendmsg failed: %s", strerror(errno));
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result send_fme_event_request(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
int fme_operation)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
int fd = FILE_DESCRIPTOR(event_handle);
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
opae_fme_info fme_info = { 0 };
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (fme_operation != FPGA_IRQ_ASSIGN
|
|
Packit |
534379 |
&& fme_operation != FPGA_IRQ_DEASSIGN) {
|
|
Packit |
534379 |
OPAE_ERR("Invalid FME operation requested");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = opae_get_fme_info(_handle->fddev, &fme_info);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*capability field is set to 1 if the platform supports interrupts*/
|
|
Packit |
534379 |
if (fme_info.capability & FPGA_FME_CAP_ERR_IRQ) {
|
|
Packit |
534379 |
res = opae_fme_set_err_irq(_handle->fddev, 0, fme_operation == FPGA_IRQ_ASSIGN ? fd : -1);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
OPAE_ERR("Could not set eventfd %s", strerror(errno));
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
OPAE_ERR("FME interrupts not supported in hw");
|
|
Packit |
534379 |
res = FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result send_port_event_request(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
int port_operation)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
int fd = FILE_DESCRIPTOR(event_handle);
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
opae_port_info port_info = { 0 };
|
|
Packit |
534379 |
if (port_operation != FPGA_IRQ_ASSIGN
|
|
Packit |
534379 |
&& port_operation != FPGA_IRQ_DEASSIGN) {
|
|
Packit |
534379 |
OPAE_ERR("Invalid PORT operation requested");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = opae_get_port_info(_handle->fddev, &port_info);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*capability field is set to 1 if the platform supports interrupts*/
|
|
Packit |
534379 |
if (port_info.capability & FPGA_PORT_CAP_ERR_IRQ) {
|
|
Packit |
534379 |
res = opae_port_set_err_irq(_handle->fddev, 0, port_operation == FPGA_IRQ_ASSIGN ? fd : -1);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
OPAE_ERR("Could not set eventfd");
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
OPAE_ERR("PORT interrupts not supported in hw");
|
|
Packit |
534379 |
res = FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result send_uafu_event_request(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
uint32_t flags, int uafu_operation)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
int res = FPGA_OK;
|
|
Packit |
534379 |
int fd = FILE_DESCRIPTOR(event_handle);
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh =
|
|
Packit |
534379 |
(struct _fpga_event_handle *)event_handle;
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
opae_port_info port_info = { 0 };
|
|
Packit |
534379 |
int32_t neg = -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (uafu_operation != FPGA_IRQ_ASSIGN
|
|
Packit |
534379 |
&& uafu_operation != FPGA_IRQ_DEASSIGN) {
|
|
Packit |
534379 |
OPAE_ERR("Invalid UAFU operation requested");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = opae_get_port_info(_handle->fddev, &port_info);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*capability field is set to 1 if the platform supports interrupts*/
|
|
Packit |
534379 |
if (port_info.capability & FPGA_PORT_CAP_UAFU_IRQ) {
|
|
Packit |
534379 |
if (flags >= port_info.num_uafu_irqs) {
|
|
Packit |
534379 |
OPAE_ERR("Invalid User Interrupt vector id");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (uafu_operation == FPGA_IRQ_ASSIGN) {
|
|
Packit |
534379 |
res = opae_port_set_user_irq(_handle->fddev, 0, flags, 1, &fd;;
|
|
Packit |
534379 |
_eh->flags = flags;
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
res = opae_port_set_user_irq(_handle->fddev, 0, _eh->flags, 1, &neg;;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
OPAE_ERR("Could not set eventfd");
|
|
Packit |
534379 |
res = FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
OPAE_ERR("UAFU interrupts not supported in hw");
|
|
Packit |
534379 |
res = FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/*
|
|
Packit |
534379 |
* Uses driver ioctls to determine whether the driver supports interrupts
|
|
Packit |
534379 |
* on this platform. objtype is an output parameter.
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
STATIC fpga_result check_interrupts_supported(fpga_handle handle,
|
|
Packit |
534379 |
fpga_objtype *objtype)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
fpga_result destroy_res = FPGA_OK;
|
|
Packit |
534379 |
fpga_properties prop = NULL;
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
opae_fme_info fme_info = { 0 };
|
|
Packit |
534379 |
opae_port_info port_info = { 0 };
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = xfpga_fpgaGetPropertiesFromHandle(handle, &prop);
|
|
Packit |
534379 |
if (res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_MSG("Could not get FPGA properties from handle");
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = fpgaPropertiesGetObjectType(prop, objtype);
|
|
Packit |
534379 |
if (res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_MSG("Could not determine FPGA object type");
|
|
Packit |
534379 |
goto destroy_prop;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (*objtype == FPGA_DEVICE) {
|
|
Packit |
534379 |
res = opae_get_fme_info(_handle->fddev, &fme_info);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
res = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto destroy_prop;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (fme_info.capability & FPGA_FME_CAP_ERR_IRQ) {
|
|
Packit |
534379 |
res = FPGA_OK;
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
OPAE_MSG("Interrupts not supported in hw");
|
|
Packit |
534379 |
res = FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
} else if (*objtype == FPGA_ACCELERATOR) {
|
|
Packit |
534379 |
res = opae_get_port_info(_handle->fddev, &port_info);
|
|
Packit |
534379 |
if (res) {
|
|
Packit |
534379 |
OPAE_ERR("Could not get PORT info: %s",
|
|
Packit |
534379 |
strerror(errno));
|
|
Packit |
534379 |
goto destroy_prop;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (port_info.capability & FPGA_PORT_CAP_ERR_IRQ) {
|
|
Packit |
534379 |
res = FPGA_OK;
|
|
Packit |
534379 |
} else {
|
|
Packit |
534379 |
OPAE_MSG("Interrupts not supported in hw");
|
|
Packit |
534379 |
res = FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
destroy_prop:
|
|
Packit |
534379 |
destroy_res = fpgaDestroyProperties(&prop);
|
|
Packit |
534379 |
if (destroy_res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_MSG("Could not destroy FPGA properties");
|
|
Packit |
534379 |
return destroy_res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result driver_register_event(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_type event_type,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
uint32_t flags)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_objtype objtype;
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = check_interrupts_supported(handle, &objtype);
|
|
Packit |
534379 |
if (res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_MSG(
|
|
Packit |
534379 |
"Could not determine whether interrupts are supported");
|
|
Packit |
534379 |
return FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (event_type) {
|
|
Packit |
534379 |
case FPGA_EVENT_ERROR:
|
|
Packit |
534379 |
if (objtype == FPGA_DEVICE) {
|
|
Packit |
534379 |
return send_fme_event_request(handle, event_handle,
|
|
Packit |
534379 |
FPGA_IRQ_ASSIGN);
|
|
Packit |
534379 |
} else if (objtype == FPGA_ACCELERATOR) {
|
|
Packit |
534379 |
return send_port_event_request(handle, event_handle,
|
|
Packit |
534379 |
FPGA_IRQ_ASSIGN);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
OPAE_ERR("Invalid objtype: %d", objtype);
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
case FPGA_EVENT_INTERRUPT:
|
|
Packit |
534379 |
if (objtype != FPGA_ACCELERATOR) {
|
|
Packit |
534379 |
OPAE_MSG("User events need an accelerator object");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return send_uafu_event_request(handle, event_handle, flags,
|
|
Packit |
534379 |
FPGA_IRQ_ASSIGN);
|
|
Packit |
534379 |
case FPGA_EVENT_POWER_THERMAL:
|
|
Packit |
534379 |
OPAE_MSG("Thermal interrupts not supported");
|
|
Packit |
534379 |
return FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
default:
|
|
Packit |
534379 |
OPAE_ERR("Invalid event type");
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result driver_unregister_event(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_type event_type,
|
|
Packit |
534379 |
fpga_event_handle event_handle)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_objtype objtype;
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = check_interrupts_supported(handle, &objtype);
|
|
Packit |
534379 |
if (res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_MSG(
|
|
Packit |
534379 |
"Could not determine whether interrupts are supported");
|
|
Packit |
534379 |
return FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (event_type) {
|
|
Packit |
534379 |
case FPGA_EVENT_ERROR:
|
|
Packit |
534379 |
if (objtype == FPGA_DEVICE) {
|
|
Packit |
534379 |
return send_fme_event_request(handle, event_handle,
|
|
Packit |
534379 |
FPGA_IRQ_DEASSIGN);
|
|
Packit |
534379 |
} else if (objtype == FPGA_ACCELERATOR) {
|
|
Packit |
534379 |
return send_port_event_request(handle, event_handle,
|
|
Packit |
534379 |
FPGA_IRQ_DEASSIGN);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
OPAE_ERR("Invalid objtype: %d", objtype);
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
case FPGA_EVENT_INTERRUPT:
|
|
Packit |
534379 |
if (objtype != FPGA_ACCELERATOR) {
|
|
Packit |
534379 |
OPAE_MSG("User events need an Accelerator object");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return send_uafu_event_request(handle, event_handle, 0,
|
|
Packit |
534379 |
FPGA_IRQ_DEASSIGN);
|
|
Packit |
534379 |
case FPGA_EVENT_POWER_THERMAL:
|
|
Packit |
534379 |
OPAE_MSG("Thermal interrupts not supported");
|
|
Packit |
534379 |
return FPGA_NOT_SUPPORTED;
|
|
Packit |
534379 |
default:
|
|
Packit |
534379 |
OPAE_ERR("Invalid event type");
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result daemon_register_event(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_type event_type,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
uint32_t flags)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
int fd = FILE_DESCRIPTOR(event_handle);
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
struct sockaddr_un addr;
|
|
Packit |
534379 |
struct event_request req;
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
fpga_properties prop = NULL;
|
|
Packit |
534379 |
uint64_t object_id = (uint64_t) -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
UNUSED_PARAM(flags);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (_handle->fdfpgad < 0) {
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* connect to event socket */
|
|
Packit |
534379 |
_handle->fdfpgad = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
Packit |
534379 |
if (_handle->fdfpgad < 0) {
|
|
Packit |
534379 |
OPAE_ERR("socket: %s", strerror(errno));
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
addr.sun_family = AF_UNIX;
|
|
Packit |
534379 |
strncpy(addr.sun_path, EVENT_SOCKET_NAME,
|
|
Packit |
534379 |
EVENT_SOCKET_NAME_LEN);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (connect(_handle->fdfpgad, (struct sockaddr *)&addr,
|
|
Packit |
534379 |
sizeof(addr))
|
|
Packit |
534379 |
< 0) {
|
|
Packit |
534379 |
OPAE_DBG("connect: %s", strerror(errno));
|
|
Packit |
534379 |
result = FPGA_NO_DAEMON;
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* get the requestor's object ID */
|
|
Packit |
534379 |
result = xfpga_fpgaGetPropertiesFromHandle(handle, &prop);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("failed to get props");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaPropertiesGetObjectID(prop, &object_id);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
fpgaDestroyProperties(&prop);
|
|
Packit |
534379 |
OPAE_ERR("failed to get object ID");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaDestroyProperties(&prop);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("failed to destroy props");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* create event registration request */
|
|
Packit |
534379 |
req.type = REGISTER_EVENT;
|
|
Packit |
534379 |
req.event = event_type;
|
|
Packit |
534379 |
req.object_id = object_id;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* send event packet */
|
|
Packit |
534379 |
result = send_event_request(_handle->fdfpgad, fd, &req;;
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("send_event_request failed");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_close_conn:
|
|
Packit |
534379 |
close(_handle->fdfpgad);
|
|
Packit |
534379 |
_handle->fdfpgad = -1;
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result daemon_unregister_event(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_type event_type)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
struct event_request req;
|
|
Packit |
534379 |
ssize_t n;
|
|
Packit |
534379 |
fpga_properties prop = NULL;
|
|
Packit |
534379 |
uint64_t object_id = (uint64_t) -1;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (_handle->fdfpgad < 0) {
|
|
Packit |
534379 |
OPAE_MSG("No fpgad connection");
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* get the requestor's object ID */
|
|
Packit |
534379 |
result = xfpga_fpgaGetPropertiesFromHandle(handle, &prop);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("failed to get properties");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaPropertiesGetObjectID(prop, &object_id);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
fpgaDestroyProperties(&prop);
|
|
Packit |
534379 |
OPAE_ERR("failed to get object ID");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = fpgaDestroyProperties(&prop);
|
|
Packit |
534379 |
if (result != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("failed to destroy properties");
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
req.type = UNREGISTER_EVENT;
|
|
Packit |
534379 |
req.event = event_type;
|
|
Packit |
534379 |
req.object_id = object_id;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
n = send(_handle->fdfpgad, &req, sizeof(req), 0);
|
|
Packit |
534379 |
if (n < 0) {
|
|
Packit |
534379 |
OPAE_ERR("send : %s", strerror(errno));
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_close_conn;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_close_conn:
|
|
Packit |
534379 |
close(_handle->fdfpgad);
|
|
Packit |
534379 |
_handle->fdfpgad = -1;
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result __XFPGA_API__
|
|
Packit |
534379 |
xfpga_fpgaCreateEventHandle(fpga_event_handle *event_handle)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh;
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
pthread_mutexattr_t mattr;
|
|
Packit |
534379 |
int err = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
ASSERT_NOT_NULL(event_handle);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_eh = malloc(sizeof(struct _fpga_event_handle));
|
|
Packit |
534379 |
if (NULL == _eh) {
|
|
Packit |
534379 |
OPAE_ERR("Could not allocate memory for event handle");
|
|
Packit |
534379 |
return FPGA_NO_MEMORY;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_eh->magic = FPGA_EVENT_HANDLE_MAGIC;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* create eventfd */
|
|
Packit |
534379 |
_eh->fd = eventfd(0, 0);
|
|
Packit |
534379 |
if (_eh->fd < 0) {
|
|
Packit |
534379 |
OPAE_ERR("eventfd : %s", strerror(errno));
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (pthread_mutexattr_init(&mattr)) {
|
|
Packit |
534379 |
OPAE_MSG("Failed to initialized event handle mutex attributes");
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)) {
|
|
Packit |
534379 |
OPAE_MSG("Failed to initialize event handle mutex attributes");
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_attr_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (pthread_mutex_init(&_eh->lock, &mattr)) {
|
|
Packit |
534379 |
OPAE_MSG("Failed to initialize event handle mutex");
|
|
Packit |
534379 |
result = FPGA_EXCEPTION;
|
|
Packit |
534379 |
goto out_attr_destroy;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
pthread_mutexattr_destroy(&mattr);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
*event_handle = (fpga_event_handle)_eh;
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_attr_destroy:
|
|
Packit |
534379 |
err = pthread_mutexattr_destroy(&mattr);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutexatr_destroy() failed: %s",
|
|
Packit |
534379 |
strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_free:
|
|
Packit |
534379 |
free(_eh);
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result __XFPGA_API__
|
|
Packit |
534379 |
xfpga_fpgaDestroyEventHandle(fpga_event_handle *event_handle)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh;
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
int err = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// sanity check
|
|
Packit |
534379 |
if (!event_handle) {
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_eh = (struct _fpga_event_handle *)*event_handle;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = event_handle_check_and_lock(_eh);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (close(_eh->fd) < 0) {
|
|
Packit |
534379 |
OPAE_ERR("eventfd : %s", strerror(errno));
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %S",
|
|
Packit |
534379 |
strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (errno == EBADF)
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
else
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_eh->magic = FPGA_INVALID_MAGIC;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %S", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
err = pthread_mutex_destroy(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_destroy() failed: %S", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
free(*event_handle);
|
|
Packit |
534379 |
*event_handle = NULL;
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result __XFPGA_API__
|
|
Packit |
534379 |
xfpga_fpgaGetOSObjectFromEventHandle(const fpga_event_handle eh, int *fd)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh = (struct _fpga_event_handle *)eh;
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
int err = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = event_handle_check_and_lock(_eh);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
*fd = _eh->fd;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %s", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result __XFPGA_API__ xfpga_fpgaRegisterEvent(fpga_handle handle,
|
|
Packit |
534379 |
fpga_event_type event_type,
|
|
Packit |
534379 |
fpga_event_handle event_handle,
|
|
Packit |
534379 |
uint32_t flags)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh =
|
|
Packit |
534379 |
(struct _fpga_event_handle *)event_handle;
|
|
Packit |
534379 |
struct _fpga_token *_token;
|
|
Packit |
534379 |
int err;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = handle_check_and_lock(_handle);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = event_handle_check_and_lock(_eh);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
goto out_unlock_handle;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_token = (struct _fpga_token *)_handle->token;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (_token->magic != FPGA_TOKEN_MAGIC) {
|
|
Packit |
534379 |
OPAE_MSG("Invalid token found in handle");
|
|
Packit |
534379 |
result = FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
goto out_unlock;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (event_type) {
|
|
Packit |
534379 |
case FPGA_EVENT_INTERRUPT:
|
|
Packit |
534379 |
if (!strstr(_token->devpath, "port")) {
|
|
Packit |
534379 |
OPAE_MSG("Handle does not refer to accelerator object");
|
|
Packit |
534379 |
result = FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
goto out_unlock;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case FPGA_EVENT_ERROR: /* fall through */
|
|
Packit |
534379 |
case FPGA_EVENT_POWER_THERMAL:
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* TODO: reject unknown flags */
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* try driver first */
|
|
Packit |
534379 |
result = driver_register_event(handle, event_type, event_handle, flags);
|
|
Packit |
534379 |
if (result == FPGA_NOT_SUPPORTED) {
|
|
Packit |
534379 |
result = daemon_register_event(handle, event_type, event_handle,
|
|
Packit |
534379 |
flags);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_unlock:
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %s", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_unlock_handle:
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_handle->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %s", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result __XFPGA_API__
|
|
Packit |
534379 |
xfpga_fpgaUnregisterEvent(fpga_handle handle, fpga_event_type event_type,
|
|
Packit |
534379 |
fpga_event_handle event_handle)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result result = FPGA_OK;
|
|
Packit |
534379 |
int err;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct _fpga_handle *_handle = (struct _fpga_handle *)handle;
|
|
Packit |
534379 |
struct _fpga_event_handle *_eh =
|
|
Packit |
534379 |
(struct _fpga_event_handle *)event_handle;
|
|
Packit |
534379 |
struct _fpga_token *_token;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = handle_check_and_lock(_handle);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
result = event_handle_check_and_lock(_eh);
|
|
Packit |
534379 |
if (result)
|
|
Packit |
534379 |
goto out_unlock_handle;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
_token = (struct _fpga_token *)_handle->token;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (_token->magic != FPGA_TOKEN_MAGIC) {
|
|
Packit |
534379 |
OPAE_MSG("Invalid token found in handle");
|
|
Packit |
534379 |
result = FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
goto out_unlock;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (event_type) {
|
|
Packit |
534379 |
case FPGA_EVENT_INTERRUPT:
|
|
Packit |
534379 |
if (!strstr(_token->devpath, "port")) {
|
|
Packit |
534379 |
OPAE_MSG("Handle does not refer to accelerator object");
|
|
Packit |
534379 |
result = FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
goto out_unlock;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
case FPGA_EVENT_ERROR: /* fall through */
|
|
Packit |
534379 |
case FPGA_EVENT_POWER_THERMAL:
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
/* try driver first */
|
|
Packit |
534379 |
result = driver_unregister_event(handle, event_type, event_handle);
|
|
Packit |
534379 |
if (result == FPGA_NOT_SUPPORTED) {
|
|
Packit |
534379 |
result = daemon_unregister_event(handle, event_type);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_unlock:
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_eh->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %s", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_unlock_handle:
|
|
Packit |
534379 |
err = pthread_mutex_unlock(&_handle->lock);
|
|
Packit |
534379 |
if (err)
|
|
Packit |
534379 |
OPAE_ERR("pthread_mutex_unlock() failed: %s", strerror(err));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return result;
|
|
Packit |
534379 |
}
|