12483b4eaSChristian König /*
22483b4eaSChristian König * Copyright 2013 Advanced Micro Devices, Inc.
32483b4eaSChristian König *
42483b4eaSChristian König * Permission is hereby granted, free of charge, to any person obtaining a
52483b4eaSChristian König * copy of this software and associated documentation files (the "Software"),
62483b4eaSChristian König * to deal in the Software without restriction, including without limitation
72483b4eaSChristian König * the rights to use, copy, modify, merge, publish, distribute, sublicense,
82483b4eaSChristian König * and/or sell copies of the Software, and to permit persons to whom the
92483b4eaSChristian König * Software is furnished to do so, subject to the following conditions:
102483b4eaSChristian König *
112483b4eaSChristian König * The above copyright notice and this permission notice shall be included in
122483b4eaSChristian König * all copies or substantial portions of the Software.
132483b4eaSChristian König *
142483b4eaSChristian König * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
152483b4eaSChristian König * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
162483b4eaSChristian König * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
172483b4eaSChristian König * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
182483b4eaSChristian König * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
192483b4eaSChristian König * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
202483b4eaSChristian König * OTHER DEALINGS IN THE SOFTWARE.
212483b4eaSChristian König *
222483b4eaSChristian König * Authors: Alex Deucher
232483b4eaSChristian König */
24c182615fSSam Ravnborg
252483b4eaSChristian König #include "radeon.h"
262483b4eaSChristian König #include "radeon_asic.h"
27*5561ecbaSLee Jones #include "r600.h"
282483b4eaSChristian König #include "r600d.h"
292483b4eaSChristian König
302483b4eaSChristian König /*
312483b4eaSChristian König * DMA
322483b4eaSChristian König * Starting with R600, the GPU has an asynchronous
332483b4eaSChristian König * DMA engine. The programming model is very similar
342483b4eaSChristian König * to the 3D engine (ring buffer, IBs, etc.), but the
352483b4eaSChristian König * DMA controller has it's own packet format that is
362483b4eaSChristian König * different form the PM4 format used by the 3D engine.
372483b4eaSChristian König * It supports copying data, writing embedded data,
382483b4eaSChristian König * solid fills, and a number of other things. It also
392483b4eaSChristian König * has support for tiling/detiling of buffers.
402483b4eaSChristian König */
412483b4eaSChristian König
422483b4eaSChristian König /**
432483b4eaSChristian König * r600_dma_get_rptr - get the current read pointer
442483b4eaSChristian König *
452483b4eaSChristian König * @rdev: radeon_device pointer
462483b4eaSChristian König * @ring: radeon ring pointer
472483b4eaSChristian König *
482483b4eaSChristian König * Get the current rptr from the hardware (r6xx+).
492483b4eaSChristian König */
r600_dma_get_rptr(struct radeon_device * rdev,struct radeon_ring * ring)502483b4eaSChristian König uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
512483b4eaSChristian König struct radeon_ring *ring)
522483b4eaSChristian König {
53ea31bf69SAlex Deucher u32 rptr;
54ea31bf69SAlex Deucher
55ea31bf69SAlex Deucher if (rdev->wb.enabled)
56ea31bf69SAlex Deucher rptr = rdev->wb.wb[ring->rptr_offs/4];
57ea31bf69SAlex Deucher else
58ea31bf69SAlex Deucher rptr = RREG32(DMA_RB_RPTR);
59ea31bf69SAlex Deucher
60ea31bf69SAlex Deucher return (rptr & 0x3fffc) >> 2;
612483b4eaSChristian König }
622483b4eaSChristian König
632483b4eaSChristian König /**
642483b4eaSChristian König * r600_dma_get_wptr - get the current write pointer
652483b4eaSChristian König *
662483b4eaSChristian König * @rdev: radeon_device pointer
672483b4eaSChristian König * @ring: radeon ring pointer
682483b4eaSChristian König *
692483b4eaSChristian König * Get the current wptr from the hardware (r6xx+).
702483b4eaSChristian König */
r600_dma_get_wptr(struct radeon_device * rdev,struct radeon_ring * ring)712483b4eaSChristian König uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
722483b4eaSChristian König struct radeon_ring *ring)
732483b4eaSChristian König {
74ea31bf69SAlex Deucher return (RREG32(DMA_RB_WPTR) & 0x3fffc) >> 2;
752483b4eaSChristian König }
762483b4eaSChristian König
772483b4eaSChristian König /**
782483b4eaSChristian König * r600_dma_set_wptr - commit the write pointer
792483b4eaSChristian König *
802483b4eaSChristian König * @rdev: radeon_device pointer
812483b4eaSChristian König * @ring: radeon ring pointer
822483b4eaSChristian König *
832483b4eaSChristian König * Write the wptr back to the hardware (r6xx+).
842483b4eaSChristian König */
r600_dma_set_wptr(struct radeon_device * rdev,struct radeon_ring * ring)852483b4eaSChristian König void r600_dma_set_wptr(struct radeon_device *rdev,
862483b4eaSChristian König struct radeon_ring *ring)
872483b4eaSChristian König {
88ea31bf69SAlex Deucher WREG32(DMA_RB_WPTR, (ring->wptr << 2) & 0x3fffc);
892483b4eaSChristian König }
902483b4eaSChristian König
912483b4eaSChristian König /**
922483b4eaSChristian König * r600_dma_stop - stop the async dma engine
932483b4eaSChristian König *
942483b4eaSChristian König * @rdev: radeon_device pointer
952483b4eaSChristian König *
962483b4eaSChristian König * Stop the async dma engine (r6xx-evergreen).
972483b4eaSChristian König */
r600_dma_stop(struct radeon_device * rdev)982483b4eaSChristian König void r600_dma_stop(struct radeon_device *rdev)
992483b4eaSChristian König {
1002483b4eaSChristian König u32 rb_cntl = RREG32(DMA_RB_CNTL);
1012483b4eaSChristian König
10250efa51aSAlex Deucher if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX)
1032483b4eaSChristian König radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
1042483b4eaSChristian König
1052483b4eaSChristian König rb_cntl &= ~DMA_RB_ENABLE;
1062483b4eaSChristian König WREG32(DMA_RB_CNTL, rb_cntl);
1072483b4eaSChristian König
1082483b4eaSChristian König rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false;
1092483b4eaSChristian König }
1102483b4eaSChristian König
1112483b4eaSChristian König /**
1122483b4eaSChristian König * r600_dma_resume - setup and start the async dma engine
1132483b4eaSChristian König *
1142483b4eaSChristian König * @rdev: radeon_device pointer
1152483b4eaSChristian König *
1162483b4eaSChristian König * Set up the DMA ring buffer and enable it. (r6xx-evergreen).
1172483b4eaSChristian König * Returns 0 for success, error for failure.
1182483b4eaSChristian König */
r600_dma_resume(struct radeon_device * rdev)1192483b4eaSChristian König int r600_dma_resume(struct radeon_device *rdev)
1202483b4eaSChristian König {
1212483b4eaSChristian König struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
1222483b4eaSChristian König u32 rb_cntl, dma_cntl, ib_cntl;
1232483b4eaSChristian König u32 rb_bufsz;
1242483b4eaSChristian König int r;
1252483b4eaSChristian König
1262483b4eaSChristian König WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0);
1272483b4eaSChristian König WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0);
1282483b4eaSChristian König
1292483b4eaSChristian König /* Set ring buffer size in dwords */
1309c725e5bSDave Airlie rb_bufsz = order_base_2(ring->ring_size / 4);
1312483b4eaSChristian König rb_cntl = rb_bufsz << 1;
1322483b4eaSChristian König #ifdef __BIG_ENDIAN
1332483b4eaSChristian König rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE;
1342483b4eaSChristian König #endif
1352483b4eaSChristian König WREG32(DMA_RB_CNTL, rb_cntl);
1362483b4eaSChristian König
1372483b4eaSChristian König /* Initialize the ring buffer's read and write pointers */
1382483b4eaSChristian König WREG32(DMA_RB_RPTR, 0);
1392483b4eaSChristian König WREG32(DMA_RB_WPTR, 0);
1402483b4eaSChristian König
1412483b4eaSChristian König /* set the wb address whether it's enabled or not */
1422483b4eaSChristian König WREG32(DMA_RB_RPTR_ADDR_HI,
1432483b4eaSChristian König upper_32_bits(rdev->wb.gpu_addr + R600_WB_DMA_RPTR_OFFSET) & 0xFF);
1442483b4eaSChristian König WREG32(DMA_RB_RPTR_ADDR_LO,
1452483b4eaSChristian König ((rdev->wb.gpu_addr + R600_WB_DMA_RPTR_OFFSET) & 0xFFFFFFFC));
1462483b4eaSChristian König
1472483b4eaSChristian König if (rdev->wb.enabled)
1482483b4eaSChristian König rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE;
1492483b4eaSChristian König
1502483b4eaSChristian König WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
1512483b4eaSChristian König
1522483b4eaSChristian König /* enable DMA IBs */
1532483b4eaSChristian König ib_cntl = DMA_IB_ENABLE;
1542483b4eaSChristian König #ifdef __BIG_ENDIAN
1552483b4eaSChristian König ib_cntl |= DMA_IB_SWAP_ENABLE;
1562483b4eaSChristian König #endif
1572483b4eaSChristian König WREG32(DMA_IB_CNTL, ib_cntl);
1582483b4eaSChristian König
1592483b4eaSChristian König dma_cntl = RREG32(DMA_CNTL);
1602483b4eaSChristian König dma_cntl &= ~CTXEMPTY_INT_ENABLE;
1612483b4eaSChristian König WREG32(DMA_CNTL, dma_cntl);
1622483b4eaSChristian König
1632483b4eaSChristian König if (rdev->family >= CHIP_RV770)
1642483b4eaSChristian König WREG32(DMA_MODE, 1);
1652483b4eaSChristian König
1662483b4eaSChristian König ring->wptr = 0;
1672483b4eaSChristian König WREG32(DMA_RB_WPTR, ring->wptr << 2);
1682483b4eaSChristian König
1692483b4eaSChristian König WREG32(DMA_RB_CNTL, rb_cntl | DMA_RB_ENABLE);
1702483b4eaSChristian König
1712483b4eaSChristian König ring->ready = true;
1722483b4eaSChristian König
1732483b4eaSChristian König r = radeon_ring_test(rdev, R600_RING_TYPE_DMA_INDEX, ring);
1742483b4eaSChristian König if (r) {
1752483b4eaSChristian König ring->ready = false;
1762483b4eaSChristian König return r;
1772483b4eaSChristian König }
1782483b4eaSChristian König
17950efa51aSAlex Deucher if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX)
1802483b4eaSChristian König radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
1812483b4eaSChristian König
1822483b4eaSChristian König return 0;
1832483b4eaSChristian König }
1842483b4eaSChristian König
1852483b4eaSChristian König /**
1862483b4eaSChristian König * r600_dma_fini - tear down the async dma engine
1872483b4eaSChristian König *
1882483b4eaSChristian König * @rdev: radeon_device pointer
1892483b4eaSChristian König *
1902483b4eaSChristian König * Stop the async dma engine and free the ring (r6xx-evergreen).
1912483b4eaSChristian König */
r600_dma_fini(struct radeon_device * rdev)1922483b4eaSChristian König void r600_dma_fini(struct radeon_device *rdev)
1932483b4eaSChristian König {
1942483b4eaSChristian König r600_dma_stop(rdev);
1952483b4eaSChristian König radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
1962483b4eaSChristian König }
1972483b4eaSChristian König
1982483b4eaSChristian König /**
1992483b4eaSChristian König * r600_dma_is_lockup - Check if the DMA engine is locked up
2002483b4eaSChristian König *
2012483b4eaSChristian König * @rdev: radeon_device pointer
2022483b4eaSChristian König * @ring: radeon_ring structure holding ring information
2032483b4eaSChristian König *
2042483b4eaSChristian König * Check if the async DMA engine is locked up.
2052483b4eaSChristian König * Returns true if the engine appears to be locked up, false if not.
2062483b4eaSChristian König */
r600_dma_is_lockup(struct radeon_device * rdev,struct radeon_ring * ring)2072483b4eaSChristian König bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
2082483b4eaSChristian König {
2092483b4eaSChristian König u32 reset_mask = r600_gpu_check_soft_reset(rdev);
2102483b4eaSChristian König
2112483b4eaSChristian König if (!(reset_mask & RADEON_RESET_DMA)) {
212ff212f25SChristian König radeon_ring_lockup_update(rdev, ring);
2132483b4eaSChristian König return false;
2142483b4eaSChristian König }
2152483b4eaSChristian König return radeon_ring_test_lockup(rdev, ring);
2162483b4eaSChristian König }
2172483b4eaSChristian König
2182483b4eaSChristian König
2192483b4eaSChristian König /**
2202483b4eaSChristian König * r600_dma_ring_test - simple async dma engine test
2212483b4eaSChristian König *
2222483b4eaSChristian König * @rdev: radeon_device pointer
2232483b4eaSChristian König * @ring: radeon_ring structure holding ring information
2242483b4eaSChristian König *
2252483b4eaSChristian König * Test the DMA engine by writing using it to write an
2262483b4eaSChristian König * value to memory. (r6xx-SI).
2272483b4eaSChristian König * Returns 0 for success, error for failure.
2282483b4eaSChristian König */
r600_dma_ring_test(struct radeon_device * rdev,struct radeon_ring * ring)2292483b4eaSChristian König int r600_dma_ring_test(struct radeon_device *rdev,
2302483b4eaSChristian König struct radeon_ring *ring)
2312483b4eaSChristian König {
2322483b4eaSChristian König unsigned i;
2332483b4eaSChristian König int r;
234adfed2b0SAlex Deucher unsigned index;
2352483b4eaSChristian König u32 tmp;
236adfed2b0SAlex Deucher u64 gpu_addr;
2372483b4eaSChristian König
238adfed2b0SAlex Deucher if (ring->idx == R600_RING_TYPE_DMA_INDEX)
239adfed2b0SAlex Deucher index = R600_WB_DMA_RING_TEST_OFFSET;
240adfed2b0SAlex Deucher else
241adfed2b0SAlex Deucher index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
242adfed2b0SAlex Deucher
243adfed2b0SAlex Deucher gpu_addr = rdev->wb.gpu_addr + index;
2442483b4eaSChristian König
2452483b4eaSChristian König tmp = 0xCAFEDEAD;
246adfed2b0SAlex Deucher rdev->wb.wb[index/4] = cpu_to_le32(tmp);
2472483b4eaSChristian König
2482483b4eaSChristian König r = radeon_ring_lock(rdev, ring, 4);
2492483b4eaSChristian König if (r) {
2502483b4eaSChristian König DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r);
2512483b4eaSChristian König return r;
2522483b4eaSChristian König }
2532483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1));
254adfed2b0SAlex Deucher radeon_ring_write(ring, lower_32_bits(gpu_addr));
255adfed2b0SAlex Deucher radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xff);
2562483b4eaSChristian König radeon_ring_write(ring, 0xDEADBEEF);
2571538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ring, false);
2582483b4eaSChristian König
2592483b4eaSChristian König for (i = 0; i < rdev->usec_timeout; i++) {
260adfed2b0SAlex Deucher tmp = le32_to_cpu(rdev->wb.wb[index/4]);
2612483b4eaSChristian König if (tmp == 0xDEADBEEF)
2622483b4eaSChristian König break;
2630e1a351dSSam Ravnborg udelay(1);
2642483b4eaSChristian König }
2652483b4eaSChristian König
2662483b4eaSChristian König if (i < rdev->usec_timeout) {
2672483b4eaSChristian König DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i);
2682483b4eaSChristian König } else {
2692483b4eaSChristian König DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
2702483b4eaSChristian König ring->idx, tmp);
2712483b4eaSChristian König r = -EINVAL;
2722483b4eaSChristian König }
2732483b4eaSChristian König return r;
2742483b4eaSChristian König }
2752483b4eaSChristian König
2762483b4eaSChristian König /**
2772483b4eaSChristian König * r600_dma_fence_ring_emit - emit a fence on the DMA ring
2782483b4eaSChristian König *
2792483b4eaSChristian König * @rdev: radeon_device pointer
2802483b4eaSChristian König * @fence: radeon fence object
2812483b4eaSChristian König *
2822483b4eaSChristian König * Add a DMA fence packet to the ring to write
2832483b4eaSChristian König * the fence seq number and DMA trap packet to generate
2842483b4eaSChristian König * an interrupt if needed (r6xx-r7xx).
2852483b4eaSChristian König */
r600_dma_fence_ring_emit(struct radeon_device * rdev,struct radeon_fence * fence)2862483b4eaSChristian König void r600_dma_fence_ring_emit(struct radeon_device *rdev,
2872483b4eaSChristian König struct radeon_fence *fence)
2882483b4eaSChristian König {
2892483b4eaSChristian König struct radeon_ring *ring = &rdev->ring[fence->ring];
2902483b4eaSChristian König u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
2912483b4eaSChristian König
2922483b4eaSChristian König /* write the fence */
2932483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0));
2942483b4eaSChristian König radeon_ring_write(ring, addr & 0xfffffffc);
2952483b4eaSChristian König radeon_ring_write(ring, (upper_32_bits(addr) & 0xff));
2962483b4eaSChristian König radeon_ring_write(ring, lower_32_bits(fence->seq));
2972483b4eaSChristian König /* generate an interrupt */
2982483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0));
2992483b4eaSChristian König }
3002483b4eaSChristian König
3012483b4eaSChristian König /**
3022483b4eaSChristian König * r600_dma_semaphore_ring_emit - emit a semaphore on the dma ring
3032483b4eaSChristian König *
3042483b4eaSChristian König * @rdev: radeon_device pointer
3052483b4eaSChristian König * @ring: radeon_ring structure holding ring information
3062483b4eaSChristian König * @semaphore: radeon semaphore object
3072483b4eaSChristian König * @emit_wait: wait or signal semaphore
3082483b4eaSChristian König *
3092483b4eaSChristian König * Add a DMA semaphore packet to the ring wait on or signal
3102483b4eaSChristian König * other rings (r6xx-SI).
3112483b4eaSChristian König */
r600_dma_semaphore_ring_emit(struct radeon_device * rdev,struct radeon_ring * ring,struct radeon_semaphore * semaphore,bool emit_wait)3121654b817SChristian König bool r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
3132483b4eaSChristian König struct radeon_ring *ring,
3142483b4eaSChristian König struct radeon_semaphore *semaphore,
3152483b4eaSChristian König bool emit_wait)
3162483b4eaSChristian König {
3172483b4eaSChristian König u64 addr = semaphore->gpu_addr;
3182483b4eaSChristian König u32 s = emit_wait ? 0 : 1;
3192483b4eaSChristian König
3202483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SEMAPHORE, 0, s, 0));
3212483b4eaSChristian König radeon_ring_write(ring, addr & 0xfffffffc);
3222483b4eaSChristian König radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
3231654b817SChristian König
3241654b817SChristian König return true;
3252483b4eaSChristian König }
3262483b4eaSChristian König
3272483b4eaSChristian König /**
3282483b4eaSChristian König * r600_dma_ib_test - test an IB on the DMA engine
3292483b4eaSChristian König *
3302483b4eaSChristian König * @rdev: radeon_device pointer
3312483b4eaSChristian König * @ring: radeon_ring structure holding ring information
3322483b4eaSChristian König *
3332483b4eaSChristian König * Test a simple IB in the DMA ring (r6xx-SI).
3342483b4eaSChristian König * Returns 0 on success, error on failure.
3352483b4eaSChristian König */
r600_dma_ib_test(struct radeon_device * rdev,struct radeon_ring * ring)3362483b4eaSChristian König int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
3372483b4eaSChristian König {
3382483b4eaSChristian König struct radeon_ib ib;
3392483b4eaSChristian König unsigned i;
3400b021c58SAlex Deucher unsigned index;
3412483b4eaSChristian König int r;
3422483b4eaSChristian König u32 tmp = 0;
3430b021c58SAlex Deucher u64 gpu_addr;
3442483b4eaSChristian König
3450b021c58SAlex Deucher if (ring->idx == R600_RING_TYPE_DMA_INDEX)
3460b021c58SAlex Deucher index = R600_WB_DMA_RING_TEST_OFFSET;
3470b021c58SAlex Deucher else
3480b021c58SAlex Deucher index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
3492483b4eaSChristian König
3500b021c58SAlex Deucher gpu_addr = rdev->wb.gpu_addr + index;
3512483b4eaSChristian König
3522483b4eaSChristian König r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
3532483b4eaSChristian König if (r) {
3542483b4eaSChristian König DRM_ERROR("radeon: failed to get ib (%d).\n", r);
3552483b4eaSChristian König return r;
3562483b4eaSChristian König }
3572483b4eaSChristian König
3582483b4eaSChristian König ib.ptr[0] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1);
3590b021c58SAlex Deucher ib.ptr[1] = lower_32_bits(gpu_addr);
3600b021c58SAlex Deucher ib.ptr[2] = upper_32_bits(gpu_addr) & 0xff;
3612483b4eaSChristian König ib.ptr[3] = 0xDEADBEEF;
3622483b4eaSChristian König ib.length_dw = 4;
3632483b4eaSChristian König
3641538a9e0SMichel Dänzer r = radeon_ib_schedule(rdev, &ib, NULL, false);
3652483b4eaSChristian König if (r) {
3662483b4eaSChristian König radeon_ib_free(rdev, &ib);
3672483b4eaSChristian König DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
3682483b4eaSChristian König return r;
3692483b4eaSChristian König }
37004db4cafSMatthew Dawson r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies(
37104db4cafSMatthew Dawson RADEON_USEC_IB_TEST_TIMEOUT));
37204db4cafSMatthew Dawson if (r < 0) {
3732483b4eaSChristian König DRM_ERROR("radeon: fence wait failed (%d).\n", r);
3742483b4eaSChristian König return r;
37504db4cafSMatthew Dawson } else if (r == 0) {
37604db4cafSMatthew Dawson DRM_ERROR("radeon: fence wait timed out.\n");
37704db4cafSMatthew Dawson return -ETIMEDOUT;
3782483b4eaSChristian König }
37904db4cafSMatthew Dawson r = 0;
3802483b4eaSChristian König for (i = 0; i < rdev->usec_timeout; i++) {
3810b021c58SAlex Deucher tmp = le32_to_cpu(rdev->wb.wb[index/4]);
3822483b4eaSChristian König if (tmp == 0xDEADBEEF)
3832483b4eaSChristian König break;
3840e1a351dSSam Ravnborg udelay(1);
3852483b4eaSChristian König }
3862483b4eaSChristian König if (i < rdev->usec_timeout) {
3872483b4eaSChristian König DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i);
3882483b4eaSChristian König } else {
3892483b4eaSChristian König DRM_ERROR("radeon: ib test failed (0x%08X)\n", tmp);
3902483b4eaSChristian König r = -EINVAL;
3912483b4eaSChristian König }
3922483b4eaSChristian König radeon_ib_free(rdev, &ib);
3932483b4eaSChristian König return r;
3942483b4eaSChristian König }
3952483b4eaSChristian König
3962483b4eaSChristian König /**
3972483b4eaSChristian König * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine
3982483b4eaSChristian König *
3992483b4eaSChristian König * @rdev: radeon_device pointer
4002483b4eaSChristian König * @ib: IB object to schedule
4012483b4eaSChristian König *
4022483b4eaSChristian König * Schedule an IB in the DMA ring (r6xx-r7xx).
4032483b4eaSChristian König */
r600_dma_ring_ib_execute(struct radeon_device * rdev,struct radeon_ib * ib)4042483b4eaSChristian König void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
4052483b4eaSChristian König {
4062483b4eaSChristian König struct radeon_ring *ring = &rdev->ring[ib->ring];
4072483b4eaSChristian König
4082483b4eaSChristian König if (rdev->wb.enabled) {
4092483b4eaSChristian König u32 next_rptr = ring->wptr + 4;
4102483b4eaSChristian König while ((next_rptr & 7) != 5)
4112483b4eaSChristian König next_rptr++;
4122483b4eaSChristian König next_rptr += 3;
4132483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1));
4142483b4eaSChristian König radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
4152483b4eaSChristian König radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff);
4162483b4eaSChristian König radeon_ring_write(ring, next_rptr);
4172483b4eaSChristian König }
4182483b4eaSChristian König
4192483b4eaSChristian König /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring.
4202483b4eaSChristian König * Pad as necessary with NOPs.
4212483b4eaSChristian König */
4222483b4eaSChristian König while ((ring->wptr & 7) != 5)
4232483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
4242483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_INDIRECT_BUFFER, 0, 0, 0));
4252483b4eaSChristian König radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0));
4262483b4eaSChristian König radeon_ring_write(ring, (ib->length_dw << 16) | (upper_32_bits(ib->gpu_addr) & 0xFF));
4272483b4eaSChristian König
4282483b4eaSChristian König }
4292483b4eaSChristian König
4302483b4eaSChristian König /**
4312483b4eaSChristian König * r600_copy_dma - copy pages using the DMA engine
4322483b4eaSChristian König *
4332483b4eaSChristian König * @rdev: radeon_device pointer
4342483b4eaSChristian König * @src_offset: src GPU address
4352483b4eaSChristian König * @dst_offset: dst GPU address
4362483b4eaSChristian König * @num_gpu_pages: number of GPU pages to xfer
43757d20a43SChristian König * @resv: reservation object to sync to
4382483b4eaSChristian König *
4392483b4eaSChristian König * Copy GPU paging using the DMA engine (r6xx).
4402483b4eaSChristian König * Used by the radeon ttm implementation to move pages if
4412483b4eaSChristian König * registered as the asic copy callback.
4422483b4eaSChristian König */
r600_copy_dma(struct radeon_device * rdev,uint64_t src_offset,uint64_t dst_offset,unsigned num_gpu_pages,struct dma_resv * resv)44357d20a43SChristian König struct radeon_fence *r600_copy_dma(struct radeon_device *rdev,
4442483b4eaSChristian König uint64_t src_offset, uint64_t dst_offset,
4452483b4eaSChristian König unsigned num_gpu_pages,
44652791eeeSChristian König struct dma_resv *resv)
4472483b4eaSChristian König {
44857d20a43SChristian König struct radeon_fence *fence;
449975700d2SChristian König struct radeon_sync sync;
4502483b4eaSChristian König int ring_index = rdev->asic->copy.dma_ring_index;
4512483b4eaSChristian König struct radeon_ring *ring = &rdev->ring[ring_index];
4522483b4eaSChristian König u32 size_in_dw, cur_size_in_dw;
4532483b4eaSChristian König int i, num_loops;
4542483b4eaSChristian König int r = 0;
4552483b4eaSChristian König
456975700d2SChristian König radeon_sync_create(&sync);
4572483b4eaSChristian König
4582483b4eaSChristian König size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4;
4592483b4eaSChristian König num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFE);
4602483b4eaSChristian König r = radeon_ring_lock(rdev, ring, num_loops * 4 + 8);
4612483b4eaSChristian König if (r) {
4622483b4eaSChristian König DRM_ERROR("radeon: moving bo (%d).\n", r);
463975700d2SChristian König radeon_sync_free(rdev, &sync, NULL);
46457d20a43SChristian König return ERR_PTR(r);
4652483b4eaSChristian König }
4662483b4eaSChristian König
467975700d2SChristian König radeon_sync_resv(rdev, &sync, resv, false);
468975700d2SChristian König radeon_sync_rings(rdev, &sync, ring->idx);
4692483b4eaSChristian König
4702483b4eaSChristian König for (i = 0; i < num_loops; i++) {
4712483b4eaSChristian König cur_size_in_dw = size_in_dw;
4722483b4eaSChristian König if (cur_size_in_dw > 0xFFFE)
4732483b4eaSChristian König cur_size_in_dw = 0xFFFE;
4742483b4eaSChristian König size_in_dw -= cur_size_in_dw;
4752483b4eaSChristian König radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw));
4762483b4eaSChristian König radeon_ring_write(ring, dst_offset & 0xfffffffc);
4772483b4eaSChristian König radeon_ring_write(ring, src_offset & 0xfffffffc);
4782483b4eaSChristian König radeon_ring_write(ring, (((upper_32_bits(dst_offset) & 0xff) << 16) |
4792483b4eaSChristian König (upper_32_bits(src_offset) & 0xff)));
4802483b4eaSChristian König src_offset += cur_size_in_dw * 4;
4812483b4eaSChristian König dst_offset += cur_size_in_dw * 4;
4822483b4eaSChristian König }
4832483b4eaSChristian König
48457d20a43SChristian König r = radeon_fence_emit(rdev, &fence, ring->idx);
4852483b4eaSChristian König if (r) {
4862483b4eaSChristian König radeon_ring_unlock_undo(rdev, ring);
487975700d2SChristian König radeon_sync_free(rdev, &sync, NULL);
48857d20a43SChristian König return ERR_PTR(r);
4892483b4eaSChristian König }
4902483b4eaSChristian König
4911538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ring, false);
492975700d2SChristian König radeon_sync_free(rdev, &sync, fence);
4932483b4eaSChristian König
49457d20a43SChristian König return fence;
4952483b4eaSChristian König }
496