drm/radeon: precompute fence cpu/gpu addr once v3
authorJerome Glisse <jglisse@redhat.com>
Sun, 20 Nov 2011 20:45:34 +0000 (20:45 +0000)
committerDave Airlie <airlied@redhat.com>
Tue, 20 Dec 2011 19:51:19 +0000 (19:51 +0000)
Add a start fence driver helper function which will be call
once for each ring and will compute cpu/gpu addr for fence
depending on wether to use wb buffer or scratch reg.

This patch replace initialize fence driver separately which
was broken in regard of GPU lockup. The fence list for created,
emited, signaled must be initialize once and only from the
asic init callback not from the startup call back which is
call from the gpu reset.

v2: With this in place we no longer need to know the number of
    rings in fence_driver_init, also writing to the scratch reg
    before knowing its offset is a bad idea.

v3: rebase on top of change to previous patch in the serie

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
14 files changed:
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c

index b19ace86121eeebb045024d60b62758f5c0564fb..ba19b9a697b0754a5d9082abb80532085af3d41d 100644 (file)
@@ -3111,6 +3111,12 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r = r600_irq_init(rdev);
        if (r) {
@@ -3229,7 +3235,7 @@ int evergreen_init(struct radeon_device *rdev)
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        /* initialize AGP */
index 022a606c783b4ea9638d83b780c50778d1a92879..a9b0e615804f865078abcafabd63c22cdbc0d7b4 100644 (file)
@@ -1384,6 +1384,24 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
+       r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
+       r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r = r600_irq_init(rdev);
        if (r) {
@@ -1492,7 +1510,7 @@ int cayman_init(struct radeon_device *rdev)
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 3);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        /* initialize memory controller */
index a40e893a7b692d4d82519af4395da645fdbfa8b4..bed56c7b690b636e9221aba1e5cfc5d162c37ad9 100644 (file)
@@ -3916,6 +3916,12 @@ static int r100_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r100_irq_set(rdev);
        rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -4059,7 +4065,7 @@ int r100_init(struct radeon_device *rdev)
        /* initialize VRAM */
        r100_mc_init(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index 6a96b31b558f2313ce1053095df63c015a9f19d3..e2dfae4b40e68975efdec59ac1e85ebb53de2fa1 100644 (file)
@@ -1399,6 +1399,12 @@ static int r300_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -1521,7 +1527,7 @@ int r300_init(struct radeon_device *rdev)
        /* initialize memory controller */
        r300_mc_init(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index 1d3231f3a090b24fa4b1cedac033c831938ea4b3..17ecff1000e793a5037bdba63f6e1662431c2636 100644 (file)
@@ -258,6 +258,12 @@ static int r420_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -391,7 +397,7 @@ int r420_init(struct radeon_device *rdev)
        r300_mc_init(rdev);
        r420_debugfs(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r) {
                return r;
        }
index cb96a51f7f7c09b1506f95ba533ca937c71cca4e..39b31544c6e7df5eb87e6816d9a713506b5c5346 100644 (file)
@@ -187,6 +187,12 @@ static int r520_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -278,7 +284,7 @@ int r520_init(struct radeon_device *rdev)
        r520_mc_init(rdev);
        rv515_debugfs(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index 17538926cc478feebd263864b683e8704bb415ad..f2deadfcd88f822ce806f72075576a7d3e7a917d 100644 (file)
@@ -2313,8 +2313,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        struct radeon_ring *ring = &rdev->ring[fence->ring];
 
        if (rdev->wb.use_event) {
-               u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
-                       (u64)(rdev->fence_drv[fence->ring].scratch_reg - rdev->scratch.reg_base);
+               u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
                /* flush read cache over gart */
                radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
                radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
@@ -2459,6 +2458,12 @@ int r600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r = r600_irq_init(rdev);
        if (r) {
@@ -2589,7 +2594,7 @@ int r600_init(struct radeon_device *rdev)
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        if (rdev->flags & RADEON_IS_AGP) {
index 014065af60dcc4a4eae0bac7b72eea267233108c..5777afb361de94f1b021fa2c975a0049c726c9ab 100644 (file)
@@ -192,6 +192,8 @@ extern int sumo_get_temp(struct radeon_device *rdev);
  */
 struct radeon_fence_driver {
        uint32_t                        scratch_reg;
+       uint64_t                        gpu_addr;
+       volatile uint32_t               *cpu_addr;
        atomic_t                        seq;
        uint32_t                        last_seq;
        unsigned long                   last_jiffies;
@@ -215,7 +217,8 @@ struct radeon_fence {
        int                             ring;
 };
 
-int radeon_fence_driver_init(struct radeon_device *rdev, int num_rings);
+int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
+int radeon_fence_driver_init(struct radeon_device *rdev);
 void radeon_fence_driver_fini(struct radeon_device *rdev);
 int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring);
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence);
index 809e66e8a86e05cd27856bd27a5db69ae254ce39..8d626baaa0641078846d1a010eebd32599a8dcfc 100644 (file)
 
 static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring)
 {
-       u32 scratch_index;
-
        if (rdev->wb.enabled) {
-               if (rdev->wb.use_event)
-                       scratch_index = R600_WB_EVENT_OFFSET +
-                               rdev->fence_drv[ring].scratch_reg - rdev->scratch.reg_base;
-               else
-                       scratch_index = RADEON_WB_SCRATCH_OFFSET +
-                               rdev->fence_drv[ring].scratch_reg - rdev->scratch.reg_base;
-               rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);
-       } else
+               *rdev->fence_drv[ring].cpu_addr = cpu_to_le32(seq);
+       } else {
                WREG32(rdev->fence_drv[ring].scratch_reg, seq);
+       }
 }
 
 static u32 radeon_fence_read(struct radeon_device *rdev, int ring)
 {
        u32 seq = 0;
-       u32 scratch_index;
 
        if (rdev->wb.enabled) {
-               if (rdev->wb.use_event)
-                       scratch_index = R600_WB_EVENT_OFFSET +
-                               rdev->fence_drv[ring].scratch_reg - rdev->scratch.reg_base;
-               else
-                       scratch_index = RADEON_WB_SCRATCH_OFFSET +
-                               rdev->fence_drv[ring].scratch_reg - rdev->scratch.reg_base;
-               seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
-       } else
+               seq = le32_to_cpu(*rdev->fence_drv[ring].cpu_addr);
+       } else {
                seq = RREG32(rdev->fence_drv[ring].scratch_reg);
+       }
        return seq;
 }
 
@@ -389,36 +376,61 @@ int radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
        return not_processed;
 }
 
-int radeon_fence_driver_init(struct radeon_device *rdev, int num_rings)
+int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
 {
        unsigned long irq_flags;
-       int r, ring;
+       uint64_t index;
+       int r;
 
-       for (ring = 0; ring < num_rings; ring++) {
-               write_lock_irqsave(&rdev->fence_lock, irq_flags);
+       write_lock_irqsave(&rdev->fence_lock, irq_flags);
+       radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
+       if (rdev->wb.use_event) {
+               rdev->fence_drv[ring].scratch_reg = 0;
+               index = R600_WB_EVENT_OFFSET + ring * 4;
+       } else {
                r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg);
                if (r) {
                        dev_err(rdev->dev, "fence failed to get scratch register\n");
                        write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
                        return r;
                }
-               radeon_fence_write(rdev, 0, ring);
-               atomic_set(&rdev->fence_drv[ring].seq, 0);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].created);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled);
-               init_waitqueue_head(&rdev->fence_drv[ring].queue);
-               rdev->fence_drv[ring].initialized = true;
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
+               index = RADEON_WB_SCRATCH_OFFSET +
+                       rdev->fence_drv[ring].scratch_reg -
+                       rdev->scratch.reg_base;
        }
