All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/radeon: make ib size variable
@ 2011-12-21 17:13 alexdeucher
  2011-12-21 17:13 ` [PATCH 2/2] drm/radeon: allocate semaphore from the ib pool alexdeucher
  0 siblings, 1 reply; 3+ messages in thread
From: alexdeucher @ 2011-12-21 17:13 UTC (permalink / raw)
  To: airlied, dri-devel; +Cc: Alex Deucher, Jerome Glisse

From: Jerome Glisse <jglisse@redhat.com>

This avoid to waste ib pool size and avoid a bunch of wait for
previous ib to finish.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/radeon/r100.c          |    2 +-
 drivers/gpu/drm/radeon/r600.c          |    2 +-
 drivers/gpu/drm/radeon/r600_blit_kms.c |   16 +++++++++-------
 drivers/gpu/drm/radeon/radeon.h        |    3 ++-
 drivers/gpu/drm/radeon/radeon_cs.c     |    5 +++--
 drivers/gpu/drm/radeon/radeon_ring.c   |    7 +++++--
 6 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 657040b..947ba22 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3708,7 +3708,7 @@ int r100_ib_test(struct radeon_device *rdev)
 		return r;
 	}
 	WREG32(scratch, 0xCAFEDEAD);
-	r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &ib);
+	r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &ib, 256);
 	if (r) {
 		return r;
 	}
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 951566f..4f08e5e 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2711,7 +2711,7 @@ int r600_ib_test(struct radeon_device *rdev, int ring)
 		return r;
 	}
 	WREG32(scratch, 0xCAFEDEAD);
-	r = radeon_ib_get(rdev, ring, &ib);
+	r = radeon_ib_get(rdev, ring, &ib, 256);
 	if (r) {
 		DRM_ERROR("radeon: failed to get ib (%d).\n", r);
 		return r;
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 02a7574..d996f43 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -619,16 +619,17 @@ void r600_blit_fini(struct radeon_device *rdev)
 	radeon_bo_unref(&rdev->r600_blit.shader_obj);
 }
 
-static int r600_vb_ib_get(struct radeon_device *rdev)
+static int r600_vb_ib_get(struct radeon_device *rdev, unsigned size)
 {
 	int r;
-	r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->r600_blit.vb_ib);
+	r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX,
+			  &rdev->r600_blit.vb_ib, size);
 	if (r) {
 		DRM_ERROR("failed to get IB for vertex buffer\n");
 		return r;
 	}
 
-	rdev->r600_blit.vb_total = 64*1024;
+	rdev->r600_blit.vb_total = size;
 	rdev->r600_blit.vb_used = 0;
 	return 0;
 }
@@ -693,10 +694,6 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
 	int num_loops = 0;
 	int dwords_per_loop = rdev->r600_blit.ring_size_per_loop;
 
-	r = r600_vb_ib_get(rdev);
-	if (r)
-		return r;
-
 	/* num loops */
 	while (num_gpu_pages) {
 		num_gpu_pages -=
@@ -705,6 +702,11 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
 		num_loops++;
 	}
 
+	/* 48 bytes for vertex per loop */
+	r = r600_vb_ib_get(rdev, (num_loops*48)+256);
+	if (r)
+		return r;
+
 	/* calculate number of loops correctly */
 	ring_size = num_loops * dwords_per_loop;
 	ring_size += rdev->r600_blit.ring_size_common;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f29edbf..0301896 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -638,7 +638,8 @@ struct r600_blit {
 
 void r600_blit_suspend(struct radeon_device *rdev);
 
-int radeon_ib_get(struct radeon_device *rdev, int ring, struct radeon_ib **ib);
+int radeon_ib_get(struct radeon_device *rdev, int ring,
+		  struct radeon_ib **ib, unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 09ef486..6559cc4 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -246,7 +246,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
-	r =  radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &parser.ib);
+	ib_chunk = &parser.chunks[parser.chunk_ib_idx];
+	r =  radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &parser.ib,
+			   ib_chunk->length_dw * 4);
 	if (r) {
 		DRM_ERROR("Failed to get ib !\n");
 		radeon_cs_parser_fini(&parser, r);
@@ -264,7 +266,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	/* Copy the packet into the IB, the parser will read from the
 	 * input memory (cached) and write to the IB (which can be
 	 * uncached). */
-	ib_chunk = &parser.chunks[parser.chunk_ib_idx];
 	parser.ib->length_dw = ib_chunk->length_dw;
 	r = radeon_cs_parse(&parser);
 	if (r || parser.parser_error) {
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index f6a4fbd..bc844fe 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -93,13 +93,16 @@ static bool radeon_ib_try_free(struct radeon_device *rdev,
 	return done;
 }
 
-int radeon_ib_get(struct radeon_device *rdev, int ring, struct radeon_ib **ib)
+int radeon_ib_get(struct radeon_device *rdev, int ring,
+		  struct radeon_ib **ib, unsigned size)
 {
 	struct radeon_fence *fence;
 	unsigned cretry = 0;
 	int r = 0, i, idx;
 
 	*ib = NULL;
+	/* align size on 256 bytes */
+	size = ALIGN(size, 256);
 
 	r = radeon_fence_create(rdev, &fence, ring);
 	if (r) {
@@ -122,7 +125,7 @@ retry:
 		if (rdev->ib_pool.ibs[idx].fence == NULL) {
 			r = radeon_sa_bo_new(rdev, &rdev->ib_pool.sa_manager,
 					     &rdev->ib_pool.ibs[idx].sa_bo,
-					     64*1024, 64);
+					     size, 256);
 			if (!r) {
 				*ib = &rdev->ib_pool.ibs[idx];
 				(*ib)->ptr = rdev->ib_pool.sa_manager.cpu_ptr;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] drm/radeon: allocate semaphore from the ib pool
  2011-12-21 17:13 [PATCH 1/2] drm/radeon: make ib size variable alexdeucher
@ 2011-12-21 17:13 ` alexdeucher
  0 siblings, 0 replies; 3+ messages in thread
