irq.c 3.0 KB
Newer Older
1
/*
A
Anton Ivanov 已提交
2 3
 * Copyright (C) 2017 - Cambridge Greys Ltd
 * Copyright (C) 2011 - 2014 Cisco Systems Inc
J
Jeff Dike 已提交
4
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5 6 7 8 9
 * Licensed under the GPL
 */

#include <stdlib.h>
#include <errno.h>
A
Anton Ivanov 已提交
10
#include <sys/epoll.h>
11 12
#include <signal.h>
#include <string.h>
13 14 15
#include <irq_user.h>
#include <os.h>
#include <um_malloc.h>
16

A
Anton Ivanov 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/* Epoll support */

static int epollfd = -1;

#define MAX_EPOLL_EVENTS 64

static struct epoll_event epoll_events[MAX_EPOLL_EVENTS];

/* Helper to return an Epoll data pointer from an epoll event structure.
 * We need to keep this one on the userspace side to keep includes separate
 */

void *os_epoll_get_data_pointer(int index)
{
	return epoll_events[index].data.ptr;
}

/* Helper to compare events versus the events in the epoll structure.
 * Same as above - needs to be on the userspace side
 */


int os_epoll_triggered(int index, int events)
{
	return epoll_events[index].events & events;
}
/* Helper to set the event mask.
 * The event mask is opaque to the kernel side, because it does not have
 * access to the right includes/defines for EPOLL constants.
 */

int os_event_mask(int irq_type)
{
	if (irq_type == IRQ_READ)
		return EPOLLIN | EPOLLPRI;
	if (irq_type == IRQ_WRITE)
		return EPOLLOUT;
	return 0;
}

J
Jeff Dike 已提交
57
/*
A
Anton Ivanov 已提交
58
 * Initial Epoll Setup
J
Jeff Dike 已提交
59
 */
A
Anton Ivanov 已提交
60 61 62 63 64
int os_setup_epoll(void)
{
	epollfd = epoll_create(MAX_EPOLL_EVENTS);
	return epollfd;
}
65

A
Anton Ivanov 已提交
66 67 68 69
/*
 * Helper to run the actual epoll_wait
 */
int os_waiting_for_events_epoll(void)
70
{
A
Anton Ivanov 已提交
71
	int n, err;
72

A
Anton Ivanov 已提交
73 74
	n = epoll_wait(epollfd,
		(struct epoll_event *) &epoll_events, MAX_EPOLL_EVENTS, 0);
75
	if (n < 0) {
76
		err = -errno;
77
		if (errno != EINTR)
A
Anton Ivanov 已提交
78 79 80 81 82
			printk(
				UM_KERN_ERR "os_waiting_for_events:"
				" epoll returned %d, error = %s\n", n,
				strerror(errno)
			);
83 84 85 86 87 88
		return err;
	}
	return n;
}


A
Anton Ivanov 已提交
89 90 91 92
/*
 * Helper to add a fd to epoll
 */
int os_add_epoll_fd(int events, int fd, void *data)
93
{
A
Anton Ivanov 已提交
94 95 96 97 98 99 100 101 102 103 104
	struct epoll_event event;
	int result;

	event.data.ptr = data;
	event.events = events | EPOLLET;
	result = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
	if ((result) && (errno == EEXIST))
		result = os_mod_epoll_fd(events, fd, data);
	if (result)
		printk("epollctl add err fd %d, %s\n", fd, strerror(errno));
	return result;
105 106
}

A
Anton Ivanov 已提交
107 108 109 110
/*
 * Helper to mod the fd event mask and/or data backreference
 */
int os_mod_epoll_fd(int events, int fd, void *data)
111
{
A
Anton Ivanov 已提交
112 113 114 115 116 117 118 119 120 121
	struct epoll_event event;
	int result;

	event.data.ptr = data;
	event.events = events;
	result = epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
	if (result)
		printk(UM_KERN_ERR
			"epollctl mod err fd %d, %s\n", fd, strerror(errno));
	return result;
122 123
}

A
Anton Ivanov 已提交
124 125 126 127
/*
 * Helper to delete the epoll fd
 */
int os_del_epoll_fd(int fd)
128
{
A
Anton Ivanov 已提交
129 130 131 132 133 134 135
	struct epoll_event event;
	int result;
	/* This is quiet as we use this as IO ON/OFF - so it is often
	 * invoked on a non-existent fd
	 */
	result = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event);
	return result;
136 137 138 139
}

void os_set_ioignore(void)
{
140
	signal(SIGIO, SIG_IGN);
141
}
A
Anton Ivanov 已提交
142 143 144 145 146 147

void os_close_epoll_fd(void)
{
	/* Needed so we do not leak an fd when rebooting */
	os_close_file(epollfd);
}