diff options
author | Robin Peng <robinpeng@google.com> | 2022-07-06 12:39:21 +0800 |
---|---|---|
committer | Robin Peng <robinpeng@google.com> | 2022-07-06 12:39:21 +0800 |
commit | 2219ddfde5dc05830f51284763e7c48540fe9e00 (patch) | |
tree | 75469d80e8beaa6e37cf1bc90e65b8cd640aec33 | |
parent | 1a4c201bca53689c4b10e1b73e4d1c72ffa01df2 (diff) | |
parent | 2571eaf565fb151e284c3ed6bd922800e398df70 (diff) | |
download | gchips-2219ddfde5dc05830f51284763e7c48540fe9e00.tar.gz |
Merge android13-gs-pixel-5.10-tm-d1 into android13-gs-pixel-5.10-tm-qpr1
Bug: 233569354
Signed-off-by: Robin Peng <robinpeng@google.com>
Change-Id: I596748c902171beccd54fadbee532ac887771c1f
-rw-r--r-- | bigo.c | 47 | ||||
-rw-r--r-- | bigo_iommu.c | 10 | ||||
-rw-r--r-- | bigo_pm.c | 39 | ||||
-rw-r--r-- | bigo_prioq.c | 17 | ||||
-rw-r--r-- | bigo_prioq.h | 2 | ||||
-rw-r--r-- | bigo_priv.h | 3 |
6 files changed, 95 insertions, 23 deletions
@@ -36,6 +36,7 @@ #define DEFAULT_FPS 60 #define BIGO_SMC_ID 0xd #define BIGO_MAX_INST_NUM 16 +#define BIGO_HBD_BIT BIT(17) static int bigo_worker_thread(void *data); @@ -147,6 +148,7 @@ static int bigo_open(struct inode *inode, struct file *file) inst->height = DEFAULT_WIDTH; inst->width = DEFAULT_HEIGHT; inst->fps = DEFAULT_FPS; + inst->bpp = 1; inst->core = core; inst->job.regs_size = core->regs_size; inst->job.regs = kzalloc(core->regs_size, GFP_KERNEL); @@ -187,17 +189,15 @@ err: static void bigo_close(struct kref *ref) { struct bigo_inst *inst = container_of(ref, struct bigo_inst, refcount); - struct bigo_core *core = inst->core; - if (!inst || !core) { - pr_err("No instance or core\n"); - return; + if (inst && inst->core) { + clear_job_from_prioq(inst->core, inst); + bigo_unmap_all(inst); + kfree(inst->job.regs); + kfree(inst); + bigo_update_qos(inst->core); + pr_info("closed instance\n"); } - bigo_unmap_all(inst); - kfree(inst->job.regs); - kfree(inst); - bigo_update_qos(core); - pr_info("closed instance\n"); } static int bigo_release(struct inode *inode, struct file *file) @@ -342,6 +342,8 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, 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) { @@ -356,18 +358,42 @@ 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: { struct bigo_ioc_regs desc; struct bigo_job *job = &inst->job; long ret; + u32 hbd; + u32 bpp; if (copy_regs_from_user(core, &desc, user_desc, job)) { pr_err("Failed to copy regs from user\n"); return -EFAULT; } + hbd = (((u32*)job->regs)[3]) & BIGO_HBD_BIT; + bpp = hbd ? 2:1; + if (bpp != inst->bpp) { + inst->bpp = bpp; + bigo_update_qos(core); + } + if(enqueue_prioq(core, inst)) { pr_err("Failed enqueue frame\n"); return -EFAULT; @@ -378,6 +404,7 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, 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; @@ -452,6 +479,7 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, break; } + kref_put(&inst->refcount, bigo_close); return rc; } @@ -589,7 +617,6 @@ static int bigo_worker_thread(void *data) done: job->status = rc; complete(&inst->job_comp); - kref_put(&inst->refcount, bigo_close); } return 0; } diff --git a/bigo_iommu.c b/bigo_iommu.c index f59d279..029dd3d 100644 --- a/bigo_iommu.c +++ b/bigo_iommu.c @@ -15,16 +15,12 @@ #include "bigo_iommu.h" -static void bigo_unmap_one(struct bigo_core *core, struct bufinfo *binfo) +static void bigo_unmap_one(struct bufinfo *binfo) { - /* This lock is needed to unmap. Look @ b/180443732 */ - mutex_lock(&core->lock); - binfo->attachment->dma_map_attrs |= DMA_ATTR_SKIP_LAZY_UNMAP; dma_buf_unmap_attachment(binfo->attachment, binfo->sgt, DMA_BIDIRECTIONAL); dma_buf_detach(binfo->dmabuf, binfo->attachment); dma_buf_put(binfo->dmabuf); - mutex_unlock(&core->lock); } void bigo_unmap_all(struct bigo_inst *inst) @@ -34,7 +30,7 @@ void bigo_unmap_all(struct bigo_inst *inst) mutex_lock(&inst->lock); list_for_each_entry_safe(curr, next, &inst->buffers, list) { list_del(&curr->list); - bigo_unmap_one(inst->core, curr); + bigo_unmap_one(curr); kfree(curr); } mutex_unlock(&inst->lock); @@ -136,7 +132,7 @@ int bigo_unmap(struct bigo_inst *inst, struct bigo_ioc_mapping *mapping) if (!found) return -ENOENT; - bigo_unmap_one(inst->core, found); + bigo_unmap_one(found); kfree(found); return 0; } @@ -17,6 +17,8 @@ #include "bigo_pm.h" #include "bigo_io.h" +#define LARGE_LOAD_MIF_FLOOR 1539000 + static inline u32 bigo_get_total_load(struct bigo_core *core) { struct bigo_inst *inst; @@ -41,6 +43,29 @@ static inline u32 bigo_get_total_load(struct bigo_core *core) return load; } +static inline void update_mif_floor(struct bigo_core *core) +{ + struct bigo_inst *inst; + u32 load = 0; + u32 curr_load = 0; + + if (!list_empty(&core->instances)) { + list_for_each_entry(inst, &core->instances, list) { + curr_load = inst->width * inst->height * inst->fps * inst->bpp / 1024; + load += curr_load; + } + } + + if (load > core->pm.max_load) { + if (!exynos_pm_qos_request_active(&core->pm.qos_req_mif)) + exynos_pm_qos_add_request(&core->pm.qos_req_mif, PM_QOS_BUS_THROUGHPUT, LARGE_LOAD_MIF_FLOOR); + else + exynos_pm_qos_update_request(&core->pm.qos_req_mif, LARGE_LOAD_MIF_FLOOR); + } else if (exynos_pm_qos_request_active(&core->pm.qos_req_mif)) { + exynos_pm_qos_remove_request(&core->pm.qos_req_mif); + } +} + static inline u32 bigo_get_target_freq(struct bigo_core *core, u32 load) { struct bigo_opp *opp; @@ -85,11 +110,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); } @@ -111,6 +139,7 @@ void bigo_update_qos(struct bigo_core *core) if (rc) pr_warn("%s: failed to scale bandwidth: %d\n", __func__, rc); + update_mif_floor(core); bigo_scale_freq(core); mutex_unlock(&core->lock); } diff --git a/bigo_prioq.c b/bigo_prioq.c index 19da48a..c6e36ef 100644 --- a/bigo_prioq.c +++ b/bigo_prioq.c @@ -24,7 +24,6 @@ int enqueue_prioq(struct bigo_core *core, struct bigo_inst *inst) set_bit(inst->priority, &core->prioq.bitmap); mutex_unlock(&core->prioq.lock); - kref_get(&inst->refcount); wake_up(&core->worker); return 0; } @@ -63,5 +62,21 @@ exit: 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 <ruofeim@google.com>"); diff --git a/bigo_prioq.h b/bigo_prioq.h index 0a49290..77cb337 100644 --- a/bigo_prioq.h +++ b/bigo_prioq.h @@ -14,4 +14,6 @@ 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/bigo_priv.h b/bigo_priv.h index 0eb29cb..e951229 100644 --- a/bigo_priv.h +++ b/bigo_priv.h @@ -55,6 +55,7 @@ struct bigo_bw { struct power_manager { int bwindex; struct exynos_pm_qos_request qos_bigo; + struct exynos_pm_qos_request qos_req_mif; struct list_head opps; struct list_head bw; u32 max_load; @@ -132,6 +133,8 @@ struct bigo_inst { u32 hw_cycles[AVG_CNT]; struct completion job_comp; struct bigo_job job; + /* bytes per pixel */ + u32 bpp; }; inline void set_curr_inst(struct bigo_core *core, struct bigo_inst *inst); |