From: alexdeucher @ 2011-12-21 17:13 UTC (permalink / raw)
  To: airlied, dri-devel; +Cc: Alex Deucher, Jerome Glisse

From: Jerome Glisse <jglisse@redhat.com>

This allow to share the ib pool with semaphore and avoid
having more bo around.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/radeon/radeon.h           |   67 ++++++++-----
 drivers/gpu/drm/radeon/radeon_device.c    |    2 +-
 drivers/gpu/drm/radeon/radeon_ring.c      |    5 +-
 drivers/gpu/drm/radeon/radeon_semaphore.c |  157 ++++++++++++++++-------------
 4 files changed, 131 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 0301896..374f9a4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -243,32 +243,6 @@ void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
 
 /*
- * Semaphores.
- */
-struct radeon_ring;
-
-struct radeon_semaphore_driver {
-	rwlock_t		lock;
-	struct list_head	free;
-};
-
-struct radeon_semaphore {
-	struct radeon_bo	*robj;
-	struct list_head	list;
-	uint64_t		gpu_addr;
-};
-
-void radeon_semaphore_driver_fini(struct radeon_device *rdev);
-int radeon_semaphore_create(struct radeon_device *rdev,
-			    struct radeon_semaphore **semaphore);
-void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
-				  struct radeon_semaphore *semaphore);
-void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
-				struct radeon_semaphore *semaphore);
-void radeon_semaphore_free(struct radeon_device *rdev,
-			   struct radeon_semaphore *semaphore);
-
-/*
  * Tiling registers
  */
 struct radeon_surface_reg {
@@ -387,6 +361,46 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 			     uint32_t handle);
 
 /*
+ * Semaphores.
+ */
+struct radeon_ring;
+
+#define	RADEON_SEMAPHORE_BO_SIZE	256
+
+struct radeon_semaphore_driver {
+	rwlock_t			lock;
+	struct list_head		bo;
+};
+
+struct radeon_semaphore_bo;
+
+/* everything here is constant */
+struct radeon_semaphore {
+	struct list_head		list;
+	uint64_t			gpu_addr;
+	uint32_t			*cpu_ptr;
+	struct radeon_semaphore_bo	*bo;
+};
+
+struct radeon_semaphore_bo {
+	struct list_head		list;
+	struct radeon_ib		*ib;
+	struct list_head		free;
+	struct radeon_semaphore		semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
+	unsigned			nused;
+};
+
+void radeon_semaphore_driver_fini(struct radeon_device *rdev);
+int radeon_semaphore_create(struct radeon_device *rdev,
+			    struct radeon_semaphore **semaphore);
+void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
+				  struct radeon_semaphore *semaphore);
+void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
+				struct radeon_semaphore *semaphore);
+void radeon_semaphore_free(struct radeon_device *rdev,
+			   struct radeon_semaphore *semaphore);
+
+/*
  * GART structures, functions & helpers
  */
 struct radeon_mc;
