From 8245d1a2d16ecbbe91b72ef8fdf5428ac0b2b232 Mon Sep 17 00:00:00 2001 From: engstk Date: Wed, 9 Nov 2022 15:37:00 +0000 Subject: [PATCH] Merge branch android-gs-raviole-5.10-android13 (android-13.0.0_r0.44) Signed-off-by: engstk --- drivers/media/platform/bigocean/Makefile | 2 +- drivers/media/platform/bigocean/bigo.c | 363 +++++++++++++------ drivers/media/platform/bigocean/bigo_pm.c | 44 ++- drivers/media/platform/bigocean/bigo_pm.h | 2 + drivers/media/platform/bigocean/bigo_prioq.c | 82 +++++ drivers/media/platform/bigocean/bigo_prioq.h | 19 + drivers/media/platform/bigocean/bigo_priv.h | 19 +- drivers/media/platform/bigocean/bigo_slc.c | 6 +- drivers/media/platform/bigocean/bigo_slc.h | 4 +- 9 files changed, 425 insertions(+), 116 deletions(-) create mode 100644 drivers/media/platform/bigocean/bigo_prioq.c create mode 100644 drivers/media/platform/bigocean/bigo_prioq.h diff --git a/drivers/media/platform/bigocean/Makefile b/drivers/media/platform/bigocean/Makefile index 9bc7a2131d..cbac244dbd 100644 --- a/drivers/media/platform/bigocean/Makefile +++ b/drivers/media/platform/bigocean/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_BIGOCEAN) += bigocean.o -bigocean-$(CONFIG_BIGOCEAN) += bigo.o bigo_pm.o bigo_io.o bigo_of.o bigo_iommu.o +bigocean-$(CONFIG_BIGOCEAN) += bigo.o bigo_pm.o bigo_io.o bigo_of.o bigo_iommu.o bigo_prioq.o bigocean-$(CONFIG_SLC_PARTITION_MANAGER) += bigo_slc.o bigocean-$(CONFIG_DEBUG_FS) += bigo_debug.o diff --git a/drivers/media/platform/bigocean/bigo.c b/drivers/media/platform/bigocean/bigo.c index 4d1c7a799d..2b75d3e37c 100644 --- a/drivers/media/platform/bigocean/bigo.c +++ b/drivers/media/platform/bigocean/bigo.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "bigo_io.h" #include "bigo_iommu.h" @@ -25,6 +26,7 @@ #include "bigo_priv.h" #include "bigo_slc.h" #include "bigo_debug.h" +#include "bigo_prioq.h" #define BIGO_DEVCLASS_NAME "video_codec" #define BIGO_CHRDEV_NAME "bigocean" @@ -35,6 +37,10 @@ #define BIGO_SMC_ID 0xd #define BIGO_MAX_INST_NUM 16 +#define BIGO_IDLE_TIMEOUT_MS 1000 + +static int bigo_worker_thread(void *data); + static struct sscd_platform_data bigo_sscd_platdata; static void bigo_sscd_release(struct device *dev) @@ -73,15 +79,32 @@ static void bigo_coredump(struct bigo_core *core, const char *crash_info) static inline int on_first_instance_open(struct bigo_core *core) { - int rc = bigo_pt_client_enable(core); + int rc; + + core->worker_thread = kthread_run(bigo_worker_thread, (void *)core, + "bigo_worker_thread"); + if (IS_ERR(core->worker_thread)) { + rc = PTR_ERR(core->worker_thread); + core->worker_thread = NULL; + pr_err("failed to create worker thread rc = %d\n", rc); + goto exit; + } - if (rc) + rc = bigo_pt_client_enable(core); + if (rc) { pr_info("failed to enable SLC"); + kthread_stop(core->worker_thread); + goto exit; + } #if IS_ENABLED(CONFIG_PM) rc = pm_runtime_get_sync(core->dev); - if (rc) + if (rc) { pr_err("failed to resume: %d\n", rc); + kthread_stop(core->worker_thread); + } #endif + +exit: return rc; } @@ -92,11 +115,9 @@ static inline void on_last_inst_close(struct bigo_core *core) pr_warn("failed to suspend\n"); #endif bigo_pt_client_disable(core); - kfree(core->job.regs); - core->job.regs = NULL; } -static inline int bigo_add_inst(struct bigo_inst *inst, struct bigo_core *core) +static inline int bigo_count_inst(struct bigo_core *core) { int count = 0; struct list_head *pos; @@ -104,11 +125,7 @@ static inline int bigo_add_inst(struct bigo_inst *inst, struct bigo_core *core) list_for_each(pos, &core->instances) count++; - if (count >= BIGO_MAX_INST_NUM) - return -ENOMEM; - - list_add_tail(&inst->list, &core->instances); - return 0; + return count; } static int bigo_open(struct inode *inode, struct file *file) @@ -121,59 +138,87 @@ static int bigo_open(struct inode *inode, struct file *file) if (!inst) { rc = -ENOMEM; pr_err("Failed to create instance\n"); - return rc; + goto err; } INIT_LIST_HEAD(&inst->list); INIT_LIST_HEAD(&inst->buffers); + kref_init(&inst->refcount); mutex_init(&inst->lock); + init_completion(&inst->job_comp); file->private_data = inst; inst->height = DEFAULT_WIDTH; inst->width = DEFAULT_HEIGHT; inst->fps = DEFAULT_FPS; inst->core = core; + inst->idle = true; + inst->job.regs_size = core->regs_size; + inst->job.regs = kzalloc(core->regs_size, GFP_KERNEL); + if (!inst->job.regs) { + rc = -ENOMEM; + pr_err("Failed to alloc job regs\n"); + goto err_first_inst; + } mutex_lock(&core->lock); + if (bigo_count_inst(core) >= BIGO_MAX_INST_NUM) { + rc = -ENOMEM; + pr_err("Reaches max number of supported instances\n"); + mutex_unlock(&core->lock); + goto err_inst_open; + } if (list_empty(&core->instances)) { rc = on_first_instance_open(core); if (rc) { pr_err("failed to setup first instance"); - goto err; + mutex_unlock(&core->lock); + goto err_inst_open; } } - rc = bigo_add_inst(inst, core); - if (rc) { - pr_err("Reaches max number of supported instances\n"); - goto err; - } + list_add_tail(&inst->list, &core->instances); mutex_unlock(&core->lock); - bigo_update_qos(core); - pr_info("opened bigocean instance\n"); + bigo_mark_qos_dirty(core); + pr_info("opened instance\n"); + return rc; - return 0; -err: - mutex_unlock(&core->lock); +err_inst_open: + kfree(inst->job.regs); +err_first_inst: kfree(inst); +err: return rc; } +static void bigo_close(struct kref *ref) +{ + struct bigo_inst *inst = container_of(ref, struct bigo_inst, refcount); + + if (inst && inst->core) { + clear_job_from_prioq(inst->core, inst); + bigo_unmap_all(inst); + bigo_mark_qos_dirty(inst->core); + bigo_update_qos(inst->core); + kfree(inst->job.regs); + kfree(inst); + pr_info("closed instance\n"); + } +} + static int bigo_release(struct inode *inode, struct file *file) { - struct bigo_core *core = - container_of(inode->i_cdev, struct bigo_core, cdev); struct bigo_inst *inst = file->private_data; + struct bigo_core *core = inst->core; - if (!inst || !core) { - pr_err("No instance or core\n"); + if (!inst || !core) return -EINVAL; - } - bigo_unmap_all(inst); + mutex_lock(&core->lock); list_del(&inst->list); - kfree(inst); - if (list_empty(&core->instances)) + if (list_empty(&core->instances)) { + kthread_stop(core->worker_thread); on_last_inst_close(core); + } mutex_unlock(&core->lock); - bigo_update_qos(core); - pr_info("closed bigocean instance\n"); + + kref_put(&inst->refcount, bigo_close); return 0; } @@ -182,6 +227,7 @@ static int bigo_run_job(struct bigo_core *core, struct bigo_job *job) long ret = 0; int rc = 0; u32 status = 0; + unsigned long flags; bigo_bypass_ssmt_pid(core); bigo_push_regs(core, job->regs); @@ -190,6 +236,11 @@ static int bigo_run_job(struct bigo_core *core, struct bigo_job *job) msecs_to_jiffies(JOB_COMPLETE_TIMEOUT_MS)); if (!ret) { pr_err("timed out waiting for HW\n"); + + spin_lock_irqsave(&core->status_lock, flags); + core->stat_with_irq = bigo_core_readl(core, BIGO_REG_STAT); + spin_unlock_irqrestore(&core->status_lock, flags); + bigo_core_disable(core); rc = -ETIMEDOUT; } else { @@ -213,58 +264,12 @@ static int bigo_run_job(struct bigo_core *core, struct bigo_job *job) return rc; } -static int bigo_process(struct bigo_core *core, struct bigo_ioc_regs *desc) -{ - int rc = 0; - struct bigo_job *job = &core->job; - - if (!desc) { - pr_err("Invalid input\n"); - return -EINVAL; - } - if (desc->regs_size != core->regs_size) { - pr_err("Register size passed from userspace(%u) is different(%u)\n", - (unsigned int)desc->regs_size, core->regs_size); - return -EINVAL; - } - - if (!job->regs) { - job->regs = kzalloc(core->regs_size, GFP_KERNEL); - if (!job->regs) { - rc = -ENOMEM; - goto exit; - } - } - - if (copy_from_user(job->regs, (void *)desc->regs, core->regs_size)) { - pr_err("Failed to copy from user\n"); - rc = -EFAULT; - goto exit; - } - - /*TODO(vinaykalia@): Replace this with EDF scheduler.*/ - rc = bigo_run_job(core, job); - if (rc) { - pr_err("Error running job\n"); - goto exit; - } - - if (copy_to_user((void *)desc->regs, job->regs, core->regs_size)) { - pr_err("Failed to copy to user\n"); - rc = -EFAULT; - goto exit; - } - -exit: - return rc; -} - inline void bigo_config_frmrate(struct bigo_inst *inst, __u32 frmrate) { mutex_lock(&inst->lock); inst->fps = frmrate; mutex_unlock(&inst->lock); - bigo_update_qos(inst->core); + bigo_mark_qos_dirty(inst->core); } inline void bigo_config_frmsize(struct bigo_inst *inst, @@ -274,7 +279,7 @@ inline void bigo_config_frmsize(struct bigo_inst *inst, inst->height = frmsize->height; inst->width = frmsize->width; mutex_unlock(&inst->lock); - bigo_update_qos(inst->core); + bigo_mark_qos_dirty(inst->core); } inline void bigo_config_secure(struct bigo_inst *inst, __u32 is_secure) @@ -284,6 +289,41 @@ inline void bigo_config_secure(struct bigo_inst *inst, __u32 is_secure) mutex_unlock(&inst->lock); } +static int copy_regs_from_user(struct bigo_core *core, + struct bigo_ioc_regs *desc, + void __user *user_desc, + struct bigo_job *job) +{ + if (!core || !desc || !user_desc || !job) + return -EINVAL; + + if (copy_from_user(desc, user_desc, sizeof(*desc))) + return -EFAULT; + + if (desc->regs_size != core->regs_size) { + pr_err("Reg size of userspace(%u) is different(%u)\n", + (unsigned int)desc->regs_size, core->regs_size); + return -EINVAL; + } + + if (copy_from_user(job->regs, (void *)desc->regs, desc->regs_size)) + return -EFAULT; + + return 0; +} + +static int copy_regs_to_user(struct bigo_ioc_regs *desc, + struct bigo_job *job) +{ + if (!desc || !job) + return -EINVAL; + + if (copy_to_user((void *)desc->regs, job->regs, desc->regs_size)) + return -EFAULT; + + return 0; +} + static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -291,10 +331,11 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, struct bigo_core *core = container_of(file->f_inode->i_cdev, struct bigo_core, cdev); void __user *user_desc = (void __user *)arg; - struct bigo_ioc_regs desc; struct bigo_ioc_mapping mapping; struct bigo_ioc_frmsize frmsize; struct bigo_cache_info cinfo; + struct bigo_inst *curr_inst; + bool found = false; int rc = 0; if (_IOC_TYPE(cmd) != BIGO_IOC_MAGIC) { @@ -309,35 +350,59 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, pr_err("No instance or core\n"); return -EINVAL; } + mutex_lock(&core->lock); + list_for_each_entry(curr_inst, &core->instances, list) { + if (curr_inst == inst) { + found = true; + break; + } + } + + if (!found) { + mutex_unlock(&core->lock); + pr_err("this instance is invalid"); + return -EINVAL; + } + kref_get(&inst->refcount); + mutex_unlock(&core->lock); switch (cmd) { case BIGO_IOCX_PROCESS: - if (copy_from_user(&desc, user_desc, sizeof(desc))) { - pr_err("Failed to copy from user\n"); + { + struct bigo_ioc_regs desc; + struct bigo_job *job = &inst->job; + long ret; + + if (copy_regs_from_user(core, &desc, user_desc, job)) { + pr_err("Failed to copy regs from user\n"); return -EFAULT; } - mutex_lock(&core->lock); - if (inst->is_secure) { - rc = exynos_smc(SMC_PROTECTION_SET, 0, BIGO_SMC_ID, - SMC_PROTECTION_ENABLE); - if (rc) { - pr_err("failed to enable SMC_PROTECTION_SET: %d\n", rc); - mutex_unlock(&core->lock); - break; - } + + if(enqueue_prioq(core, inst)) { + pr_err("Failed enqueue frame\n"); + return -EFAULT; + } + + ret = wait_for_completion_timeout( + &inst->job_comp, + msecs_to_jiffies(JOB_COMPLETE_TIMEOUT_MS * 16)); + if (!ret) { + pr_err("timed out waiting for HW: %d\n", rc); + clear_job_from_prioq(core, inst); + rc = -ETIMEDOUT; + } else { + rc = (ret > 0) ? 0 : ret; } - rc = bigo_process(core, &desc); if (rc) - pr_err("Error processing data: %d\n", rc); + break; - if (inst->is_secure) { - rc = exynos_smc(SMC_PROTECTION_SET, 0, BIGO_SMC_ID, - SMC_PROTECTION_DISABLE); - if (rc) - pr_err("failed to disable SMC_PROTECTION_SET: %d\n", rc); + rc = job->status; + if(copy_regs_to_user(&desc, job)) { + pr_err("Failed to copy regs to user\n"); + rc = -EFAULT; } - mutex_unlock(&core->lock); break; + } case BIGO_IOCX_MAP: if (copy_from_user(&mapping, user_desc, sizeof(mapping))) { pr_err("Failed to copy from user\n"); @@ -392,6 +457,7 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, break; } + kref_put(&inst->refcount, bigo_close); return rc; } @@ -482,9 +548,90 @@ static void deinit_chardev(struct bigo_core *core) unregister_chrdev_region(core->devno, 1); } +static inline void mark_instances_idle(struct bigo_core *core) +{ + struct bigo_inst *curr_inst; + mutex_lock(&core->lock); + list_for_each_entry(curr_inst, &core->instances, list) + curr_inst->idle = true; + mutex_unlock(&core->lock); +} + +static int bigo_worker_thread(void *data) +{ + struct bigo_core *core = (struct bigo_core *)data; + struct bigo_inst *inst; + struct bigo_job *job = NULL; + bool should_stop; + int rc; + + if (!core) + return -ENOMEM; + + while(1) { + rc = wait_event_timeout(core->worker, + dequeue_prioq(core, &job, &should_stop), + msecs_to_jiffies(BIGO_IDLE_TIMEOUT_MS)); + if (!rc && !should_stop) { + /* Mark all instances as IDLE since none of these + * instances queued a job for BIGO_IDLE_TIMEOUT_MS + */ + mark_instances_idle(core); + bigo_clocks_off(core); + bigo_mark_qos_dirty(core); + pr_info("bigocean entered idle state\n"); + wait_event(core->worker, + dequeue_prioq(core, &job, &should_stop)); + pr_info("bigocean resumed to work\n"); + } + if(should_stop) { + pr_info("worker thread received stop signal, exit\n"); + return 0; + } + if (!job) + continue; + + inst = container_of(job, struct bigo_inst, job); + + if (inst->idle) { + inst->idle = false; + bigo_mark_qos_dirty(core); + } + + bigo_update_qos(core); + if (inst->is_secure) { + rc = exynos_smc(SMC_PROTECTION_SET, 0, BIGO_SMC_ID, + SMC_PROTECTION_ENABLE); + if (rc) { + pr_err("failed to enable SMC_PROTECTION_SET: %d\n", rc); + goto done; + } + } + + rc = bigo_run_job(core, job); + if (rc) { + pr_err("Error running job\n"); + goto done; + } + + if (inst->is_secure) { + rc = exynos_smc(SMC_PROTECTION_SET, 0, BIGO_SMC_ID, + SMC_PROTECTION_DISABLE); + if (rc) + pr_err("failed to disable SMC_PROTECTION_SET: %d\n", rc); + } + + done: + job->status = rc; + complete(&inst->job_comp); + } + return 0; +} + static int bigo_probe(struct platform_device *pdev) { int rc = 0; + int i; struct bigo_core *core; core = devm_kzalloc(&pdev->dev, sizeof(struct bigo_core), GFP_KERNEL); @@ -494,11 +641,15 @@ static int bigo_probe(struct platform_device *pdev) } mutex_init(&core->lock); + mutex_init(&core->prioq.lock); INIT_LIST_HEAD(&core->instances); INIT_LIST_HEAD(&core->pm.opps); INIT_LIST_HEAD(&core->pm.bw); + for(i = 0; i < BO_MAX_PRIO; ++i) + INIT_LIST_HEAD(&core->prioq.queue[i]); spin_lock_init(&core->status_lock); init_completion(&core->frame_done); + init_waitqueue_head(&core->worker); core->dev = &pdev->dev; platform_set_drvdata(pdev, core); @@ -534,7 +685,13 @@ static int bigo_probe(struct platform_device *pdev) goto err_fault_handler; } - bigo_pt_client_register(pdev->dev.of_node, core); + rc = bigo_pt_client_register(pdev->dev.of_node, core); + if (rc == -EPROBE_DEFER) { + pr_warn("pt_client returns -EPROBE_DEFER, try again later\n"); + goto err_pt_client; + } else { + rc = 0; + } if(platform_device_register(&bigo_sscd_dev)) pr_warn("Failed to register bigo_sscd_dev.\n"); @@ -543,6 +700,8 @@ static int bigo_probe(struct platform_device *pdev) return rc; +err_pt_client: + iommu_unregister_device_fault_handler(&pdev->dev); err_fault_handler: pm_runtime_disable(&pdev->dev); err_io: diff --git a/drivers/media/platform/bigocean/bigo_pm.c b/drivers/media/platform/bigocean/bigo_pm.c index 25fc7aa2e6..60c52996e5 100644 --- a/drivers/media/platform/bigocean/bigo_pm.c +++ b/drivers/media/platform/bigocean/bigo_pm.c @@ -27,6 +27,8 @@ static inline u32 bigo_get_total_load(struct bigo_core *core) return 0; list_for_each_entry(inst, &core->instances, list) { + if (inst->idle) + continue; curr_load = inst->width * inst->height * inst->fps / 1024; if (curr_load < core->pm.max_load - load) { load += curr_load; @@ -85,11 +87,14 @@ static void bigo_scale_freq(struct bigo_core *core) static void bigo_get_bw(struct bigo_core *core, struct bts_bw *bw) { u32 load = bigo_get_total_load(core); - struct bigo_bw *bandwidth = bigo_get_target_bw(core, load); - - bw->read = bandwidth->rd_bw; - bw->write = bandwidth->wr_bw; - bw->peak = bandwidth->pk_bw; + if (load) { + struct bigo_bw *bandwidth = bigo_get_target_bw(core, load); + bw->read = bandwidth->rd_bw; + bw->write = bandwidth->wr_bw; + bw->peak = bandwidth->pk_bw; + } else { + memset(bw, 0, sizeof(*bw)); + } pr_debug("BW: load: %u, rd: %u, wr: %u, pk: %u", load, bw->read, bw->write, bw->peak); } @@ -101,17 +106,38 @@ static int bigo_scale_bw(struct bigo_core *core) return bts_update_bw(core->pm.bwindex, bw); } +void bigo_mark_qos_dirty(struct bigo_core *core) +{ + mutex_lock(&core->lock); + core->qos_dirty = true; + mutex_unlock(&core->lock); +} + void bigo_update_qos(struct bigo_core *core) { int rc; mutex_lock(&core->lock); - rc = bigo_scale_bw(core); + if (core->qos_dirty) { + rc = bigo_scale_bw(core); + if (rc) + pr_warn("%s: failed to scale bandwidth: %d\n", __func__, rc); - if (rc) - pr_warn("%s: failed to scale bandwidth: %d\n", __func__, rc); + bigo_scale_freq(core); + core->qos_dirty = false; + } + mutex_unlock(&core->lock); +} - bigo_scale_freq(core); +void bigo_clocks_off(struct bigo_core *core) +{ + struct bts_bw bw; + + memset(&bw, 0, sizeof(struct bts_bw)); + + mutex_lock(&core->lock); + bts_update_bw(core->pm.bwindex, bw); + bigo_set_freq(core, bigo_get_target_freq(core, 0)); mutex_unlock(&core->lock); } diff --git a/drivers/media/platform/bigocean/bigo_pm.h b/drivers/media/platform/bigocean/bigo_pm.h index c571b87f64..50064a5538 100644 --- a/drivers/media/platform/bigocean/bigo_pm.h +++ b/drivers/media/platform/bigocean/bigo_pm.h @@ -21,5 +21,7 @@ int bigo_runtime_suspend(struct device *dev); int bigo_runtime_resume(struct device *dev); #endif void bigo_update_qos(struct bigo_core *core); +void bigo_clocks_off(struct bigo_core *core); +void bigo_mark_qos_dirty(struct bigo_core *core); #endif //_BIGO_PM_H_ diff --git a/drivers/media/platform/bigocean/bigo_prioq.c b/drivers/media/platform/bigocean/bigo_prioq.c new file mode 100644 index 0000000000..c6e36ef7b4 --- /dev/null +++ b/drivers/media/platform/bigocean/bigo_prioq.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Priority queue impletation with BigOcean + * + * Copyright 2021 Google LLC. + * + * Author: Ruofei Ma + */ + +#include +#include + +#include "bigo_prioq.h" + +int enqueue_prioq(struct bigo_core *core, struct bigo_inst *inst) +{ + struct bigo_job *job = &inst->job; + + if(!core || !inst) + return -EINVAL; + + mutex_lock(&core->prioq.lock); + list_add_tail(&job->list, &core->prioq.queue[inst->priority]); + set_bit(inst->priority, &core->prioq.bitmap); + mutex_unlock(&core->prioq.lock); + + wake_up(&core->worker); + return 0; +} + +bool dequeue_prioq(struct bigo_core *core, struct bigo_job **job, + bool *should_stop) +{ + int high_prio; + struct bigo_job *j = NULL; + struct list_head *queue; + if (!core || !job || !should_stop) + return false; + + *should_stop = false; + if(kthread_should_stop()) { + *should_stop = true; + return true; + } + + mutex_lock(&core->prioq.lock); + high_prio = ffs(core->prioq.bitmap) - 1; + if (high_prio < 0) + goto exit; + + queue = &core->prioq.queue[high_prio]; + j = list_first_entry_or_null(queue, struct bigo_job, list); + if (j) { + list_del(&j->list); + if (list_empty(queue)) + clear_bit(high_prio, &core->prioq.bitmap); + } + +exit: + mutex_unlock(&core->prioq.lock); + *job = j; + return *job != NULL; +} + +void clear_job_from_prioq(struct bigo_core *core, struct bigo_inst *inst) +{ + int i; + struct bigo_job *curr, *next; + struct bigo_inst *curr_inst; + mutex_lock(&core->prioq.lock); + for (i = 0; i < BO_MAX_PRIO; i++) { + list_for_each_entry_safe(curr, next, &core->prioq.queue[i], list) { + curr_inst = container_of(curr, struct bigo_inst, job); + if (inst == curr_inst) + list_del(&curr->list); + } + } + mutex_unlock(&core->prioq.lock); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ruofei Ma "); diff --git a/drivers/media/platform/bigocean/bigo_prioq.h b/drivers/media/platform/bigocean/bigo_prioq.h new file mode 100644 index 0000000000..dcd100c9e5 --- /dev/null +++ b/drivers/media/platform/bigocean/bigo_prioq.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2021 Google LLC. + * + * Author: Ruofei Ma + */ + +#ifndef _BIGO_PRIOQ_H_ +#define _BIGO_PRIOQ_H_ + +#include "bigo_priv.h" + +bool dequeue_prioq(struct bigo_core *core, struct bigo_job **job, + bool *should_stop); +int enqueue_prioq(struct bigo_core *core, struct bigo_inst *inst); + +void clear_job_from_prioq(struct bigo_core *core, struct bigo_inst *inst); + +#endif //_BIGO_PRIOQ_H_ diff --git a/drivers/media/platform/bigocean/bigo_priv.h b/drivers/media/platform/bigocean/bigo_priv.h index 649dbc6051..6d07cf10e5 100644 --- a/drivers/media/platform/bigocean/bigo_priv.h +++ b/drivers/media/platform/bigocean/bigo_priv.h @@ -25,6 +25,7 @@ #define AVG_CNT 30 #define PEAK_CNT 5 #define BUS_WIDTH 16 +#define BO_MAX_PRIO 2 struct bufinfo { struct list_head list; @@ -69,8 +70,10 @@ struct slc_manager { }; struct bigo_job { + struct list_head list; void *regs; size_t regs_size; + int status; }; struct bigo_debugfs { @@ -79,6 +82,12 @@ struct bigo_debugfs { u32 trigger_ssr; }; +struct bigo_prio_array { + struct mutex lock; + unsigned long bitmap; + struct list_head queue[BO_MAX_PRIO]; +}; + struct bigo_core { struct class *_class; struct cdev cdev; @@ -93,7 +102,6 @@ struct bigo_core { struct list_head instances; struct ion_client *mem_client; u32 stat_with_irq; - struct bigo_job job; struct power_manager pm; struct slc_manager slc; unsigned int regs_size; @@ -101,6 +109,10 @@ struct bigo_core { phys_addr_t paddr; struct bigo_debugfs debugfs; spinlock_t status_lock; + struct task_struct *worker_thread; + wait_queue_head_t worker; + struct bigo_prio_array prioq; + u32 qos_dirty; }; struct bigo_inst { @@ -108,15 +120,20 @@ struct bigo_inst { struct list_head buffers; /* mutex protecting this data structure */ struct mutex lock; + struct kref refcount; struct bigo_core *core; u32 height; u32 width; u32 fps; u32 is_secure; + int priority; struct bigo_bw avg_bw[AVG_CNT]; struct bigo_bw pk_bw[AVG_CNT]; int job_cnt; u32 hw_cycles[AVG_CNT]; + struct completion job_comp; + struct bigo_job job; + bool idle; }; inline void set_curr_inst(struct bigo_core *core, struct bigo_inst *inst); diff --git a/drivers/media/platform/bigocean/bigo_slc.c b/drivers/media/platform/bigocean/bigo_slc.c index 744d77ca4b..61d8c19e6a 100644 --- a/drivers/media/platform/bigocean/bigo_slc.c +++ b/drivers/media/platform/bigocean/bigo_slc.c @@ -79,13 +79,17 @@ static void bigo_pt_resize_cb(void *data, int id, size_t size_allocated) core->slc.size = size_allocated; } -void bigo_pt_client_register(struct device_node *node, struct bigo_core *core) +int bigo_pt_client_register(struct device_node *node, struct bigo_core *core) { + int rc = 0; core->slc.pt_hnd = pt_client_register(node, (void *)core, bigo_pt_resize_cb); if (IS_ERR(core->slc.pt_hnd)) { + rc = PTR_ERR(core->slc.pt_hnd); core->slc.pt_hnd = NULL; pr_warn("Failed to register pt_client.\n"); + return rc; } + return rc; } void bigo_pt_client_unregister(struct bigo_core *core) diff --git a/drivers/media/platform/bigocean/bigo_slc.h b/drivers/media/platform/bigocean/bigo_slc.h index cf9c1df59c..16e41104d6 100644 --- a/drivers/media/platform/bigocean/bigo_slc.h +++ b/drivers/media/platform/bigocean/bigo_slc.h @@ -12,14 +12,14 @@ #if IS_ENABLED(CONFIG_SLC_PARTITION_MANAGER) #include -void bigo_pt_client_register(struct device_node *node, struct bigo_core *core); +int bigo_pt_client_register(struct device_node *node, struct bigo_core *core); void bigo_pt_client_unregister(struct bigo_core *core); int bigo_pt_client_enable(struct bigo_core *core); void bigo_pt_client_disable(struct bigo_core *core); void bigo_get_cache_info(struct bigo_core *core, struct bigo_cache_info *cinfo); void bigo_bypass_ssmt_pid(struct bigo_core *core); #else -static inline void bigo_pt_client_register(struct device_node *node, struct bigo_core *core) { } +static inline int bigo_pt_client_register(struct device_node *node, struct bigo_core *core) { } static inline void bigo_pt_client_unregister(struct bigo_core *core) { } static inline int bigo_pt_client_enable(struct bigo_core *core) { return -EINVAL; } static inline void bigo_pt_client_disable(struct bigo_core *core) { }