Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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;
+28 −12
Original line number Original line Diff line number Diff line
@@ -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,


	/* 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)


	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)
{
{
	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)

	if (result) {
		if (kref_get_unless_zero(&result->refcount))
			mutex_lock(&result->lock);
			mutex_lock(&result->lock);
	mutex_unlock(&fpriv->bo_list_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,
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)