xref: /dpdk/lib/eal/windows/eal_interrupts.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright 2020 Mellanox Technologies, Ltd
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <rte_interrupts.h>
699a2dd95SBruce Richardson 
799a2dd95SBruce Richardson #include "eal_private.h"
899a2dd95SBruce Richardson #include "eal_windows.h"
999a2dd95SBruce Richardson 
10cfdaa678SDmitry Kozlyuk #define IOCP_KEY_SHUTDOWN UINT32_MAX
11cfdaa678SDmitry Kozlyuk 
12db77fe7dSTyler Retzlaff static rte_thread_t intr_thread;
1399a2dd95SBruce Richardson 
1499a2dd95SBruce Richardson static HANDLE intr_iocp;
153888f319SDmitry Kozlyuk static HANDLE intr_thread_handle;
1699a2dd95SBruce Richardson 
1799a2dd95SBruce Richardson static void
eal_intr_process(const OVERLAPPED_ENTRY * event)1899a2dd95SBruce Richardson eal_intr_process(const OVERLAPPED_ENTRY *event)
1999a2dd95SBruce Richardson {
2099a2dd95SBruce Richardson 	RTE_SET_USED(event);
2199a2dd95SBruce Richardson }
2299a2dd95SBruce Richardson 
233888f319SDmitry Kozlyuk static int
eal_intr_thread_handle_init(void)243888f319SDmitry Kozlyuk eal_intr_thread_handle_init(void)
253888f319SDmitry Kozlyuk {
263888f319SDmitry Kozlyuk 	DWORD thread_id = GetCurrentThreadId();
273888f319SDmitry Kozlyuk 
283888f319SDmitry Kozlyuk 	intr_thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
293888f319SDmitry Kozlyuk 	if (intr_thread_handle == NULL) {
303888f319SDmitry Kozlyuk 		RTE_LOG_WIN32_ERR("OpenThread(%lu)", thread_id);
313888f319SDmitry Kozlyuk 		return -1;
323888f319SDmitry Kozlyuk 	}
333888f319SDmitry Kozlyuk 	return 0;
343888f319SDmitry Kozlyuk }
353888f319SDmitry Kozlyuk 
36db77fe7dSTyler Retzlaff static uint32_t
eal_intr_thread_main(LPVOID arg __rte_unused)3799a2dd95SBruce Richardson eal_intr_thread_main(LPVOID arg __rte_unused)
3899a2dd95SBruce Richardson {
39cfdaa678SDmitry Kozlyuk 	bool finished = false;
40cfdaa678SDmitry Kozlyuk 
413888f319SDmitry Kozlyuk 	if (eal_intr_thread_handle_init() < 0) {
42*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot open interrupt thread handle");
433888f319SDmitry Kozlyuk 		goto cleanup;
443888f319SDmitry Kozlyuk 	}
453888f319SDmitry Kozlyuk 
46cfdaa678SDmitry Kozlyuk 	while (!finished) {
4799a2dd95SBruce Richardson 		OVERLAPPED_ENTRY events[16];
4899a2dd95SBruce Richardson 		ULONG event_count, i;
4999a2dd95SBruce Richardson 		BOOL result;
5099a2dd95SBruce Richardson 
5199a2dd95SBruce Richardson 		result = GetQueuedCompletionStatusEx(
5299a2dd95SBruce Richardson 			intr_iocp, events, RTE_DIM(events), &event_count,
5399a2dd95SBruce Richardson 			INFINITE, /* no timeout */
5499a2dd95SBruce Richardson 			TRUE);    /* alertable wait for alarm APCs */
5599a2dd95SBruce Richardson 
5699a2dd95SBruce Richardson 		if (!result) {
5799a2dd95SBruce Richardson 			DWORD error = GetLastError();
5899a2dd95SBruce Richardson 			if (error != WAIT_IO_COMPLETION) {
5999a2dd95SBruce Richardson 				RTE_LOG_WIN32_ERR("GetQueuedCompletionStatusEx()");
60*ae67895bSDavid Marchand 				EAL_LOG(ERR, "Failed waiting for interrupts");
6199a2dd95SBruce Richardson 				break;
6299a2dd95SBruce Richardson 			}
6399a2dd95SBruce Richardson 
6499a2dd95SBruce Richardson 			/* No I/O events, all work is done in completed APCs. */
6599a2dd95SBruce Richardson 			continue;
6699a2dd95SBruce Richardson 		}
6799a2dd95SBruce Richardson 
68cfdaa678SDmitry Kozlyuk 		for (i = 0; i < event_count; i++) {
69cfdaa678SDmitry Kozlyuk 			if (events[i].lpCompletionKey == IOCP_KEY_SHUTDOWN) {
70cfdaa678SDmitry Kozlyuk 				finished = true;
71cfdaa678SDmitry Kozlyuk 				break;
72cfdaa678SDmitry Kozlyuk 			}
7399a2dd95SBruce Richardson 			eal_intr_process(&events[i]);
7499a2dd95SBruce Richardson 		}
75cfdaa678SDmitry Kozlyuk 	}
7699a2dd95SBruce Richardson 
773888f319SDmitry Kozlyuk 	CloseHandle(intr_thread_handle);
783888f319SDmitry Kozlyuk 	intr_thread_handle = NULL;
793888f319SDmitry Kozlyuk 
803888f319SDmitry Kozlyuk cleanup:
81db77fe7dSTyler Retzlaff 	intr_thread.opaque_id = 0;
8235dff5d3SDmitry Kozlyuk 
8399a2dd95SBruce Richardson 	CloseHandle(intr_iocp);
8499a2dd95SBruce Richardson 	intr_iocp = NULL;
8535dff5d3SDmitry Kozlyuk 
86db77fe7dSTyler Retzlaff 	return 0;
8799a2dd95SBruce Richardson }
8899a2dd95SBruce Richardson 
8999a2dd95SBruce Richardson int
rte_eal_intr_init(void)9099a2dd95SBruce Richardson rte_eal_intr_init(void)
9199a2dd95SBruce Richardson {
9299a2dd95SBruce Richardson 	int ret = 0;
9399a2dd95SBruce Richardson 
9499a2dd95SBruce Richardson 	intr_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
9599a2dd95SBruce Richardson 	if (intr_iocp == NULL) {
9699a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("CreateIoCompletionPort()");
97*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot create interrupt IOCP");
9899a2dd95SBruce Richardson 		return -1;
9999a2dd95SBruce Richardson 	}
10099a2dd95SBruce Richardson 
1011c1abf17SThomas Monjalon 	ret = rte_thread_create_internal_control(&intr_thread, "intr",
10299a2dd95SBruce Richardson 			eal_intr_thread_main, NULL);
10399a2dd95SBruce Richardson 	if (ret != 0) {
10499a2dd95SBruce Richardson 		rte_errno = -ret;
105*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot create interrupt thread");
10699a2dd95SBruce Richardson 	}
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson 	return ret;
10999a2dd95SBruce Richardson }
11099a2dd95SBruce Richardson 
11199a2dd95SBruce Richardson int
rte_thread_is_intr(void)11299a2dd95SBruce Richardson rte_thread_is_intr(void)
11399a2dd95SBruce Richardson {
114db77fe7dSTyler Retzlaff 	return rte_thread_equal(intr_thread, rte_thread_self());
11599a2dd95SBruce Richardson }
11699a2dd95SBruce Richardson 
11799a2dd95SBruce Richardson int
rte_intr_rx_ctl(__rte_unused struct rte_intr_handle * intr_handle,__rte_unused int epfd,__rte_unused int op,__rte_unused unsigned int vec,__rte_unused void * data)11899a2dd95SBruce Richardson rte_intr_rx_ctl(__rte_unused struct rte_intr_handle *intr_handle,
11999a2dd95SBruce Richardson 		__rte_unused int epfd, __rte_unused int op,
12099a2dd95SBruce Richardson 		__rte_unused unsigned int vec, __rte_unused void *data)
12199a2dd95SBruce Richardson {
12299a2dd95SBruce Richardson 	return -ENOTSUP;
12399a2dd95SBruce Richardson }
12499a2dd95SBruce Richardson 
12599a2dd95SBruce Richardson int
eal_intr_thread_schedule(void (* func)(void * arg),void * arg)12699a2dd95SBruce Richardson eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
12799a2dd95SBruce Richardson {
1283888f319SDmitry Kozlyuk 	if (!QueueUserAPC((PAPCFUNC)(ULONG_PTR)func,
1293888f319SDmitry Kozlyuk 			intr_thread_handle, (ULONG_PTR)arg)) {
13099a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("QueueUserAPC()");
13199a2dd95SBruce Richardson 		return -EINVAL;
13299a2dd95SBruce Richardson 	}
13399a2dd95SBruce Richardson 
13499a2dd95SBruce Richardson 	return 0;
13599a2dd95SBruce Richardson }
13699a2dd95SBruce Richardson 
137cfdaa678SDmitry Kozlyuk void
eal_intr_thread_cancel(void)138cfdaa678SDmitry Kozlyuk eal_intr_thread_cancel(void)
139cfdaa678SDmitry Kozlyuk {
140cfdaa678SDmitry Kozlyuk 	if (!PostQueuedCompletionStatus(
141cfdaa678SDmitry Kozlyuk 			intr_iocp, 0, IOCP_KEY_SHUTDOWN, NULL)) {
142cfdaa678SDmitry Kozlyuk 		RTE_LOG_WIN32_ERR("PostQueuedCompletionStatus()");
143*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot cancel interrupt thread");
144cfdaa678SDmitry Kozlyuk 		return;
145cfdaa678SDmitry Kozlyuk 	}
146cfdaa678SDmitry Kozlyuk 
147cfdaa678SDmitry Kozlyuk 	WaitForSingleObject(intr_thread_handle, INFINITE);
148cfdaa678SDmitry Kozlyuk }
149cfdaa678SDmitry Kozlyuk 
15099a2dd95SBruce Richardson int
rte_intr_callback_register(__rte_unused const struct rte_intr_handle * intr_handle,__rte_unused rte_intr_callback_fn cb,__rte_unused void * cb_arg)15199a2dd95SBruce Richardson rte_intr_callback_register(
15299a2dd95SBruce Richardson 	__rte_unused const struct rte_intr_handle *intr_handle,
15399a2dd95SBruce Richardson 	__rte_unused rte_intr_callback_fn cb, __rte_unused void *cb_arg)
15499a2dd95SBruce Richardson {
15599a2dd95SBruce Richardson 	return -ENOTSUP;
15699a2dd95SBruce Richardson }
15799a2dd95SBruce Richardson 
15899a2dd95SBruce Richardson int
rte_intr_callback_unregister_pending(__rte_unused const struct rte_intr_handle * intr_handle,__rte_unused rte_intr_callback_fn cb_fn,__rte_unused void * cb_arg,__rte_unused rte_intr_unregister_callback_fn ucb_fn)15999a2dd95SBruce Richardson rte_intr_callback_unregister_pending(
16099a2dd95SBruce Richardson 	__rte_unused const struct rte_intr_handle *intr_handle,
16199a2dd95SBruce Richardson 	__rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg,
16299a2dd95SBruce Richardson 	__rte_unused rte_intr_unregister_callback_fn ucb_fn)
16399a2dd95SBruce Richardson {
16499a2dd95SBruce Richardson 	return -ENOTSUP;
16599a2dd95SBruce Richardson }
16699a2dd95SBruce Richardson 
16799a2dd95SBruce Richardson int
rte_intr_callback_unregister(__rte_unused const struct rte_intr_handle * intr_handle,__rte_unused rte_intr_callback_fn cb_fn,__rte_unused void * cb_arg)16899a2dd95SBruce Richardson rte_intr_callback_unregister(
16999a2dd95SBruce Richardson 	__rte_unused const struct rte_intr_handle *intr_handle,
17099a2dd95SBruce Richardson 	__rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
17199a2dd95SBruce Richardson {
17299a2dd95SBruce Richardson 	return 0;
17399a2dd95SBruce Richardson }
17499a2dd95SBruce Richardson 
17599a2dd95SBruce Richardson int
rte_intr_callback_unregister_sync(__rte_unused const struct rte_intr_handle * intr_handle,__rte_unused rte_intr_callback_fn cb_fn,__rte_unused void * cb_arg)17699a2dd95SBruce Richardson rte_intr_callback_unregister_sync(
17799a2dd95SBruce Richardson 	__rte_unused const struct rte_intr_handle *intr_handle,
17899a2dd95SBruce Richardson 	__rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
17999a2dd95SBruce Richardson {
18099a2dd95SBruce Richardson 	return 0;
18199a2dd95SBruce Richardson }
18299a2dd95SBruce Richardson 
18399a2dd95SBruce Richardson int
rte_intr_enable(__rte_unused const struct rte_intr_handle * intr_handle)18499a2dd95SBruce Richardson rte_intr_enable(__rte_unused const struct rte_intr_handle *intr_handle)
18599a2dd95SBruce Richardson {
18699a2dd95SBruce Richardson 	return -ENOTSUP;
18799a2dd95SBruce Richardson }
18899a2dd95SBruce Richardson 
18999a2dd95SBruce Richardson int
rte_intr_ack(__rte_unused const struct rte_intr_handle * intr_handle)19099a2dd95SBruce Richardson rte_intr_ack(__rte_unused const struct rte_intr_handle *intr_handle)
19199a2dd95SBruce Richardson {
19299a2dd95SBruce Richardson 	return -ENOTSUP;
19399a2dd95SBruce Richardson }
19499a2dd95SBruce Richardson 
19599a2dd95SBruce Richardson int
rte_intr_disable(__rte_unused const struct rte_intr_handle * intr_handle)19699a2dd95SBruce Richardson rte_intr_disable(__rte_unused const struct rte_intr_handle *intr_handle)
19799a2dd95SBruce Richardson {
19899a2dd95SBruce Richardson 	return -ENOTSUP;
19999a2dd95SBruce Richardson }
20099a2dd95SBruce Richardson 
20199a2dd95SBruce Richardson int
rte_intr_efd_enable(struct rte_intr_handle * intr_handle,uint32_t nb_efd)20299a2dd95SBruce Richardson rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
20399a2dd95SBruce Richardson {
20499a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
20599a2dd95SBruce Richardson 	RTE_SET_USED(nb_efd);
20699a2dd95SBruce Richardson 
20799a2dd95SBruce Richardson 	return 0;
20899a2dd95SBruce Richardson }
20999a2dd95SBruce Richardson 
21099a2dd95SBruce Richardson void
rte_intr_efd_disable(struct rte_intr_handle * intr_handle)21199a2dd95SBruce Richardson rte_intr_efd_disable(struct rte_intr_handle *intr_handle)
21299a2dd95SBruce Richardson {
21399a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
21499a2dd95SBruce Richardson }
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson int
rte_intr_dp_is_en(struct rte_intr_handle * intr_handle)21799a2dd95SBruce Richardson rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
21899a2dd95SBruce Richardson {
21999a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
22099a2dd95SBruce Richardson 
22199a2dd95SBruce Richardson 	return 0;
22299a2dd95SBruce Richardson }
22399a2dd95SBruce Richardson 
22499a2dd95SBruce Richardson int
rte_intr_allow_others(struct rte_intr_handle * intr_handle)22599a2dd95SBruce Richardson rte_intr_allow_others(struct rte_intr_handle *intr_handle)
22699a2dd95SBruce Richardson {
22799a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
22899a2dd95SBruce Richardson 
22999a2dd95SBruce Richardson 	return 1;
23099a2dd95SBruce Richardson }
23199a2dd95SBruce Richardson 
23299a2dd95SBruce Richardson int
rte_intr_cap_multiple(struct rte_intr_handle * intr_handle)23399a2dd95SBruce Richardson rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
23499a2dd95SBruce Richardson {
23599a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
23699a2dd95SBruce Richardson 
23799a2dd95SBruce Richardson 	return 0;
23899a2dd95SBruce Richardson }
23999a2dd95SBruce Richardson 
24099a2dd95SBruce Richardson int
rte_epoll_wait(int epfd,struct rte_epoll_event * events,int maxevents,int timeout)24199a2dd95SBruce Richardson rte_epoll_wait(int epfd, struct rte_epoll_event *events,
24299a2dd95SBruce Richardson 		int maxevents, int timeout)
24399a2dd95SBruce Richardson {
24499a2dd95SBruce Richardson 	RTE_SET_USED(epfd);
24599a2dd95SBruce Richardson 	RTE_SET_USED(events);
24699a2dd95SBruce Richardson 	RTE_SET_USED(maxevents);
24799a2dd95SBruce Richardson 	RTE_SET_USED(timeout);
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson 	return -ENOTSUP;
25099a2dd95SBruce Richardson }
25199a2dd95SBruce Richardson 
25299a2dd95SBruce Richardson int
rte_epoll_wait_interruptible(int epfd,struct rte_epoll_event * events,int maxevents,int timeout)25399a2dd95SBruce Richardson rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
25499a2dd95SBruce Richardson 			     int maxevents, int timeout)
25599a2dd95SBruce Richardson {
25699a2dd95SBruce Richardson 	RTE_SET_USED(epfd);
25799a2dd95SBruce Richardson 	RTE_SET_USED(events);
25899a2dd95SBruce Richardson 	RTE_SET_USED(maxevents);
25999a2dd95SBruce Richardson 	RTE_SET_USED(timeout);
26099a2dd95SBruce Richardson 
26199a2dd95SBruce Richardson 	return -ENOTSUP;
26299a2dd95SBruce Richardson }
26399a2dd95SBruce Richardson 
26499a2dd95SBruce Richardson int
rte_epoll_ctl(int epfd,int op,int fd,struct rte_epoll_event * event)26599a2dd95SBruce Richardson rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event)
26699a2dd95SBruce Richardson {
26799a2dd95SBruce Richardson 	RTE_SET_USED(epfd);
26899a2dd95SBruce Richardson 	RTE_SET_USED(op);
26999a2dd95SBruce Richardson 	RTE_SET_USED(fd);
27099a2dd95SBruce Richardson 	RTE_SET_USED(event);
27199a2dd95SBruce Richardson 
27299a2dd95SBruce Richardson 	return -ENOTSUP;
27399a2dd95SBruce Richardson }
27499a2dd95SBruce Richardson 
27599a2dd95SBruce Richardson int
rte_intr_tls_epfd(void)27699a2dd95SBruce Richardson rte_intr_tls_epfd(void)
27799a2dd95SBruce Richardson {
27899a2dd95SBruce Richardson 	return -ENOTSUP;
27999a2dd95SBruce Richardson }
28099a2dd95SBruce Richardson 
28199a2dd95SBruce Richardson void
rte_intr_free_epoll_fd(struct rte_intr_handle * intr_handle)28299a2dd95SBruce Richardson rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
28399a2dd95SBruce Richardson {
28499a2dd95SBruce Richardson 	RTE_SET_USED(intr_handle);
28599a2dd95SBruce Richardson }
286