mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
video: rockchip: mpp: Add device task capacity
1. Add mpp_dev task capacity and default is 1. The task capacity is the task queue length that hardware can accept. Default 1 means normal hardware can only accept one task at once. 2. Attach mpp_dev to mpp_taskqueue for status probe. The task queue capacity is the minimum task capacity of all the attached mpp_dev. Change-Id: I8cafe806ec9399902237418d2bbcb088240ed415 Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
@@ -84,6 +84,8 @@ const char *enc_info_item_name[ENC_INFO_BUTT] = {
|
||||
#endif
|
||||
|
||||
static void mpp_free_task(struct kref *ref);
|
||||
static void mpp_attach_workqueue(struct mpp_dev *mpp,
|
||||
struct mpp_taskqueue *queue);
|
||||
|
||||
/* task queue schedule */
|
||||
static int
|
||||
@@ -185,10 +187,9 @@ mpp_taskqueue_pop_running(struct mpp_taskqueue *queue,
|
||||
}
|
||||
|
||||
static void
|
||||
mpp_taskqueue_trigger_work(struct mpp_taskqueue *queue,
|
||||
struct workqueue_struct *workq)
|
||||
mpp_taskqueue_trigger_work(struct mpp_dev *mpp)
|
||||
{
|
||||
queue_work(workq, &queue->work);
|
||||
queue_work(mpp->workq, &mpp->work);
|
||||
}
|
||||
|
||||
int mpp_power_on(struct mpp_dev *mpp)
|
||||
@@ -388,7 +389,7 @@ static int mpp_process_task(struct mpp_session *session,
|
||||
mpp_taskqueue_push_pending(mpp->queue, task);
|
||||
set_bit(TASK_STATE_PENDING, &task->state);
|
||||
/* trigger current queue to run task */
|
||||
mpp_taskqueue_trigger_work(mpp->queue, mpp->workq);
|
||||
mpp_taskqueue_trigger_work(mpp);
|
||||
kref_put(&task->ref, mpp_free_task);
|
||||
|
||||
return 0;
|
||||
@@ -543,10 +544,8 @@ static int mpp_task_run(struct mpp_dev *mpp,
|
||||
static void mpp_task_try_run(struct work_struct *work_s)
|
||||
{
|
||||
struct mpp_task *task;
|
||||
struct mpp_dev *mpp;
|
||||
struct mpp_taskqueue *queue = container_of(work_s,
|
||||
struct mpp_taskqueue,
|
||||
work);
|
||||
struct mpp_dev *mpp = container_of(work_s, struct mpp_dev, work);
|
||||
struct mpp_taskqueue *queue = mpp->queue;
|
||||
|
||||
mpp_debug_enter();
|
||||
|
||||
@@ -702,6 +701,7 @@ static int mpp_attach_service(struct mpp_dev *mpp, struct device *dev)
|
||||
u32 reset_group_node = 0;
|
||||
struct device_node *np = NULL;
|
||||
struct platform_device *pdev = NULL;
|
||||
struct mpp_taskqueue *queue = NULL;
|
||||
int ret = 0;
|
||||
|
||||
np = of_parse_phandle(dev->of_node, "rockchip,srv", 0);
|
||||
@@ -728,28 +728,29 @@ static int mpp_attach_service(struct mpp_dev *mpp, struct device *dev)
|
||||
|
||||
ret = of_property_read_u32(dev->of_node,
|
||||
"rockchip,taskqueue-node", &taskqueue_node);
|
||||
if (taskqueue_node >= mpp->srv->taskqueue_cnt) {
|
||||
dev_err(dev, "taskqueue-node %d must less than %d\n",
|
||||
taskqueue_node, mpp->srv->taskqueue_cnt);
|
||||
ret = -ENODEV;
|
||||
goto err_put_pdev;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* if device not set, then alloc one */
|
||||
struct mpp_taskqueue *queue;
|
||||
|
||||
queue = devm_kzalloc(dev, sizeof(*queue), GFP_KERNEL);
|
||||
if (!queue) {
|
||||
ret = -ENOMEM;
|
||||
queue = mpp_taskqueue_init(dev);
|
||||
if (!queue)
|
||||
goto err_put_pdev;
|
||||
}
|
||||
mpp_taskqueue_init(queue, mpp->srv);
|
||||
mpp->queue = queue;
|
||||
} else {
|
||||
/* set taskqueue according dtsi */
|
||||
if (taskqueue_node >= mpp->srv->taskqueue_cnt) {
|
||||
dev_err(dev, "taskqueue-node %d must less than %d\n",
|
||||
taskqueue_node, mpp->srv->taskqueue_cnt);
|
||||
queue = mpp->srv->task_queues[taskqueue_node];
|
||||
if (!queue) {
|
||||
dev_err(dev, "taskqueue attach to invalid node %d\n",
|
||||
taskqueue_node);
|
||||
ret = -ENODEV;
|
||||
goto err_put_pdev;
|
||||
} else {
|
||||
mpp->queue = mpp->srv->task_queues[taskqueue_node];
|
||||
}
|
||||
}
|
||||
mpp_attach_workqueue(mpp, queue);
|
||||
|
||||
ret = of_property_read_u32(dev->of_node,
|
||||
"rockchip,resetgroup-node", &reset_group_node);
|
||||
@@ -777,20 +778,48 @@ err_put_pdev:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mpp_taskqueue_init(struct mpp_taskqueue *queue,
|
||||
struct mpp_service *srv)
|
||||
struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev)
|
||||
{
|
||||
struct mpp_taskqueue *queue = devm_kzalloc(dev, sizeof(*queue),
|
||||
GFP_KERNEL);
|
||||
if (!queue)
|
||||
return NULL;
|
||||
|
||||
mutex_init(&queue->pending_lock);
|
||||
mutex_init(&queue->running_lock);
|
||||
mutex_init(&queue->mmu_lock);
|
||||
mutex_init(&queue->dev_lock);
|
||||
INIT_LIST_HEAD(&queue->pending_list);
|
||||
INIT_LIST_HEAD(&queue->running_list);
|
||||
INIT_LIST_HEAD(&queue->mmu_list);
|
||||
INIT_WORK(&queue->work, mpp_task_try_run);
|
||||
INIT_LIST_HEAD(&queue->dev_list);
|
||||
/* default taskqueue has max 16 task capacity */
|
||||
queue->task_capacity = MPP_MAX_TASK_CAPACITY;
|
||||
|
||||
queue->srv = srv;
|
||||
return queue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void mpp_attach_workqueue(struct mpp_dev *mpp,
|
||||
struct mpp_taskqueue *queue)
|
||||
{
|
||||
mpp->queue = queue;
|
||||
INIT_LIST_HEAD(&mpp->queue_link);
|
||||
mutex_lock(&queue->dev_lock);
|
||||
list_add_tail(&mpp->queue_link, &queue->dev_list);
|
||||
if (queue->task_capacity > mpp->task_capacity)
|
||||
queue->task_capacity = mpp->task_capacity;
|
||||
mutex_unlock(&queue->dev_lock);
|
||||
}
|
||||
|
||||
static void mpp_detach_workqueue(struct mpp_dev *mpp)
|
||||
{
|
||||
struct mpp_taskqueue *queue = mpp->queue;
|
||||
|
||||
if (queue) {
|
||||
mutex_lock(&queue->dev_lock);
|
||||
list_del_init(&mpp->queue_link);
|
||||
mutex_unlock(&queue->dev_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static int mpp_check_cmd_v1(__u32 cmd)
|
||||
@@ -1627,6 +1656,16 @@ int mpp_dev_probe(struct mpp_dev *mpp,
|
||||
struct device_node *np = dev->of_node;
|
||||
struct mpp_hw_info *hw_info = mpp->var->hw_info;
|
||||
|
||||
/* read link table capacity */
|
||||
ret = of_property_read_u32(np, "rockchip,task-capacity",
|
||||
&mpp->task_capacity);
|
||||
if (ret) {
|
||||
mpp->task_capacity = 1;
|
||||
INIT_WORK(&mpp->work, mpp_task_try_run);
|
||||
} else {
|
||||
INIT_WORK(&mpp->work, NULL);
|
||||
}
|
||||
|
||||
/* Get and attach to service */
|
||||
ret = mpp_attach_service(mpp, dev);
|
||||
if (ret) {
|
||||
@@ -1719,6 +1758,7 @@ failed_init:
|
||||
pm_runtime_put_sync(dev);
|
||||
failed:
|
||||
destroy_workqueue(mpp->workq);
|
||||
mpp_detach_workqueue(mpp);
|
||||
device_init_wakeup(dev, false);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
@@ -1738,6 +1778,7 @@ int mpp_dev_remove(struct mpp_dev *mpp)
|
||||
mpp->workq = NULL;
|
||||
}
|
||||
|
||||
mpp_detach_workqueue(mpp);
|
||||
device_init_wakeup(mpp->dev, false);
|
||||
pm_runtime_disable(mpp->dev);
|
||||
|
||||
@@ -1788,7 +1829,7 @@ irqreturn_t mpp_dev_isr_sched(int irq, void *param)
|
||||
ret = mpp->dev_ops->isr(mpp);
|
||||
|
||||
/* trigger current queue to run next task */
|
||||
mpp_taskqueue_trigger_work(mpp->queue, mpp->workq);
|
||||
mpp_taskqueue_trigger_work(mpp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#define MPP_MAX_MSG_NUM (16)
|
||||
#define MPP_MAX_REG_TRANS_NUM (60)
|
||||
#define MPP_MAX_TASK_CAPACITY (16)
|
||||
/* define flags for mpp_request */
|
||||
#define MPP_FLAGS_MULTI_MSG (0x00000001)
|
||||
#define MPP_FLAGS_LAST_MSG (0x00000002)
|
||||
@@ -277,6 +278,16 @@ struct mpp_dev {
|
||||
struct mpp_hw_ops *hw_ops;
|
||||
struct mpp_dev_ops *dev_ops;
|
||||
|
||||
/* per-device work for attached taskqueue */
|
||||
struct work_struct work;
|
||||
/* task for work queue */
|
||||
struct workqueue_struct *workq;
|
||||
/*
|
||||
* The task capacity is the task queue length that hardware can accept.
|
||||
* Default 1 means normal hardware can only accept one task at once.
|
||||
*/
|
||||
u32 task_capacity;
|
||||
|
||||
int irq;
|
||||
u32 irq_status;
|
||||
|
||||
@@ -288,8 +299,6 @@ struct mpp_dev {
|
||||
atomic_t session_index;
|
||||
atomic_t task_count;
|
||||
atomic_t task_index;
|
||||
/* task for work queue */
|
||||
struct workqueue_struct *workq;
|
||||
/* current task in running */
|
||||
struct mpp_task *cur_task;
|
||||
/* set session max buffers */
|
||||
@@ -299,6 +308,8 @@ struct mpp_dev {
|
||||
/* point to MPP Service */
|
||||
struct platform_device *pdev_srv;
|
||||
struct mpp_service *srv;
|
||||
|
||||
struct list_head queue_link;
|
||||
};
|
||||
|
||||
struct mpp_task;
|
||||
@@ -379,9 +390,6 @@ struct mpp_task {
|
||||
};
|
||||
|
||||
struct mpp_taskqueue {
|
||||
/* work for taskqueue */
|
||||
struct work_struct work;
|
||||
|
||||
/* lock for pending list */
|
||||
struct mutex pending_lock;
|
||||
struct list_head pending_list;
|
||||
@@ -394,6 +402,14 @@ struct mpp_taskqueue {
|
||||
/* lock for mmu list */
|
||||
struct mutex mmu_lock;
|
||||
struct list_head mmu_list;
|
||||
/* lock for dev list */
|
||||
struct mutex dev_lock;
|
||||
struct list_head dev_list;
|
||||
/*
|
||||
* task_capacity in taskqueue is the minimum task capacity of the
|
||||
* device task capacity which is attached to the taskqueue
|
||||
*/
|
||||
u32 task_capacity;
|
||||
};
|
||||
|
||||
struct mpp_reset_group {
|
||||
@@ -488,8 +504,7 @@ struct mpp_dev_ops {
|
||||
int (*dump_session)(struct mpp_session *session, struct seq_file *seq);
|
||||
};
|
||||
|
||||
int mpp_taskqueue_init(struct mpp_taskqueue *queue,
|
||||
struct mpp_service *srv);
|
||||
struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev);
|
||||
|
||||
struct mpp_mem_region *
|
||||
mpp_task_attach_fd(struct mpp_task *task, int fd);
|
||||
|
||||
@@ -310,11 +310,10 @@ static int mpp_service_probe(struct platform_device *pdev)
|
||||
struct mpp_taskqueue *queue;
|
||||
|
||||
for (i = 0; i < srv->taskqueue_cnt; i++) {
|
||||
queue = devm_kzalloc(dev, sizeof(*queue), GFP_KERNEL);
|
||||
queue = mpp_taskqueue_init(dev);
|
||||
if (!queue)
|
||||
continue;
|
||||
|
||||
mpp_taskqueue_init(queue, srv);
|
||||
srv->task_queues[i] = queue;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user