@@ -641,6 +655,7 @@ void r600_blit_suspend(struct radeon_device *rdev);
 int radeon_ib_get(struct radeon_device *rdev, int ring,
 		  struct radeon_ib **ib, unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
+bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index e81c333..846eeb8 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -731,7 +731,7 @@ int radeon_device_init(struct radeon_device *rdev,
 	INIT_LIST_HEAD(&rdev->gem.objects);
 	init_waitqueue_head(&rdev->irq.vblank_queue);
 	init_waitqueue_head(&rdev->irq.idle_queue);
-	INIT_LIST_HEAD(&rdev->semaphore_drv.free);
+	INIT_LIST_HEAD(&rdev->semaphore_drv.bo);
 
 	/* Set asic functions */
 	r = radeon_asic_init(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index bc844fe..465fb34 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -77,8 +77,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
 /*
  * IB.
  */
-static bool radeon_ib_try_free(struct radeon_device *rdev,
-			       struct radeon_ib *ib)
+bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib)
 {
 	bool done = false;
 
@@ -148,7 +147,7 @@ retry:
 	/* this should be rare event, ie all ib scheduled none signaled yet.
 	 */
 	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-		if (rdev->ib_pool.ibs[idx].fence) {
+		if (rdev->ib_pool.ibs[idx].fence && rdev->ib_pool.ibs[idx].fence->emitted) {
 			r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false);
 			if (!r) {
 				goto retry;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index f8cf044..61dd4e3 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -31,90 +31,109 @@
 #include "drm.h"
 #include "radeon.h"
 
-static int allocate_semaphores(struct radeon_device *rdev)
+static int radeon_semaphore_add_bo(struct radeon_device *rdev)
 {
-	const unsigned long bo_size = PAGE_SIZE * 4;
-
-	struct radeon_bo *bo;
-	struct list_head new_entrys;
+	struct radeon_semaphore_bo *bo;
 	unsigned long irq_flags;
 	uint64_t gpu_addr;
-	void *map;
-	int i, r;
+	uint32_t *cpu_ptr;
+	int r, i;
 
-	r = radeon_bo_create(rdev, bo_size, RADEON_GPU_PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_GTT, &bo);
-	if (r) {
-		dev_err(rdev->dev, "(%d) failed to allocate semaphore bo\n", r);
-		return r;
-	}
-
-	r = radeon_bo_reserve(bo, false);
-	if (r) {
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) failed to reserve semaphore bo\n", r);
-		return r;
-	}
 
-	r = radeon_bo_kmap(bo, &map);
-	if (r) {
-		radeon_bo_unreserve(bo);
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) semaphore map failed\n", r);
-		return r;
+	bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL);
+	if (bo == NULL) {
+		return -ENOMEM;
 	}
-	memset(map, 0, bo_size);
-	radeon_bo_kunmap(bo);
+	INIT_LIST_HEAD(&bo->free);
+	INIT_LIST_HEAD(&bo->list);
+	bo->nused = 0;
 
-	r = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE);
 	if (r) {
-		radeon_bo_unreserve(bo);
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) semaphore pin failed\n", r);
+		dev_err(rdev->dev, "failed to get a bo after 5 retry\n");
+		kfree(bo);
 		return r;
 	}
-
-	INIT_LIST_HEAD(&new_entrys);
-	for (i = 0; i < bo_size/8; ++i) {
-		struct radeon_semaphore *sem = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
-		ttm_bo_reference(&bo->tbo);
-		sem->robj = bo;
-		sem->gpu_addr = gpu_addr;
+	gpu_addr = rdev->ib_pool.sa_manager.gpu_addr;
+	gpu_addr += bo->ib->sa_bo.offset;
+	cpu_ptr = rdev->ib_pool.sa_manager.cpu_ptr;
+	cpu_ptr += (bo->ib->sa_bo.offset >> 2);
+	for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) {
+		bo->semaphores[i].gpu_addr = gpu_addr;
+		bo->semaphores[i].cpu_ptr = cpu_ptr;
+		bo->semaphores[i].bo = bo;
+		list_add_tail(&bo->semaphores[i].list, &bo->free);
 		gpu_addr += 8;
-		list_add_tail(&sem->list, &new_entrys);
+		cpu_ptr += 2;
 	}
-
-	radeon_bo_unreserve(bo);
-	radeon_bo_unref(&bo);
-
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	list_splice_tail(&new_entrys, &rdev->semaphore_drv.free);
+	list_add_tail(&bo->list, &rdev->semaphore_drv.bo);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
+	return 0;
+}
 
-	DRM_INFO("%d new semaphores allocated\n", (int)(bo_size/8));
+static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev,
+					   struct radeon_semaphore_bo *bo)
+{
+	radeon_sa_bo_free(rdev, &bo->ib->sa_bo);
+	radeon_fence_unref(&bo->ib->fence);
+	list_del(&bo->list);
+	kfree(bo);
+}
 
