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.
39 #include <cmdline_parse.h>
41 #include <rte_common.h>
42 #include <rte_cycles.h>
43 #include <rte_interrupts.h>
47 #define TEST_INTERRUPT_CHECK_INTERVAL 1000 /* ms */
49 enum test_interrupt_handl_type {
50 TEST_INTERRUPT_HANDLE_INVALID,
51 TEST_INTERRUPT_HANDLE_VALID,
52 TEST_INTERRUPT_HANDLE_CASE1,
53 TEST_INTERRUPT_HANDLE_MAX
56 static volatile int flag;
57 static struct rte_intr_handle intr_handles[TEST_INTERRUPT_HANDLE_MAX];
59 #ifdef RTE_EXEC_ENV_LINUXAPP
70 static union intr_pipefds pfds;
73 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
75 if (!intr_handle || intr_handle->fd < 0)
82 test_interrupt_init(void)
84 if (pipe(pfds.pipefd) < 0)
87 intr_handles[TEST_INTERRUPT_HANDLE_INVALID].fd = -1;
88 intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type = RTE_INTR_HANDLE_UNKNOWN;
90 intr_handles[TEST_INTERRUPT_HANDLE_VALID].fd = pfds.readfd;
91 intr_handles[TEST_INTERRUPT_HANDLE_VALID].type = RTE_INTR_HANDLE_UNKNOWN;
93 intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.readfd;
94 intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_ALARM;
100 test_interrupt_deinit(void)
102 close(pfds.pipefd[0]);
103 close(pfds.pipefd[1]);
109 test_interrupt_trigger_interrupt(void)
111 if (write(pfds.writefd, "1", 1) < 0)
118 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
119 struct rte_intr_handle *intr_handle_r)
121 if (!intr_handle_l || !intr_handle_r)
124 if (intr_handle_l->fd != intr_handle_r->fd ||
125 intr_handle_l->type != intr_handle_r->type)
132 /* to be implemented for baremetal later */
134 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
136 RTE_SET_USED(intr_handle);
142 test_interrupt_init(void)
148 test_interrupt_deinit(void)
154 test_interrupt_trigger_interrupt(void)
160 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
161 struct rte_intr_handle *intr_handle_r)
168 #endif /* RTE_EXEC_ENV_LINUXAPP */
171 test_interrupt_callback(struct rte_intr_handle *intr_handle, void *arg)
173 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
174 printf("null or invalid intr_handle for %s\n", __func__);
179 if (rte_intr_callback_unregister(intr_handle,
180 test_interrupt_callback, arg) >= 0) {
181 printf("%s: unexpectedly able to unregister itself\n",
187 if (test_interrupt_handle_compare(intr_handle,
188 &(intr_handles[TEST_INTERRUPT_HANDLE_VALID])) == 0) {
194 test_interrupt_callback_1(struct rte_intr_handle *intr_handle,
195 __attribute__((unused)) void *arg)
197 if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
198 printf("null or invalid intr_handle for %s\n", __func__);
205 test_interrupt_enable(void)
207 struct rte_intr_handle test_intr_handle;
209 /* check with null intr_handle */
210 if (rte_intr_enable(NULL) == 0) {
211 printf("unexpectedly enable null intr_handle successfully\n");
215 /* check with invalid intr_handle */
216 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
217 if (rte_intr_enable(&test_intr_handle) == 0) {
218 printf("unexpectedly enable invalid intr_handle "
223 /* check with valid intr_handle */
224 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
225 if (rte_intr_enable(&test_intr_handle) == 0) {
226 printf("unexpectedly enable a specific intr_handle "
231 /* check with specific valid intr_handle */
232 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
233 if (rte_intr_enable(&test_intr_handle) == 0) {
234 printf("unexpectedly enable a specific intr_handle "
243 test_interrupt_disable(void)
245 struct rte_intr_handle test_intr_handle;
247 /* check with null intr_handle */
248 if (rte_intr_disable(NULL) == 0) {
249 printf("unexpectedly disable null intr_handle "
254 /* check with invalid intr_handle */
255 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
256 if (rte_intr_disable(&test_intr_handle) == 0) {
257 printf("unexpectedly disable invalid intr_handle "
262 /* check with valid intr_handle */
263 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
264 if (rte_intr_disable(&test_intr_handle) == 0) {
265 printf("unexpectedly disable a specific intr_handle "
270 /* check with specific valid intr_handle */
271 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
272 if (rte_intr_disable(&test_intr_handle) == 0) {
273 printf("unexpectedly disable a specific intr_handle "
285 struct rte_intr_handle test_intr_handle;
287 if (test_interrupt_init() < 0) {
288 printf("fail to do test init\n");
292 printf("check if callback registered can be called\n");
296 /* check if callback registered can be called */
298 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
299 if (rte_intr_callback_register(&test_intr_handle,
300 test_interrupt_callback, NULL) < 0) {
301 printf("fail to register callback\n");
304 /* trigger an interrupt and then check if the callback can be called */
305 if (test_interrupt_trigger_interrupt() < 0) {
306 printf("fail to trigger an interrupt\n");
309 /* check flag in 3 seconds */
310 for (count = 0; flag == 0 && count < 3; count++)
311 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
313 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
315 if ((ret = rte_intr_callback_unregister(&test_intr_handle,
316 test_interrupt_callback, NULL)) < 0) {
317 printf("rte_intr_callback_unregister() failed with error "
325 printf("registered callback has not been called\n");
327 } else if (flag < 0) {
328 printf("registered callback failed\n");
333 printf("start register/unregister test\n");
335 /* check if it will fail to register cb with intr_handle = NULL */
336 if (rte_intr_callback_register(NULL, test_interrupt_callback,
338 printf("unexpectedly register successfully with null "
343 /* check if it will fail to register cb with invalid intr_handle */
344 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
345 if (rte_intr_callback_register(&test_intr_handle,
346 test_interrupt_callback, NULL) == 0) {
347 printf("unexpectedly register successfully with invalid "
352 /* check if it will fail to register without callback */
353 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
354 if (rte_intr_callback_register(&test_intr_handle, NULL, NULL) == 0) {
355 printf("unexpectedly register successfully with "
360 /* check if it will fail to unregister cb with intr_handle = NULL */
361 if (rte_intr_callback_unregister(NULL,
362 test_interrupt_callback, NULL) > 0) {
363 printf("unexpectedly unregister successfully with "
364 "null intr_handle\n");
368 /* check if it will fail to unregister cb with invalid intr_handle */
369 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
370 if (rte_intr_callback_unregister(&test_intr_handle,
371 test_interrupt_callback, NULL) > 0) {
372 printf("unexpectedly unregister successfully with "
373 "invalid intr_handle\n");
377 /* check if it is ok to register the same intr_handle twice */
378 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
379 if (rte_intr_callback_register(&test_intr_handle,
380 test_interrupt_callback, NULL) < 0) {
381 printf("it fails to register test_interrupt_callback\n");
384 if (rte_intr_callback_register(&test_intr_handle,
385 test_interrupt_callback_1, NULL) < 0) {
386 printf("it fails to register test_interrupt_callback_1\n");
389 /* check if it will fail to unregister with invalid parameter */
390 if (rte_intr_callback_unregister(&test_intr_handle,
391 test_interrupt_callback, (void *)0xff) != 0) {
392 printf("unexpectedly unregisters successfully with invalid arg\n");
395 if (rte_intr_callback_unregister(&test_intr_handle,
396 test_interrupt_callback, NULL) <= 0) {
397 printf("it fails to unregister test_interrupt_callback\n");
400 if (rte_intr_callback_unregister(&test_intr_handle,
401 test_interrupt_callback_1, (void *)-1) <= 0) {
402 printf("it fails to unregister test_interrupt_callback_1 "
406 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
408 printf("start interrupt enable/disable test\n");
410 /* check interrupt enable/disable functions */
411 if (test_interrupt_enable() < 0)
413 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
415 if (test_interrupt_disable() < 0)
417 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
422 /* clear registered callbacks */
423 test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
424 rte_intr_callback_unregister(&test_intr_handle,
425 test_interrupt_callback, (void *)-1);
426 rte_intr_callback_unregister(&test_intr_handle,
427 test_interrupt_callback_1, (void *)-1);
429 rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
431 test_interrupt_deinit();