gpu: nvgpu: update queue unit tests

Update the unit tests for Posix queue implementation.
Add new tests to check the boundary values and modify some
of the existing tests according to the changes in queue
implementation.

JIRA NVGPU-6908

Change-Id: Ie216e1281ca0f354c66c458830ca1ac2193fddb9
Signed-off-by: ajesh <akv@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2536556
(cherry picked from commit 9a528c13093314296b928720d8f8ace3a5ddaf8a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2536970
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
ajesh
2021-05-28 21:11:27 +03:00
committed by mobile promotions
parent 3cd256b344
commit 966938d3e6
4 changed files with 186 additions and 49 deletions

View File

@@ -642,6 +642,7 @@ nvgpu_queue_in_locked
nvgpu_queue_out nvgpu_queue_out
nvgpu_queue_out_locked nvgpu_queue_out_locked
nvgpu_queue_out_get_fault_injection nvgpu_queue_out_get_fault_injection
nvgpu_queue_available
nvgpu_preempt_channel nvgpu_preempt_channel
nvgpu_preempt_get_timeout nvgpu_preempt_get_timeout
nvgpu_preempt_poll_tsg_on_pbdma nvgpu_preempt_poll_tsg_on_pbdma

View File

@@ -659,6 +659,7 @@ nvgpu_queue_in_locked
nvgpu_queue_out nvgpu_queue_out
nvgpu_queue_out_locked nvgpu_queue_out_locked
nvgpu_queue_out_get_fault_injection nvgpu_queue_out_get_fault_injection
nvgpu_queue_available
nvgpu_preempt_channel nvgpu_preempt_channel
nvgpu_preempt_get_timeout nvgpu_preempt_get_timeout
nvgpu_preempt_poll_tsg_on_pbdma nvgpu_preempt_poll_tsg_on_pbdma

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -98,6 +98,14 @@ int test_nvgpu_queue_alloc_and_free(struct unit_module *m, struct gk20a *g,
} }
nvgpu_queue_free(&q); nvgpu_queue_free(&q);
ret = nvgpu_queue_alloc(&q, (unsigned int)INT32_MAX);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
nvgpu_queue_free(&q);
fail: fail:
return err; return err;
} }
@@ -119,9 +127,10 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
goto fail; goto fail;
} }
#ifdef CONFIG_NVGPU_NON_FUSA
/* Enqueue message of length BUF_LEN */ /* Enqueue message of length BUF_LEN */
ret = nvgpu_queue_in(&q, buf, BUF_LEN); ret = nvgpu_queue_in(&q, buf, BUF_LEN);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
@@ -134,12 +143,12 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
q.in = BUF_LEN; q.in = BUF_LEN;
q.out = BUF_LEN; q.out = BUF_LEN;
ret = nvgpu_queue_in(&q, buf, BUF_LEN); ret = nvgpu_queue_in(&q, buf, BUF_LEN);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#endif
/* /*
* Reset "in" and "out" indexes and enqueue message of length BUF_LEN * Reset "in" and "out" indexes and enqueue message of length BUF_LEN
* with the lock. * with the lock.
@@ -147,7 +156,7 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
q.in = 0; q.in = 0;
q.out = 0; q.out = 0;
ret = nvgpu_queue_in_locked(&q, buf, BUF_LEN, &lock); ret = nvgpu_queue_in_locked(&q, buf, BUF_LEN, &lock);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
@@ -161,6 +170,16 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
goto fail; goto fail;
} }
q.in = (UINT32_MAX - (BUF_LEN/2));
q.out = q.in;
ret = nvgpu_queue_in_locked(&q, buf, BUF_LEN, &lock);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. queue in failed err=%d\n", __LINE__, ret);
goto fail;
}
#ifdef CONFIG_NVGPU_NON_FUSA
/* Enqueue message of length BUF_LEN again (without lock) and expect /* Enqueue message of length BUF_LEN again (without lock) and expect
* memory full. * memory full.
*/ */
@@ -170,6 +189,7 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#endif
fail: fail:
if (q.data != NULL) if (q.data != NULL)
@@ -198,6 +218,7 @@ int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args)
goto fail; goto fail;
} }
#ifdef CONFIG_NVGPU_NON_FUSA
/* Queue is empty. Dequeue message should return "-ENOMEM" */ /* Queue is empty. Dequeue message should return "-ENOMEM" */
ret = nvgpu_queue_out(&q, buf, BUF_LEN); ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != -ENOMEM) { if (ret != -ENOMEM) {
@@ -205,6 +226,7 @@ int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args)
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#endif
/* Queue is empty. Dequeue message with lock should return "-ENOMEM" */ /* Queue is empty. Dequeue message with lock should return "-ENOMEM" */
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock); ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
@@ -214,18 +236,19 @@ int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args)
goto fail; goto fail;
} }
#ifdef CONFIG_NVGPU_NON_FUSA
/* /*
* Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN * Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN
*/ */
q.in = BUF_LEN; q.in = BUF_LEN;
q.out = 0; q.out = 0;
ret = nvgpu_queue_out(&q, buf, BUF_LEN); ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#endif
/* /*
* Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN * Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN
* with the lock. * with the lock.
@@ -233,24 +256,35 @@ int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args)
q.in = BUF_LEN; q.in = BUF_LEN;
q.out = 0; q.out = 0;
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock); ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#ifdef CONFIG_NVGPU_NON_FUSA
/* /*
* Update "in" and "out" indexes and dequeue message of length BUF_LEN * Update "in" and "out" indexes and dequeue message of length BUF_LEN
* such that we wrap around the Queue while dequeuing the message. * such that we wrap around the Queue while dequeuing the message.
*/ */
q.in = 1; q.in = 0;
q.out = QUEUE_LEN_POW_2 -(BUF_LEN -1); q.out = UINT32_MAX - BUF_LEN;
ret = nvgpu_queue_out(&q, buf, BUF_LEN); ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != BUF_LEN) { if (ret != 0) {
err = UNIT_FAIL; err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret); unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail; goto fail;
} }
#endif
q.in = 0;
q.out = UINT32_MAX - BUF_LEN;
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. queue in failed err=%d\n", __LINE__, ret);
goto fail;
}
/* /*
* Fault injection so that immediate call to nvgpu_queue_out_locked() * Fault injection so that immediate call to nvgpu_queue_out_locked()
@@ -274,11 +308,70 @@ fail:
return err; return err;
} }
int test_nvgpu_queue_available(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret = 0, err = UNIT_SUCCESS;
unsigned int count = 0;
struct nvgpu_queue q = {0};
struct nvgpu_mutex lock;
nvgpu_mutex_init(&lock);
ret = nvgpu_queue_alloc(&q, QUEUE_LEN_POW_2);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_alloc failed err=%d\n", __LINE__, ret);
goto fail;
}
q.out = 10;
q.in = 10;
count = nvgpu_queue_available(&q);
if (count != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. incorrect queue available count=%d\n",
__LINE__, count);
goto fail;
}
q.out = 0;
q.in = BUF_LEN;
count = nvgpu_queue_available(&q);
if (count != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. incorrect queue available count=%d\n",
__LINE__, count);
goto fail;
}
/*
* This is to test the wrap around condition for IN index.
*/
q.out = UINT32_MAX - (BUF_LEN - 1);
q.in = 0;
count = nvgpu_queue_available(&q);
if (count != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. Invalid out index accepted, count=%d\n",
__LINE__, count);
goto fail;
}
fail:
if (q.data != NULL)
free(q.data);
nvgpu_mutex_destroy(&lock);
return err;
}
struct unit_module_test posix_queue_tests[] = { struct unit_module_test posix_queue_tests[] = {
UNIT_TEST(nvgpu_queue_alloc_free, test_nvgpu_queue_alloc_and_free, UNIT_TEST(nvgpu_queue_alloc_free, test_nvgpu_queue_alloc_and_free,
NULL, 0), NULL, 0),
UNIT_TEST(nvgpu_queue_in, test_nvgpu_queue_in, NULL, 0), UNIT_TEST(nvgpu_queue_in, test_nvgpu_queue_in, NULL, 0),
UNIT_TEST(nvgpu_queue_out, test_nvgpu_queue_out, NULL, 0), UNIT_TEST(nvgpu_queue_out, test_nvgpu_queue_out, NULL, 0),
UNIT_TEST(nvgpu_queue_available, test_nvgpu_queue_available,
NULL, 0),
}; };
UNIT_MODULE(posix_queue, posix_queue_tests, UNIT_PRIO_POSIX_TEST); UNIT_MODULE(posix_queue, posix_queue_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -44,25 +44,30 @@
* *
* Steps: * Steps:
* - Pass NULL nvgpu_queue pointer as argument to nvgpu_queue_alloc() API and * - Pass NULL nvgpu_queue pointer as argument to nvgpu_queue_alloc() API and
* check that the API returns "-EINVAL" error. * check that the API returns -EINVAL error.
* - Pass zero size queue length as argument to nvgpu_queue_alloc() API and * - Pass zero size queue length as argument to nvgpu_queue_alloc() API and
* check that the API returns "-EINVAL" error. * check that the API returns -EINVAL error.
* - Pass "INT64_MAX" size queue length as argument to nvgpu_queue_alloc() API * - Pass INT64_MAX size queue length as argument to nvgpu_queue_alloc() API
* and check that the API returns "-EINVAL" error. * and check that the API returns -EINVAL error.
* - Inject fault so that immediate call to nvgpu_kzalloc() API would fail. * - Inject fault so that immediate call to nvgpu_kzalloc() API would fail.
* - Check that when the nvgpu_queue_alloc() API is called with valid arguments, * - Check that when the nvgpu_queue_alloc() API is called with valid arguments,
* it would fail by returning "-ENOMEM" error. * it would fail by returning -ENOMEM error.
* - Remove the injected fault in nvgpu_kzalloc() API. * - Remove the injected fault in nvgpu_kzalloc() API.
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the * - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success. * API returns success.
* - Valid pointer to "struct nvgpu_queue" * - Valid pointer to struct nvgpu_queue
* - Queue size which is not power of 2 * - Queue size which is not power of 2
* - Free the allocated queue by caling nvgpu_queue_free() API. * - Free the allocated queue by caling nvgpu_queue_free() API.
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the * - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success. * API returns success.
* - Valid pointer to "struct nvgpu_queue" * - Valid pointer to struct nvgpu_queue
* - Queue size which is power of 2 * - Queue size which is power of 2
* - Free the allocated queue by caling nvgpu_queue_free() API. * - Free the allocated queue by caling nvgpu_queue_free() API.
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success.
* - Valid pointer to struct nvgpu_queue
* - Queue size equal to INT32_MAX
* - Free the allocated queue by caling nvgpu_queue_free() API.
* *
* Output: Returns PASS if the steps above were executed successfully. FAIL * Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise. * otherwise.
@@ -86,21 +91,25 @@ int test_nvgpu_queue_alloc_and_free(struct unit_module *m, struct gk20a *g,
* Steps: * Steps:
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the * - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success. * API returns success.
* - Valid pointer to "struct nvgpu_queue" * - Valid pointer to struct nvgpu_queue
* - Queue size which is power of 2 * - Queue size which is power of 2 and less than INT_MAX, exact value used
* - Enqueue message of length "BUF_LEN" calling nvgpu_queue_in() API and check * is 16.
* that the API returns "BUF_LEN". * - Enqueue message of length BUF_LEN calling nvgpu_queue_in() API and check
* - Update "in" and "out" indexes and enqueue message of length BUF_LEN such * that the API returns 0.
* - Update In and Out indexes and enqueue message of length BUF_LEN such
* that we wrap around the Queue while enqueuing the message using * that we wrap around the Queue while enqueuing the message using
* nvgpu_queue_in() API. Check that the API returns "BUF_LEN". * nvgpu_queue_in() API. Check that the API returns 0.
* - Reset "in" and "out" indexes and enqueue message of length "BUF_LEN" with * - Reset In and Out indexes and enqueue message of length BUF_LEN with
* the lock using nvgpu_queue_in_locked() API. Check that the API returns * the lock using nvgpu_queue_in_locked() API. Check that the API returns 0.
* "BUF_LEN". * - Enqueue message of length BUF_LEN again using nvgpu_queue_in_locked()
* - Enqueue message of length "BUF_LEN" again using nvgpu_queue_in_locked() * API. Check that the API returns error -ENOMEM.
* API. Check that the API returns error "-ENOMEM". * - Set In and Out index to UINT32_MAX - BUf_LEN/2, which indicates that the
* - Enqueue message of length "BUF_LEN" again using nvgpu_queue_in() API. Check * queue is empty and try to enqueue BUF_LEN size message. This should cause
* that the API returns error "-ENOMEM". * a wrap around of In index, but the API should be able to handle it and
* - Uninitialize the allocated resources. * return 0 to indicate successful enqueue operation.
* - Enqueue message of length BUF_LEN again using nvgpu_queue_in() API. Check
* that the API returns error -ENOMEM.
* - Free the allocated resources.
* *
* Output: Returns PASS if the steps above were executed successfully. FAIL * Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise. * otherwise.
@@ -122,32 +131,65 @@ int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args);
* Steps: * Steps:
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the * - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success. * API returns success.
* - Valid pointer to "struct nvgpu_queue" * - Valid pointer to struct nvgpu_queue
* - Queue size which is power of 2 * - Queue size which is power of 2 and less than INT_MAX. Exact value used
* - Dequeue message of length "BUF_LEN" from the empty queue calling * is 16.
* nvgpu_queue_out() API and check that the API returns "-ENOMEM" error. * - Dequeue message of length BUF_LEN from the empty queue calling
* - Dequeue message of length "BUF_LEN" from the empty queue calling * nvgpu_queue_out() API and check that the API returns -ENOMEM error.
* nvgpu_queue_out_locked() API and check that the API returns "-ENOMEM" * - Dequeue message of length BUF_LEN from the empty queue calling
* nvgpu_queue_out_locked() API and check that the API returns -ENOMEM
* error. * error.
* - Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN by * - Set In index as BUF_LEN and dequeue message of length BUF_LEN by
* calling nvgpu_queue_out() API and check that the API returns "BUF_LEN". * calling nvgpu_queue_out() API and check that the API returns 0.
* - Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN by * - Set In index as BUF_LEN and dequeue message of length BUF_LEN by
* calling nvgpu_queue_out_locked() API and check that the API returns * calling nvgpu_queue_out_locked() API and check that the API returns 0.
* "BUF_LEN". * - Set In index as 0 and Out index as (UINT32_MAX - BUF_LEN). This
* - Update "in" and "out" indexes and dequeue message of length BUF_LEN such * indicates a condition were In index has wrapped around due to an enqueue
* that we wrap around the Queue while dequeuing the message using * operation. Use nvgpu_queue_out API to dequeue message of length BUF_LEN.
* nvgpu_queue_out() API. Check that the API returns "BUF_LEN". * The dequeue operation should successfully return 0.
* - Repeat the above step to test API nvgpu_queue_out_locked.
* - Do fault injection so that immediate call to nvgpu_queue_out_locked() API * - Do fault injection so that immediate call to nvgpu_queue_out_locked() API
* would return error. * would return error.
* - Invoke nvgpu_queue_out_locked() API and check that API returns -1 error. * - Invoke nvgpu_queue_out_locked() API and check that API returns -1 error.
* - Remove the injected fault. * - Remove the injected fault.
* - Uninitialize the allocated resources. * - Free the allocated resources.
* *
* Output: Returns PASS if the steps above were executed successfully. FAIL * Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise. * otherwise.
*/ */
int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args); int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_queue_available
*
* Description: Test the functionality of the function which returns the
* available data in the queue.
*
* Test Type: Feature
*
* Targets: nvgpu_queue_available
*
* Input: None
*
* Steps:
* - The following combinations of Out and In index values are provided to the
* public API,
* - Out and In are populated with same value. Expected return value is 0.
* - Out is populated with a value less than In. The difference is less than
* the size allocated for the queue. Expected return value is the difference
* between In and Out values indicating the number of bytes of data present
* in the queue.
* - Out is populated with a value greater than In. This scenario can happen
* when In index is wrapped around explicitly. The API should handle this
* scenario and return the valid number of bytes present in the queue. Out
* and In value are selected so as the size of the queue is not violated.
*
* Output: Returns PASS if the steps above returns expected values, FAIL
* otherwise.
*/
int test_nvgpu_queue_available(struct unit_module *m, struct gk20a *g,
void *args);
#endif /* __UNIT_POSIX_QUEUE_H__ */ #endif /* __UNIT_POSIX_QUEUE_H__ */
/* /*
* @} * @}