blob: 1a0e93a3c12efd6e42b92e2e426a6d7a92b3173a [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.
*/
#include <linux/types.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>
#define NPU_LOG_TAG "if-session-protodrv"
#include "npu-config.h"
#include "npu-common.h"
#include "npu-if-session-protodrv.h"
#include "npu-util-llq.h"
#include "npu-log.h"
#include "npu-queue.h"
extern int npu_session_save_result(struct npu_session *session, struct nw_result nw_result);
extern void npu_session_queue_done(struct npu_queue *queue, struct vb_container_list *inclist, struct vb_container_list *otclist, unsigned long flag);
/* Context information */
static struct npu_if_session_protodrv_ctx ctx = {
.is_opened = ATOMIC_INIT(0),
};
/* TODO: Link appripirate function in Session manager */
struct npu_if_session_protodrv_ops npu_if_session_protodrv_ops = {
.queue_done = npu_session_queue_done,
};
/* Initializer and deallocator */
struct npu_if_session_protodrv_ctx *npu_if_session_protodrv_ctx_open(void)
{
npu_info("start in npu_if_session_protodrv_ctx_open\n");
spin_lock_init(&ctx.buffer_q_lock);
spin_lock_init(&ctx.ncp_mgmt_lock);
INIT_KFIFO(ctx.buffer_q_list);
INIT_KFIFO(ctx.ncp_mgmt_list);
atomic_set(&ctx.is_opened, 1);
npu_info("complete in npu_if_session_protodrv_ctx_open\n");
return &ctx;
}
void npu_if_session_protodrv_ctx_close(void)
{
npu_info("start in npu_if_session_protodrv_ctx_close\n");
atomic_set(&ctx.is_opened, 0);
kfifo_reset(&ctx.buffer_q_list);
kfifo_reset(&ctx.ncp_mgmt_list);
npu_info("complete in npu_if_session_protodrv_ctx_close\n");
}
/* Return 1 if the npu_if_session_protodrv is opened state
* Otherwise, returns 0
*/
int npu_if_session_protodrv_is_opened(void)
{
return atomic_read(&ctx.is_opened);
}
/* Operations for buffer_q */
int npu_buffer_q_get(struct npu_frame *frame)
{
BUG_ON(!frame);
return kfifo_out_spinlocked(&ctx.buffer_q_list, frame, 1, &ctx.buffer_q_lock);
}
int npu_buffer_q_put(const struct npu_frame *frame)
{
int ret;
BUG_ON(!frame);
ret = kfifo_in_spinlocked(&ctx.buffer_q_list, frame, 1, &ctx.buffer_q_lock);
if (ret > 0) {
if (ctx.buffer_q_callback) {
ctx.buffer_q_callback();
}
}
return ret;
}
int npu_buffer_q_is_available(void)
{
return !kfifo_is_empty(&ctx.buffer_q_list);
}
void npu_buffer_q_register_cb(LLQ_task_t cb)
{
npu_info("callback for buffer_q: [%pK]\n", cb);
BUG_ON(!cb);
ctx.buffer_q_callback = cb;
}
void npu_buffer_q_notify_done(const struct npu_frame *frame)
{
unsigned long flags = 0;
set_bit(VS4L_CL_FLAG_DONE, &flags);
if (frame->result_code) {
/* Error occurred - Assert invalid flag */
npu_ufwarn("NDONE flag asserted.\n", frame);
set_bit(VS4L_CL_FLAG_INVALID, &flags);
}
if (npu_if_session_protodrv_ops.queue_done) {
if (frame->src_queue && frame->input && frame->output) {
npu_uftrace("Calling npu_queue_done, frame_id = [%u]\n", frame, frame->frame_id);
npu_if_session_protodrv_ops.queue_done(
frame->src_queue, frame->input, frame->output, flags);
npu_ufinfo("Succeeded frame_id = [%u]\n", frame, frame->frame_id);
} else
npu_ufinfo("Skip calling queue_done[queue=%pK, in=%pK, out=%pK]\n",
frame, frame->src_queue, frame->input, frame->output);
} else {
npu_warn("not defined: queue_done\n");
}
}
/* Operations for ncp_mgmt */
int npu_ncp_mgmt_get(struct npu_nw *frame)
{
BUG_ON(!frame);
return kfifo_out_spinlocked(&ctx.ncp_mgmt_list, frame, 1, &ctx.ncp_mgmt_lock);
}
int npu_ncp_mgmt_put(const struct npu_nw *frame)
{
int ret;
BUG_ON(!frame);
ret = kfifo_in_spinlocked(&ctx.ncp_mgmt_list, frame, 1, &ctx.ncp_mgmt_lock);
if (ret > 0) {
if (ctx.ncp_mgmt_callback) {
ctx.ncp_mgmt_callback();
}
}
return ret;
}
int npu_ncp_mgmt_is_available(void)
{
return !kfifo_is_empty(&ctx.ncp_mgmt_list);
}
void npu_ncp_mgmt_register_cb(LLQ_task_t cb)
{
npu_info("callback for ncp_mgmt(%pK)\n", cb);
BUG_ON(!cb);
ctx.ncp_mgmt_callback = cb;
}
int npu_ncp_mgmt_save_result(
save_result_func notify_func,
struct npu_session *sess,
struct nw_result result)
{
if (notify_func) {
npu_dbg("notify_func invoked. sess=%pK, result=0x%08x\n",
sess, result.result_code);
return notify_func(sess, result);
} else {
npu_warn("not defined: save_result function\n");
return 0;
}
}