aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c40
2 files changed, 30 insertions, 12 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 9f827aca90ee..12d61edb3597 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -869,6 +869,8 @@ struct amdgpu_fpriv {
869 869
870struct amdgpu_bo_list { 870struct amdgpu_bo_list {
871 struct mutex lock; 871 struct mutex lock;
872 struct rcu_head rhead;
873 struct kref refcount;
872 struct amdgpu_bo *gds_obj; 874 struct amdgpu_bo *gds_obj;
873 struct amdgpu_bo *gws_obj; 875 struct amdgpu_bo *gws_obj;
874 struct amdgpu_bo *oa_obj; 876 struct amdgpu_bo *oa_obj;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index 7b5c3bb2142e..f621ee115c98 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -41,6 +41,20 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
41 struct drm_amdgpu_bo_list_entry *info, 41 struct drm_amdgpu_bo_list_entry *info,
42 unsigned num_entries); 42 unsigned num_entries);
43 43
44static void amdgpu_bo_list_release_rcu(struct kref *ref)
45{
46 unsigned i;
47 struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list,
48 refcount);
49
50 for (i = 0; i < list->num_entries; ++i)
51 amdgpu_bo_unref(&list->array[i].robj);
52
53 mutex_destroy(&list->lock);
54 kvfree(list->array);
55 kfree_rcu(list, rhead);
56}
57
44static int amdgpu_bo_list_create(struct amdgpu_device *adev, 58static int amdgpu_bo_list_create(struct amdgpu_device *adev,
45 struct drm_file *filp, 59 struct drm_file *filp,
46 struct drm_amdgpu_bo_list_entry *info, 60 struct drm_amdgpu_bo_list_entry *info,
@@ -57,7 +71,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev,
57 71
58 /* initialize bo list*/ 72 /* initialize bo list*/
59 mutex_init(&list->lock); 73 mutex_init(&list->lock);
60 74 kref_init(&list->refcount);
61 r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); 75 r = amdgpu_bo_list_set(adev, filp, list, info, num_entries);
62 if (r) { 76 if (r) {
63 kfree(list); 77 kfree(list);
@@ -83,14 +97,9 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
83 97
84 mutex_lock(&fpriv->bo_list_lock); 98 mutex_lock(&fpriv->bo_list_lock);
85 list = idr_remove(&fpriv->bo_list_handles, id); 99 list = idr_remove(&fpriv->bo_list_handles, id);
86 if (list) {
87 /* Another user may have a reference to this list still */
88 mutex_lock(&list->lock);
89 mutex_unlock(&list->lock);
90 amdgpu_bo_list_free(list);
91 }
92
93 mutex_unlock(&fpriv->bo_list_lock); 100 mutex_unlock(&fpriv->bo_list_lock);
101 if (list)
102 kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
94} 103}
95 104
96static int amdgpu_bo_list_set(struct amdgpu_device *adev, 105static int amdgpu_bo_list_set(struct amdgpu_device *adev,
@@ -185,11 +194,17 @@ amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id)
185{ 194{
186 struct amdgpu_bo_list *result; 195 struct amdgpu_bo_list *result;
187 196
188 mutex_lock(&fpriv->bo_list_lock); 197 rcu_read_lock();
189 result = idr_find(&fpriv->bo_list_handles, id); 198 result = idr_find(&fpriv->bo_list_handles, id);
190 if (result) 199
191 mutex_lock(&result->lock); 200 if (result) {
192 mutex_unlock(&fpriv->bo_list_lock); 201 if (kref_get_unless_zero(&result->refcount))
202 mutex_lock(&result->lock);
203 else
204 result = NULL;
205 }
206 rcu_read_unlock();
207
193 return result; 208 return result;
194} 209}
195 210
@@ -227,6 +242,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list,
227void amdgpu_bo_list_put(struct amdgpu_bo_list *list) 242void amdgpu_bo_list_put(struct amdgpu_bo_list *list)
228{ 243{
229 mutex_unlock(&list->lock); 244 mutex_unlock(&list->lock);
245 kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
230} 246}
231 247
232void amdgpu_bo_list_free(struct amdgpu_bo_list *list) 248void amdgpu_bo_list_free(struct amdgpu_bo_list *list)