diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-09-04 05:04:34 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-10-05 21:38:08 -0400 |
commit | d0f8a854c340986359a3b0a97e380c71def7a440 (patch) | |
tree | 4f4065bb8c920badc92f56c25b5b105066ae6fc2 /drivers/gpu/drm | |
parent | 724c80e1d630296d1324859e964d80d35007d83c (diff) |
drm/radeon/kms/r6xx+: use new style fencing (v3)
On r6xx+ a newer fence mechanism was implemented to replace
the old wait_until plus scratch regs setup. A single EOP event
will flush the destination caches, write a fence value, and generate
an interrupt. This is the recommended fence mechanism on r6xx+ asics.
This requires my previous writeback patch.
v2: fix typo that enabled event fence checking on all asics
rather than just r6xx+.
v3: properly enable EOP interrupts
Should fix:
https://bugs.freedesktop.org/show_bug.cgi?id=29972
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 6 |
6 files changed, 64 insertions, 17 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e47d221e24ac..4c82cc830271 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1594,6 +1594,7 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
1594 | if (rdev->irq.sw_int) { | 1594 | if (rdev->irq.sw_int) { |
1595 | DRM_DEBUG("evergreen_irq_set: sw int\n"); | 1595 | DRM_DEBUG("evergreen_irq_set: sw int\n"); |
1596 | cp_int_cntl |= RB_INT_ENABLE; | 1596 | cp_int_cntl |= RB_INT_ENABLE; |
1597 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | ||
1597 | } | 1598 | } |
1598 | if (rdev->irq.crtc_vblank_int[0]) { | 1599 | if (rdev->irq.crtc_vblank_int[0]) { |
1599 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); | 1600 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); |
@@ -2012,6 +2013,7 @@ restart_ih: | |||
2012 | break; | 2013 | break; |
2013 | case 181: /* CP EOP event */ | 2014 | case 181: /* CP EOP event */ |
2014 | DRM_DEBUG("IH: CP EOP\n"); | 2015 | DRM_DEBUG("IH: CP EOP\n"); |
2016 | radeon_fence_process(rdev); | ||
2015 | break; | 2017 | break; |
2016 | case 233: /* GUI IDLE */ | 2018 | case 233: /* GUI IDLE */ |
2017 | DRM_DEBUG("IH: CP EOP\n"); | 2019 | DRM_DEBUG("IH: CP EOP\n"); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index fbce58b2cd04..7c5f855a43e6 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -2279,21 +2279,31 @@ int r600_ring_test(struct radeon_device *rdev) | |||
2279 | void r600_fence_ring_emit(struct radeon_device *rdev, | 2279 | void r600_fence_ring_emit(struct radeon_device *rdev, |
2280 | struct radeon_fence *fence) | 2280 | struct radeon_fence *fence) |
2281 | { | 2281 | { |
2282 | /* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */ | 2282 | if (rdev->wb.use_event) { |
2283 | 2283 | u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET + | |
2284 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); | 2284 | (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base); |
2285 | radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT); | 2285 | /* EVENT_WRITE_EOP - flush caches, send int */ |
2286 | /* wait for 3D idle clean */ | 2286 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); |
2287 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 2287 | radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); |
2288 | radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | 2288 | radeon_ring_write(rdev, addr & 0xffffffff); |
2289 | radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); | 2289 | radeon_ring_write(rdev, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); |
2290 | /* Emit fence sequence & fire IRQ */ | 2290 | radeon_ring_write(rdev, fence->seq); |
2291 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 2291 | radeon_ring_write(rdev, 0); |
2292 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | 2292 | } else { |
2293 | radeon_ring_write(rdev, fence->seq); | 2293 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); |
2294 | /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ | 2294 | radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); |
2295 | radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); | 2295 | /* wait for 3D idle clean */ |
2296 | radeon_ring_write(rdev, RB_INT_STAT); | 2296 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
2297 | radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | ||
2298 | radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); | ||
2299 | /* Emit fence sequence & fire IRQ */ | ||
2300 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
2301 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | ||
2302 | radeon_ring_write(rdev, fence->seq); | ||
2303 | /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ | ||
2304 | radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); | ||
2305 | radeon_ring_write(rdev, RB_INT_STAT); | ||
2306 | } | ||
2297 | } | 2307 | } |
2298 | 2308 | ||
2299 | int r600_copy_blit(struct radeon_device *rdev, | 2309 | int r600_copy_blit(struct radeon_device *rdev, |
@@ -3012,6 +3022,7 @@ int r600_irq_set(struct radeon_device *rdev) | |||
3012 | if (rdev->irq.sw_int) { | 3022 | if (rdev->irq.sw_int) { |
3013 | DRM_DEBUG("r600_irq_set: sw int\n"); | 3023 | DRM_DEBUG("r600_irq_set: sw int\n"); |
3014 | cp_int_cntl |= RB_INT_ENABLE; | 3024 | cp_int_cntl |= RB_INT_ENABLE; |
3025 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | ||
3015 | } | 3026 | } |
3016 | if (rdev->irq.crtc_vblank_int[0]) { | 3027 | if (rdev->irq.crtc_vblank_int[0]) { |
3017 | DRM_DEBUG("r600_irq_set: vblank 0\n"); | 3028 | DRM_DEBUG("r600_irq_set: vblank 0\n"); |
@@ -3377,6 +3388,7 @@ restart_ih: | |||
3377 | break; | 3388 | break; |
3378 | case 181: /* CP EOP event */ | 3389 | case 181: /* CP EOP event */ |
3379 | DRM_DEBUG("IH: CP EOP\n"); | 3390 | DRM_DEBUG("IH: CP EOP\n"); |
3391 | radeon_fence_process(rdev); | ||
3380 | break; | 3392 | break; |
3381 | case 233: /* GUI IDLE */ | 3393 | case 233: /* GUI IDLE */ |
3382 | DRM_DEBUG("IH: CP EOP\n"); | 3394 | DRM_DEBUG("IH: CP EOP\n"); |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 858a1920c0d7..966a793e225b 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -474,6 +474,7 @@ | |||
474 | #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 | 474 | #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 |
475 | #define VTX_REUSE_DEPTH_MASK 0x000000FF | 475 | #define VTX_REUSE_DEPTH_MASK 0x000000FF |
476 | #define VGT_EVENT_INITIATOR 0x28a90 | 476 | #define VGT_EVENT_INITIATOR 0x28a90 |
477 | # define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) | ||
477 | # define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) | 478 | # define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) |
478 | 479 | ||
479 | #define VM_CONTEXT0_CNTL 0x1410 | 480 | #define VM_CONTEXT0_CNTL 0x1410 |
@@ -775,7 +776,27 @@ | |||
775 | #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) | 776 | #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) |
776 | #define PACKET3_COND_WRITE 0x45 | 777 | #define PACKET3_COND_WRITE 0x45 |
777 | #define PACKET3_EVENT_WRITE 0x46 | 778 | #define PACKET3_EVENT_WRITE 0x46 |
779 | #define EVENT_TYPE(x) ((x) << 0) | ||
780 | #define EVENT_INDEX(x) ((x) << 8) | ||
781 | /* 0 - any non-TS event | ||
782 | * 1 - ZPASS_DONE | ||
783 | * 2 - SAMPLE_PIPELINESTAT | ||
784 | * 3 - SAMPLE_STREAMOUTSTAT* | ||
785 | * 4 - *S_PARTIAL_FLUSH | ||
786 | * 5 - TS events | ||
787 | */ | ||
778 | #define PACKET3_EVENT_WRITE_EOP 0x47 | 788 | #define PACKET3_EVENT_WRITE_EOP 0x47 |
789 | #define DATA_SEL(x) ((x) << 29) | ||
790 | /* 0 - discard | ||
791 | * 1 - send low 32bit data | ||
792 | * 2 - send 64bit data | ||
793 | * 3 - send 64bit counter value | ||
794 | */ | ||
795 | #define INT_SEL(x) ((x) << 24) | ||
796 | /* 0 - none | ||
797 | * 1 - interrupt only (DATA_SEL = 0) | ||
798 | * 2 - interrupt when data write is confirmed | ||
799 | */ | ||
779 | #define PACKET3_ONE_REG_WRITE 0x57 | 800 | #define PACKET3_ONE_REG_WRITE 0x57 |
780 | #define PACKET3_SET_CONFIG_REG 0x68 | 801 | #define PACKET3_SET_CONFIG_REG 0x68 |
781 | #define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000 | 802 | #define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4e10938d8dd1..2bfae5679135 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -595,11 +595,13 @@ struct radeon_wb { | |||
595 | volatile uint32_t *wb; | 595 | volatile uint32_t *wb; |
596 | uint64_t gpu_addr; | 596 | uint64_t gpu_addr; |
597 | bool enabled; | 597 | bool enabled; |
598 | bool use_event; | ||
598 | }; | 599 | }; |
599 | 600 | ||
600 | #define RADEON_WB_SCRATCH_OFFSET 0 | 601 | #define RADEON_WB_SCRATCH_OFFSET 0 |
601 | #define RADEON_WB_CP_RPTR_OFFSET 1024 | 602 | #define RADEON_WB_CP_RPTR_OFFSET 1024 |
602 | #define R600_WB_IH_WPTR_OFFSET 2048 | 603 | #define R600_WB_IH_WPTR_OFFSET 2048 |
604 | #define R600_WB_EVENT_OFFSET 3072 | ||
603 | 605 | ||
604 | /** | 606 | /** |
605 | * struct radeon_pm - power management datas | 607 | * struct radeon_pm - power management datas |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cfc162d05010..8adfedfe547f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -208,6 +208,8 @@ int radeon_wb_init(struct radeon_device *rdev) | |||
208 | return r; | 208 | return r; |
209 | } | 209 | } |
210 | 210 | ||
211 | /* disable event_write fences */ | ||
212 | rdev->wb.use_event = false; | ||
211 | /* disabled via module param */ | 213 | /* disabled via module param */ |
212 | if (radeon_no_wb == 1) | 214 | if (radeon_no_wb == 1) |
213 | rdev->wb.enabled = false; | 215 | rdev->wb.enabled = false; |
@@ -215,8 +217,12 @@ int radeon_wb_init(struct radeon_device *rdev) | |||
215 | /* often unreliable on AGP */ | 217 | /* often unreliable on AGP */ |
216 | if (rdev->flags & RADEON_IS_AGP) { | 218 | if (rdev->flags & RADEON_IS_AGP) { |
217 | rdev->wb.enabled = false; | 219 | rdev->wb.enabled = false; |
218 | } else | 220 | } else { |
219 | rdev->wb.enabled = true; | 221 | rdev->wb.enabled = true; |
222 | /* event_write fences are only available on r600+ */ | ||
223 | if (rdev->family >= CHIP_R600) | ||
224 | rdev->wb.use_event = true; | ||
225 | } | ||
220 | } | 226 | } |
221 | 227 | ||
222 | dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); | 228 | dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 698a7ed3a6a1..216392d0353b 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -73,7 +73,11 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) | |||
73 | unsigned long cjiffies; | 73 | unsigned long cjiffies; |
74 | 74 | ||
75 | if (rdev->wb.enabled) { | 75 | if (rdev->wb.enabled) { |
76 | u32 scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; | 76 | u32 scratch_index; |
77 | if (rdev->wb.use_event) | ||
78 | scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; | ||
79 | else | ||
80 | scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; | ||
77 | seq = rdev->wb.wb[scratch_index/4]; | 81 | seq = rdev->wb.wb[scratch_index/4]; |
78 | } else | 82 | } else |
79 | seq = RREG32(rdev->fence_drv.scratch_reg); | 83 | seq = RREG32(rdev->fence_drv.scratch_reg); |