All of lore.kernel.org
 help / color / mirror / Atom feed
From: j.glisse@gmail.com
To: dri-devel@lists.freedesktop.org
Cc: Jerome Glisse <jglisse@redhat.com>
Subject: [PATCH 09/27] drm/radeon: improve sa allocator
Date: Tue,  1 May 2012 13:19:19 -0400	[thread overview]
Message-ID: <1335892777-7357-10-git-send-email-j.glisse@gmail.com> (raw)
In-Reply-To: <1335892777-7357-1-git-send-email-j.glisse@gmail.com>

From: Jerome Glisse <jglisse@redhat.com>

The sa allocator is suppose to be a ring allocator, ie allocation
happen first at the end and if there is no more room we start at
the begining again. This patch make the code match this design.
sa_manager keep track of the start & end hole, it first try to
allocate in the end hole, if it fails it allocate in the begining
hole, if it fails it returns (caller is expected to retry).

When freeing we need to make sure that we properly grow the end
hole and start hole. We take advantage of the fact that the sa_bo
list is ordered by offset. That means that when we free an sa_bo
the previous sa_bo in list is also the sa_bo just before the
sa_bo we are freeing and reversly for the next.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/radeon.h    |    3 +
 drivers/gpu/drm/radeon/radeon_sa.c |  101 ++++++++++++++++++++++++------------
 2 files changed, 71 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 34c1041..ad12ef8 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -385,6 +385,9 @@ struct radeon_sa_manager {
 	struct radeon_bo	*bo;
 	struct list_head	sa_bo;
 	unsigned		size;
+	unsigned		ehole_size;
+	unsigned		shole_size;
+	unsigned		ehole_offset;
 	uint64_t		gpu_addr;
 	void			*cpu_ptr;
 	uint32_t		domain;
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
index 88906c9..8c0b3e6 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -40,6 +40,9 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
 	mutex_init(&sa_manager->mutex);
 	sa_manager->bo = NULL;
 	sa_manager->size = size;
+	sa_manager->shole_size = 0;
+	sa_manager->ehole_size = size;
+	sa_manager->ehole_offset = 0;
 	sa_manager->domain = domain;
 	INIT_LIST_HEAD(&sa_manager->sa_bo);
 
@@ -134,61 +137,93 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
 		     struct radeon_sa_bo *sa_bo,
 		     unsigned size, unsigned align)
 {
-	struct radeon_sa_bo *tmp;
-	struct list_head *head;
 	unsigned offset = 0, wasted = 0;
 
 	BUG_ON(align > RADEON_GPU_PAGE_SIZE);
 	BUG_ON(size > sa_manager->size);
+
 	mutex_lock(&sa_manager->mutex);
 
-	/* no one ? */
-	if (list_empty(&sa_manager->sa_bo)) {
-		head = &sa_manager->sa_bo;
+	wasted = (align - (sa_manager->ehole_offset % align)) % align;
+	if ((size + wasted) < sa_manager->ehole_size) {
+		/* we keep sa_bo list ordered by offset */
+		list_add_tail(&sa_bo->list, &sa_manger->sa_bo);
+		offset = sa_manager->ehole_offset + wasted;
+		sa_manager->ehole_offset += wasted + size;
+		sa_manager->ehole_size -= wasted + size;
 		goto out;
 	}
 
-	/* look for a hole big enough */
-	list_for_each_entry(tmp, &sa_manager->sa_bo, list) {
-		/* room before this object ? */
-		if (offset < tmp->offset && (tmp->offset - offset) >= size) {
-			head = tmp->list.prev;
-			goto out;
-		}
-		offset = tmp->offset + tmp->size;
-		wasted = offset % align;
-		if (wasted) {
-			offset += align - wasted;
-		}
-	}
-	/* room at the end ? */
-	head = sa_manager->sa_bo.prev;
-	tmp = list_entry(head, struct radeon_sa_bo, list);
-	offset = tmp->offset + tmp->size;
-	wasted = offset % align;
-	if (wasted) {
-		offset += wasted = align - wasted;
-	}
-	if ((sa_manager->size - offset) < size) {
-		/* failed to find somethings big enough */
-		mutex_unlock(&sa_manager->mutex);
-		return -ENOMEM;
+	if (size < sa_manager->shole_size) {
+		/* keep sa_bo list ordered by offset */
+		list_add(&sa_bo->list, &sa_manger->sa_bo);
+		sa_manager->shole_size = 0;
+		offset = 0;
+		goto out;
 	}
 
+	mutex_unlock(&sa_manager->mutex);
+	return -ENOMEM;
+
 out:
 	sa_bo->manager = sa_manager;
 	sa_bo->offset = offset;
 	sa_bo->size = size;
-	list_add(&sa_bo->list, head);
 	mutex_unlock(&sa_manager->mutex);
 	return 0;
 }
 
 void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo *sa_bo)
 {
-	mutex_lock(&sa_bo->manager->mutex);
+	struct radeon_sa_manager *sa_manager = sa_bo->manager;
+	struct radeon_sa_bo *tmp;
+
+	mutex_lock(&manager->mutex);
+
+	/* try first to grow the end hole as we want to allocate from the
+	 * end first
+	 */
+	if ((sa_bo->offset + sa_bo->size) == sa_manager->ehole_offset) {
+		if (sa_bo->list.prev != &sa_manager->sa_bo) {
+			/* all sa_bo are in list in offset order if there is a
+			 * sa_bo before the one we are freeing then make sure
+			 * we grow the end hole down to the end of the previous
+			 * sa_bo
+			 */
+			tmp = list_entry(sa_bo->list.prev, struct radeon_sa_bo, list);
+			sa_manager->ehole_offset = tmp->offset + tmp->size;
+			sa_manager->ehole_size += sa_manager->size - sa_manager->ehole_offset;
+		} else {
+			/* this bo was alone in the list */
+			sa_manager->ehole_offset = 0;
+			sa_manager->ehole_size = sa_manager->size;
+			sa_manager->shole_size = 0;
+		}
+	} else if (sa_bo->offset == sa_manager->shole_size) {
+		if (sa_bo->list.next != &sa_manager->sa_bo) {
+			/* all sa_bo are in list in offset order if there is a
+			 * sa_bo after the one we are freeing then make sure
+			 * we grow the start hole up to the begining of the next
+			 * sa_bo
+			 */
+			tmp = list_entry(sa_bo->list.next, struct radeon_sa_bo, list);
+			sa_manager->shole_size = tmp->offset;
+		} else {
+			/* this case should never happen as it means this sa_b
+			 * was alone in the list so that :
+			 * (sa_bo->offset + sa_bo->size) == sa_manager->ehole_offset
+			 * should be true and we should have been in previous
+			 * branch restore things and print an warning
+			 */
+			sa_manager->ehole_offset = 0;
+			sa_manager->ehole_size = sa_manager->size;
+			sa_manager->shole_size = 0;
+			dev_warn(rdev->dev, "sa allocator structure corrupted\n");
+		}
+	}
 	list_del_init(&sa_bo->list);
-	mutex_unlock(&sa_bo->manager->mutex);
+
+	mutex_unlock(&manager->mutex);
 }
 
 #if defined(CONFIG_DEBUG_FS)
-- 
1.7.7.6

  parent reply	other threads:[~2012-05-01 17:20 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <·>
2012-05-01 17:19 ` Include request for reset-rework branch v2 j.glisse
2012-05-01 17:19   ` [PATCH 01/27] drm/radeon: make radeon_gpu_is_lockup a per ring function j.glisse
2012-05-01 17:19   ` [PATCH 02/27] drm/radeon: replace gpu_lockup with ring->ready flag j.glisse
2012-05-01 17:19   ` [PATCH 03/27] drm/radeon: register ring debugfs handlers on init j.glisse
2012-05-01 17:19   ` [PATCH 04/27] drm/radeon: use central function for IB testing j.glisse
2012-05-01 17:19   ` [PATCH 05/27] drm/radeon: rework gpu lockup detection and processing j.glisse
2012-05-01 17:19   ` [PATCH 06/27] drm/radeon: fix a bug in the SA code j.glisse
2012-05-01 17:19   ` [PATCH 07/27] drm/radeon: add proper locking to the SA v3 j.glisse
2012-05-02  8:21     ` Christian König
2012-05-01 17:19   ` [PATCH 08/27] drm/radeon: add sub allocator debugfs file v2 j.glisse
2012-05-01 17:19   ` j.glisse [this message]
2012-05-01 17:19   ` [PATCH 10/27] drm/radeon: sa allocator add wakequeue j.glisse
2012-05-01 17:19   ` [PATCH 11/27] drm/radeon: use inline functions to calc sa_bo addr j.glisse
2012-05-01 17:19   ` [PATCH 12/27] drm/radeon: simplify semaphore handling j.glisse
2012-05-01 17:19   ` [PATCH 13/27] drm/radeon: return -ENOENT in fence_wait_next v2 j.glisse
2012-05-01 17:19   ` [PATCH 14/27] drm/radeon: rename fence_wait_last to fence_wait_empty j.glisse
2012-05-01 17:19   ` [PATCH 15/27] drm/radeon: add general purpose fence signaled callback j.glisse
2012-05-01 17:19   ` [PATCH 16/27] drm/radeon: don't keep list of created fences j.glisse
2012-05-01 17:19   ` [PATCH 17/27] drm/radeon: add try_free callback to the SA v2 j.glisse
2012-05-01 17:19   ` [PATCH 18/27] drm/radeon: rip out the ib pool v3 j.glisse
2012-05-01 17:19   ` [PATCH 19/27] drm/radeon: fix a bug with the ring syncing code j.glisse
2012-05-01 17:19   ` [PATCH 20/27] drm/radeon: rework recursive gpu reset handling j.glisse
2012-05-01 17:19   ` [PATCH 21/27] drm/radeon: remove recursive mutex implementation j.glisse
2012-05-01 17:19   ` [PATCH 22/27] drm/radeon: move lockup detection code into radeon_ring.c j.glisse
2012-05-01 17:19   ` [PATCH 23/27] drm/radeon: make lockup timeout a module param j.glisse
2012-05-01 17:19   ` [PATCH 24/27] drm/radeon: unlock the ring mutex while waiting for the next fence j.glisse
2012-05-01 17:19   ` [PATCH 25/27] drm/radeon: make forcing ring activity a common function j.glisse
2012-05-01 17:19   ` [PATCH 26/27] drm/radeon: remove r300_gpu_is_lockup j.glisse
2012-05-01 17:19   ` [PATCH 27/27] drm/radeon: remove cayman_gpu_is_lockup j.glisse
2012-05-01 17:28   ` Include request for reset-rework branch v2 Jerome Glisse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1335892777-7357-10-git-send-email-j.glisse@gmail.com \
    --to=j.glisse@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jglisse@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.