1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
9 #include <rte_common.h>
10 #include <rte_cycles.h>
11 #include <rte_interrupts.h>
15 #define TEST_INTERRUPT_CHECK_INTERVAL 100 /* ms */
17 /* predefined interrupt handle types */
18 enum test_interrupt_handle_type {
19 TEST_INTERRUPT_HANDLE_INVALID = 0,
20 TEST_INTERRUPT_HANDLE_VALID,
21 TEST_INTERRUPT_HANDLE_VALID_UIO,
22 TEST_INTERRUPT_HANDLE_VALID_ALARM,
23 TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT,
24 TEST_INTERRUPT_HANDLE_CASE1,
25 TEST_INTERRUPT_HANDLE_MAX
28 /* flag of if callback is called */
29 static volatile int flag;
30 static struct rte_intr_handle *intr_handles[TEST_INTERRUPT_HANDLE_MAX];
31 static enum test_interrupt_handle_type test_intr_type =
32 TEST_INTERRUPT_HANDLE_MAX;
34 #ifdef RTE_EXEC_ENV_LINUX
45 static union intr_pipefds pfds;
48 * Check if the interrupt handle is valid.
51 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
53 if (!intr_handle || rte_intr_fd_get(intr_handle) < 0)
60 * Initialization for interrupt test.
63 test_interrupt_init(void)
65 struct rte_intr_handle *test_intr_handle;
68 if (pipe(pfds.pipefd) < 0)
71 for (i = 0; i < TEST_INTERRUPT_HANDLE_MAX; i++) {
73 rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
78 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
79 if (rte_intr_fd_set(test_intr_handle, -1))
81 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UNKNOWN))
84 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
85 if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
87 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UNKNOWN))
90 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
91 if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
93 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UIO))
96 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
97 if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
99 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_ALARM))
102 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
103 if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
105 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_DEV_EVENT))
108 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
109 if (rte_intr_fd_set(test_intr_handle, pfds.writefd))
111 if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UIO))
118 * Deinitialization for interrupt test.
121 test_interrupt_deinit(void)
125 for (i = 0; i < TEST_INTERRUPT_HANDLE_MAX; i++)
126 rte_intr_instance_free(intr_handles[i]);
127 close(pfds.pipefd[0]);
128 close(pfds.pipefd[1]);
134 * Write the pipe to simulate an interrupt.
137 test_interrupt_trigger_interrupt(void)
139 if (write(pfds.writefd, "1", 1) < 0)
146 * Check if two interrupt handles are the same.
149 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
150 struct rte_intr_handle *intr_handle_r)
152 if (!intr_handle_l || !intr_handle_r)
155 if (rte_intr_fd_get(intr_handle_l) !=
156 rte_intr_fd_get(intr_handle_r) ||
157 rte_intr_type_get(intr_handle_l) !=
158 rte_intr_type_get(intr_handle_r))
165 /* to be implemented for bsd later */
167 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
169 RTE_SET_USED(intr_handle);
175 test_interrupt_init(void)
181 test_interrupt_deinit(void)
187 test_interrupt_trigger_interrupt(void)
193 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
194 struct rte_intr_handle *intr_handle_r)
201 #endif /* RTE_EXEC_ENV_LINUX */
204 * Callback for the test interrupt.
207 test_interrupt_callback(void *arg)
209 struct rte_intr_handle *intr_handle = arg;
210 struct rte_intr_handle *test_intr_handle;
212 if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) {
213 printf("invalid interrupt type\n");
218 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
219 printf("null or invalid intr_handle for %s\n", __func__);
224 if (rte_intr_callback_unregister(intr_handle,
225 test_interrupt_callback, arg) >= 0) {
226 printf("%s: unexpectedly able to unregister itself\n",
232 test_intr_handle = intr_handles[test_intr_type];
233 if (test_interrupt_handle_compare(intr_handle, test_intr_handle) == 0)
238 * Callback for the test interrupt.
241 test_interrupt_callback_1(void *arg)
243 struct rte_intr_handle *intr_handle = arg;
244 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
245 printf("null or invalid intr_handle for %s\n", __func__);
252 * Tests for rte_intr_enable().
255 test_interrupt_enable(void)
257 struct rte_intr_handle *test_intr_handle;
259 /* check with null intr_handle */
260 if (rte_intr_enable(NULL) == 0) {
261 printf("unexpectedly enable null intr_handle successfully\n");
265 /* check with invalid intr_handle */
266 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
267 if (rte_intr_enable(test_intr_handle) == 0) {
268 printf("unexpectedly enable invalid intr_handle "
273 /* check with valid intr_handle */
274 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
275 if (rte_intr_enable(test_intr_handle) == 0) {
276 printf("unexpectedly enable a specific intr_handle "
281 /* check with specific valid intr_handle */
282 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
283 if (rte_intr_enable(test_intr_handle) == 0) {
284 printf("unexpectedly enable a specific intr_handle "
289 /* check with specific valid intr_handle */
290 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
291 if (rte_intr_enable(test_intr_handle) == 0) {
292 printf("unexpectedly enable a specific intr_handle "
297 /* check with valid handler and its type */
298 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
299 if (rte_intr_enable(test_intr_handle) < 0) {
300 printf("fail to enable interrupt on a simulated handler\n");
304 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
305 if (rte_intr_enable(test_intr_handle) == 0) {
306 printf("unexpectedly enable a specific intr_handle "
315 * Tests for rte_intr_disable().
318 test_interrupt_disable(void)
320 struct rte_intr_handle *test_intr_handle;
322 /* check with null intr_handle */
323 if (rte_intr_disable(NULL) == 0) {
324 printf("unexpectedly disable null intr_handle "
329 /* check with invalid intr_handle */
330 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
331 if (rte_intr_disable(test_intr_handle) == 0) {
332 printf("unexpectedly disable invalid intr_handle "
337 /* check with valid intr_handle */
338 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
339 if (rte_intr_disable(test_intr_handle) == 0) {
340 printf("unexpectedly disable a specific intr_handle "
345 /* check with specific valid intr_handle */
346 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
347 if (rte_intr_disable(test_intr_handle) == 0) {
348 printf("unexpectedly disable a specific intr_handle "
353 /* check with specific valid intr_handle */
354 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
355 if (rte_intr_disable(test_intr_handle) == 0) {
356 printf("unexpectedly disable a specific intr_handle "
361 /* check with valid handler and its type */
362 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
363 if (rte_intr_disable(test_intr_handle) < 0) {
364 printf("fail to disable interrupt on a simulated handler\n");
368 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
369 if (rte_intr_disable(test_intr_handle) == 0) {
370 printf("unexpectedly disable a specific intr_handle "
379 * Check the full path of a specified type of interrupt simulated.
382 test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type)
385 struct rte_intr_handle *test_intr_handle;
388 test_intr_handle = intr_handles[intr_type];
389 test_intr_type = intr_type;
390 if (rte_intr_callback_register(test_intr_handle,
391 test_interrupt_callback, test_intr_handle) < 0) {
392 printf("fail to register callback\n");
396 if (test_interrupt_trigger_interrupt() < 0)
400 for (count = 0; flag == 0 && count < 3; count++)
401 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
403 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
405 rte_intr_callback_unregister(test_intr_handle,
406 test_interrupt_callback,
407 test_intr_handle)) < 0) {
408 if (count != -EAGAIN)
413 printf("callback has not been called\n");
415 } else if (flag < 0) {
416 printf("it has internal error in callback\n");
424 * Main function of testing interrupt.
430 struct rte_intr_handle *test_intr_handle;
432 if (RTE_EXEC_ENV_IS_WINDOWS)
435 if (test_interrupt_init() < 0) {
436 printf("fail to initialize for testing interrupt\n");
440 printf("Check unknown valid interrupt full path\n");
441 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) {
442 printf("failure occurred during checking unknown valid "
443 "interrupt full path\n");
447 printf("Check valid UIO interrupt full path\n");
448 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO)
450 printf("failure occurred during checking valid UIO interrupt "
455 printf("Check valid device event interrupt full path\n");
456 if (test_interrupt_full_path_check(
457 TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) {
458 printf("failure occurred during checking valid device event "
459 "interrupt full path\n");
463 printf("Check valid alarm interrupt full path\n");
464 if (test_interrupt_full_path_check(
465 TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) {
466 printf("failure occurred during checking valid alarm "
467 "interrupt full path\n");
471 printf("start register/unregister test\n");
472 /* check if it will fail to register cb with intr_handle = NULL */
473 if (rte_intr_callback_register(NULL, test_interrupt_callback,
475 printf("unexpectedly register successfully with null "
480 /* check if it will fail to register cb with invalid intr_handle */
481 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
482 if (rte_intr_callback_register(test_intr_handle,
483 test_interrupt_callback, test_intr_handle) == 0) {
484 printf("unexpectedly register successfully with invalid "
489 /* check if it will fail to register without callback */
490 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
491 if (rte_intr_callback_register(test_intr_handle, NULL,
492 test_intr_handle) == 0) {
493 printf("unexpectedly register successfully with "
498 /* check if it will fail to unregister cb with intr_handle = NULL */
499 if (rte_intr_callback_unregister(NULL,
500 test_interrupt_callback, NULL) > 0) {
501 printf("unexpectedly unregister successfully with "
502 "null intr_handle\n");
506 /* check if it will fail to unregister cb with invalid intr_handle */
507 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
508 if (rte_intr_callback_unregister(test_intr_handle,
509 test_interrupt_callback, test_intr_handle) > 0) {
510 printf("unexpectedly unregister successfully with "
511 "invalid intr_handle\n");
515 /* check if it is ok to register the same intr_handle twice */
516 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
517 if (rte_intr_callback_register(test_intr_handle,
518 test_interrupt_callback, test_intr_handle) < 0) {
519 printf("it fails to register test_interrupt_callback\n");
522 if (rte_intr_callback_register(test_intr_handle,
523 test_interrupt_callback_1, test_intr_handle) < 0) {
524 printf("it fails to register test_interrupt_callback_1\n");
527 /* check if it will fail to unregister with invalid parameter */
528 if (rte_intr_callback_unregister(test_intr_handle,
529 test_interrupt_callback, (void *)0xff) != 0) {
530 printf("unexpectedly unregisters successfully with "
534 if (rte_intr_callback_unregister(test_intr_handle,
535 test_interrupt_callback, test_intr_handle) <= 0) {
536 printf("it fails to unregister test_interrupt_callback\n");
539 if (rte_intr_callback_unregister(test_intr_handle,
540 test_interrupt_callback_1, (void *)-1) <= 0) {
541 printf("it fails to unregister test_interrupt_callback_1 "
545 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
547 printf("start interrupt enable/disable test\n");
548 /* check interrupt enable/disable functions */
549 if (test_interrupt_enable() < 0) {
550 printf("fail to check interrupt enabling\n");
553 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
555 if (test_interrupt_disable() < 0) {
556 printf("fail to check interrupt disabling\n");
559 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
564 printf("Clearing for interrupt tests\n");
565 /* clear registered callbacks */
566 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
567 rte_intr_callback_unregister(test_intr_handle,
568 test_interrupt_callback, (void *)-1);
569 rte_intr_callback_unregister(test_intr_handle,
570 test_interrupt_callback_1, (void *)-1);
572 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
573 rte_intr_callback_unregister(test_intr_handle,
574 test_interrupt_callback, (void *)-1);
575 rte_intr_callback_unregister(test_intr_handle,
576 test_interrupt_callback_1, (void *)-1);
578 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
579 rte_intr_callback_unregister(test_intr_handle,
580 test_interrupt_callback, (void *)-1);
581 rte_intr_callback_unregister(test_intr_handle,
582 test_interrupt_callback_1, (void *)-1);
584 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
585 rte_intr_callback_unregister(test_intr_handle,
586 test_interrupt_callback, (void *)-1);
587 rte_intr_callback_unregister(test_intr_handle,
588 test_interrupt_callback_1, (void *)-1);
590 rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
592 test_interrupt_deinit();
597 REGISTER_TEST_COMMAND(interrupt_autotest, test_interrupt);