kernel_samsung_a34x-permissive/drivers/misc/mediatek/vpu/3.0/vpu_pool.c
2024-04-28 15:51:13 +02:00

248 lines
4.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/slab.h>
#include "vpu_pool.h"
#include "vpu_cmn.h"
void vpu_pool_init(struct vpu_pool *p, const char *name, int type)
{
if (name)
strlcpy(p->name, name, sizeof(p->name));
else
p->name[0] = 0;
LOG_DBG("%s: \"%s\"\n", __func__, p->name);
INIT_LIST_HEAD(&p->pool);
mutex_init(&p->lock);
p->size = 0;
p->type = type;
p->priv = NULL;
}
int vpu_pool_size(struct vpu_pool *p)
{
int ret;
mutex_lock(&p->lock);
ret = p->size;
mutex_unlock(&p->lock);
return ret;
}
int vpu_pool_is_empty(struct vpu_pool *p)
{
int ret;
mutex_lock(&p->lock);
ret = list_empty(&p->pool);
mutex_unlock(&p->lock);
return ret;
}
static int vpu_pool_enqueue_dep(struct vpu_pool *p, struct vpu_request *req)
{
int ret = 0;
struct vpu_pool_dep *dep, *n;
WARN_ON(!(req->requested_core & VPU_CORE_MULTIPROC));
mutex_lock(&p->lock);
/* Match & insert to sub-pool */
list_for_each_entry_safe(dep, n, &p->pool, link) {
if (dep->user != req->user_id)
continue;
if (dep->tail_id == req->request_id)
goto insert_out;
}
/* Allocate & init new sub-pool */
dep = kzalloc(sizeof(struct vpu_pool_dep), GFP_KERNEL);
if (!dep) {
ret = -ENOMEM;
goto out;
}
dep->head_id = req->request_id;
dep->user = req->user_id;
INIT_LIST_HEAD(&dep->sub_pool);
list_add_tail(&dep->link, &p->pool);
LOG_DBG("%s: %s: NEW dep: %p, user: %p, head: %p\n",
__func__,
p->name,
dep,
dep->user,
dep->head_id);
insert_out:
list_add_tail(vlist_link(req, struct vpu_request), &dep->sub_pool);
p->size++;
/**
* The sub-pool is ready for processing, if the last
* dependency request is enqueued, Eq. tail_id = 0
*/
dep->tail_id = req->next_req_id;
LOG_DBG("%s: %s: user: %p, head: %p, tail: %p, req: %p\n",
__func__,
p->name,
dep->user,
dep->head_id,
dep->tail_id,
req->request_id);
out:
mutex_unlock(&p->lock);
return ret;
}
static struct vpu_request *vpu_pool_dequeue_dep(struct vpu_pool *p)
{
struct vpu_request *req = NULL;
struct vpu_pool_dep *dep, *n;
mutex_lock(&p->lock);
if (list_empty(&p->pool))
goto out;
/* Get next request from current active sub-pool */
dep = (struct vpu_pool_dep *)p->priv;
if (dep) {
if (!list_empty(&dep->sub_pool)) {
req = vlist_node_of(dep->sub_pool.next,
struct vpu_request);
goto got_req;
}
}
/* Get head request from the first ready sub-pool */
list_for_each_entry_safe(dep, n, &p->pool, link) {
if (!dep)
break;
if (dep->tail_id) /* Skip non-ready sub-pools */
continue;
if (!list_empty(&dep->sub_pool)) {
p->priv = dep; /* mark active */
req = vlist_node_of(dep->sub_pool.next,
struct vpu_request);
break;
}
}
got_req:
if (req) {
list_del_init(vlist_link(req, struct vpu_request));
LOG_DBG("%s: %s: user: %p, head: %p, tail: %p, req: %p\n",
__func__,
p->name,
dep->user,
dep->head_id,
dep->tail_id,
req->request_id);
/* free & remove the sub-pool, if it's empty */
if (list_empty(&dep->sub_pool)) {
p->priv = NULL; /* remove active */
WARN_ON(dep->tail_id != 0);
list_del_init(&dep->link);
LOG_DBG("%s: %s: FREE dep: user: %p, head: %p\n",
__func__,
p->name,
dep->user,
dep->head_id);
kfree(dep);
}
p->size--;
}
LOG_DBG("flag - 3: get %s pool, size(%d)\n", p->name, p->size);
out:
mutex_unlock(&p->lock);
return req;
}
static int vpu_pool_enqueue_pri(struct vpu_pool *p, struct vpu_request *req,
unsigned int *priority)
{
LOG_DBG("%s: request_id: %p, core: %x => %s Pool\n",
__func__,
req->request_id,
req->requested_core,
p->name);
WARN_ON(req->requested_core & VPU_CORE_MULTIPROC);
mutex_lock(&p->lock);
list_add_tail(vlist_link(req, struct vpu_request), &p->pool);
p->size++;
if (priority)
*priority += 1;
mutex_unlock(&p->lock);
return 0;
}
static struct vpu_request *vpu_pool_dequeue_pri(struct vpu_pool *p,
unsigned int *priority)
{
struct vpu_request *req = NULL;
mutex_lock(&p->lock);
if (list_empty(&p->pool))
goto out;
req = vlist_node_of(p->pool.next, struct vpu_request);
list_del_init(vlist_link(req, struct vpu_request));
p->size--;
if (priority)
*priority -= 1;
LOG_DBG("flag - 3: get %s pool, size(%d)\n", p->name, p->size);
out:
mutex_unlock(&p->lock);
if (req)
LOG_DBG("%s: request_id: %p, core: %x => %s Pool\n",
__func__,
req->request_id,
req->requested_core,
p->name);
return req;
}
int vpu_pool_enqueue(struct vpu_pool *p, struct vpu_request *req,
unsigned int *priority)
{
if (!req)
return -ENOENT;
if (p->type == VPU_POOL_DEP)
return vpu_pool_enqueue_dep(p, req);
return vpu_pool_enqueue_pri(p, req, priority);
}
struct vpu_request *vpu_pool_dequeue(struct vpu_pool *p,
unsigned int *priority)
{
if (p->type == VPU_POOL_DEP)
return vpu_pool_dequeue_dep(p);
return vpu_pool_dequeue_pri(p, priority);
}