blob: 89799dc9fba669ff2b0d52757b1b69d1d3fe9723 [file] [log] [blame]
/*
* Samsung Exynos SoC series NPU driver
*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifdef IDIOT_DECL_SECTION
#include "npu-config.h"
#include "npu-util-llq.h"
#include "npu-util-autosleepthr.h"
#include "npu-errno.h"
#include "npu-if-protodrv-mbox2.h"
#include "npu-if-session-protodrv.h"
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/random.h>
#define PROTODRV_04_UID_CNT 5
#define PROTODRV_04_REPEAT_CNT 1024
int uids[PROTODRV_04_UID_CNT] = {0};
int idxes[PROTODRV_04_REPEAT_CNT] = {0};
enum PROTODRV_IDIOT_MSG_STATE {
MSG_STATE_FREE = 0,
MSG_STATE_REQUESTED,
MSG_STATE_DONE,
MSG_STATE_MODIFYING = 100,
};
enum protodrv_mock_result {
EXPECT_UNINITIALIZED,
EXPECT_FAILED,
EXPECT_SUCCESS,
};
/* Compare constants */
static const u32 OK = 0;
static const u32 LAST = 1;
static const u32 NOT_LAST = 0;
/* A dummy device used as a parameter to probe/close function of protodrv */
struct npu_device dummy_device_4_test = {.dev=NULL};
/* Forward declaration */
void mbox_mock_signal(void);
LLQ_DECLARE(nw_result_q, int, NPU_MAX_MSG_ID_CNT);
LLQ_DECLARE(frame_result_q, int, NPU_MAX_MSG_ID_CNT);
struct expected_flag {
u32 setup;
int hw_response;
enum protodrv_mock_result result;
};
/* Autosleep thread for Dummy Mailbox manager */
static struct mbox_mock_protodrv {
struct auto_sleep_thread ast;
struct auto_sleep_thread_param ast_param;
atomic_t nw_used[NPU_MAX_MSG_ID_CNT];
atomic_t frame_used[NPU_MAX_MSG_ID_CNT];
struct npu_nw nw_msg[NPU_MAX_MSG_ID_CNT];
struct npu_frame frame_msg[NPU_MAX_MSG_ID_CNT];
struct expected_flag nw_expected_flag;
struct expected_flag frame_expected_flag;
struct expected_flag frame_timeout_flag;
struct npu_nw nw_expected;
struct npu_frame frame_expected;
struct npu_frame frame_timeout;
protodrv_notifier send_notify_func;
int (*msgid_get_type)(int);
} mbox_mock_protodrv;
struct session_mock_protodrv {
atomic_t wait_signal;
volatile struct nw_result nw_result;
volatile unsigned long frame_result;
volatile int frame_done_cnt;
};
/* Global session reference */
static struct protodrv_test_session {
struct npu_session sess;
struct session_mock_protodrv session_mock;
struct npu_queue npu_queue; /* Dummy queue to keep track of session */
} *protodrv_test_session;
/* Convinient reference to first session */
static struct npu_session* test_sess;
/*************************************************************************
* session_mock_protodrv operation
*/
struct session_mock_protodrv *session_mock_ref(const int sess_idx)
{
return &protodrv_test_session[sess_idx].session_mock;
}
static void session_mock_prepare_wait(const int sess_idx)
{
atomic_set(&protodrv_test_session[sess_idx].session_mock.wait_signal, 0);
protodrv_test_session[sess_idx].session_mock.frame_result = 0xDEADFFFF;
protodrv_test_session[sess_idx].session_mock.nw_result.result_code = 0xDEAD4444;
}
static int session_mock_is_done(const int sess_idx)
{
return atomic_read(&protodrv_test_session[sess_idx].session_mock.wait_signal) == 1;
}
static unsigned long session_mock_get_frame_result(const int sess_idx)
{
return protodrv_test_session[sess_idx].session_mock.frame_result;
}
static void session_mock_set_frame_result(const int sess_idx, const unsigned long result_code)
{
protodrv_test_session[sess_idx].session_mock.frame_result = result_code;
}
static struct nw_result session_mock_get_nw_result(const int sess_idx)
{
return protodrv_test_session[sess_idx].session_mock.nw_result;
}
static int session_mock_save_result(struct npu_session *sess, struct nw_result result)
{
struct protodrv_test_session *ts;
if (!sess)
ts = &protodrv_test_session[0];
else
ts = container_of(sess, struct protodrv_test_session, sess);
ts->session_mock.nw_result = result;
atomic_set(&ts->session_mock.wait_signal, 1);
return 0;
}
static void session_mock_queue_done(struct npu_queue *queue,
struct vb_container_list *in_cl, struct vb_container_list *ot_cl, unsigned long result)
{
struct protodrv_test_session *ts;
if (!queue)
ts = &protodrv_test_session[0];
else
ts = container_of(queue, struct protodrv_test_session, npu_queue);
ts->session_mock.frame_result = result;
ts->session_mock.frame_done_cnt++;
}
struct npu_if_session_protodrv_ops npu_protodrv_session_if_ops = {
.queue_done = session_mock_queue_done,
};
static struct npu_if_session_protodrv_ops npu_protodrv_session_if_ops_backup;
/*************************************************************************
* mbox_mock_protodrv operation
*/
static void reset_mbox_mock(void)
{
memset(&mbox_mock_protodrv, 0, sizeof(struct mbox_mock_protodrv));
}
static void __set_frame_expectation(struct npu_frame* frame)
{
mbox_mock_protodrv.frame_expected = *frame;
mbox_mock_protodrv.frame_expected_flag.setup = 1;
mbox_mock_protodrv.frame_expected_flag.result = EXPECT_FAILED;
}
static void set_frame_expectation(struct npu_frame* frame)
{
__set_frame_expectation(frame);
mbox_mock_protodrv.frame_expected_flag.hw_response = 0; /* DONE */
}
__attribute__((unused)) static void set_frame_ndone_expectation(struct npu_frame* frame)
{
__set_frame_expectation(frame);
mbox_mock_protodrv.frame_expected_flag.hw_response = 1; /* NDONE */
}
static void set_frame_timeout(struct npu_frame* frame)
{
mbox_mock_protodrv.frame_timeout = *frame;
mbox_mock_protodrv.frame_timeout_flag.setup = 1;
mbox_mock_protodrv.frame_timeout_flag.result = EXPECT_FAILED;
}
static enum protodrv_mock_result check_frame_expectation(void)
{
if (mbox_mock_protodrv.frame_expected_flag.setup) {
mbox_mock_protodrv.frame_expected_flag.setup = 0;
return mbox_mock_protodrv.frame_expected_flag.result;
} else
return EXPECT_UNINITIALIZED;
}
static enum protodrv_mock_result peek_frame_expectation(void)
{
if (mbox_mock_protodrv.frame_expected_flag.setup)
return mbox_mock_protodrv.frame_expected_flag.result;
else
return EXPECT_UNINITIALIZED;
}
static void __set_nw_expectation(struct npu_nw* nw)
{
mbox_mock_protodrv.nw_expected = *nw;
mbox_mock_protodrv.nw_expected_flag.setup = 1;
mbox_mock_protodrv.nw_expected_flag.result = EXPECT_FAILED;
}
static void set_nw_expectation(struct npu_nw* nw)
{
__set_nw_expectation(nw);
mbox_mock_protodrv.nw_expected_flag.hw_response = 0; /* DONE */
}
__attribute__((unused)) static void set_nw_ndone_expectation(struct npu_nw* nw)
{
__set_nw_expectation(nw);
mbox_mock_protodrv.nw_expected_flag.hw_response = 1; /* NDONE */
}
static enum protodrv_mock_result check_nw_expectation(void)
{
if (mbox_mock_protodrv.nw_expected_flag.setup) {
mbox_mock_protodrv.nw_expected_flag.setup = 0;
return mbox_mock_protodrv.nw_expected_flag.result;
} else
return EXPECT_UNINITIALIZED;
}
/*************************************************************************
* Interfacing functions
*/
static int protodrv_idiot_frame_result_available(void)
{
return !LLQ_IS_EMPTY(frame_result_q);
}
static int protodrv_idiot_frame_post_request(int msgid, struct npu_frame *frame)
{
if (atomic_cmpxchg(&mbox_mock_protodrv.frame_used[msgid], MSG_STATE_FREE, MSG_STATE_MODIFYING) == MSG_STATE_FREE) {
/* 100 - Writing message */
memcpy(&mbox_mock_protodrv.frame_msg[msgid], frame, sizeof(*frame));
atomic_set(&mbox_mock_protodrv.frame_used[msgid], MSG_STATE_REQUESTED);
mbox_mock_signal();
return 1;
}
return 0;
}
static int protodrv_idiot_frame_get_result(int *ret_msgid, struct npu_frame *frame)
{
int ret = LLQ_GET(frame_result_q, ret_msgid);
if (ret) {
/* Valid result */
*frame = mbox_mock_protodrv.frame_msg[*ret_msgid];
atomic_set(&mbox_mock_protodrv.frame_used[*ret_msgid], MSG_STATE_FREE);
}
return ret;
}
static int protodrv_idiot_nw_result_available(void)
{
return !LLQ_IS_EMPTY(nw_result_q);
}
static int protodrv_idiot_nw_post_request(int msgid, struct npu_nw *nw)
{
if (atomic_cmpxchg(&mbox_mock_protodrv.nw_used[msgid], MSG_STATE_FREE, MSG_STATE_MODIFYING) == MSG_STATE_FREE) {
/* 100 - Writing message */
memcpy(&mbox_mock_protodrv.nw_msg[msgid], nw, sizeof(*nw));
atomic_set(&mbox_mock_protodrv.nw_used[msgid], MSG_STATE_REQUESTED);
mbox_mock_signal();
return 1;
}
return 0;
}
static int protodrv_idiot_nw_get_result(int *ret_msgid, struct npu_nw *nw)
{
int ret = LLQ_GET(nw_result_q, ret_msgid);
if (ret) {
/* Valid result */
*nw = mbox_mock_protodrv.nw_msg[*ret_msgid];
atomic_set(&mbox_mock_protodrv.nw_used[*ret_msgid], MSG_STATE_FREE);
}
return ret;
}
static int protodrv_idiot_register_notifier(protodrv_notifier sig_func)
{
if (sig_func) {
mbox_mock_protodrv.send_notify_func = sig_func;
return 0;
}
return -EINVAL;
}
static int protodrv_idiot_register_msgid_type_getter(int (*msgid_get_type_func)(int))
{
if (msgid_get_type_func) {
mbox_mock_protodrv.msgid_get_type = msgid_get_type_func;
return 0;
}
return -EINVAL;
}
static struct npu_if_protodrv_mbox_ops npu_protodrv_idiot_mbox_ops = {
.frame_result_available = protodrv_idiot_frame_result_available,
.frame_post_request = protodrv_idiot_frame_post_request,
.frame_get_result = protodrv_idiot_frame_get_result,
.nw_result_available = protodrv_idiot_nw_result_available,
.nw_post_request = protodrv_idiot_nw_post_request,
.nw_get_result = protodrv_idiot_nw_get_result,
.register_notifier = protodrv_idiot_register_notifier,
.register_msgid_type_getter = protodrv_idiot_register_msgid_type_getter,
};
static struct npu_if_protodrv_mbox_ops npu_protodrv_idiot_mbox_ops_backup;
/* Operations for mbox_mock_lsm */
#define BASIC_DO_TASK_RESULT_CODE_NW 0
#define BASIC_DO_TASK_RESULT_CODE_FRAME 0
#define BASIC_DO_TASK_NDONE_CODE_NW 1
#define BASIC_DO_TASK_NDONE_CODE_FRAME 1
#define TIMEOUT_DELAY_NS ((s64)(20L * S2N))
int mbox_mock_do_task(struct auto_sleep_thread_param* data) {
struct npu_nw *nw_req;
struct npu_frame *frame_req;
int ret = 0;
int i;
static int is_keeping = 0;
static int keep_idx = -1;
static s64 keep_time;
/* Frame request */
for (i = 0; i < NPU_MAX_MSG_ID_CNT; i++) {
if (atomic_read(&mbox_mock_protodrv.frame_used[i]) == MSG_STATE_REQUESTED) {
frame_req = &mbox_mock_protodrv.frame_msg[i];
BUG_ON(mbox_mock_protodrv.msgid_get_type(i) != PROTO_DRV_REQ_TYPE_FRAME);
if (is_keeping == 1 && keep_idx == i) {
/* Check timed out frame */
if (get_time_ns() > keep_time + TIMEOUT_DELAY_NS) {
npu_dbg("Current(%lld) / keep (%lld) / Delay (%lld)\n",
get_time_ns(), keep_time, TIMEOUT_DELAY_NS);
while(LLQ_PUT(frame_result_q, keep_idx) == 0) {
/* Wait until the output queue is available */
msleep(1);
}
atomic_set(&mbox_mock_protodrv.frame_used[keep_idx], MSG_STATE_DONE);
npu_dbg("Timeout frame released - ID[%d]\n", keep_idx);
ret++;
is_keeping = 0;
keep_idx = -1;
}
} else if (mbox_mock_protodrv.frame_timeout_flag.setup
&& (mbox_mock_protodrv.frame_timeout.uid == frame_req->uid)
&& (mbox_mock_protodrv.frame_timeout.frame_id == frame_req->frame_id)
&& (mbox_mock_protodrv.frame_timeout.input == frame_req->input)
&& (mbox_mock_protodrv.frame_timeout.output == frame_req->output)
&& (mbox_mock_protodrv.frame_timeout.cmd == frame_req->cmd)) {
/* Keep the frame, until got the RESUME ID */
is_keeping = 1;
keep_idx = i;
keep_time = get_time_ns();
npu_dbg("Timeout frame kept ID[%d][uid=%u][in=%p][out=%p]\n",
i, frame_req->uid, frame_req->input, frame_req->output);
ret++;
} else {
/* Compare to expectation */
if (mbox_mock_protodrv.frame_expected_flag.setup) {
if ((mbox_mock_protodrv.frame_expected.uid == frame_req->uid)
&& (mbox_mock_protodrv.frame_expected.input == frame_req->input)
&& (mbox_mock_protodrv.frame_expected.output == frame_req->output)
&& (mbox_mock_protodrv.frame_expected.cmd == frame_req->cmd)) {
npu_dbg("Expected frame matched [uid=%u][in=%p][out=[%p]\n",
frame_req->uid, frame_req->input, frame_req->output);
mbox_mock_protodrv.frame_expected_flag.result = EXPECT_SUCCESS;
} else {
mbox_mock_protodrv.frame_expected_flag.result = EXPECT_FAILED;
}
}
/* Set result and put it back to result */
switch (mbox_mock_protodrv.frame_expected_flag.hw_response) {
case 0:
/* DONE */
frame_req->result_code = BASIC_DO_TASK_RESULT_CODE_FRAME;
break;
case 1:
frame_req->result_code = BASIC_DO_TASK_NDONE_CODE_FRAME;
break;
default:
BUG_ON(1);
}
npu_dbg("PROCESSED %s at mbox_mock : uid=%u, frame_id=%u, req_id=%u, cmd=%u, IO=(%p,%p)\n",
TYPE_NAME_FRAME, frame_req->uid, frame_req->frame_id,
frame_req->npu_req_id, frame_req->cmd, frame_req->input, frame_req->output);
while(LLQ_PUT(frame_result_q, i) == 0) {
/* Wait until the output queue is available */
msleep(1);
}
atomic_set(&mbox_mock_protodrv.frame_used[i], MSG_STATE_DONE);
ret++;
}
}
}
/* Network request */
for (i = 0; i < NPU_MAX_MSG_ID_CNT; i++) {
if (atomic_read(&mbox_mock_protodrv.nw_used[i]) == MSG_STATE_REQUESTED) {
nw_req = &mbox_mock_protodrv.nw_msg[i];
BUG_ON(mbox_mock_protodrv.msgid_get_type(i) != PROTO_DRV_REQ_TYPE_NW);
/* Compare to expectation */
if (mbox_mock_protodrv.nw_expected_flag.setup) {
if ((mbox_mock_protodrv.nw_expected.uid == nw_req->uid)
&& (mbox_mock_protodrv.nw_expected.cmd == nw_req->cmd))
mbox_mock_protodrv.nw_expected_flag.result = EXPECT_SUCCESS;
else
mbox_mock_protodrv.nw_expected_flag.result = EXPECT_FAILED;
}
npu_dbg("Compare UID[%u / %u], cmd [%u / %u] == Result:%d\n",
mbox_mock_protodrv.nw_expected.uid, nw_req->uid,
mbox_mock_protodrv.nw_expected.cmd, nw_req->cmd,
mbox_mock_protodrv.nw_expected_flag.result);
/* Set result and put it back to result */
switch (mbox_mock_protodrv.nw_expected_flag.hw_response) {
case 0:
/* DONE */
nw_req->result_code = BASIC_DO_TASK_RESULT_CODE_FRAME;
break;
case 1:
nw_req->result_code = BASIC_DO_TASK_NDONE_CODE_FRAME;
break;
default:
BUG_ON(1);
}
npu_dbg("PROCESSED %s at mbox_mock : uid=%u, req_id=%u, cmd=%u, ncp_hdr@=%p\n",
TYPE_NAME_NW, nw_req->uid,
nw_req->npu_req_id, nw_req->cmd, nw_req->ncp_addr.vaddr);
while(LLQ_PUT(nw_result_q, i) == 0) {
/* Wait until the output queue is available */
msleep(1);
}
atomic_set(&mbox_mock_protodrv.nw_used[i], MSG_STATE_DONE);
ret++;
}
}
if (ret)
mbox_mock_protodrv.send_notify_func(NULL);
return ret;
}
int mbox_mock_check_work(struct auto_sleep_thread_param* data) {
int i;
for (i = 0; i < NPU_MAX_MSG_ID_CNT; i++) {
if ((atomic_read(&mbox_mock_protodrv.frame_used[i]) == 1)
|| (atomic_read(&mbox_mock_protodrv.nw_used[i]) == 1)) {
return 1;
}
}
return 0;
}
void mbox_mock_signal(void) {
auto_sleep_thread_signal(&mbox_mock_protodrv.ast);
}
/* Setup and teardown for session ref test */
static void sess_ref_setup(void)
{
reset_session_ref();
protodrv_test_session = kmalloc(sizeof(*protodrv_test_session), GFP_KERNEL);
/* Set convinient reference */
test_sess = &protodrv_test_session[0].sess;
memset(protodrv_test_session, 0, sizeof(*protodrv_test_session));
}
static void sess_ref_teardown(void)
{
kfree(protodrv_test_session);
protodrv_test_session = NULL;
test_sess = NULL;
}
static void sess_ref_setup_reg(void)
{
reset_session_ref();
protodrv_test_session = kmalloc(sizeof(*protodrv_test_session), GFP_KERNEL);
/* Set convinient reference */
test_sess = &protodrv_test_session[0].sess;
memset(protodrv_test_session, 0, sizeof(*protodrv_test_session));
register_session_ref(&protodrv_test_session->sess);
}
static void sess_ref_teardown_reg(void)
{
drop_session_ref(protodrv_test_session->sess.uid);
kfree(protodrv_test_session);
protodrv_test_session = NULL;
test_sess = NULL;
}
#ifdef MBOX_MOCK_ENABLE
int setup_for_mbox_mock(void)
{
int ret;
LLQ_INIT(nw_result_q);
LLQ_INIT(frame_result_q);
/* Replace ops structure with testing ops */
npu_protodrv_idiot_mbox_ops_backup = npu_if_protodrv_mbox_ops; /* Defined in npu-if-protodrv-mbox2.c */
npu_if_protodrv_mbox_ops = npu_protodrv_idiot_mbox_ops;
#if 0
npu_protodrv_session_if_ops_backup = npu_if_session_protodrv_ops; /* Defined in npu-if-session-protodrv.c */
npu_if_session_protodrv_ops = npu_protodrv_session_if_ops;
#endif
/* Initialize and run the mbox mock */
ret = auto_sleep_thread_create(&mbox_mock_protodrv.ast, "Mbox mock for protodrv-basic"
,mbox_mock_do_task ,mbox_mock_check_work, NULL);
if(ret) {
return -1;
}
ret = auto_sleep_thread_start(&mbox_mock_protodrv.ast, mbox_mock_protodrv.ast_param);
if(ret) {
return -2;
}
return 0;
}
int deinit_for_mbox_mock(void)
{
auto_sleep_thread_terminate(&mbox_mock_protodrv.ast);
LLQ_DESTROY(nw_result_q);
LLQ_DESTROY(frame_result_q);
/* Restore original ops */
npu_if_protodrv_mbox_ops = npu_protodrv_idiot_mbox_ops_backup;
#if 0
npu_if_session_protodrv_ops = npu_protodrv_session_if_ops_backup;
#endif
return 0;
}
#endif
/* Setup and teardown for protodrv. Includes session object initialization */
int setup_with_session(int session_num) {
int ret;
LLQ_INIT(nw_result_q);
LLQ_INIT(frame_result_q);
/* Test session creation */
protodrv_test_session = kzalloc(sizeof(*protodrv_test_session) * session_num, GFP_KERNEL);
/* Set convinient reference */
test_sess = &protodrv_test_session[0].sess;
/* Mbox mock reset */
reset_mbox_mock();
/* Replace ops structure with testing ops */
npu_protodrv_idiot_mbox_ops_backup = npu_if_protodrv_mbox_ops; /* Defined in npu-if-protodrv-mbox2.c */
npu_if_protodrv_mbox_ops = npu_protodrv_idiot_mbox_ops;
npu_protodrv_session_if_ops_backup = npu_if_session_protodrv_ops; /* Defined in npu-if-session-protodrv.c */
npu_if_session_protodrv_ops = npu_protodrv_session_if_ops;
proto_drv_open(&dummy_device_4_test);
/* Initialize and run the mbox mock */
ret = auto_sleep_thread_create(&mbox_mock_protodrv.ast, "Mbox mock for protodrv-basic"
,mbox_mock_do_task ,mbox_mock_check_work, NULL);
if(ret) {
return -1;
}
ret = auto_sleep_thread_start(&mbox_mock_protodrv.ast, mbox_mock_protodrv.ast_param);
if(ret) {
return -2;
}
return 0;
}
int teardown_with_session(void) {
int ret = 0;
auto_sleep_thread_terminate(&mbox_mock_protodrv.ast);
proto_drv_close(&dummy_device_4_test);
LLQ_DESTROY(nw_result_q);
LLQ_DESTROY(frame_result_q);
/* Destroy test session */
kfree(protodrv_test_session);
protodrv_test_session = NULL;
test_sess = NULL;
/* Restore original ops */
npu_if_protodrv_mbox_ops = npu_protodrv_idiot_mbox_ops_backup;
npu_if_session_protodrv_ops = npu_protodrv_session_if_ops_backup;
return ret;
}
int setup_basic(void) {
return setup_with_session(1);
}
int teardown_basic(void) {
return teardown_with_session();
}
#endif /* IDIOT_DECL_SECTION */
/*
* Check whether the setup and teardown is working
*/
TESTDEF(protodrv_01_basic_base,
IDIOT_ASSERT_EQ(setup_basic(), 0, %d);
IDIOT_ASSERT_EQ(teardown_basic(), 0, %d);
)
/*
* Put one network request and verify it is processed.
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_02_one_nw_req,
struct npu_nw test_nw_input = {
.uid = 4023,
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
test_sess->uid = test_nw_input.uid;
session_mock_prepare_wait(0);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ(1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ(session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
session_mock_prepare_wait(0);
test_nw_input.cmd = NPU_NW_CMD_UNLOAD;
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ((1+0), session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ(session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
)
/*
* Put one network request and verify it is processed.
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_03_one_nw_req_chk,
struct npu_nw golden_nw_input;
struct npu_nw test_nw_input = {
.uid = 4023,
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
test_sess->uid = test_nw_input.uid;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ(1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ(session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ(check_nw_expectation(), EXPECT_SUCCESS, %d);
session_mock_prepare_wait(0);
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ((1+0), session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ(session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ(check_nw_expectation(), EXPECT_SUCCESS, %d);
)
/*
* Request Q_BUF without stream on
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_04_no_stream_on,
static const u32 TEST_UID = 4083;
struct npu_frame golden_frame;
struct npu_frame test_frame = {
.uid = TEST_UID,
.frame_id = 1,
.cmd = NPU_FRAME_CMD_Q,
.src_queue = &protodrv_test_session[0].npu_queue,
.input = (void *)0xAEAEAEAE,
.output = (void *)0x0E0E0E0E,
.session = test_sess,
};
struct npu_nw golden_nw_input;
struct npu_nw test_nw_input = {
.uid = TEST_UID,
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
test_sess->uid = TEST_UID;
/* Prepare golden */
golden_nw_input = test_nw_input;
golden_frame = test_frame;
/* Load */
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(LOAD_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(LOAD_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(LOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
/* Q frame, without stream on */
session_mock_set_frame_result(0, 0xFFFFFFFF);
set_frame_expectation(&golden_frame);
npu_buffer_q_put(&test_frame);
msleep(1000);
/* Shall not be processed */
IDIOT_ASSERT_EQ_T(QBUF_RES_NOTYET, session_mock_get_frame_result(0), 0xFFFFFFFF, %lx);
IDIOT_ASSERT_EQ_T(QBUF_EXP_NOTYET, check_frame_expectation(), EXPECT_FAILED, %d);
/* Stream on */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMON;
session_mock_prepare_wait(0);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Now the frame shall be processed */
IDIOT_ASSERT_EQ_T(QBUF_RES, session_mock_ref(0)->frame_result, BASIC_DO_TASK_RESULT_CODE_NW, %lx);
/* Stream off */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMOFF;
session_mock_prepare_wait(0);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Unload */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(UNLOAD_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(UNLOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
)
/*
* Request Q_BUF 1000 times
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(NPU_DD_PD_PERF_01,
int i;
static const u32 TEST_UID = 4083;
static const int REPEAT_CNT = 1000;
struct npu_frame golden_frame;
struct npu_frame test_frame = {
.uid = TEST_UID,
.frame_id = 1,
.cmd = NPU_FRAME_CMD_Q,
.src_queue = &protodrv_test_session[0].npu_queue,
.input = (void *)0xAEAEAEAE,
.output = (void *)0x0E0E0E0E,
.session = test_sess,
};
struct npu_nw golden_nw_input;
struct npu_nw test_nw_input = {
.uid = TEST_UID,
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
test_sess->uid = TEST_UID;
/* Prepare golden */
golden_nw_input = test_nw_input;
golden_frame = test_frame;
/* Load */
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(LOAD_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(LOAD_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(LOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
/* Stream on */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMON;
session_mock_prepare_wait(0);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result - Stream ON/OFF does not go to mbox, so mbox expectation can not be used */
IDIOT_ASSERT_EQ_T(S_ON_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(S_ON_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
/* Q frame */
session_mock_ref(0)->frame_done_cnt = 0;
for (i = 1; i <= REPEAT_CNT; i++) {
test_frame.frame_id = i;
npu_buffer_q_put(&test_frame);
}
/* Stream off */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMOFF;
session_mock_prepare_wait(0);
npu_ncp_mgmt_put(&test_nw_input);
msleep(20000);
/* Should have a result - Stream ON/OFF does not go to mbox, so mbox expectation can not be used */
IDIOT_ASSERT_EQ_T(S_OFF_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(S_OFF_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
/* All the frame should be done after STREAMOFF */
IDIOT_ASSERT_EQ_T("DONE_CNT", session_mock_ref(0)->frame_done_cnt, REPEAT_CNT, %d);
/* Unload */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(UNLOAD_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(UNLOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
)
/*
* Create 5 sessions and issue load/unload on each session
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(5);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(protodrv_07_5_session_basec,
int i;
const int BASE_UID = 3927;
struct npu_nw golden_nw_input;
struct npu_nw test_nw_input = {
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
golden_nw_input = test_nw_input;
/* Set UID */
for(i = 0; i < 5; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < 5; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(i);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(LOAD_DONE, 1, session_mock_is_done(i), %d);
IDIOT_ASSERT_EQ_T(LOAD_RES, session_mock_get_nw_result(i).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(LOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
}
/* We have session reference */
IDIOT_ASSERT_EQ_T(CHECK_HAVE_SESSION, is_session_ref_exist(), 1, %d);
/* Unload, on reverse order */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
for(i = 4; i >= 0; i--) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(i);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(UNLOAD_DONE, 1, session_mock_is_done(i), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_RES, session_mock_get_nw_result(i).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(UNLOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
}
/* No session should be left */
IDIOT_ASSERT_EQ_T(CHECK_NO_SESSION, is_session_ref_exist(), 0, %d);
)
/*
* Create 5 sessions and issue load/unload on each session
* And call powerdown command
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(5);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(protodrv_08_5_session_power_down,
int i;
const int BASE_UID = 3927;
struct npu_nw golden_nw_input;
struct npu_nw test_nw_input = {
.cmd = NPU_NW_CMD_LOAD,
.ncp_addr = {
.vaddr = (char *)0x70F329,
},
.session = test_sess,
.notify_func = session_mock_save_result,
};
golden_nw_input = test_nw_input;
/* Set UID */
for(i = 0; i < 5; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < 5; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(i);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(LOAD_DONE, 1, session_mock_is_done(i), %d);
IDIOT_ASSERT_EQ_T(LOAD_RES, session_mock_get_nw_result(i).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(LOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
}
/* We have session reference */
IDIOT_ASSERT_EQ_T(CHECK_HAVE_SESSION, is_session_ref_exist(), 1, %d);
/* Unload, on reverse order */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
for(i = 4; i >= 0; i--) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(i);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(UNLOAD_DONE, 1, session_mock_is_done(i), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_RES, session_mock_get_nw_result(i).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(UNLOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
}
/* No session should be left */
IDIOT_ASSERT_EQ_T(CHECK_NO_SESSION, is_session_ref_exist(), 0, %d);
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_POWER_DOWN;
test_nw_input.session = NULL;
test_nw_input.uid = 0;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(0);
set_nw_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result */
IDIOT_ASSERT_EQ_T(PDOWN_DONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(PDOWN_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(PDOWN_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
)
#define DECLARE_PART \
static const u32 TEST_UID = 4083; \
__attribute__((unused)) u32 incr_frame_id = 1; \
struct npu_frame golden_frame; \
struct npu_frame test_frame = { \
.uid = TEST_UID, \
.frame_id = 0, \
.cmd = NPU_FRAME_CMD_Q, \
.src_queue = &protodrv_test_session[0].npu_queue, \
.input = (void *)0xAEAEAEAE, \
.output = (void *)0x0E0E0E0E, \
.session = test_sess, \
}; \
\
struct npu_nw golden_nw_input; \
struct npu_nw test_nw_input = { \
.uid = TEST_UID, \
.cmd = NPU_NW_CMD_LOAD, \
.ncp_addr = { \
.vaddr = (char *)0x70F329, \
}, \
.session = test_sess, \
.notify_func = session_mock_save_result, \
}; \
test_sess->uid = TEST_UID; \
\
/* Prepare golden */ \
golden_nw_input = test_nw_input; \
golden_frame = test_frame; \
#define LOAD_PART_FOR(IDX) \
/* Load */ \
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_LOAD; \
session_mock_prepare_wait((IDX)); \
set_nw_expectation(&golden_nw_input); \
npu_ncp_mgmt_put(&test_nw_input); \
msleep(100); \
/* Should have a result */ \
IDIOT_ASSERT_EQ_T(LOAD_DONE, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(LOAD_RES, session_mock_get_nw_result((IDX)).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %x);\
IDIOT_ASSERT_EQ_T(LOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d); \
#define LOAD_PART LOAD_PART_FOR(0)
#define ISSUE_STREAM_ON_FOR(IDX) \
/* Stream on */ \
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMON; \
session_mock_prepare_wait((IDX)); \
npu_ncp_mgmt_put(&test_nw_input); \
msleep(100); \
#define CHECK_STREAM_ON_COMPLETED_FOR(IDX) \
/* Should have a result - Stream ON/OFF does not go to mbox, so mbox expectation can not be used */ \
IDIOT_ASSERT_EQ_T(S_ON_DONE, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(S_ON_RES, session_mock_get_nw_result((IDX)).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %x); \
#define CHECK_STREAM_ON_ERR_FOR(IDX, errcode) \
IDIOT_ASSERT_EQ_T(S_ON_DONE_ERR, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(S_ON_RES_ERR, session_mock_get_nw_result((IDX)).result_code, (errcode), %x); \
#define ISSUE_STREAM_ON ISSUE_STREAM_ON_FOR(0)
#define CHECK_STREAM_ON_COMPLETED CHECK_STREAM_ON_COMPLETED_FOR(0)
#define CHECK_STREAM_ON_ERR(errcode) CHECK_STREAM_ON_ERR_FOR(0, errcode)
#define STREAM_ON_PART \
ISSUE_STREAM_ON \
CHECK_STREAM_ON_COMPLETED \
#define ISSUE_QBUF_FOR_NO_FRAMEID(IDX) \
/* Q frame */ \
session_mock_set_frame_result((IDX), 0xFFFFFFFF); \
set_frame_expectation(&golden_frame); \
npu_buffer_q_put(&test_frame); \
msleep(100); \
#define ISSUE_QBUF_FOR(IDX) \
golden_frame.frame_id = test_frame.frame_id = incr_frame_id++; \
ISSUE_QBUF_FOR_NO_FRAMEID(IDX) \
#define ISSUE_QBUF_FOR_TIMEDOUT_NO_FRAMEID(IDX) \
set_frame_timeout(&golden_frame); \
ISSUE_QBUF_FOR_NO_FRAMEID(IDX) \
#define ISSUE_QBUF_FOR_TIMEDOUT(IDX) \
golden_frame.frame_id = test_frame.frame_id = incr_frame_id++; \
ISSUE_QBUF_FOR_TIMEDOUT_NO_FRAMEID(IDX) \
#define CHECK_QBUF_COMPLETED_FOR(IDX) \
/* Shall be processed */ \
IDIOT_ASSERT_EQ_T(QBUF_RES, session_mock_get_frame_result((IDX)), BASIC_DO_TASK_RESULT_CODE_FRAME, %lx); \
IDIOT_ASSERT_EQ_T(QBUF_EXP, check_frame_expectation(), EXPECT_SUCCESS, %d); \
/* Wait result for timeout_ms */
#define CHECK_QBUF_WAIT_COMPLETED_FOR(IDX, timeout_ms) \
{ \
int __repeat = 0; \
while (session_mock_get_frame_result((IDX)) == 0xFFFFFFFF) { \
IDIOT_ASSERT_LE_T(QBUF_W_TIMEOUT, __repeat, (timeout_ms), %d); \
__repeat++; \
msleep(1); \
} \
IDIOT_ASSERT_EQ_T(QBUF_W_RES, session_mock_get_frame_result((IDX)), BASIC_DO_TASK_RESULT_CODE_FRAME, %lx); \
IDIOT_ASSERT_EQ_T(QBUF_W_EXP, check_frame_expectation(), EXPECT_SUCCESS, %d); \
} \
#define CHECK_QBUF_PEND_FOR(IDX) \
/* Shall not be processed yet */ \
IDIOT_ASSERT_EQ_T(QBUF_RES_NOTYET, session_mock_get_frame_result((IDX)), 0xFFFFFFFF, %lx); \
IDIOT_ASSERT_EQ_T(QBUF_EXP_NOTYET, peek_frame_expectation(), EXPECT_FAILED, %d); \
#define EXPECT_QBUF_ERR_WO_HW_FOR(IDX, errcode) \
/* Error with result == errcode, request should not be passed to NPU H/W */ \
IDIOT_ASSERT_EQ_T(QBUF_RES_ERR, session_mock_get_frame_result((IDX)), errcode, %lx); \
IDIOT_ASSERT_EQ_T(QBUF_EXP_ERR, check_frame_expectation(), EXPECT_FAILED, %d); \
#define ISSUE_QBUF ISSUE_QBUF_FOR(0)
#define CHECK_QBUF_COMPLETED CHECK_QBUF_COMPLETED_FOR(0)
#define CHECK_QBUF_PEND CHECK_QBUF_PEND_FOR(0)
#define EXPECT_QBUF_ERR_WO_HW(errcode) EXPECT_QBUF_ERR_WO_HW_FOR(0, errcode)
#define QBUF_PART \
ISSUE_QBUF \
CHECK_QBUF_COMPLETED \
#define ISSUE_STREAM_OFF_FOR(IDX) \
/* Stream off */ \
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMOFF; \
session_mock_prepare_wait((IDX)); \
set_nw_expectation(&golden_nw_input); \
npu_ncp_mgmt_put(&test_nw_input); \
msleep(100); \
#define CHECK_STREAM_OFF_COMPLETED_FOR(IDX) \
/* Should have a result - Stream ON/OFF does not go to mbox, so mbox expectation can not be used */ \
IDIOT_ASSERT_EQ_T(S_OFF_DONE, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(S_OFF_RES, session_mock_get_nw_result((IDX)).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %x); \
IDIOT_ASSERT_EQ_T(S_OFF_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d); \
#define CHECK_STREAM_OFF_ERR_FOR(IDX, errcode) \
IDIOT_ASSERT_EQ_T(S_OFF_DONE_ERR, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(S_OFF_RES_ERR, session_mock_get_nw_result((IDX)).result_code, (errcode), %x); \
IDIOT_ASSERT_EQ_T(S_OFF_EXP, check_nw_expectation(), EXPECT_FAILED, %d); \
#define ISSUE_STREAM_OFF ISSUE_STREAM_OFF_FOR(0)
#define CHECK_STREAM_OFF_COMPLETED CHECK_STREAM_OFF_COMPLETED_FOR(0)
#define CHECK_STREAM_OFF_ERR(errcode) CHECK_STREAM_OFF_ERR_FOR(0, errcode)
#define STREAM_OFF_PART \
ISSUE_STREAM_OFF \
CHECK_STREAM_OFF_COMPLETED \
#define ISSUE_UNLOAD_FOR(IDX) \
/* Unload */ \
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD; \
session_mock_prepare_wait((IDX)); \
set_nw_expectation(&golden_nw_input); \
npu_ncp_mgmt_put(&test_nw_input); \
msleep(100); \
#define CHECK_UNLOAD_COMPLETED_FOR(IDX) \
/* Should have a result */ \
IDIOT_ASSERT_EQ_T(UNLOAD_DONE, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(UNLOAD_RES, session_mock_get_nw_result((IDX)).result_code, BASIC_DO_TASK_RESULT_CODE_NW, %x); \
IDIOT_ASSERT_EQ_T(UNLOAD_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d); \
#define CHECK_UNLOAD_ERR_FOR(IDX, errcode) \
IDIOT_ASSERT_EQ_T(UNLOAD_DONE_ERR, 1, session_mock_is_done((IDX)), %d); \
IDIOT_ASSERT_EQ_T(UNLOAD_RES_ERR, session_mock_get_nw_result((IDX)).result_code, errcode, %x); \
IDIOT_ASSERT_EQ_T(UNLOAD_EXP_ERR, check_nw_expectation(), EXPECT_FAILED, %d); \
#define ISSUE_UNLOAD ISSUE_UNLOAD_FOR(0)
#define CHECK_UNLOAD_COMPLETED CHECK_UNLOAD_COMPLETED_FOR(0)
#define CHECK_UNLOAD_ERR(errcode) CHECK_UNLOAD_ERR_FOR(0, errcode)
#define UNLOAD_PART \
ISSUE_UNLOAD \
CHECK_UNLOAD_COMPLETED \
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(NPU_DD_PD_FUNC_01,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_02,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
QBUF_PART
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_03,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_04,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
STREAM_OFF_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_05,
DECLARE_PART
LOAD_PART
/* Qbuf before stream on - should not be processed now */
ISSUE_QBUF
CHECK_QBUF_PEND
STREAM_ON_PART
/* Now the frame shall be processed */
CHECK_QBUF_COMPLETED
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_06,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
/* Qbuf after stream off - should not be processed now */
ISSUE_QBUF
CHECK_QBUF_PEND
STREAM_ON_PART
/* Now the frame shall be processed */
CHECK_QBUF_COMPLETED
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_FUNC_07,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
/* Skip notification for UNLOAD */
test_nw_input.notify_func = NULL;
ISSUE_UNLOAD
/* Expection should be matched, but should not notified to Session */
IDIOT_ASSERT_EQ_T(UNLOAD_SKIP_DONE, 0, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_SKIP_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d); \
)
TESTDEF(NPU_DD_PD_NPUE_01,
DECLARE_PART
/* Load */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_LOAD;
session_mock_prepare_wait((0));
set_nw_ndone_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(100);
/* Should have a result - NDONE */
IDIOT_ASSERT_EQ_T(LOAD_NDONE, 1, session_mock_is_done((0)), %d);
IDIOT_ASSERT_EQ_T(LOAD_NDONE_RES, session_mock_get_nw_result((0)).result_code, BASIC_DO_TASK_NDONE_CODE_NW, %x);
IDIOT_ASSERT_EQ_T(LOAD_NDONE_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_NPUE_02,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
/* Qbuf with NDONE */
golden_frame.frame_id = test_frame.frame_id = incr_frame_id++;
session_mock_set_frame_result((0), 0xFFFFFFFF);
set_frame_ndone_expectation(&golden_frame);
npu_buffer_q_put(&test_frame);
msleep(100);
/* Should have a result - NDONE */
IDIOT_ASSERT_EQ_T(QBUF_NDONE_RES, session_mock_get_frame_result((0)), BASIC_DO_TASK_NDONE_CODE_FRAME, %lx);
IDIOT_ASSERT_EQ_T(QBUF_NDONE_EXP, check_frame_expectation(), EXPECT_SUCCESS, %d);
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
)
#ifndef BYPASS_HW_STREAMOFF
TESTDEF(NPU_DD_PD_NPUE_03,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
/* Stream off with NDONE */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_STREAMOFF;
session_mock_prepare_wait((0));
set_nw_ndone_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(100);
/* Should have a result - NDONE */
IDIOT_ASSERT_EQ_T(S_OFF_NDONE, 1, session_mock_is_done((0)), %d);
IDIOT_ASSERT_EQ_T(S_OFF_NDONE_RES, session_mock_get_nw_result((0)).result_code, BASIC_DO_TASK_NDONE_CODE_NW, %x);
IDIOT_ASSERT_EQ_T(S_OFF_NDONE_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
STREAM_OFF_PART
UNLOAD_PART
)
#endif
TESTDEF(NPU_DD_PD_NPUE_04,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
/* Unload with NDONE */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_UNLOAD;
session_mock_prepare_wait((0));
set_nw_ndone_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(100);
/* Should have a result - NDONE */
IDIOT_ASSERT_EQ_T(UNLOAD_NDONE, 1, session_mock_is_done((0)), %d);
IDIOT_ASSERT_EQ_T(UNLOAD_NDONE_RES, session_mock_get_nw_result((0)).result_code, BASIC_DO_TASK_NDONE_CODE_NW, %x);
IDIOT_ASSERT_EQ_T(UNLOAD_NDONE_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_NPUE_05,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
QBUF_PART
STREAM_OFF_PART
UNLOAD_PART
/* Power down with NDONE */
test_nw_input.cmd = golden_nw_input.cmd = NPU_NW_CMD_POWER_DOWN;
test_nw_input.session = NULL;
test_nw_input.uid = 0;
golden_nw_input = test_nw_input;
session_mock_prepare_wait(0);
set_nw_ndone_expectation(&golden_nw_input);
npu_ncp_mgmt_put(&test_nw_input);
msleep(1000);
/* Should have a result - NDONE */
IDIOT_ASSERT_EQ_T(PDOWN_NDONE, 1, session_mock_is_done(0), %d);
IDIOT_ASSERT_EQ_T(PDOWN_NDONE_RES, session_mock_get_nw_result(0).result_code, BASIC_DO_TASK_NDONE_CODE_NW, %u);
IDIOT_ASSERT_EQ_T(PDOWN_NDONE_EXP, check_nw_expectation(), EXPECT_SUCCESS, %d);
)
/*
* Create 5 sessions and issue 100 processing for each session
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(5);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(NPU_DD_PD_PERF_02,
int i, r;
const int BASE_UID = 3927;
const int req_cnt = 100;
const int sess_cnt = 5;
DECLARE_PART;
/* Set UID */
for(i = 0; i < sess_cnt; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
LOAD_PART_FOR(i);
}
/* Do stream on */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_ON_FOR(i);
CHECK_STREAM_ON_COMPLETED_FOR(i);
}
for(r = 0; r < req_cnt; r++) {
/* QBUF to each session and check result */
for(i = 0; i < sess_cnt; i++) {
test_frame.session = &protodrv_test_session[i].sess;
test_frame.uid = protodrv_test_session[i].sess.uid;
test_frame.src_queue = &protodrv_test_session[i].npu_queue;
test_frame.frame_id = r;
golden_frame = test_frame;
ISSUE_QBUF_FOR_NO_FRAMEID(i);
CHECK_QBUF_WAIT_COMPLETED_FOR(i, 100);
}
}
/* Do stream off */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_OFF_FOR(i);
CHECK_STREAM_OFF_COMPLETED_FOR(i);
}
/* Check processed count */
for(i = 0; i < sess_cnt; i++) {
IDIOT_ASSERT_EQ_T("DONE_CNT", session_mock_ref(i)->frame_done_cnt, req_cnt, %d);
}
/* Do unload */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_UNLOAD_FOR(i);
CHECK_UNLOAD_COMPLETED_FOR(i);
}
)
/*
* Create 100 sessions and issue 10 processing for each session
* (Exact same test with NPU_DD_PD_PERF_02, except req_cnt and sess_cnt)
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(100);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(NPU_DD_PD_PERF_03,
int i, r;
const int BASE_UID = 3927;
const int req_cnt = 10;
const int sess_cnt = 100;
DECLARE_PART;
/* Set UID */
for(i = 0; i < sess_cnt; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
LOAD_PART_FOR(i);
}
/* Do stream on */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_ON_FOR(i);
CHECK_STREAM_ON_COMPLETED_FOR(i);
}
for(r = 0; r < req_cnt; r++) {
/* QBUF to each session and check result */
for(i = 0; i < sess_cnt; i++) {
test_frame.session = &protodrv_test_session[i].sess;
test_frame.uid = protodrv_test_session[i].sess.uid;
test_frame.src_queue = &protodrv_test_session[i].npu_queue;
test_frame.frame_id = r;
golden_frame = test_frame;
ISSUE_QBUF_FOR_NO_FRAMEID(i);
CHECK_QBUF_WAIT_COMPLETED_FOR(i, 100);
}
}
/* Do stream off */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_OFF_FOR(i);
CHECK_STREAM_OFF_COMPLETED_FOR(i);
}
/* Check processed count */
for(i = 0; i < sess_cnt; i++) {
IDIOT_ASSERT_EQ_T("DONE_CNT", session_mock_ref(i)->frame_done_cnt, req_cnt, %d);
}
/* Do unload */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_UNLOAD_FOR(i);
CHECK_UNLOAD_COMPLETED_FOR(i);
}
)
TESTDEF(NPU_DD_PD_EXCP_01,
DECLARE_PART
// Specify invalid session
golden_nw_input.session = test_nw_input.session = NULL;
ISSUE_STREAM_ON
CHECK_STREAM_ON_ERR(NPU_ERR_DRIVER(NPU_ERR_INVALID_UID))
)
TESTDEF(NPU_DD_PD_EXCP_02,
DECLARE_PART
// Specify invalid session
golden_nw_input.session = test_nw_input.session = NULL;
ISSUE_STREAM_OFF
CHECK_STREAM_OFF_ERR(NPU_ERR_DRIVER(NPU_ERR_INVALID_UID))
)
TESTDEF(NPU_DD_PD_EXCP_03,
DECLARE_PART
// Specify invalid session
golden_frame.session = test_frame.session = NULL;
ISSUE_QBUF
EXPECT_QBUF_ERR_WO_HW(NPU_ERR_DRIVER(NPU_ERR_INVALID_UID))
)
TESTDEF(NPU_DD_PD_EXCP_04,
DECLARE_PART
// Specify invalid session
golden_nw_input.session = test_nw_input.session = NULL;
ISSUE_UNLOAD
CHECK_UNLOAD_ERR(NPU_ERR_DRIVER(NPU_ERR_INVALID_UID))
)
TESTDEF(NPU_DD_PD_EXCP_05,
DECLARE_PART
LOAD_PART
ISSUE_STREAM_OFF
CHECK_STREAM_OFF_ERR(NPU_ERR_DRIVER(NPU_ERR_INVALID_STATE))
UNLOAD_PART
)
TESTDEF(NPU_DD_PD_EXCP_06,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
ISSUE_QBUF_FOR_TIMEDOUT(0)
msleep(30 * 1000);
IDIOT_ASSERT_EQ_T(QBUF_RES_ERR,
session_mock_get_frame_result((0)),
NPU_CRITICAL_DRIVER(NPU_ERR_NPU_TIMEOUT), %lx);
STREAM_OFF_PART
UNLOAD_PART
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(5);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(NPU_DD_PD_EXCP_07,
int i, r;
const int BASE_UID = 1022;
const int req_cnt = 100;
const int sess_cnt = 5;
const u32 timeout_sess_id = 2;
const u32 timeout_frame_id = req_cnt/2;
DECLARE_PART;
/* Set UID */
for(i = 0; i < sess_cnt; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
LOAD_PART_FOR(i);
}
/* Do stream on */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_ON_FOR(i);
CHECK_STREAM_ON_COMPLETED_FOR(i);
}
for(r = 0; r < req_cnt; r++) {
/* QBUF to each session and check result */
for(i = 0; i < sess_cnt; i++) {
test_frame.session = &protodrv_test_session[i].sess;
test_frame.uid = protodrv_test_session[i].sess.uid;
test_frame.src_queue = &protodrv_test_session[i].npu_queue;
test_frame.frame_id = r;
golden_frame = test_frame;
if (test_frame.frame_id == timeout_frame_id && i == timeout_sess_id) {
npu_dbg("Timeout request queued.\n");
ISSUE_QBUF_FOR_TIMEDOUT_NO_FRAMEID(i);
} else {
ISSUE_QBUF_FOR_NO_FRAMEID(i);
}
}
}
/* Do stream off */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_OFF_FOR(i);
CHECK_STREAM_OFF_COMPLETED_FOR(i);
}
/* Check processed count */
for(i = 0; i < sess_cnt; i++) {
IDIOT_ASSERT_EQ_T("DONE_CNT", session_mock_ref(i)->frame_done_cnt, req_cnt, %d);
}
/* Do unload */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_UNLOAD_FOR(i);
CHECK_UNLOAD_COMPLETED_FOR(i);
}
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_with_session(100);
#define TEARDOWN_CODE teardown_with_session();
TESTDEF(NPU_DD_PD_EXCP_08,
int i, r;
const int BASE_UID = 2138;
const int req_cnt = 10;
const int sess_cnt = 100;
const u32 timeout_sess_id = 64;
const u32 timeout_frame_id = req_cnt/2;
DECLARE_PART;
/* Set UID */
for(i = 0; i < sess_cnt; i++) {
protodrv_test_session[i].sess.uid = BASE_UID + i;
}
/* Put 5 load command */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
LOAD_PART_FOR(i);
}
/* Do stream on */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_ON_FOR(i);
CHECK_STREAM_ON_COMPLETED_FOR(i);
}
for(r = 0; r < req_cnt; r++) {
/* QBUF to each session and check result */
for(i = 0; i < sess_cnt; i++) {
test_frame.session = &protodrv_test_session[i].sess;
test_frame.uid = protodrv_test_session[i].sess.uid;
test_frame.src_queue = &protodrv_test_session[i].npu_queue;
test_frame.frame_id = r;
golden_frame = test_frame;
if (test_frame.frame_id == timeout_frame_id && i == timeout_sess_id) {
npu_dbg("Timeout request queued.\n");
ISSUE_QBUF_FOR_TIMEDOUT_NO_FRAMEID(i);
} else {
ISSUE_QBUF_FOR_NO_FRAMEID(i);
}
}
}
/* Do stream off */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_STREAM_OFF_FOR(i);
CHECK_STREAM_OFF_COMPLETED_FOR(i);
}
/* Check processed count */
for(i = 0; i < sess_cnt; i++) {
IDIOT_ASSERT_EQ_T("DONE_CNT", session_mock_ref(i)->frame_done_cnt, req_cnt, %d);
}
/* Do unload */
for(i = 0; i < sess_cnt; i++) {
test_nw_input.session = &protodrv_test_session[i].sess;
test_nw_input.uid = protodrv_test_session[i].sess.uid;
golden_nw_input = test_nw_input;
ISSUE_UNLOAD_FOR(i);
CHECK_UNLOAD_COMPLETED_FOR(i);
}
)
TESTDEF(NPU_DD_PD_EXCP_09,
DECLARE_PART
LOAD_PART
STREAM_ON_PART
/* Unload without stream off */
ISSUE_UNLOAD
CHECK_UNLOAD_ERR(NPU_ERR_DRIVER(NPU_ERR_INVALID_STATE))
STREAM_OFF_PART
UNLOAD_PART
)
#if 0
/*
* Put five network request and verify it is processed in order.
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_03_multi_nw_req,
int ret;
int i;
const int REPEAT_CNT = 5;
const u32 FRAME_ID_BASE = 4823;
struct npu_nw test_nw_input = {
.uid = 4023,
.frame_id = 0,
.cmd = 9,
.ncp_addr = (char *)0x70F329,
.notify_func = session_mock_save_result,
};
struct npu_nw test_nw_output;
/* Post request, with increasing frame_id */
for(i = 0; i < REPEAT_CNT; i++) {
test_nw_input.frame_id = FRAME_ID_BASE + i;
npu_ncp_mgmt_put(&test_nw_input);
}
msleep(1000);
/* Get result */
for(i = 0; i < REPEAT_CNT; i++) {
memset(&test_nw_output, 0, sizeof(test_nw_output));
result = get_result();
/* Should have a result */
IDIOT_ASSERT_NEQ(ret, 0, %d);
/* Check its frame_id is increasing order */
IDIOT_ASSERT_EQ(test_nw_output.frame_id, FRAME_ID_BASE + i, %u);
/* Other fields shoud be same */
IDIOT_ASSERT_EQ(test_nw_output.uid, test_nw_input.uid, %u);
IDIOT_ASSERT_EQ(test_nw_output.cmd, test_nw_input.cmd, %u);
IDIOT_ASSERT_EQ(test_nw_output.ncp_addr, test_nw_input.ncp_addr, %p);
IDIOT_ASSERT_EQ(test_nw_output.result_code, BASIC_DO_TASK_RESULT_CODE_NW, %d);
}
/* Should not have result anymore */
ret = LLQ_GET(nw_result_q, &test_nw_output);
IDIOT_ASSERT_EQ(ret, 0, %d);
)
/*
* Put 1024 network request over 3 different uid and verify it is processed in order.
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_04_1_1k_nw_req,
int ret;
int i;
const u32 FRAME_ID_BASE = 9987;
const int UID_BASE = 1000;
u32 uid_sel;
struct npu_nw test_nw_input = {
.cmd = 128,
.ncp_addr = (char *)0x70F329,
.notify_func = session_mock_save_result,
};
struct npu_nw test_nw_output;
for(i = 0; i < PROTODRV_04_UID_CNT; ++i) {
uids[i] = UID_BASE+i;
}
/* Post request, with increasing frame_id. Use random uid and store it */
for(i = 0; i < PROTODRV_04_REPEAT_CNT; ++i) {
get_random_bytes(&uid_sel, sizeof(uid_sel)); /* Random# gen. */
uid_sel %= PROTODRV_04_UID_CNT;
idxes[i] = test_nw_input.uid = uids[uid_sel];
test_nw_input.frame_id = FRAME_ID_BASE + i;
while(LLQ_PUT(nw_req_q, test_nw_input) == 0) {
msleep(1);
}
}
msleep(1000);
/* Get result */
for(i = 0; i < PROTODRV_04_REPEAT_CNT; ++i) {
memset(&test_nw_output, 0, sizeof(test_nw_output));
while(LLQ_GET(nw_result_q, &test_nw_output) == 0) {
msleep(1);
}
/* Check its frame_id is increasing order */
IDIOT_ASSERT_EQ(test_nw_output.frame_id, FRAME_ID_BASE + i, %u);
IDIOT_ASSERT_EQ(test_nw_output.uid, idxes[i], %u);
/* Other fields shoud be same */
IDIOT_ASSERT_EQ(test_nw_output.cmd, test_nw_input.cmd, %u);
IDIOT_ASSERT_EQ(test_nw_output.ncp_addr, test_nw_input.ncp_addr, %p);
IDIOT_ASSERT_EQ(test_nw_output.result_code, BASIC_DO_TASK_RESULT_CODE_NW, %d);
}
/* Should not have result anymore */
ret = LLQ_GET(nw_result_q, &test_nw_output);
IDIOT_ASSERT_EQ(ret, 0, %d);
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_04_2_1k_npu_q_req,
int ret;
int i;
const u32 FRAME_ID_BASE = 9980;
const int UID_BASE = 3000;
u32 uid_sel;
struct npu_frame test_frame_input = {
.cmd = 9,
.priority = 64,
.input = (struct vb_container_list*)0xFFFF0924,
.output = (struct vb_container_list*)0xFFFF2428,
};
struct npu_frame test_frame_output;
for(i = 0; i < PROTODRV_04_UID_CNT; ++i) {
uids[i] = UID_BASE+i;
}
/* Post request, with increasing frame_id. Use random uid and store it */
for(i = 0; i < PROTODRV_04_REPEAT_CNT; ++i) {
get_random_bytes(&uid_sel, sizeof(uid_sel)); /* Random# gen. */
uid_sel %= PROTODRV_04_UID_CNT;
idxes[i] = test_frame_input.uid = uids[uid_sel];
test_frame_input.frame_id = FRAME_ID_BASE + i;
while(LLQ_PUT(frame_req_q, test_frame_input) == 0) {
msleep(1);
}
}
msleep(1000);
/* Get result */
for(i = 0; i < PROTODRV_04_REPEAT_CNT; ++i) {
memset(&test_frame_output, 0, sizeof(test_frame_output));
while(LLQ_GET(frame_result_q, &test_frame_output) == 0) {
msleep(1);
}
/* Check its frame_id is increasing order */
IDIOT_ASSERT_EQ(test_frame_output.frame_id, FRAME_ID_BASE + i, %u);
IDIOT_ASSERT_EQ(test_frame_output.uid, idxes[i], %u);
/* Other fields shoud be same */
IDIOT_ASSERT_EQ(test_frame_output.cmd, test_frame_input.cmd, %u);
IDIOT_ASSERT_EQ(test_frame_output.input, test_frame_input.input, %p);
IDIOT_ASSERT_EQ(test_frame_output.output, test_frame_input.output, %p);
IDIOT_ASSERT_EQ(test_frame_output.result_code, BASIC_DO_TASK_RESULT_CODE_FRAME, %d);
}
/* Should not have result anymore */
ret = LLQ_GET(frame_result_q, &test_frame_output);
IDIOT_ASSERT_EQ(ret, 0, %d);
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE setup_basic();
#define TEARDOWN_CODE teardown_basic();
TESTDEF(protodrv_05_frame_timeout_basic,
struct npu_frame test_frame_output;
struct npu_frame test_frame_input_timeout = {
.cmd = 9,
.frame_id = BASIC_DO_TASK_KEEP_FRAME_ID,
.input = (struct vb_container_list*)0xFFFF0924,
.output = (struct vb_container_list*)0xFFFF2428,
};
struct npu_frame test_frame_input_resume = {
.cmd = 4029,
.frame_id = BASIC_DO_TASK_RESUME_FRAME_ID,
.input = (struct vb_container_list*)0xAAAA0924,
.output = (struct vb_container_list*)0xAAAA2428,
};
/* Put the frame which causes timeout */
IDIOT_ASSERT_NEQ(LLQ_PUT(frame_req_q, test_frame_input_timeout), 0, %d);
msleep(500);
/* Should not be returned at this time */
IDIOT_ASSERT_EQ(LLQ_GET(frame_result_q, &test_frame_output), 0, %d);
/* Wait until timeout happened */
msleep(10000);
/* Got timeout frame, with proper error code */
IDIOT_ASSERT_NEQ(LLQ_GET(frame_result_q, &test_frame_output), 0, %d);
IDIOT_ASSERT_EQ(test_frame_output.input, test_frame_input_timeout.input, %p);
IDIOT_ASSERT_EQ(test_frame_output.output, test_frame_input_timeout.output, %p);
IDIOT_ASSERT_EQ(test_frame_output.result_code, NPU_ERR_DRIVER(NPU_ERR_NPU_TIMEOUT), %d);
/* Putting a resume frame -> It makes the mbox mock return result for
timeout frame - but it should be ignored. */
IDIOT_ASSERT_NEQ(LLQ_PUT(frame_req_q, test_frame_input_resume), 0, %d);
msleep(500);
/* Got the resume frame first */
IDIOT_ASSERT_NEQ(LLQ_GET(frame_result_q, &test_frame_output), 0, %d);
IDIOT_ASSERT_EQ(test_frame_output.input, test_frame_input_resume.input, %p);
IDIOT_ASSERT_EQ(test_frame_output.output, test_frame_input_resume.output, %p);
IDIOT_ASSERT_EQ(test_frame_output.result_code, BASIC_DO_TASK_RESULT_CODE_FRAME, %d);
msleep(500);
/* Should not have result anymore */
IDIOT_ASSERT_EQ(LLQ_GET(frame_result_q, &test_frame_output), 0, %d);
)
/* Keep old state and set the state to known value
-> Accessing of npu_proto_drv.state directly is not permitted,
but allowed here for testing, as an exception case.
*/
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE int oldval = atomic_read(&npu_proto_drv.state);
#define TEARDOWN_CODE atomic_set(&npu_proto_drv.state, oldval);
TESTDEF(protodrv_06_state_check,
int from, to;
int ret1, ret2, ret3;
for(from = 0; from < PROTO_DRV_STATE_INVALID; ++from) {
atomic_set(&npu_proto_drv.state, from);
/* Check state test macro */
ret1 = EXPECT_STATE(from);
IDIOT_ASSERT_EQ(ret1, 1, %d);
for(to = 0; to < PROTO_DRV_STATE_INVALID; ++to) {
if(from != to) {
ret2 = EXPECT_STATE(to);
IDIOT_ASSERT_EQ(ret2, 0, %d);
}
/* Test transition, based on the table */
ret3 = IS_TRANSITABLE(to);
if(proto_drv_thread_state_transition[from][to]) {
IDIOT_ASSERT_EQ(ret3, 1, %d);
} else {
IDIOT_ASSERT_EQ(ret3, 0, %d);
}
}
}
)
#endif
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE sess_ref_setup();
#define TEARDOWN_CODE sess_ref_teardown();
TESTDEF(protodrv_sess_ref_register_and_drop,
struct proto_req_frame frame = {
.frame = {
.session = test_sess,
.uid = test_sess->uid,
}
};
struct session_ref_entry* sess_entry;
IDIOT_ASSERT_EQ(register_session_ref(test_sess), 0, %d);
sess_entry = find_session_ref_frame(&frame);
IDIOT_ASSERT_EQ(sess_entry->session, test_sess, %p);
IDIOT_ASSERT_EQ(drop_session_ref(test_sess->uid), 0, %d);
IDIOT_ASSERT_EQ(find_session_ref_frame(&frame), NULL, %p);
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE sess_ref_setup_reg();
#define TEARDOWN_CODE sess_ref_teardown_reg();
TESTDEF(protodrv_sess_ref_is_last,
struct proto_req_frame frame = {
.frame = {
.session = test_sess,
.uid = test_sess->uid,
}
};
struct proto_req_nw nw_1 = {
.nw = {
.session = test_sess,
.uid = test_sess->uid,
}
};
struct proto_req_nw nw_2 = {
.nw = {
.session = test_sess,
.uid = test_sess->uid,
}
};
/* Link nw_1 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_1), OK, %d);
/* nw_1 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), LAST, %d);
/* Link frame and unlink nw_1 */
IDIOT_ASSERT_EQ(link_session_frame(&frame), OK, %d);
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_1), OK, %d);
/* nw_1 is not the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), NOT_LAST, %d);
/* Link nw_2 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_2), OK, %d);
/* nw_2 is not the last (Frame is linked) */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
/* unlink frame */
IDIOT_ASSERT_EQ(unlink_session_frame(&frame), OK, %d);
/* now the nw_2 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), LAST, %d);
/* Unlink nw_2 */
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_2), OK, %d);
/* nw_2 is not the last because its not valid */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
)
#undef SETUP_CODE
#undef TEARDOWN_CODE
#define SETUP_CODE \
struct npu_session* sess_array = NULL; \
static const int SESS_CNT = SESS_REF_HASH_TABLE_SIZE + 4; \
reset_session_ref(); \
sess_array = vmalloc(sizeof(*sess_array) * SESS_CNT); \
#define TEARDOWN_CODE if(sess_array) vfree(sess_array);
TESTDEF(protodrv_sess_ref_sess_full_incr,
struct session_ref_entry* sess_entry;
struct proto_req_frame frame;
int i;
/* Create many sessions, with increasing uid */
IDIOT_ASSERT_NEQ(sess_array, NULL, %p);
for (i = 0; i < SESS_CNT; i++) {
sess_array[i].uid = i;
IDIOT_ASSERT_EQ(register_session_ref(&sess_array[i]), OK, %d);
}
/* Check whether the last session can be found */
memset(&frame, 0, sizeof(frame));
frame.frame.session = &sess_array[SESS_CNT - 1];
frame.frame.uid = frame.frame.session->uid;
sess_entry = find_session_ref_frame(&frame);
IDIOT_ASSERT_NEQ(sess_entry, NULL, %p);
/* Remove all session, in ascending order */
for (i = 0; i < SESS_CNT; i++) {
IDIOT_ASSERT_EQ(drop_session_ref(sess_array[i].uid), OK, %d);
}
)
TESTDEF(protodrv_sess_ref_sess_full_coll,
struct session_ref_entry* sess_entry;
struct proto_req_frame frame;
int i;
u32 uid = 0;
/* Create many sessions, with intended collision when determining uid */
IDIOT_ASSERT_NEQ(sess_array, NULL, %p);
for (i = 0; i < SESS_CNT; i++) {
uid += SESS_REF_HASH_MAGIC;
sess_array[i].uid = uid;
IDIOT_ASSERT_EQ(register_session_ref(&sess_array[i]), OK, %d);
}
/* Check whether the last session can be found */
memset(&frame, 0, sizeof(frame));
frame.frame.session = &sess_array[SESS_CNT - 1];
frame.frame.uid = frame.frame.session->uid;
sess_entry = find_session_ref_frame(&frame);
IDIOT_ASSERT_NEQ(sess_entry, NULL, %p);
/* Remove all session, in decending order */
for (i = SESS_CNT - 1; i >= 0; i--) {
IDIOT_ASSERT_EQ(drop_session_ref(sess_array[i].uid), OK, %d);
}
)
TESTDEF(protodrv_sess_ref_is_last_many_sess,
struct proto_req_frame frame;
struct proto_req_nw nw_1, nw_2;
int i;
/* Create many sessions, with increasing uid */
IDIOT_ASSERT_NEQ(sess_array, NULL, %p);
for (i = 0; i < SESS_CNT; i++) {
sess_array[i].uid = i;
IDIOT_ASSERT_EQ(register_session_ref(&sess_array[i]), OK, %d);
}
memset(&frame, 0, sizeof(frame));
memset(&nw_1, 0, sizeof(nw_1));
memset(&nw_2, 0, sizeof(nw_2));
frame.frame.session = &sess_array[SESS_CNT - 1];
frame.frame.uid = frame.frame.session->uid;
nw_1.nw.session = &sess_array[SESS_CNT - 1];
nw_1.nw.uid = nw_1.nw.session->uid;
nw_2.nw.session = &sess_array[SESS_CNT - 1];
nw_2.nw.uid = nw_2.nw.session->uid;
/* Link nw_1 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_1), OK, %d);
/* nw_1 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), LAST, %d);
/* Link frame and unlink nw_1 */
IDIOT_ASSERT_EQ(link_session_frame(&frame), OK, %d);
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_1), OK, %d);
/* nw_1 is not the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), NOT_LAST, %d);
/* Link nw_2 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_2), OK, %d);
/* nw_2 is not the last (Frame is linked) */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
/* unlink frame */
IDIOT_ASSERT_EQ(unlink_session_frame(&frame), OK, %d);
/* now the nw_2 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), LAST, %d);
/* Unlink nw_2 */
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_2), OK, %d);
/* nw_2 is not the last because its not valid */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
)
TESTDEF(protodrv_sess_ref_dupl_reg,
struct proto_req_nw nw_1;
int i;
/* Create many sessions, with increasing uid */
IDIOT_ASSERT_NEQ(sess_array, NULL, %p);
for (i = 0; i < SESS_CNT; i++) {
sess_array[i].uid = i;
IDIOT_ASSERT_EQ(register_session_ref(&sess_array[i]), OK, %d);
}
memset(&nw_1, 0, sizeof(nw_1));
nw_1.nw.session = &sess_array[SESS_CNT - 1];
nw_1.nw.uid = nw_1.nw.session->uid;
/* Link nw_1 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_1), OK, %d);
/* nw_1 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), LAST, %d);
/* Link nw_1 Again -> Fault */
IDIOT_ASSERT_EQ(link_session_nw(&nw_1), -EFAULT, %d);
/* Unlink nw_1 */
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_1), OK, %d);
/* No nw_1 left */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), NOT_LAST, %d);
)
TESTDEF(protodrv_sess_ref_is_last_2_nw,
struct proto_req_frame frame;
struct proto_req_nw nw_1, nw_2;
struct proto_req_nw nw_A, nw_B;
int i;
/* Create many sessions, with increasing uid */
IDIOT_ASSERT_NEQ(sess_array, NULL, %p);
for (i = 0; i < SESS_CNT; i++) {
sess_array[i].uid = i;
IDIOT_ASSERT_EQ(register_session_ref(&sess_array[i]), OK, %d);
}
memset(&frame, 0, sizeof(frame));
memset(&nw_1, 0, sizeof(nw_1));
memset(&nw_2, 0, sizeof(nw_2));
memset(&nw_A, 0, sizeof(nw_A));
memset(&nw_B, 0, sizeof(nw_B));
frame.frame.session = &sess_array[SESS_CNT - 1];
frame.frame.uid = frame.frame.session->uid;
nw_1.nw.session = &sess_array[SESS_CNT - 1];
nw_1.nw.uid = nw_1.nw.session->uid;
nw_2.nw.session = &sess_array[SESS_CNT - 1];
nw_2.nw.uid = nw_2.nw.session->uid;
nw_A.nw.session = &sess_array[1];
nw_A.nw.uid = nw_A.nw.session->uid;
nw_B.nw.session = &sess_array[1];
nw_B.nw.uid = nw_B.nw.session->uid;
/* Link nw_1 */
IDIOT_ASSERT_EQ(link_session_nw(&nw_1), OK, %d);
/* nw_1 is the last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), LAST, %d);
/* Link nw_A */
IDIOT_ASSERT_EQ(link_session_nw(&nw_A), OK, %d);
/* nw_1 and nw_A are last on their session */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_A), LAST, %d);
/* Link nw_2 and nw_B */
IDIOT_ASSERT_EQ(link_session_nw(&nw_2), OK, %d);
IDIOT_ASSERT_EQ(link_session_nw(&nw_B), OK, %d);
/* No nw is last */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_1), NOT_LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_A), NOT_LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_B), NOT_LAST, %d);
/* Put frame on nw_1's session */
memset(&frame, 0, sizeof(frame));
frame.frame.session = nw_1.nw.session;
frame.frame.uid = frame.frame.session->uid;
IDIOT_ASSERT_EQ(link_session_frame(&frame), OK, %d);
/* Unlink nw_1 and nw_A */
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_1), OK, %d);
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_A), OK, %d);
/* nw_B is now last, but nw_2 is not last yet (due to the frame) */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), NOT_LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_B), LAST, %d);
/* Unlink frame from nw_2's session and link to nw_B's session */
IDIOT_ASSERT_EQ(unlink_session_frame(&frame), OK, %d);
frame.frame.session = nw_B.nw.session;
frame.frame.uid = frame.frame.session->uid;
IDIOT_ASSERT_EQ(link_session_frame(&frame), OK, %d);
/* nw_2 is now last, but nw_B is not last yet (due to the frame) */
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_2), LAST, %d);
IDIOT_ASSERT_EQ(is_last_session_ref(&nw_B), NOT_LAST, %d);
/* unlink everything */
IDIOT_ASSERT_EQ(unlink_session_frame(&frame), OK, %d);
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_2), OK, %d);
IDIOT_ASSERT_EQ(unlink_session_nw(&nw_B), OK, %d);
)