-	return 0;
+void radeon_semaphore_shrink_locked(struct radeon_device *rdev)
+{
+	struct radeon_semaphore_bo *bo, *n;
+
+	if (list_empty(&rdev->semaphore_drv.bo)) {
+		return;
+	}
+	/* only shrink if first bo has free semaphore */
+	bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list);
+	if (list_empty(&bo->free)) {
+		return;
+	}
+	list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) {
+		if (bo->nused)
+			continue;
+		radeon_semaphore_del_bo_locked(rdev, bo);
+	}
 }
 
 int radeon_semaphore_create(struct radeon_device *rdev,
 			    struct radeon_semaphore **semaphore)
 {
+	struct radeon_semaphore_bo *bo;
 	unsigned long irq_flags;
+	bool do_retry = true;
+	int r;
 
+retry:
+	*semaphore = NULL;
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	if (list_empty(&rdev->semaphore_drv.free)) {
-		int r;
-		write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-		r = allocate_semaphores(rdev);
-		if (r)
-			return r;
-		write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
+	list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) {
+		if (list_empty(&bo->free))
+			continue;
+		*semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list);
+		(*semaphore)->cpu_ptr[0] = 0;
+		(*semaphore)->cpu_ptr[1] = 0;
+		list_del(&(*semaphore)->list);
+		bo->nused++;
+		break;
 	}
+	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 
-	*semaphore = list_first_entry(&rdev->semaphore_drv.free, struct radeon_semaphore, list);
-	list_del(&(*semaphore)->list);
+	if (*semaphore == NULL) {
+		if (do_retry) {
+			do_retry = false;
+			r = radeon_semaphore_add_bo(rdev);
+			if (r)
+				return r;
+			goto retry;
+		}
+		return -ENOMEM;
+	}
 
-	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 	return 0;
 }
 
@@ -131,31 +150,29 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
 }
 
 void radeon_semaphore_free(struct radeon_device *rdev,
-			  struct radeon_semaphore *semaphore)
+			   struct radeon_semaphore *semaphore)
 {
 	unsigned long irq_flags;
 
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	list_add_tail(&semaphore->list, &rdev->semaphore_drv.free);
+	semaphore->bo->nused--;
+	list_add_tail(&semaphore->list, &semaphore->bo->free);
+	radeon_semaphore_shrink_locked(rdev);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 }
 
 void radeon_semaphore_driver_fini(struct radeon_device *rdev)
 {
-	struct radeon_semaphore *i, *n;
-	struct list_head entrys;
+	struct radeon_semaphore_bo *bo, *n;
 	unsigned long irq_flags;
 
-	INIT_LIST_HEAD(&entrys);
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	if (!list_empty(&rdev->semaphore_drv.free)) {
-		list_splice(&rdev->semaphore_drv.free, &entrys);
+	/* we force to free everything */
+	list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) {
+		if (!list_empty(&bo->free)) {
+			dev_err(rdev->dev, "still in use semaphore\n");
+		}
+		radeon_semaphore_del_bo_locked(rdev, bo);
 	}
-	INIT_LIST_HEAD(&rdev->semaphore_drv.free);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-
-	list_for_each_entry_safe(i, n, &entrys, list) {
-		radeon_bo_unref(&i->robj);
-		kfree(i);
-	}
 }
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] drm/radeon: allocate semaphore from the ib pool
  2011-12-05 23:39 Make ib allocation size function of cs size j.glisse
