X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=app%2Ftest%2Ftest_interrupts.c;h=233b14a70b20efd4f663475f66b89f191ce60e60;hb=cd9fa688ee1c1a6d29ea36420a6c39a98e6ae59c;hp=f16cf5a94a88f4fb65223ebd46588280853e236b;hpb=b6df9fc8715f9a925136006b18fdd65f9c621757;p=dpdk.git diff --git a/app/test/test_interrupts.c b/app/test/test_interrupts.c index f16cf5a94a..233b14a70b 100644 --- a/app/test/test_interrupts.c +++ b/app/test/test_interrupts.c @@ -1,62 +1,37 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation */ #include #include #include -#include - #include #include #include #include "test.h" -#define TEST_INTERRUPT_CHECK_INTERVAL 1000 /* ms */ +#define TEST_INTERRUPT_CHECK_INTERVAL 100 /* ms */ -enum test_interrupt_handl_type { +/* predefined interrupt handle types */ +enum test_interrupt_handle_type { TEST_INTERRUPT_HANDLE_INVALID, TEST_INTERRUPT_HANDLE_VALID, + TEST_INTERRUPT_HANDLE_VALID_UIO, + TEST_INTERRUPT_HANDLE_VALID_ALARM, + TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT, TEST_INTERRUPT_HANDLE_CASE1, TEST_INTERRUPT_HANDLE_MAX }; +/* flag of if callback is called */ static volatile int flag; static struct rte_intr_handle intr_handles[TEST_INTERRUPT_HANDLE_MAX]; +static enum test_interrupt_handle_type test_intr_type = + TEST_INTERRUPT_HANDLE_MAX; -#ifdef RTE_EXEC_ENV_LINUXAPP +#ifdef RTE_EXEC_ENV_LINUX union intr_pipefds{ struct { int pipefd[2]; @@ -69,6 +44,9 @@ union intr_pipefds{ static union intr_pipefds pfds; +/** + * Check if the interrupt handle is valid. + */ static inline int test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle) { @@ -78,6 +56,9 @@ test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle) return 0; } +/** + * Initialization for interrupt test. + */ static int test_interrupt_init(void) { @@ -85,17 +66,34 @@ test_interrupt_init(void) return -1; intr_handles[TEST_INTERRUPT_HANDLE_INVALID].fd = -1; - intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type = RTE_INTR_HANDLE_UNKNOWN; + intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type = + RTE_INTR_HANDLE_UNKNOWN; intr_handles[TEST_INTERRUPT_HANDLE_VALID].fd = pfds.readfd; - intr_handles[TEST_INTERRUPT_HANDLE_VALID].type = RTE_INTR_HANDLE_UNKNOWN; + intr_handles[TEST_INTERRUPT_HANDLE_VALID].type = + RTE_INTR_HANDLE_UNKNOWN; + + intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].fd = pfds.readfd; + intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].type = + RTE_INTR_HANDLE_UIO; - intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.readfd; - intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_ALARM; + intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].fd = pfds.readfd; + intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].type = + RTE_INTR_HANDLE_ALARM; + + intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT].fd = pfds.readfd; + intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT].type = + RTE_INTR_HANDLE_DEV_EVENT; + + intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.writefd; + intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_UIO; return 0; } +/** + * Deinitialization for interrupt test. + */ static int test_interrupt_deinit(void) { @@ -105,6 +103,9 @@ test_interrupt_deinit(void) return 0; } +/** + * Write the pipe to simulate an interrupt. + */ static int test_interrupt_trigger_interrupt(void) { @@ -114,6 +115,9 @@ test_interrupt_trigger_interrupt(void) return 0; } +/** + * Check if two interrupt handles are the same. + */ static int test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, struct rte_intr_handle *intr_handle_r) @@ -129,7 +133,7 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, } #else -/* to be implemented for baremetal later */ +/* to be implemented for bsd later */ static inline int test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle) { @@ -165,42 +169,57 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, return 0; } -#endif /* RTE_EXEC_ENV_LINUXAPP */ +#endif /* RTE_EXEC_ENV_LINUX */ +/** + * Callback for the test interrupt. + */ static void -test_interrupt_callback(struct rte_intr_handle *intr_handle, void *arg) +test_interrupt_callback(void *arg) { + struct rte_intr_handle *intr_handle = arg; + if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) { + printf("invalid interrupt type\n"); + flag = -1; + return; + } + if (test_interrupt_handle_sanity_check(intr_handle) < 0) { - printf("null or invalid intr_handle for %s\n", __FUNCTION__); + printf("null or invalid intr_handle for %s\n", __func__); + flag = -1; return; } if (rte_intr_callback_unregister(intr_handle, - test_interrupt_callback, arg) <= 0) { - printf("fail to unregister callback\n"); + test_interrupt_callback, arg) >= 0) { + printf("%s: unexpectedly able to unregister itself\n", + __func__); + flag = -1; return; } if (test_interrupt_handle_compare(intr_handle, - &(intr_handles[TEST_INTERRUPT_HANDLE_VALID])) == 0) { + &(intr_handles[test_intr_type])) == 0) flag = 1; - } } +/** + * Callback for the test interrupt. + */ static void -test_interrupt_callback_1(struct rte_intr_handle *intr_handle, void *arg) +test_interrupt_callback_1(void *arg) { + struct rte_intr_handle *intr_handle = arg; if (test_interrupt_handle_sanity_check(intr_handle) < 0) { - printf("null or invalid intr_handle for %s\n", __FUNCTION__); - return; - } - if (rte_intr_callback_unregister(intr_handle, - test_interrupt_callback_1, arg) <= 0) { - printf("fail to unregister callback\n"); + printf("null or invalid intr_handle for %s\n", __func__); + flag = -1; return; } } +/** + * Tests for rte_intr_enable(). + */ static int test_interrupt_enable(void) { @@ -229,7 +248,29 @@ test_interrupt_enable(void) } /* check with specific valid intr_handle */ + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; + if (rte_intr_enable(&test_intr_handle) == 0) { + printf("unexpectedly enable a specific intr_handle " + "successfully\n"); + return -1; + } + + /* check with specific valid intr_handle */ + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT]; + if (rte_intr_enable(&test_intr_handle) == 0) { + printf("unexpectedly enable a specific intr_handle " + "successfully\n"); + return -1; + } + + /* check with valid handler and its type */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1]; + if (rte_intr_enable(&test_intr_handle) < 0) { + printf("fail to enable interrupt on a simulated handler\n"); + return -1; + } + + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; if (rte_intr_enable(&test_intr_handle) == 0) { printf("unexpectedly enable a specific intr_handle " "successfully\n"); @@ -239,6 +280,9 @@ test_interrupt_enable(void) return 0; } +/** + * Tests for rte_intr_disable(). + */ static int test_interrupt_disable(void) { @@ -268,7 +312,29 @@ test_interrupt_disable(void) } /* check with specific valid intr_handle */ + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; + if (rte_intr_disable(&test_intr_handle) == 0) { + printf("unexpectedly disable a specific intr_handle " + "successfully\n"); + return -1; + } + + /* check with specific valid intr_handle */ + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT]; + if (rte_intr_disable(&test_intr_handle) == 0) { + printf("unexpectedly disable a specific intr_handle " + "successfully\n"); + return -1; + } + + /* check with valid handler and its type */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1]; + if (rte_intr_disable(&test_intr_handle) < 0) { + printf("fail to disable interrupt on a simulated handler\n"); + return -1; + } + + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; if (rte_intr_disable(&test_intr_handle) == 0) { printf("unexpectedly disable a specific intr_handle " "successfully\n"); @@ -278,43 +344,97 @@ test_interrupt_disable(void) return 0; } -int +/** + * Check the full path of a specified type of interrupt simulated. + */ +static int +test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type) +{ + int count; + struct rte_intr_handle test_intr_handle; + + flag = 0; + test_intr_handle = intr_handles[intr_type]; + test_intr_type = intr_type; + if (rte_intr_callback_register(&test_intr_handle, + test_interrupt_callback, &test_intr_handle) < 0) { + printf("fail to register callback\n"); + return -1; + } + + if (test_interrupt_trigger_interrupt() < 0) + return -1; + + /* check flag */ + for (count = 0; flag == 0 && count < 3; count++) + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); + + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); + while ((count = + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback, + &test_intr_handle)) < 0) { + if (count != -EAGAIN) + return -1; + } + + if (flag == 0) { + printf("callback has not been called\n"); + return -1; + } else if (flag < 0) { + printf("it has internal error in callback\n"); + return -1; + } + + return 0; +} + +/** + * Main function of testing interrupt. + */ +static int test_interrupt(void) { - int count = 0, ret = -1; + int ret = -1; struct rte_intr_handle test_intr_handle; if (test_interrupt_init() < 0) { - printf("fail to do test init\n"); + printf("fail to initialize for testing interrupt\n"); return -1; } - printf("check if callback registered can be called\n"); + printf("Check unknown valid interrupt full path\n"); + if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) { + printf("failure occurred during checking unknown valid " + "interrupt full path\n"); + goto out; + } - /* check if callback registered can be called */ - flag = 0; - test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; - if (rte_intr_callback_register(&test_intr_handle, - test_interrupt_callback, NULL) < 0) { - printf("fail to register callback\n"); + printf("Check valid UIO interrupt full path\n"); + if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO) + < 0) { + printf("failure occurred during checking valid UIO interrupt " + "full path\n"); goto out; } - /* trigger an interrupt and then check if the callback can be called */ - if (test_interrupt_trigger_interrupt() < 0) { - printf("fail to trigger an interrupt\n"); + + printf("Check valid device event interrupt full path\n"); + if (test_interrupt_full_path_check( + TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) { + printf("failure occurred during checking valid device event " + "interrupt full path\n"); goto out; } - /* check flag in 3 seconds */ - while (flag == 0 && count++ < 3) - rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); - if (flag == 0) { - printf("registered callback has not been called\n"); + + printf("Check valid alarm interrupt full path\n"); + if (test_interrupt_full_path_check( + TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) { + printf("failure occurred during checking valid alarm " + "interrupt full path\n"); goto out; } - rte_delay_ms(1000); printf("start register/unregister test\n"); - /* check if it will fail to register cb with intr_handle = NULL */ if (rte_intr_callback_register(NULL, test_interrupt_callback, NULL) == 0) { @@ -326,7 +446,7 @@ test_interrupt(void) /* check if it will fail to register cb with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_callback_register(&test_intr_handle, - test_interrupt_callback, NULL) == 0) { + test_interrupt_callback, &test_intr_handle) == 0) { printf("unexpectedly register successfully with invalid " "intr_handle\n"); goto out; @@ -334,7 +454,7 @@ test_interrupt(void) /* check if it will fail to register without callback */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; - if (rte_intr_callback_register(&test_intr_handle, NULL, NULL) == 0) { + if (rte_intr_callback_register(&test_intr_handle, NULL, &test_intr_handle) == 0) { printf("unexpectedly register successfully with " "null callback\n"); goto out; @@ -351,7 +471,7 @@ test_interrupt(void) /* check if it will fail to unregister cb with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_callback_unregister(&test_intr_handle, - test_interrupt_callback, NULL) > 0) { + test_interrupt_callback, &test_intr_handle) > 0) { printf("unexpectedly unregister successfully with " "invalid intr_handle\n"); goto out; @@ -360,23 +480,24 @@ test_interrupt(void) /* check if it is ok to register the same intr_handle twice */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; if (rte_intr_callback_register(&test_intr_handle, - test_interrupt_callback, NULL) < 0) { + test_interrupt_callback, &test_intr_handle) < 0) { printf("it fails to register test_interrupt_callback\n"); goto out; } if (rte_intr_callback_register(&test_intr_handle, - test_interrupt_callback_1, NULL) < 0) { + test_interrupt_callback_1, &test_intr_handle) < 0) { printf("it fails to register test_interrupt_callback_1\n"); goto out; } /* check if it will fail to unregister with invalid parameter */ if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, (void *)0xff) != 0) { - printf("unexpectedly unregisters successfully with invalid arg\n"); + printf("unexpectedly unregisters successfully with " + "invalid arg\n"); goto out; } if (rte_intr_callback_unregister(&test_intr_handle, - test_interrupt_callback, NULL) <= 0) { + test_interrupt_callback, &test_intr_handle) <= 0) { printf("it fails to unregister test_interrupt_callback\n"); goto out; } @@ -386,22 +507,26 @@ test_interrupt(void) "for all\n"); goto out; } - rte_delay_ms(1000); + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); printf("start interrupt enable/disable test\n"); - /* check interrupt enable/disable functions */ - if (test_interrupt_enable() < 0) + if (test_interrupt_enable() < 0) { + printf("fail to check interrupt enabling\n"); goto out; - rte_delay_ms(1000); + } + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); - if (test_interrupt_disable() < 0) + if (test_interrupt_disable() < 0) { + printf("fail to check interrupt disabling\n"); goto out; - rte_delay_ms(1000); + } + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); ret = 0; out: + printf("Clearing for interrupt tests\n"); /* clear registered callbacks */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; rte_intr_callback_unregister(&test_intr_handle, @@ -409,10 +534,29 @@ out: rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback_1, (void *)-1); - rte_delay_ms(2000); + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback, (void *)-1); + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback_1, (void *)-1); + + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback, (void *)-1); + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback_1, (void *)-1); + + test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT]; + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback, (void *)-1); + rte_intr_callback_unregister(&test_intr_handle, + test_interrupt_callback_1, (void *)-1); + + rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL); /* deinit */ test_interrupt_deinit(); return ret; } +REGISTER_TEST_COMMAND(interrupt_autotest, test_interrupt);