diff options
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 40 |
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 | ||
| 870 | struct amdgpu_bo_list { | 870 | struct 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 | ||
| 44 | static 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 | |||
| 44 | static int amdgpu_bo_list_create(struct amdgpu_device *adev, | 58 | static 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 | ||
| 96 | static int amdgpu_bo_list_set(struct amdgpu_device *adev, | 105 | static 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, | |||
| 227 | void amdgpu_bo_list_put(struct amdgpu_bo_list *list) | 242 | void 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 | ||
| 232 | void amdgpu_bo_list_free(struct amdgpu_bo_list *list) | 248 | void amdgpu_bo_list_free(struct amdgpu_bo_list *list) |
