Commit 5ac55629 authored by Alex Xie's avatar Alex Xie Committed by Alex Deucher

drm/amdgpu: Optimize mutex usage (v4)

In original function amdgpu_bo_list_get, the waiting
for result->lock can be quite long while mutex
bo_list_lock was holding. It can make other tasks
waiting for bo_list_lock for long period.

Secondly, this patch allows several tasks(readers of idr)
to proceed at the same time.

v2: use rcu and kref (Dave Airlie and Christian König)
v3: update v1 commit message (Michel Dänzer)
v4: rebase on upstream (Alex Deucher)
Signed-off-by: default avatarAlex Xie <AlexBin.Xie@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
parent 99eea4df
...@@ -869,6 +869,8 @@ struct amdgpu_fpriv { ...@@ -869,6 +869,8 @@ struct amdgpu_fpriv {
struct amdgpu_bo_list { struct amdgpu_bo_list {
struct mutex lock; struct mutex lock;
struct rcu_head rhead;
struct kref refcount;
struct amdgpu_bo *gds_obj; struct amdgpu_bo *gds_obj;
struct amdgpu_bo *gws_obj; struct amdgpu_bo *gws_obj;
struct amdgpu_bo *oa_obj; struct amdgpu_bo *oa_obj;
......
...@@ -41,6 +41,20 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, ...@@ -41,6 +41,20 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
struct drm_amdgpu_bo_list_entry *info, struct drm_amdgpu_bo_list_entry *info,
unsigned num_entries); unsigned num_entries);
static void amdgpu_bo_list_release_rcu(struct kref *ref)
{
unsigned i;
struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list,
refcount);
for (i = 0; i < list->num_entries; ++i)
amdgpu_bo_unref(&list->array[i].robj);
mutex_destroy(&list->lock);
kvfree(list->array);
kfree_rcu(list, rhead);
}
static int amdgpu_bo_list_create(struct amdgpu_device *adev, static int amdgpu_bo_list_create(struct amdgpu_device *adev,
struct drm_file *filp, struct drm_file *filp,
struct drm_amdgpu_bo_list_entry *info, struct drm_amdgpu_bo_list_entry *info,
...@@ -57,7 +71,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev, ...@@ -57,7 +71,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev,
/* initialize bo list*/ /* initialize bo list*/
mutex_init(&list->lock); mutex_init(&list->lock);
kref_init(&list->refcount);
r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); r = amdgpu_bo_list_set(adev, filp, list, info, num_entries);
if (r) { if (r) {
kfree(list); kfree(list);
...@@ -83,14 +97,9 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) ...@@ -83,14 +97,9 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
mutex_lock(&fpriv->bo_list_lock); mutex_lock(&fpriv->bo_list_lock);
list = idr_remove(&fpriv->bo_list_handles, id); list = idr_remove(&fpriv->bo_list_handles, id);
if (list) {
/* Another user may have a reference to this list still */
mutex_lock(&list->lock);
mutex_unlock(&list->lock);
amdgpu_bo_list_free(list);
}
mutex_unlock(&fpriv->bo_list_lock); mutex_unlock(&fpriv->bo_list_lock);
if (list)
kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
} }
static int amdgpu_bo_list_set(struct amdgpu_device *adev, 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,11 +194,17 @@ amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id)
{ {
struct amdgpu_bo_list *result; struct amdgpu_bo_list *result;
mutex_lock(&fpriv->bo_list_lock); rcu_read_lock();
result = idr_find(&fpriv->bo_list_handles, id); result = idr_find(&fpriv->bo_list_handles, id);
if (result)
mutex_lock(&result->lock); if (result) {
mutex_unlock(&fpriv->bo_list_lock); if (kref_get_unless_zero(&result->refcount))
mutex_lock(&result->lock);
else
result = NULL;
}
rcu_read_unlock();
return result; return result;
} }
...@@ -227,6 +242,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, ...@@ -227,6 +242,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list,
void amdgpu_bo_list_put(struct amdgpu_bo_list *list) void amdgpu_bo_list_put(struct amdgpu_bo_list *list)
{ {
mutex_unlock(&list->lock); mutex_unlock(&list->lock);
kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
} }
void amdgpu_bo_list_free(struct amdgpu_bo_list *list) void amdgpu_bo_list_free(struct amdgpu_bo_list *list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment