summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Peng <robinpeng@google.com>2022-07-06 12:39:21 +0800
committerRobin Peng <robinpeng@google.com>2022-07-06 12:39:21 +0800
commit2219ddfde5dc05830f51284763e7c48540fe9e00 (patch)
tree75469d80e8beaa6e37cf1bc90e65b8cd640aec33
parent1a4c201bca53689c4b10e1b73e4d1c72ffa01df2 (diff)
parent2571eaf565fb151e284c3ed6bd922800e398df70 (diff)
downloadgchips-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.c47
-rw-r--r--bigo_iommu.c10
-rw-r--r--bigo_pm.c39
-rw-r--r--bigo_prioq.c17
-rw-r--r--bigo_prioq.h2
-rw-r--r--bigo_priv.h3
6 files changed, 95 insertions, 23 deletions
diff --git a/bigo.c b/bigo.c
index 24722ac..e01f869 100644
--- a/bigo.c
+++ b/bigo.c
@@ -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;
}
diff --git a/bigo_pm.c b/bigo_pm.c
index 25fc7aa..8bd0e2a 100644
--- a/bigo_pm.c
+++ b/bigo_pm.c
@@ -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);