mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 22:23:14 -04:00
soc: qcom: hgsl: Clean up timelines in release
Applications have no chance to destroy timelines if crash. This change could clean isolated timelines. Change-Id: If15a5b8f5f45c6c6b051fcaea81bf51c2bc7aa64 Signed-off-by: Kasin Li <donglil@codeaurora.org>
This commit is contained in:
parent
b5a3e71931
commit
e056dc2591
3 changed files with 41 additions and 14 deletions
|
|
@ -1297,6 +1297,8 @@ static int hgsl_release(struct inode *inodep, struct file *filep)
|
|||
}
|
||||
}
|
||||
|
||||
hgsl_isync_fini(priv);
|
||||
|
||||
kfree(priv);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ struct hgsl_hsync_fence {
|
|||
|
||||
struct hgsl_isync_timeline {
|
||||
struct kref kref;
|
||||
struct list_head free_list;
|
||||
char name[HGSL_TIMELINE_NAME_LEN];
|
||||
int id;
|
||||
struct hgsl_priv *priv;
|
||||
|
|
@ -126,6 +127,7 @@ void hgsl_hsync_timeline_put(struct hgsl_hsync_timeline *timeline);
|
|||
int hgsl_isync_timeline_create(struct hgsl_priv *priv,
|
||||
uint32_t *timeline_id);
|
||||
int hgsl_isync_timeline_destroy(struct hgsl_priv *priv, uint32_t id);
|
||||
void hgsl_isync_fini(struct hgsl_priv *priv);
|
||||
int hgsl_isync_fence_create(struct hgsl_priv *priv, uint32_t timeline_id,
|
||||
uint32_t ts, int *fence);
|
||||
int hgsl_isync_fence_signal(struct hgsl_priv *priv, uint32_t timeline_id,
|
||||
|
|
|
|||
|
|
@ -231,12 +231,12 @@ hgsl_isync_timeline_get(struct hgsl_priv *priv, int id)
|
|||
struct hgsl_isync_timeline *timeline = NULL;
|
||||
|
||||
spin_lock(&priv->isync_timeline_lock);
|
||||
|
||||
timeline = idr_find(&priv->isync_timeline_idr, id);
|
||||
spin_unlock(&priv->isync_timeline_lock);
|
||||
|
||||
if (timeline)
|
||||
ret = kref_get_unless_zero(&timeline->kref);
|
||||
|
||||
spin_unlock(&priv->isync_timeline_lock);
|
||||
|
||||
if (!ret)
|
||||
timeline = NULL;
|
||||
|
|
@ -268,6 +268,7 @@ int hgsl_isync_timeline_create(struct hgsl_priv *priv,
|
|||
timeline->context = dma_fence_context_alloc(1);
|
||||
INIT_LIST_HEAD(&timeline->fence_list);
|
||||
spin_lock_init(&timeline->lock);
|
||||
timeline->priv = priv;
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
spin_lock(&priv->isync_timeline_lock);
|
||||
|
|
@ -354,21 +355,25 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void hgsl_isync_timeline_cleanup(struct hgsl_priv *priv,
|
||||
struct hgsl_isync_timeline *timeline)
|
||||
static int hgsl_isync_timeline_destruct(struct hgsl_priv *priv,
|
||||
struct hgsl_isync_timeline *timeline)
|
||||
{
|
||||
struct hgsl_isync_fence *cur, *next;
|
||||
|
||||
if (timeline == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&timeline->lock);
|
||||
list_for_each_entry_safe(cur, next, &timeline->fence_list,
|
||||
child_list) {
|
||||
dma_fence_signal_locked(&cur->fence);
|
||||
list_del_init(&cur->child_list);
|
||||
}
|
||||
|
||||
spin_unlock(&timeline->lock);
|
||||
|
||||
hgsl_isync_timeline_put(timeline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hgsl_isync_timeline_destroy(struct hgsl_priv *priv, uint32_t id)
|
||||
|
|
@ -377,34 +382,51 @@ int hgsl_isync_timeline_destroy(struct hgsl_priv *priv, uint32_t id)
|
|||
|
||||
spin_lock(&priv->isync_timeline_lock);
|
||||
timeline = idr_find(&priv->isync_timeline_idr, id);
|
||||
spin_unlock(&priv->isync_timeline_lock);
|
||||
|
||||
if (timeline == NULL) {
|
||||
spin_unlock(&priv->isync_timeline_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (timeline == NULL)
|
||||
return 0;
|
||||
|
||||
if (timeline->id > 0) {
|
||||
idr_remove(&priv->isync_timeline_idr, timeline->id);
|
||||
timeline->id = 0;
|
||||
}
|
||||
|
||||
return hgsl_isync_timeline_destruct(priv, timeline);
|
||||
}
|
||||
|
||||
void hgsl_isync_fini(struct hgsl_priv *priv)
|
||||
{
|
||||
LIST_HEAD(flist);
|
||||
struct hgsl_isync_timeline *cur, *t;
|
||||
uint32_t idr;
|
||||
|
||||
spin_lock(&priv->isync_timeline_lock);
|
||||
idr_for_each_entry(&priv->isync_timeline_idr,
|
||||
cur, idr) {
|
||||
idr_remove(&priv->isync_timeline_idr, idr);
|
||||
list_add(&cur->free_list, &flist);
|
||||
}
|
||||
spin_unlock(&priv->isync_timeline_lock);
|
||||
|
||||
hgsl_isync_timeline_cleanup(priv, timeline);
|
||||
list_for_each_entry_safe(cur, t, &flist, free_list) {
|
||||
list_del(&cur->free_list);
|
||||
hgsl_isync_timeline_destruct(priv, cur);
|
||||
}
|
||||
|
||||
return 0;
|
||||
idr_destroy(&priv->isync_timeline_idr);
|
||||
}
|
||||
|
||||
static int _isync_timeline_signal(
|
||||
struct hgsl_isync_timeline *timeline,
|
||||
struct dma_fence *fence)
|
||||
{
|
||||
struct hgsl_isync_fence *cur, *next;
|
||||
int ret = -EINVAL;
|
||||
struct hgsl_isync_fence *cur, *next;
|
||||
|
||||
spin_lock(&timeline->lock);
|
||||
|
||||
list_for_each_entry_safe(cur, next, &timeline->fence_list,
|
||||
child_list) {
|
||||
child_list) {
|
||||
if (fence == &cur->fence) {
|
||||
dma_fence_signal_locked(fence);
|
||||
list_del_init(&cur->child_list);
|
||||
|
|
@ -413,6 +435,7 @@ static int _isync_timeline_signal(
|
|||
}
|
||||
}
|
||||
spin_unlock(&timeline->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue