4 * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <cmdline_parse.h>
40 #include <rte_common.h>
41 #include <rte_cycles.h>
42 #include <rte_interrupts.h>
46 #define TEST_INTERRUPT_CHECK_INTERVAL 1000 /* ms */
48 /* predefined interrupt handle types */
49 enum test_interrupt_handle_type {
50 TEST_INTERRUPT_HANDLE_INVALID,
51 TEST_INTERRUPT_HANDLE_VALID,
52 TEST_INTERRUPT_HANDLE_VALID_UIO,
53 TEST_INTERRUPT_HANDLE_VALID_ALARM,
54 TEST_INTERRUPT_HANDLE_CASE1,
55 TEST_INTERRUPT_HANDLE_MAX
58 /* flag of if callback is called */
59 static volatile int flag;
60 static struct rte_intr_handle intr_handles[TEST_INTERRUPT_HANDLE_MAX];
61 static enum test_interrupt_handle_type test_intr_type =
62 TEST_INTERRUPT_HANDLE_MAX;
64 #ifdef RTE_EXEC_ENV_LINUXAPP
75 static union intr_pipefds pfds;
78 * Check if the interrupt handle is valid.
81 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
83 if (!intr_handle || intr_handle->fd < 0)
90 * Initialization for interrupt test.
93 test_interrupt_init(void)
95 if (pipe(pfds.pipefd) < 0)
98 intr_handles[TEST_INTERRUPT_HANDLE_INVALID].fd = -1;
99 intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type =
100 RTE_INTR_HANDLE_UNKNOWN;
102 intr_handles[TEST_INTERRUPT_HANDLE_VALID].fd = pfds.readfd;
103 intr_handles[TEST_INTERRUPT_HANDLE_VALID].type =
104 RTE_INTR_HANDLE_UNKNOWN;
106 intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].fd = pfds.readfd;
107 intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].type =
110 intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].fd = pfds.readfd;
111 intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].type =
112 RTE_INTR_HANDLE_ALARM;
114 intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.writefd;
115 intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_UIO;
121 * Deinitialization for interrupt test.
124 test_interrupt_deinit(void)
126 close(pfds.pipefd[0]);
127 close(pfds.pipefd[1]);
133 * Write the pipe to simulate an interrupt.
136 test_interrupt_trigger_interrupt(void)
138 if (write(pfds.writefd, "1", 1) < 0)
145 * Check if two interrupt handles are the same.
148 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
149 struct rte_intr_handle *intr_handle_r)
151 if (!intr_handle_l || !intr_handle_r)
154 if (intr_handle_l->fd != intr_handle_r->fd ||
155 intr_handle_l->type != intr_handle_r->type)
162 /* to be implemented for baremetal later */
164 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
166 RTE_SET_USED(intr_handle);
172 test_interrupt_init(void)
178 test_interrupt_deinit(void)
184 test_interrupt_trigger_interrupt(void)
190 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
191 struct rte_intr_handle *intr_handle_r)
198 #endif /* RTE_EXEC_ENV_LINUXAPP */
201 * Callback for the test interrupt.
204 test_interrupt_callback(struct rte_intr_handle *intr_handle, void *arg)
206 if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) {
207 printf("invalid interrupt type\n");
212 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
213 printf("null or invalid intr_handle for %s\n", __func__);
218 if (rte_intr_callback_unregister(intr_handle,
219 test_interrupt_callback, arg) >= 0) {
220 printf("%s: unexpectedly able to unregister itself\n",
226 if (test_interrupt_handle_compare(intr_handle,
227 &(intr_handles[test_intr_type])) == 0)
232 * Callback for the test interrupt.
235 test_interrupt_callback_1(struct rte_intr_handle *intr_handle,
236 __attribute__((unused)) void *arg)
238 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
239 printf("null or invalid intr_handle for %s\n", __func__);
246 * Tests for rte_intr_enable().
249 test_interrupt_enable(void)
251 struct rte_intr_handle test_intr_handle;
253 /* check with null intr_handle */
254 if (rte_intr_enable(NULL) == 0) {
255 printf("unexpectedly enable null intr_handle successfully\n");
259 /* check with invalid intr_handle */
260 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
261 if (rte_intr_enable(&test_intr_handle) == 0) {
262 printf("unexpectedly enable invalid intr_handle "
267 /* check with valid intr_handle */
268 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
269 if (rte_intr_enable(&test_intr_handle) == 0) {
270 printf("unexpectedly enable a specific intr_handle "
275 /* check with specific valid intr_handle */
276 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
277 if (rte_intr_enable(&test_intr_handle) == 0) {
278 printf("unexpectedly enable a specific intr_handle "
283 /* check with valid handler and its type */
284 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
285 if (rte_intr_enable(&test_intr_handle) < 0) {
286 printf("fail to enable interrupt on a simulated handler\n");
290 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
291 if (rte_intr_enable(&test_intr_handle) == 0) {
292 printf("unexpectedly enable a specific intr_handle "
301 * Tests for rte_intr_disable().
304 test_interrupt_disable(void)
306 struct rte_intr_handle test_intr_handle;
308 /* check with null intr_handle */
309 if (rte_intr_disable(NULL) == 0) {
310 printf("unexpectedly disable null intr_handle "
315 /* check with invalid intr_handle */
316 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
317 if (rte_intr_disable(&test_intr_handle) == 0) {
318 printf("unexpectedly disable invalid intr_handle "
323 /* check with valid intr_handle */
324 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
325 if (rte_intr_disable(&test_intr_handle) == 0) {
326 printf("unexpectedly disable a specific intr_handle "
331 /* check with specific valid intr_handle */
332 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
333 if (rte_intr_disable(&test_intr_handle) == 0) {
334 printf("unexpectedly disable a specific intr_handle "
339 /* check with valid handler and its type */
340 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
341 if (rte_intr_disable(&test_intr_handle) < 0) {
342 printf("fail to disable interrupt on a simulated handler\n");
346 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
347 if (rte_intr_disable(&test_intr_handle) == 0) {
348 printf("unexpectedly disable a specific intr_handle "
357 * Check the full path of a specified type of interrupt simulated.
360 test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type)
363 struct rte_intr_handle test_intr_handle;
366 test_intr_handle = intr_handles[intr_type];
367 test_intr_type = intr_type;
368 if (rte_intr_callback_register(&test_intr_handle,
369 test_interrupt_callback, NULL) < 0) {
370 printf("fail to register callback\n");
374 if (test_interrupt_trigger_interrupt() < 0)
377 /* check flag in 3 seconds */
378 for (count = 0; flag == 0 && count < 3; count++)
379 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
381 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
382 if (rte_intr_callback_unregister(&test_intr_handle,
383 test_interrupt_callback, NULL) < 0)
387 printf("callback has not been called\n");
389 } else if (flag < 0) {
390 printf("it has internal error in callback\n");
398 * Main function of testing interrupt.
404 struct rte_intr_handle test_intr_handle;
406 if (test_interrupt_init() < 0) {
407 printf("fail to initialize for testing interrupt\n");
411 printf("Check unknown valid interrupt full path\n");
412 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) {
413 printf("failure occured during checking unknown valid "
414 "interrupt full path\n");
418 printf("Check valid UIO interrupt full path\n");
419 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO)
421 printf("failure occured during checking valid UIO interrupt "
426 printf("Check valid alarm interrupt full path\n");
427 if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_ALARM)
429 printf("failure occured during checking valid alarm "
430 "interrupt full path\n");
434 printf("start register/unregister test\n");
435 /* check if it will fail to register cb with intr_handle = NULL */
436 if (rte_intr_callback_register(NULL, test_interrupt_callback,
438 printf("unexpectedly register successfully with null "
443 /* check if it will fail to register cb with invalid intr_handle */
444 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
445 if (rte_intr_callback_register(&test_intr_handle,
446 test_interrupt_callback, NULL) == 0) {
447 printf("unexpectedly register successfully with invalid "
452 /* check if it will fail to register without callback */
453 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
454 if (rte_intr_callback_register(&test_intr_handle, NULL, NULL) == 0) {
455 printf("unexpectedly register successfully with "
460 /* check if it will fail to unregister cb with intr_handle = NULL */
461 if (rte_intr_callback_unregister(NULL,
462 test_interrupt_callback, NULL) > 0) {
463 printf("unexpectedly unregister successfully with "
464 "null intr_handle\n");
468 /* check if it will fail to unregister cb with invalid intr_handle */
469 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
470 if (rte_intr_callback_unregister(&test_intr_handle,
471 test_interrupt_callback, NULL) > 0) {
472 printf("unexpectedly unregister successfully with "
473 "invalid intr_handle\n");
477 /* check if it is ok to register the same intr_handle twice */
478 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
479 if (rte_intr_callback_register(&test_intr_handle,
480 test_interrupt_callback, NULL) < 0) {
481 printf("it fails to register test_interrupt_callback\n");
484 if (rte_intr_callback_register(&test_intr_handle,
485 test_interrupt_callback_1, NULL) < 0) {
486 printf("it fails to register test_interrupt_callback_1\n");
489 /* check if it will fail to unregister with invalid parameter */
490 if (rte_intr_callback_unregister(&test_intr_handle,
491 test_interrupt_callback, (void *)0xff) != 0) {
492 printf("unexpectedly unregisters successfully with "
496 if (rte_intr_callback_unregister(&test_intr_handle,
497 test_interrupt_callback, NULL) <= 0) {
498 printf("it fails to unregister test_interrupt_callback\n");
501 if (rte_intr_callback_unregister(&test_intr_handle,
502 test_interrupt_callback_1, (void *)-1) <= 0) {
503 printf("it fails to unregister test_interrupt_callback_1 "
507 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
509 printf("start interrupt enable/disable test\n");
510 /* check interrupt enable/disable functions */
511 if (test_interrupt_enable() < 0) {
512 printf("fail to check interrupt enabling\n");
515 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
517 if (test_interrupt_disable() < 0) {
518 printf("fail to check interrupt disabling\n");
521 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
526 printf("Clearing for interrupt tests\n");
527 /* clear registered callbacks */
528 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
529 rte_intr_callback_unregister(&test_intr_handle,
530 test_interrupt_callback, (void *)-1);
531 rte_intr_callback_unregister(&test_intr_handle,
532 test_interrupt_callback_1, (void *)-1);
534 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
535 rte_intr_callback_unregister(&test_intr_handle,
536 test_interrupt_callback, (void *)-1);
537 rte_intr_callback_unregister(&test_intr_handle,
538 test_interrupt_callback_1, (void *)-1);
540 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
541 rte_intr_callback_unregister(&test_intr_handle,
542 test_interrupt_callback, (void *)-1);
543 rte_intr_callback_unregister(&test_intr_handle,
544 test_interrupt_callback_1, (void *)-1);
546 rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
548 test_interrupt_deinit();