drm/radeon: replace the per ring mutex with a global one
authorChristian König <deathsimple@vodafone.de>
Wed, 9 May 2012 13:34:45 +0000 (15:34 +0200)
committerDave Airlie <airlied@redhat.com>
Wed, 9 May 2012 16:22:14 +0000 (17:22 +0100)
A single global mutex for ring submissions seems sufficient.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_semaphore.c

index 82ffa6a05cc6760215919ce4cb98b18c891e258a..e99ea816d8c91487f28ffce6ac5dcd72e2ed842c 100644 (file)
@@ -676,7 +676,6 @@ struct radeon_ring {
        uint64_t                gpu_addr;
        uint32_t                align_mask;
        uint32_t                ptr_mask;
-       struct mutex            mutex;
        bool                    ready;
        u32                     ptr_reg_shift;
        u32                     ptr_reg_mask;
@@ -815,6 +814,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsign
 int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
 void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp);
 void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp);
+void radeon_ring_undo(struct radeon_ring *ring);
 void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
 void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring);
@@ -1534,6 +1534,7 @@ struct radeon_device {
        rwlock_t                        fence_lock;
        struct radeon_fence_driver      fence_drv[RADEON_NUM_RINGS];
        struct radeon_semaphore_driver  semaphore_drv;
+       struct mutex                    ring_lock;
        struct radeon_ring              ring[RADEON_NUM_RINGS];
        struct radeon_ib_pool           ib_pool;
        struct radeon_irq               irq;
index ff28210dedece66c6edd9419080f90b864cb1d4e..3f6ff2a0bce243825d2b933b8fc4bb3797d9c6df 100644 (file)
@@ -724,8 +724,7 @@ int radeon_device_init(struct radeon_device *rdev,
         * can recall function without having locking issues */
        radeon_mutex_init(&rdev->cs_mutex);
        radeon_mutex_init(&rdev->ib_pool.mutex);
-       for (i = 0; i < RADEON_NUM_RINGS; ++i)
-               mutex_init(&rdev->ring[i].mutex);
+       mutex_init(&rdev->ring_lock);
        mutex_init(&rdev->dc_hw_i2c_mutex);
        if (rdev->family >= CHIP_R600)
                spin_lock_init(&rdev->ih.lock);
index caa55d68f319cd6352311f836cc1597aeb3b46b3..7c3874589e3b2eda680f63d5d38a5b5eeaaa81e3 100644 (file)
@@ -252,10 +252,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
 
        mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->vram_mutex);
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               if (rdev->ring[i].ring_obj)
-                       mutex_lock(&rdev->ring[i].mutex);
-       }
+       mutex_lock(&rdev->ring_lock);
 
        /* gui idle int has issues on older chips it seems */
        if (rdev->family >= CHIP_R600) {
@@ -311,10 +308,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
 
        rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
 
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               if (rdev->ring[i].ring_obj)
-                       mutex_unlock(&rdev->ring[i].mutex);
-       }
+       mutex_unlock(&rdev->ring_lock);
        mutex_unlock(&rdev->vram_mutex);
        mutex_unlock(&rdev->ddev->struct_mutex);
 }
index 2eb4c6ed198aa7f82007c33db841c03f9396010d..a4d60ae524b16b447eef91cf6ee4164d63ddf38f 100644 (file)
@@ -346,9 +346,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
                if (ndw < ring->ring_free_dw) {
                        break;
                }
-               mutex_unlock(&ring->mutex);
+               mutex_unlock(&rdev->ring_lock);
                r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring));
-               mutex_lock(&ring->mutex);
+               mutex_lock(&rdev->ring_lock);
                if (r)
                        return r;
        }
@@ -361,10 +361,10 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig
 {
        int r;
 
-       mutex_lock(&ring->mutex);
+       mutex_lock(&rdev->ring_lock);
        r = radeon_ring_alloc(rdev, ring, ndw);
        if (r) {
-               mutex_unlock(&ring->mutex);
+               mutex_unlock(&rdev->ring_lock);
                return r;
        }
        return 0;
@@ -389,20 +389,25 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
 void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        radeon_ring_commit(rdev, ring);
-       mutex_unlock(&ring->mutex);
+       mutex_unlock(&rdev->ring_lock);
 }
 
