* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <unistd.h>
#include <sys/epoll.h>
#include <errno.h>
#include <stdint.h>
#include "ascend_hal.h"
#include "hdc_cmn.h"
#include "hdc_pcie_drv.h"
#include "hdc_epoll.h"
STATIC drvError_t drv_hdc_pcie_epoll_create(struct hdc_epoll_head *epoll_head, signed int size)
{
signed int ret;
epoll_head->bind_fd = hdc_pcie_create_bind_fd();
if (epoll_head->bind_fd == (mmProcess)EN_ERROR) {
HDC_LOG_ERR("Open pcie device failed. (strerror=\"%s\")\n", strerror(errno));
return DRV_ERROR_INVALID_HANDLE;
}
ret = hdc_pcie_epoll_alloc_fd(epoll_head->bind_fd, size, (signed int *)&epoll_head->epfd);
if (ret != 0) {
hdc_pcie_close_bind_fd(epoll_head->bind_fd);
epoll_head->bind_fd = HDC_EPOLL_FD_INVALID;
HDC_LOG_ERR("Epoll alloc fd failed. (ret=%d)\n", ret);
return DRV_ERROR_OVER_LIMIT;
}
return DRV_ERROR_NONE;
}
STATIC drvError_t drv_hdc_pcie_epoll_ctl(struct hdc_epoll_head *epoll_head,
signed int op, void *target, const struct drvHdcEvent *event)
{
signed int para1, para2 = 0;
struct hdc_server_head *server_head = (struct hdc_server_head *)target;
struct hdc_session *session_head = (struct hdc_session *)target;
struct hdcdrv_cmd_epoll_ctl epollctl;
if ((event->events & (unsigned int)HDC_EPOLL_CONN_IN) != 0U) {
para1 = server_head->deviceId;
para2 = server_head->serviceType;
} else {
para1 = session_head->sockfd;
}
epollctl.epfd = epoll_head->epfd;
epollctl.dev_id = server_head->deviceId;
epollctl.op = op;
epollctl.para1 = para1;
epollctl.para2 = para2;
return (drvError_t)hdc_pcie_epoll_ctl(epoll_head->bind_fd, &epollctl, event);
}
STATIC drvError_t drv_hdc_pcie_epoll_wait(const struct hdc_epoll_head *epoll_head,
struct drvHdcEvent *events, signed int maxevents, signed int timeout, signed int *eventnum)
{
struct hdcdrv_event *epoll_events = NULL;
struct hdcdrv_cmd_epoll_wait epollwait;
signed int ret, i;
epoll_events = (struct hdcdrv_event *)malloc((size_t)maxevents * sizeof(struct hdcdrv_event));
if (epoll_events == NULL) {
HDC_LOG_ERR("Call malloc failed.\n");
return DRV_ERROR_MALLOC_FAIL;
}
epollwait.epfd = epoll_head->epfd;
epollwait.dev_id = HDCDRV_DEFAULT_DEV_ID;
epollwait.timeout = timeout;
epollwait.maxevents = maxevents;
epollwait.event = epoll_events;
ret = hdc_pcie_epoll_wait(epoll_head->bind_fd, &epollwait);
if (ret != 0) {
if (ret == (-HDCDRV_EPOLL_CLOSE)) {
ret = DRV_ERROR_EPOLL_CLOSE;
goto out;
}
HDC_LOG_ERR("Call epoll_wait failed. (epfd=%d; ret=%d)\n", epoll_head->epfd, ret);
ret = DRV_ERROR_IOCRL_FAIL;
goto out;
}
*eventnum = epollwait.ready_event;
if ((*eventnum < 0) || (*eventnum > HDCDRV_EPOLL_FD_EVENT_NUM)) {
HDC_LOG_ERR("Input parameter eventnum is error. (epfd=%d; eventnum=%d)\n", epoll_head->epfd, *eventnum);
ret = DRV_ERROR_IOCRL_FAIL;
goto out;
}
for (i = 0; i < *eventnum; i++) {
events[i].events = epoll_events[i].events;
events[i].data = (uintptr_t)(epoll_events[i].data);
}
out:
free(epoll_events);
epoll_events = NULL;
return (drvError_t)ret;
}
STATIC drvError_t drv_hdc_pcie_epoll_close(struct hdc_epoll_head *epoll_head)
{
signed int ret;
signed int epfd;
epfd = (signed int)epoll_head->epfd;
ret = hdc_pcie_epoll_free_fd(epoll_head->bind_fd, epfd);
if (ret != 0) {
HDC_LOG_ERR("Epoll free fd failed. (epfd=%d; ret=%d)\n", epfd, ret);
return DRV_ERROR_SOCKET_CLOSE;
}
hdc_pcie_close_bind_fd(epoll_head->bind_fd);
epoll_head->bind_fd = HDC_EPOLL_FD_INVALID;
epoll_head->epfd = 0;
return DRV_ERROR_NONE;
}
struct hdc_epoll_ops *drv_get_hdc_pcie_epoll_ops(void)
{
static struct hdc_epoll_ops pcie_epoll_ops = {
drv_hdc_pcie_epoll_create,
drv_hdc_pcie_epoll_ctl,
drv_hdc_pcie_epoll_wait,
drv_hdc_pcie_epoll_close,
};
return &pcie_epoll_ops;
}