diff options
author | Vinay Kalia <vinaykalia@google.com> | 2022-06-28 22:55:38 +0000 |
---|---|---|
committer | Vinay Kalia <vinaykalia@google.com> | 2022-06-30 19:18:41 +0000 |
commit | 9a4469b98e3697f9f8adb531db708e4d673bdc70 (patch) | |
tree | a036cc45ef013d158dbe8ff48fb4a064a7f46465 | |
parent | 1a4c201bca53689c4b10e1b73e4d1c72ffa01df2 (diff) | |
download | gchips-9a4469b98e3697f9f8adb531db708e4d673bdc70.tar.gz |
bigocean: Ensure that bigocean instance is not destroyed while work is pending
Destroying the instance while hardware is active can lead to faults like
SysMMU page faults.
bug: 236515139
Signed-off-by: Vinay Kalia <vinaykalia@google.com>
Change-Id: I20e037204db4a7a09bdcfbb512f8cddc96800768
-rw-r--r-- | bigo.c | 36 | ||||
-rw-r--r-- | bigo_prioq.c | 17 | ||||
-rw-r--r-- | bigo_prioq.h | 2 |
3 files changed, 44 insertions, 11 deletions
@@ -187,17 +187,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 +340,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,6 +356,21 @@ 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: { @@ -378,6 +393,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 +468,7 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd, break; } + kref_put(&inst->refcount, bigo_close); return rc; } @@ -589,7 +606,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_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_ |