-void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
+void radeon_ring_undo(struct radeon_ring *ring)
 {
        ring->wptr = ring->wptr_old;
-       mutex_unlock(&ring->mutex);
+}
+
+void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       radeon_ring_undo(ring);
+       mutex_unlock(&rdev->ring_lock);
 }
 
 void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        int r;
 
-       mutex_lock(&ring->mutex);
+       mutex_lock(&rdev->ring_lock);
        radeon_ring_free_size(rdev, ring);
        if (ring->rptr == ring->wptr) {
                r = radeon_ring_alloc(rdev, ring, 1);
@@ -411,7 +416,7 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
                        radeon_ring_commit(rdev, ring);
                }
        }
-       mutex_unlock(&ring->mutex);
+       mutex_unlock(&rdev->ring_lock);
 }
 
 void radeon_ring_lockup_update(struct radeon_ring *ring)
@@ -520,11 +525,12 @@ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
        int r;
        struct radeon_bo *ring_obj;
 
-       mutex_lock(&ring->mutex);
+       mutex_lock(&rdev->ring_lock);
        ring_obj = ring->ring_obj;
+       ring->ready = false;
        ring->ring = NULL;
        ring->ring_obj = NULL;
-       mutex_unlock(&ring->mutex);
+       mutex_unlock(&rdev->ring_lock);
 
        if (ring_obj) {
                r = radeon_bo_reserve(ring_obj, false);
index 930a08af900f1eee546dd369b6edcc712d409953..c5b3d8ecece9cc57fe57baeaa7ae3cdf7fc26977 100644 (file)
@@ -39,7 +39,6 @@ static int radeon_semaphore_add_bo(struct radeon_device *rdev)
        uint32_t *cpu_ptr;
        int r, i;
 
-
        bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL);
        if (bo == NULL) {
                return -ENOMEM;
@@ -154,13 +153,17 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                                bool sync_to[RADEON_NUM_RINGS],
                                int dst_ring)
 {
-       int i, r;
+       int i = 0, r;
 
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               unsigned num_ops = i == dst_ring ? RADEON_NUM_RINGS : 1;
+       mutex_lock(&rdev->ring_lock);
+       r = radeon_ring_alloc(rdev, &rdev->ring[dst_ring], RADEON_NUM_RINGS * 8);
+       if (r) {
+               goto error;
+       }
 
-               /* don't lock unused rings */
-               if (!sync_to[i] && i != dst_ring)
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               /* no need to sync to our own or unused rings */
+               if (!sync_to[i] || i == dst_ring)
                        continue;
 
                /* prevent GPU deadlocks */
@@ -170,38 +173,31 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                        goto error;
                }
 
-                r = radeon_ring_lock(rdev, &rdev->ring[i], num_ops * 8);
-                if (r)
+               r = radeon_ring_alloc(rdev, &rdev->ring[i], 8);
+               if (r) {
                        goto error;
-       }
-
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               /* no need to sync to our own or unused rings */
-               if (!sync_to[i] || i == dst_ring)
-                        continue;
+               }
 
                radeon_semaphore_emit_signal(rdev, i, semaphore);
                radeon_semaphore_emit_wait(rdev, dst_ring, semaphore);
-       }
 
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-
-               /* don't unlock unused rings */
-               if (!sync_to[i] && i != dst_ring)
-                       continue;
-
-               radeon_ring_unlock_commit(rdev, &rdev->ring[i]);
+               radeon_ring_commit(rdev, &rdev->ring[i]);
        }
 
+       radeon_ring_commit(rdev, &rdev->ring[dst_ring]);
+       mutex_unlock(&rdev->ring_lock);
+
        return 0;
 
 error:
        /* unlock all locks taken so far */
        for (--i; i >= 0; --i) {
                if (sync_to[i] || i == dst_ring) {
-                       radeon_ring_unlock_undo(rdev, &rdev->ring[i]);
+                       radeon_ring_undo(&rdev->ring[i]);
                }
        }
+       radeon_ring_undo(&rdev->ring[dst_ring]);
+       mutex_unlock(&rdev->ring_lock);
        return r;
 }