177 lines
4.0 KiB
C
Executable File
177 lines
4.0 KiB
C
Executable File
/*
|
|
* Samsung Exynos SoC series VIPx driver
|
|
*
|
|
* Copyright (c) 2018 Samsung Electronics Co., Ltd
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include "vipx-log.h"
|
|
#include "vipx-common-type.h"
|
|
#include "vipx-kernel-binary.h"
|
|
|
|
int vipx_kernel_binary_set_gmodel(struct vipx_context *vctx,
|
|
struct vipx_graph_model *gmodel)
|
|
{
|
|
struct vipx_kernel_binary *kbin, *temp, *gbin, *temp2;
|
|
unsigned int kid, gid;
|
|
int kfd, gfd;
|
|
size_t ksize, gsize;
|
|
bool is_duplicate;
|
|
|
|
vipx_enter();
|
|
gid = GET_COMMON_GRAPH_MODEL_ID(gmodel->id);
|
|
list_for_each_entry_safe(kbin, temp, &vctx->binary_list, clist) {
|
|
kid = GET_COMMON_GRAPH_MODEL_ID(kbin->global_id);
|
|
if (gid == kid) {
|
|
kfd = kbin->buffer.m.fd;
|
|
ksize = kbin->buffer.size;
|
|
is_duplicate = false;
|
|
list_for_each_entry_safe(gbin, temp2,
|
|
&gmodel->kbin_list, glist) {
|
|
gfd = gbin->buffer.m.fd;
|
|
gsize = gbin->buffer.size;
|
|
if ((kfd == gfd) && (ksize == gsize)) {
|
|
is_duplicate = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!is_duplicate) {
|
|
//TODO check if list cleanup is needed
|
|
list_add_tail(&kbin->glist, &gmodel->kbin_list);
|
|
gmodel->kbin_count++;
|
|
}
|
|
}
|
|
}
|
|
vipx_leave();
|
|
return 0;
|
|
}
|
|
|
|
static int __vipx_kernel_binary_check(struct vipx_context *vctx,
|
|
unsigned int id, int fd, unsigned int size)
|
|
{
|
|
unsigned int model_id, kid;
|
|
struct vipx_kernel_binary *kbin, *temp;
|
|
|
|
model_id = GET_COMMON_GRAPH_MODEL_ID(id);
|
|
list_for_each_entry_safe(kbin, temp, &vctx->binary_list, clist) {
|
|
kid = GET_COMMON_GRAPH_MODEL_ID(kbin->global_id);
|
|
if ((model_id == kid) &&
|
|
(fd == kbin->buffer.m.fd) &&
|
|
(size == kbin->buffer.size))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int vipx_kernel_binary_add(struct vipx_context *vctx, unsigned int id,
|
|
int fd, unsigned int size)
|
|
{
|
|
int ret;
|
|
struct vipx_kernel_binary *kbin;
|
|
struct vipx_memory *mem;
|
|
unsigned long flags;
|
|
|
|
vipx_enter();
|
|
ret = __vipx_kernel_binary_check(vctx, id, fd, size);
|
|
if (ret) {
|
|
vipx_leave();
|
|
return 0;
|
|
}
|
|
|
|
kbin = kzalloc(sizeof(*kbin), GFP_KERNEL);
|
|
if (!kbin) {
|
|
ret = -ENOMEM;
|
|
vipx_err("Failed to alloc kernel binary\n");
|
|
goto p_err;
|
|
}
|
|
|
|
kbin->global_id = id;
|
|
kbin->buffer.m.fd = fd;
|
|
kbin->buffer.size = size;
|
|
|
|
mem = &vctx->core->system->memory;
|
|
ret = mem->mops->map_dmabuf(mem, &kbin->buffer);
|
|
if (ret)
|
|
goto p_err_map;
|
|
|
|
spin_lock_irqsave(&vctx->binary_slock, flags);
|
|
vctx->binary_count++;
|
|
list_add_tail(&kbin->clist, &vctx->binary_list);
|
|
spin_unlock_irqrestore(&vctx->binary_slock, flags);
|
|
|
|
kbin->vctx = vctx;
|
|
vipx_leave();
|
|
return 0;
|
|
p_err_map:
|
|
kfree(kbin);
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int vipx_kernel_binary_unload(struct vipx_context *vctx, unsigned int id,
|
|
int fd, unsigned int size)
|
|
{
|
|
unsigned int model_id, kid;
|
|
struct vipx_kernel_binary *kbin, *temp;
|
|
bool found;
|
|
|
|
vipx_enter();
|
|
found = false;
|
|
model_id = GET_COMMON_GRAPH_MODEL_ID(id);
|
|
list_for_each_entry_safe(kbin, temp, &vctx->binary_list, clist) {
|
|
kid = GET_COMMON_GRAPH_MODEL_ID(kbin->global_id);
|
|
if ((model_id == kid) &&
|
|
(fd == kbin->buffer.m.fd) &&
|
|
(size == kbin->buffer.size)) {
|
|
vipx_kernel_binary_remove(kbin);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
vipx_err("There is no kernel binary to unload\n");
|
|
vipx_leave();
|
|
return -ENOENT;
|
|
}
|
|
vipx_leave();
|
|
return 0;
|
|
}
|
|
|
|
void vipx_kernel_binary_remove(struct vipx_kernel_binary *kbin)
|
|
{
|
|
struct vipx_context *vctx;
|
|
unsigned long flags;
|
|
struct vipx_memory *mem;
|
|
|
|
vipx_enter();
|
|
vctx = kbin->vctx;
|
|
|
|
spin_lock_irqsave(&vctx->binary_slock, flags);
|
|
list_del(&kbin->clist);
|
|
vctx->binary_count--;
|
|
spin_unlock_irqrestore(&vctx->binary_slock, flags);
|
|
|
|
mem = &vctx->core->system->memory;
|
|
mem->mops->unmap_dmabuf(mem, &kbin->buffer);
|
|
|
|
kfree(kbin);
|
|
|
|
vipx_leave();
|
|
}
|
|
|
|
void vipx_kernel_binary_all_remove(struct vipx_context *vctx)
|
|
{
|
|
struct vipx_kernel_binary *kbin, *temp;
|
|
|
|
vipx_enter();
|
|
list_for_each_entry_safe(kbin, temp, &vctx->binary_list, clist) {
|
|
vipx_kernel_binary_remove(kbin);
|
|
}
|
|
vipx_leave();
|
|
}
|