[PATCH 02/10] drm/radeon: add infrastructure for advanced ring synchronization v2

2012-06-01 Thread Christian König
v2: BUG_ON not matching rings.

Signed-off-by: Christian K?nig 
Reviewed-by: Jerome Glisse 
---
 drivers/gpu/drm/radeon/radeon.h   |   25 ++-
 drivers/gpu/drm/radeon/radeon_fence.c |   73 +
 2 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5e259b4..ef132eb 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -257,8 +257,8 @@ struct radeon_fence_driver {
uint32_tscratch_reg;
uint64_tgpu_addr;
volatile uint32_t   *cpu_addr;
-   /* seq is protected by ring emission lock */
-   uint64_tseq;
+   /* sync_seq is protected by ring emission lock */
+   uint64_tsync_seq[RADEON_NUM_RINGS];
atomic64_t  last_seq;
unsigned long   last_activity;
boolinitialized;
@@ -288,6 +288,27 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
+bool radeon_fence_need_sync(struct radeon_fence *fence, int ring);
+void radeon_fence_note_sync(struct radeon_fence *fence, int ring);
+static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a,
+ struct radeon_fence *b)
+{
+   if (!a) {
+   return b;
+   }
+
+   if (!b) {
+   return a;
+   }
+
+   BUG_ON(a->ring != b->ring);
+
+   if (a->seq > b->seq) {
+   return a;
+   } else {
+   return b;
+   }
+}

 /*
  * Tiling registers
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 401d346..7b55625 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -72,7 +72,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
}
kref_init(&((*fence)->kref));
(*fence)->rdev = rdev;
-   (*fence)->seq = ++rdev->fence_drv[ring].seq;
+   (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
(*fence)->ring = ring;
radeon_fence_ring_emit(rdev, ring, *fence);
trace_radeon_fence_emit(rdev->ddev, (*fence)->seq);
@@ -449,7 +449,7 @@ int radeon_fence_wait_next_locked(struct radeon_device 
*rdev, int ring)
 * wait.
 */
seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
-   if (seq >= rdev->fence_drv[ring].seq) {
+   if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
/* nothing to wait for, last_seq is
   already the last emited fence */
return -ENOENT;
@@ -464,7 +464,7 @@ int radeon_fence_wait_empty_locked(struct radeon_device 
*rdev, int ring)
 * activity can be scheduled so there won't be concurrent access
 * to seq value.
 */
-   return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
+   return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].sync_seq[ring],
 ring, false, false);
 }

@@ -492,7 +492,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
*rdev, int ring)
 * but it's ok to report slightly wrong fence count here.
 */
radeon_fence_process(rdev, ring);
-   emitted = rdev->fence_drv[ring].seq - 
atomic64_read(&rdev->fence_drv[ring].last_seq);
+   emitted = rdev->fence_drv[ring].sync_seq[ring]
+   - atomic64_read(&rdev->fence_drv[ring].last_seq);
/* to avoid 32bits warp around */
if (emitted > 0x1000) {
emitted = 0x1000;
@@ -500,6 +501,51 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
*rdev, int ring)
return (unsigned)emitted;
 }

+bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
+{
+   struct radeon_fence_driver *fdrv;
+
+   if (!fence) {
+   return false;
+   }
+
+   if (fence->ring == dst_ring) {
+   return false;
+   }
+
+   /* we are protected by the ring mutex */
+   fdrv = &fence->rdev->fence_drv[dst_ring];
+   if (fence->seq <= fdrv->sync_seq[fence->ring]) {
+   return false;
+   }
+
+   return true;
+}
+
+void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
+{
+   struct radeon_fence_driver *dst, *src;
+   unsigned i;
+
+   if (!fence) {
+   return;
+   }
+
+   if (fence->ring == dst_ring) {
+   return;
+   }
+
+   /* we are protected by the ring mutex */
+   src = &fence->rdev->fence_drv[fence->ring];
+   dst = &fence->rdev->fence_drv[dst_ring];
+   for (i = 0; i

[PATCH 02/10] drm/radeon: add infrastructure for advanced ring synchronization v2

2012-06-01 Thread Christian König
v2: BUG_ON not matching rings.

Signed-off-by: Christian König 
Reviewed-by: Jerome Glisse 
---
 drivers/gpu/drm/radeon/radeon.h   |   25 ++-
 drivers/gpu/drm/radeon/radeon_fence.c |   73 +
 2 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5e259b4..ef132eb 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -257,8 +257,8 @@ struct radeon_fence_driver {
uint32_tscratch_reg;
uint64_tgpu_addr;
volatile uint32_t   *cpu_addr;
-   /* seq is protected by ring emission lock */
-   uint64_tseq;
+   /* sync_seq is protected by ring emission lock */
+   uint64_tsync_seq[RADEON_NUM_RINGS];
atomic64_t  last_seq;
unsigned long   last_activity;
boolinitialized;
@@ -288,6 +288,27 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
+bool radeon_fence_need_sync(struct radeon_fence *fence, int ring);
+void radeon_fence_note_sync(struct radeon_fence *fence, int ring);
+static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a,
+ struct radeon_fence *b)
+{
+   if (!a) {
+   return b;
+   }
+
+   if (!b) {
+   return a;
+   }
+
+   BUG_ON(a->ring != b->ring);
+
+   if (a->seq > b->seq) {
+   return a;
+   } else {
+   return b;
+   }
+}
 
 /*
  * Tiling registers
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 401d346..7b55625 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -72,7 +72,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
}
kref_init(&((*fence)->kref));
(*fence)->rdev = rdev;
-   (*fence)->seq = ++rdev->fence_drv[ring].seq;
+   (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
(*fence)->ring = ring;
radeon_fence_ring_emit(rdev, ring, *fence);
trace_radeon_fence_emit(rdev->ddev, (*fence)->seq);
@@ -449,7 +449,7 @@ int radeon_fence_wait_next_locked(struct radeon_device 
*rdev, int ring)
 * wait.
 */
seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
-   if (seq >= rdev->fence_drv[ring].seq) {
+   if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
/* nothing to wait for, last_seq is
   already the last emited fence */
return -ENOENT;
@@ -464,7 +464,7 @@ int radeon_fence_wait_empty_locked(struct radeon_device 
*rdev, int ring)
 * activity can be scheduled so there won't be concurrent access
 * to seq value.
 */
-   return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
+   return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].sync_seq[ring],
 ring, false, false);
 }
 
@@ -492,7 +492,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
*rdev, int ring)
 * but it's ok to report slightly wrong fence count here.
 */
radeon_fence_process(rdev, ring);
-   emitted = rdev->fence_drv[ring].seq - 
atomic64_read(&rdev->fence_drv[ring].last_seq);
+   emitted = rdev->fence_drv[ring].sync_seq[ring]
+   - atomic64_read(&rdev->fence_drv[ring].last_seq);
/* to avoid 32bits warp around */
if (emitted > 0x1000) {
emitted = 0x1000;
@@ -500,6 +501,51 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
*rdev, int ring)
return (unsigned)emitted;
 }
 
+bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
+{
+   struct radeon_fence_driver *fdrv;
+
+   if (!fence) {
+   return false;
+   }
+
+   if (fence->ring == dst_ring) {
+   return false;
+   }
+
+   /* we are protected by the ring mutex */
+   fdrv = &fence->rdev->fence_drv[dst_ring];
+   if (fence->seq <= fdrv->sync_seq[fence->ring]) {
+   return false;
+   }
+
+   return true;
+}
+
+void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
+{
+   struct radeon_fence_driver *dst, *src;
+   unsigned i;
+
+   if (!fence) {
+   return;
+   }
+
+   if (fence->ring == dst_ring) {
+   return;
+   }
+
+   /* we are protected by the ring mutex */
+   src = &fence->rdev->fence_drv[fence->ring];
+   dst = &fence->rdev->fence_drv[dst_ring];
+   for (i = 0