@ 2011-12-05 23:39 ` j.glisse
  0 siblings, 0 replies; 3+ messages in thread
From: j.glisse @ 2011-12-05 23:39 UTC (permalink / raw)
  To: dri-devel; +Cc: Jerome Glisse

From: Jerome Glisse <jglisse@redhat.com>

This allow to share the ib pool with semaphore and avoid
having more bo around.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/radeon.h           |   67 ++++++++-----
 drivers/gpu/drm/radeon/radeon_device.c    |    2 +-
 drivers/gpu/drm/radeon/radeon_ring.c      |    5 +-
 drivers/gpu/drm/radeon/radeon_semaphore.c |  157 ++++++++++++++++-------------
 4 files changed, 131 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8cb6a58..5e35423 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -247,32 +247,6 @@ void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
 
 /*
- * Semaphores.
- */
-struct radeon_ring;
-
-struct radeon_semaphore_driver {
-	rwlock_t		lock;
-	struct list_head	free;
-};
-
-struct radeon_semaphore {
-	struct radeon_bo	*robj;
-	struct list_head	list;
-	uint64_t		gpu_addr;
-};
-
-void radeon_semaphore_driver_fini(struct radeon_device *rdev);
-int radeon_semaphore_create(struct radeon_device *rdev,
-			    struct radeon_semaphore **semaphore);
-void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
-				  struct radeon_semaphore *semaphore);
-void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
-				struct radeon_semaphore *semaphore);
-void radeon_semaphore_free(struct radeon_device *rdev,
-			   struct radeon_semaphore *semaphore);
-
-/*
  * Tiling registers
  */
 struct radeon_surface_reg {
@@ -410,6 +384,46 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 			     uint32_t handle);
 
 /*
+ * Semaphores.
+ */
+struct radeon_ring;
+
+#define	RADEON_SEMAPHORE_BO_SIZE	256
+
+struct radeon_semaphore_driver {
+	rwlock_t			lock;
+	struct list_head		bo;
+};
+
+struct radeon_semaphore_bo;
+
+/* everything here is constant */
+struct radeon_semaphore {
+	struct list_head		list;
+	uint64_t			gpu_addr;
+	uint32_t			*cpu_ptr;
+	struct radeon_semaphore_bo	*bo;
+};
+
+struct radeon_semaphore_bo {
+	struct list_head		list;
+	struct radeon_ib		*ib;
+	struct list_head		free;
+	struct radeon_semaphore		semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
+	unsigned			nused;
+};
+
+void radeon_semaphore_driver_fini(struct radeon_device *rdev);
+int radeon_semaphore_create(struct radeon_device *rdev,
+			    struct radeon_semaphore **semaphore);
+void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
+				  struct radeon_semaphore *semaphore);
+void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
+				struct radeon_semaphore *semaphore);
+void radeon_semaphore_free(struct radeon_device *rdev,
+			   struct radeon_semaphore *semaphore);
+
+/*
  * GART structures, functions & helpers
  */
 struct radeon_mc;
@@ -716,6 +730,7 @@ void r600_blit_suspend(struct radeon_device *rdev);
 int radeon_ib_get(struct radeon_device *rdev, int ring,
 		  struct radeon_ib **ib, unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
+bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 6566860..aa9a11e 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -731,7 +731,7 @@ int radeon_device_init(struct radeon_device *rdev,
 	INIT_LIST_HEAD(&rdev->gem.objects);
 	init_waitqueue_head(&rdev->irq.vblank_queue);
 	init_waitqueue_head(&rdev->irq.idle_queue);
-	INIT_LIST_HEAD(&rdev->semaphore_drv.free);
+	INIT_LIST_HEAD(&rdev->semaphore_drv.bo);
 	/* initialize vm here */
 	rdev->vm_manager.use_bitmap = 1;
 	rdev->vm_manager.max_pfn = 1 << 20;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 5f9edea..4fe320f 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -77,8 +77,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
 /*
  * IB.
  */
-static bool radeon_ib_try_free(struct radeon_device *rdev,
-			       struct radeon_ib *ib)
+bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib)
 {
 	bool done = false;
 
@@ -148,7 +147,7 @@ retry:
 	/* this should be rare event, ie all ib scheduled none signaled yet.
 	 */
 	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-		if (rdev->ib_pool.ibs[idx].fence) {
+		if (rdev->ib_pool.ibs[idx].fence && rdev->ib_pool.ibs[idx].fence->emitted) {
 			r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false);
 			if (!r) {
 				goto retry;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index f8cf044..61dd4e3 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -31,90 +31,109 @@
 #include "drm.h"
 #include "radeon.h"
 
-static int allocate_semaphores(struct radeon_device *rdev)
+static int radeon_semaphore_add_bo(struct radeon_device *rdev)
 {
-	const unsigned long bo_size = PAGE_SIZE * 4;
-
-	struct radeon_bo *bo;
-	struct list_head new_entrys;
+	struct radeon_semaphore_bo *bo;
 	unsigned long irq_flags;
 	uint64_t gpu_addr;
-	void *map;
-	int i, r;
+	uint32_t *cpu_ptr;
+	int r, i;
 
-	r = radeon_bo_create(rdev, bo_size, RADEON_GPU_PAGE_SIZE, true,
-			     RADEON_GEM_DOMAIN_GTT, &bo);
-	if (r) {
-		dev_err(rdev->dev, "(%d) failed to allocate semaphore bo\n", r);
-		return r;
-	}
-
-	r = radeon_bo_reserve(bo, false);
-	if (r) {
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) failed to reserve semaphore bo\n", r);
-		return r;
-	}
 
-	r = radeon_bo_kmap(bo, &map);
-	if (r) {
-		radeon_bo_unreserve(bo);
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) semaphore map failed\n", r);
-		return r;
+	bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL);
+	if (bo == NULL) {
+		return -ENOMEM;
 	}
-	memset(map, 0, bo_size);
-	radeon_bo_kunmap(bo);
+	INIT_LIST_HEAD(&bo->free);
+	INIT_LIST_HEAD(&bo->list);
+	bo->nused = 0;
 
-	r = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE);
 	if (r) {
-		radeon_bo_unreserve(bo);
-		radeon_bo_unref(&bo);
-		dev_err(rdev->dev, "(%d) semaphore pin failed\n", r);
+		dev_err(rdev->dev, "failed to get a bo after 5 retry\n");
+		kfree(bo);
 		return r;
 	}
-
-	INIT_LIST_HEAD(&new_entrys);
-	for (i = 0; i < bo_size/8; ++i) {
-		struct radeon_semaphore *sem = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
-		ttm_bo_reference(&bo->tbo);
-		sem->robj = bo;
-		sem->gpu_addr = gpu_addr;
+	gpu_addr = rdev->ib_pool.sa_manager.gpu_addr;
+	gpu_addr += bo->ib->sa_bo.offset;
+	cpu_ptr = rdev->ib_pool.sa_manager.cpu_ptr;
+	cpu_ptr += (bo->ib->sa_bo.offset >> 2);
+	for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) {
+		bo->semaphores[i].gpu_addr = gpu_addr;
+		bo->semaphores[i].cpu_ptr = cpu_ptr;
+		bo->semaphores[i].bo = bo;
+		list_add_tail(&bo->semaphores[i].list, &bo->free);
 		gpu_addr += 8;
-		list_add_tail(&sem->list, &new_entrys);
+		cpu_ptr += 2;
 	}
-
-	radeon_bo_unreserve(bo);
-	radeon_bo_unref(&bo);
-
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	list_splice_tail(&new_entrys, &rdev->semaphore_drv.free);
+	list_add_tail(&bo->list, &rdev->semaphore_drv.bo);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
+	return 0;
+}
 
-	DRM_INFO("%d new semaphores allocated\n", (int)(bo_size/8));
+static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev,
+					   struct radeon_semaphore_bo *bo)
+{
+	radeon_sa_bo_free(rdev, &bo->ib->sa_bo);
+	radeon_fence_unref(&bo->ib->fence);
+	list_del(&bo->list);
+	kfree(bo);
+}
 
-	return 0;
+void radeon_semaphore_shrink_locked(struct radeon_device *rdev)
+{
+	struct radeon_semaphore_bo *bo, *n;
+
+	if (list_empty(&rdev->semaphore_drv.bo)) {
+		return;
+	}
+	/* only shrink if first bo has free semaphore */
+	bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list);
+	if (list_empty(&bo->free)) {
+		return;
+	}
+	list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) {
+		if (bo->nused)
+			continue;
+		radeon_semaphore_del_bo_locked(rdev, bo);
+	}
 }
 
 int radeon_semaphore_create(struct radeon_device *rdev,
 			    struct radeon_semaphore **semaphore)
 {
+	struct radeon_semaphore_bo *bo;
 	unsigned long irq_flags;
+	bool do_retry = true;
+	int r;
 
+retry:
+	*semaphore = NULL;
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	if (list_empty(&rdev->semaphore_drv.free)) {
-		int r;
-		write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-		r = allocate_semaphores(rdev);
-		if (r)
-			return r;
-		write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
+	list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) {
+		if (list_empty(&bo->free))
+			continue;
+		*semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list);
+		(*semaphore)->cpu_ptr[0] = 0;
+		(*semaphore)->cpu_ptr[1] = 0;
+		list_del(&(*semaphore)->list);
+		bo->nused++;
+		break;
 	}
+	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 
-	*semaphore = list_first_entry(&rdev->semaphore_drv.free, struct radeon_semaphore, list);
-	list_del(&(*semaphore)->list);
+	if (*semaphore == NULL) {
+		if (do_retry) {
+			do_retry = false;
+			r = radeon_semaphore_add_bo(rdev);
+			if (r)
+				return r;
+			goto retry;
+		}
+		return -ENOMEM;
+	}
 
-	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 	return 0;
 }
 
@@ -131,31 +150,29 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
 }
 
 void radeon_semaphore_free(struct radeon_device *rdev,
-			  struct radeon_semaphore *semaphore)
+			   struct radeon_semaphore *semaphore)
 {
 	unsigned long irq_flags;
 
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	list_add_tail(&semaphore->list, &rdev->semaphore_drv.free);
+	semaphore->bo->nused--;
+	list_add_tail(&semaphore->list, &semaphore->bo->free);
+	radeon_semaphore_shrink_locked(rdev);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
 }
 
 void radeon_semaphore_driver_fini(struct radeon_device *rdev)
 {
-	struct radeon_semaphore *i, *n;
-	struct list_head entrys;
+	struct radeon_semaphore_bo *bo, *n;
 	unsigned long irq_flags;
 
-	INIT_LIST_HEAD(&entrys);
 	write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-	if (!list_empty(&rdev->semaphore_drv.free)) {
-		list_splice(&rdev->semaphore_drv.free, &entrys);
+	/* we force to free everything */
+	list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) {
+		if (!list_empty(&bo->free)) {
+			dev_err(rdev->dev, "still in use semaphore\n");
+		}
+		radeon_semaphore_del_bo_locked(rdev, bo);
 	}
-	INIT_LIST_HEAD(&rdev->semaphore_drv.free);
 	write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-
-	list_for_each_entry_safe(i, n, &entrys, list) {
-		radeon_bo_unref(&i->robj);
-		kfree(i);
-	}
 }
-- 
1.7.7.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-12-21 17:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-21 17:13 [PATCH 1/2] drm/radeon: make ib size variable alexdeucher
2011-12-21 17:13 ` [PATCH 2/2] drm/radeon: allocate semaphore from the ib pool alexdeucher
  -- strict thread matches above, loose matches on Subject: below --
2011-12-05 23:39 Make ib allocation size function of cs size j.glisse
2011-12-05 23:39 ` [PATCH 2/2] drm/radeon: allocate semaphore from the ib pool j.glisse

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.