-       for (ring = num_rings; ring < RADEON_NUM_RINGS; ring++) {
-               write_lock_irqsave(&rdev->fence_lock, irq_flags);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].created);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted);
-               INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled);
-               rdev->fence_drv[ring].initialized = false;
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
+       rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
+       rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
+       radeon_fence_write(rdev, atomic_read(&rdev->fence_drv[ring].seq), ring);
+       rdev->fence_drv[ring].initialized = true;
+       DRM_INFO("fence driver on ring %d use gpu addr 0x%08Lx and cpu addr 0x%p\n",
+                ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr);
+       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
+       return 0;
+}
+
+static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring)
+{
+       rdev->fence_drv[ring].scratch_reg = -1;
+       rdev->fence_drv[ring].cpu_addr = NULL;
+       rdev->fence_drv[ring].gpu_addr = 0;
+       atomic_set(&rdev->fence_drv[ring].seq, 0);
+       INIT_LIST_HEAD(&rdev->fence_drv[ring].created);
+       INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted);
+       INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled);
+       init_waitqueue_head(&rdev->fence_drv[ring].queue);
+       rdev->fence_drv[ring].initialized = false;
+}
+
+int radeon_fence_driver_init(struct radeon_device *rdev)
+{
+       unsigned long irq_flags;
+       int ring;
+
+       write_lock_irqsave(&rdev->fence_lock, irq_flags);
+       for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
+               radeon_fence_driver_init_ring(rdev, ring);
        }
