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 (test_interrupt_init() < 0) {
433 printf("fail to initialize for testing interrupt\n");
437 printf("Check unknown valid interrupt full path\n");
438 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) {
439 printf("failure occurred during checking unknown valid "
440 "interrupt full path\n");
444 printf("Check valid UIO interrupt full path\n");
445 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO)
447 printf("failure occurred during checking valid UIO interrupt "
452 printf("Check valid device event interrupt full path\n");
453 if (test_interrupt_full_path_check(
454 TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) {
455 printf("failure occurred during checking valid device event "
456 "interrupt full path\n");
460 printf("Check valid alarm interrupt full path\n");
461 if (test_interrupt_full_path_check(
462 TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) {
463 printf("failure occurred during checking valid alarm "
464 "interrupt full path\n");
468 printf("start register/unregister test\n");
469 /* check if it will fail to register cb with intr_handle = NULL */
470 if (rte_intr_callback_register(NULL, test_interrupt_callback,
472 printf("unexpectedly register successfully with null "
477 /* check if it will fail to register cb with invalid intr_handle */
478 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
479 if (rte_intr_callback_register(test_intr_handle,
480 test_interrupt_callback, test_intr_handle) == 0) {
481 printf("unexpectedly register successfully with invalid "
486 /* check if it will fail to register without callback */
487 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
488 if (rte_intr_callback_register(test_intr_handle, NULL,
489 test_intr_handle) == 0) {
490 printf("unexpectedly register successfully with "
495 /* check if it will fail to unregister cb with intr_handle = NULL */
496 if (rte_intr_callback_unregister(NULL,
497 test_interrupt_callback, NULL) > 0) {
498 printf("unexpectedly unregister successfully with "
499 "null intr_handle\n");
503 /* check if it will fail to unregister cb with invalid intr_handle */
504 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
505 if (rte_intr_callback_unregister(test_intr_handle,
506 test_interrupt_callback, test_intr_handle) > 0) {
507 printf("unexpectedly unregister successfully with "
508 "invalid intr_handle\n");
512 /* check if it is ok to register the same intr_handle twice */
513 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
514 if (rte_intr_callback_register(test_intr_handle,
515 test_interrupt_callback, test_intr_handle) < 0) {
516 printf("it fails to register test_interrupt_callback\n");
519 if (rte_intr_callback_register(test_intr_handle,
520 test_interrupt_callback_1, test_intr_handle) < 0) {
521 printf("it fails to register test_interrupt_callback_1\n");
524 /* check if it will fail to unregister with invalid parameter */
525 if (rte_intr_callback_unregister(test_intr_handle,
526 test_interrupt_callback, (void *)0xff) != 0) {
527 printf("unexpectedly unregisters successfully with "
531 if (rte_intr_callback_unregister(test_intr_handle,
532 test_interrupt_callback, test_intr_handle) <= 0) {
533 printf("it fails to unregister test_interrupt_callback\n");
536 if (rte_intr_callback_unregister(test_intr_handle,
537 test_interrupt_callback_1, (void *)-1) <= 0) {
538 printf("it fails to unregister test_interrupt_callback_1 "
542 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
544 printf("start interrupt enable/disable test\n");
545 /* check interrupt enable/disable functions */
546 if (test_interrupt_enable() < 0) {
547 printf("fail to check interrupt enabling\n");
550 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
552 if (test_interrupt_disable() < 0) {
553 printf("fail to check interrupt disabling\n");
556 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
561 printf("Clearing for interrupt tests\n");
562 /* clear registered callbacks */
563 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
564 rte_intr_callback_unregister(test_intr_handle,
565 test_interrupt_callback, (void *)-1);
566 rte_intr_callback_unregister(test_intr_handle,
567 test_interrupt_callback_1, (void *)-1);
569 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
570 rte_intr_callback_unregister(test_intr_handle,
571 test_interrupt_callback, (void *)-1);
572 rte_intr_callback_unregister(test_intr_handle,
573 test_interrupt_callback_1, (void *)-1);
575 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
576 rte_intr_callback_unregister(test_intr_handle,
577 test_interrupt_callback, (void *)-1);
578 rte_intr_callback_unregister(test_intr_handle,
579 test_interrupt_callback_1, (void *)-1);
581 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
582 rte_intr_callback_unregister(test_intr_handle,
583 test_interrupt_callback, (void *)-1);
584 rte_intr_callback_unregister(test_intr_handle,
585 test_interrupt_callback_1, (void *)-1);
587 rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
589 test_interrupt_deinit();
594 REGISTER_TEST_COMMAND(interrupt_autotest, test_interrupt);