+       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
        if (radeon_debugfs_fence_init(rdev)) {
                dev_err(rdev->dev, "fence debugfs file creation failed\n");
        }
@@ -433,6 +445,7 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
        for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
                if (!rdev->fence_drv[ring].initialized)
                        continue;
+               radeon_fence_wait_last(rdev, ring);
                wake_up_all(&rdev->fence_drv[ring].queue);
                write_lock_irqsave(&rdev->fence_lock, irq_flags);
                radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
index c71fa16106cab49c507fc50bc5ffe4ca084220d1..5c86d5161fdbb530781bfddcfd52d62c7c494dff 100644 (file)
@@ -410,6 +410,12 @@ static int rs400_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -516,7 +522,7 @@ int rs400_init(struct radeon_device *rdev)
        /* initialize memory controller */
        rs400_mc_init(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index 1c9ab94095315ffdc370b1873b8fa0f0c023a496..3fe384741fc06197dd114fa0a614774d46f90dc5 100644 (file)
@@ -849,6 +849,12 @@ static int rs600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -962,7 +968,7 @@ int rs600_init(struct radeon_device *rdev)
        rs600_mc_init(rdev);
        rs600_debugfs(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index 8aa5e7ef2efc927d2e36278e50278996f5fe8ad4..ae941d196d3f474bc95ef265d1d7085509bdff30 100644 (file)
@@ -621,6 +621,12 @@ static int rs690_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -735,7 +741,7 @@ int rs690_init(struct radeon_device *rdev)
        rs690_mc_init(rdev);
        rv515_debugfs(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index beed57c7df969b2d8baadfd89beb7ff429c39da0..21d90d9fe11c82ef29bf09a5f5162bebde41cc1f 100644 (file)
@@ -393,6 +393,12 @@ static int rv515_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -511,7 +517,7 @@ int rv515_init(struct radeon_device *rdev)
        rv515_mc_init(rdev);
        rv515_debugfs(rdev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        r = radeon_irq_kms_init(rdev);
index f01603d522bb90d79d765e2bb245b18afab4f143..0a1283d2402784f5dc3e5b58d8e5790e365ad0c5 100644 (file)
@@ -1083,6 +1083,12 @@ static int rv770_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
+       r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+       if (r) {
+               dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+               return r;
+       }
+
        /* Enable IRQ */
        r = r600_irq_init(rdev);
        if (r) {
@@ -1196,7 +1202,7 @@ int rv770_init(struct radeon_device *rdev)
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        /* Fence driver */
-       r = radeon_fence_driver_init(rdev, 1);
+       r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
        /* initialize AGP */