nouveau_dma.c revision ba59953d281747b1f7518a60f0ba8ff671cd0d65
16ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* 26ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Copyright (C) 2007 Ben Skeggs. 36ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * All Rights Reserved. 46ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 56ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining 66ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * a copy of this software and associated documentation files (the 76ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * "Software"), to deal in the Software without restriction, including 86ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * without limitation the rights to use, copy, modify, merge, publish, 96ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * distribute, sublicense, and/or sell copies of the Software, and to 106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * permit persons to whom the Software is furnished to do so, subject to 116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the following conditions: 126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * The above copyright notice and this permission notice (including the 146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * next paragraph) shall be included in all copies or substantial 156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * portions of the Software. 166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "drmP.h" 286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "drm.h" 296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "nouveau_drv.h" 306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "nouveau_dma.h" 316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 3275c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggsvoid 3375c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggsnouveau_dma_pre_init(struct nouveau_channel *chan) 3475c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs{ 3575c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; 3675c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs chan->dma.put = 0; 3775c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs chan->dma.cur = chan->dma.put; 3875c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs chan->dma.free = chan->dma.max - chan->dma.cur; 3975c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs} 4075c99da6cdd0ec9d70747f9ced3e85b2dd955cdfBen Skeggs 416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint 426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_dma_init(struct nouveau_channel *chan) 436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{ 446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs struct drm_device *dev = chan->dev; 456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs struct nouveau_gpuobj *m2mf = NULL; 47f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez struct nouveau_gpuobj *nvsw = NULL; 486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs int ret, i; 496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ 516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? 526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 0x0039 : 0x5039, &m2mf); 536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL); 576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 60f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez /* Create an NV_SW object for various sync purposes */ 61f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw); 62f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez if (ret) 63f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez return ret; 64f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez 65f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL); 66f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez if (ret) 67f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez return ret; 68f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez 696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ 706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); 716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Map push buffer */ 756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = nouveau_bo_map(chan->pushbuf_bo); 766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Map M2MF notifier object - fbcon. */ 806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (drm_core_check_feature(dev, DRIVER_MODESET)) { 816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = nouveau_bo_map(chan->notifier_bo); 826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs } 856ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Insert NOPS for NOUVEAU_DMA_SKIPS */ 876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); 886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) 926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs OUT_RING(chan, 0); 936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ 956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs ret = RING_SPACE(chan, 4); 966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (ret) 976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return ret; 986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); 996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs OUT_RING(chan, NvM2MF); 1006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); 1016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs OUT_RING(chan, NvNotify0); 1026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 103f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez /* Initialise NV_SW */ 104f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez ret = RING_SPACE(chan, 2); 105f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez if (ret) 106f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez return ret; 107f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez BEGIN_RING(chan, NvSubSw, 0, 1); 108f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez OUT_RING(chan, NvSw); 109f03a314b4671407c4ff69a2d85e72413e8064c48Francisco Jerez 1106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* Sit back and pray the channel works.. */ 1116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs FIRE_RING(chan); 1126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return 0; 1146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs} 1156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid 1176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsOUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) 1186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{ 1196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs bool is_iomem; 1206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs u32 *mem = ttm_kmap_obj_virtual(&chan->pushbuf_bo->kmap, &is_iomem); 1216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs mem = &mem[chan->dma.cur]; 1226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (is_iomem) 1236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs memcpy_toio((void __force __iomem *)mem, data, nr_dwords * 4); 1246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs else 1256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs memcpy(mem, data, nr_dwords * 4); 1266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs chan->dma.cur += nr_dwords; 1276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs} 1286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 129ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs/* Fetch and adjust GPU GET pointer 130ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * 131ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * Returns: 132ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * value >= 0, the adjusted GET pointer 133ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * -EINVAL if GET pointer currently outside main push buffer 134ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * -EBUSY if timeout exceeded 135ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs */ 136ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggsstatic inline int 137ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben SkeggsREAD_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout) 1386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{ 1396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs uint32_t val; 1406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs val = nvchan_rd32(chan, chan->user_get); 142ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs 143ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs /* reset counter as long as GET is still advancing, this is 144ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * to avoid misdetecting a GPU lockup if the GPU happens to 145ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * just be processing an operation that takes a long time 146ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs */ 147ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (val != *prev_get) { 148ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs *prev_get = val; 149ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs *timeout = 0; 150ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs } 151ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs 152ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if ((++*timeout & 0xff) == 0) { 153ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs DRM_UDELAY(1); 154ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (*timeout > 100000) 155ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs return -EBUSY; 1566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs } 1576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 158ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (val < chan->pushbuf_base || 159ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs val > chan->pushbuf_base + (chan->dma.max << 2)) 160ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs return -EINVAL; 161ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs 162ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs return (val - chan->pushbuf_base) >> 2; 1636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs} 1646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint 1666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_dma_wait(struct nouveau_channel *chan, int size) 1676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{ 168ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs uint32_t prev_get = 0, cnt = 0; 169ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs int get; 1706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs while (chan->dma.free < size) { 172ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs get = READ_GET(chan, &prev_get, &cnt); 173ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (unlikely(get == -EBUSY)) 174ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs return -EBUSY; 1756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* loop until we have a usable GET pointer. the value 1776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * we read from the GPU may be outside the main ring if 1786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * PFIFO is processing a buffer called from the main ring, 1796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * discard these values until something sensible is seen. 1806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 1816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the other case we discard GET is while the GPU is fetching 1826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * from the SKIPS area, so the code below doesn't have to deal 1836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * with some fun corner cases. 1846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 185ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS) 1866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs continue; 1876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 1886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (get <= chan->dma.cur) { 1896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* engine is fetching behind us, or is completely 1906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * idle (GET == PUT) so we have free space up until 1916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the end of the push buffer 1926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 1936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * we can only hit that path once per call due to 1946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * looping back to the beginning of the push buffer, 1956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * we'll hit the fetching-ahead-of-us path from that 1966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * point on. 1976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 1986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the *one* exception to that rule is if we read 1996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * GET==PUT, in which case the below conditional will 2006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * always succeed and break us out of the wait loop. 2016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 2026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs chan->dma.free = chan->dma.max - chan->dma.cur; 2036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs if (chan->dma.free >= size) 2046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs break; 2056ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 2066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* not enough space left at the end of the push buffer, 2076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * instruct the GPU to jump back to the start right 2086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * after processing the currently pending commands. 2096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 2106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs OUT_RING(chan, chan->pushbuf_base | 0x20000000); 211ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs 212ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs /* wait for GET to depart from the skips area. 213ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * prevents writing GET==PUT and causing a race 214ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * condition that causes us to think the GPU is 215ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs * idle when it's not. 216ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs */ 217ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs do { 218ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs get = READ_GET(chan, &prev_get, &cnt); 219ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (unlikely(get == -EBUSY)) 220ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs return -EBUSY; 221ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs if (unlikely(get == -EINVAL)) 222ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs continue; 223ba59953d281747b1f7518a60f0ba8ff671cd0d65Ben Skeggs } while (get <= NOUVEAU_DMA_SKIPS); 2246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs WRITE_PUT(NOUVEAU_DMA_SKIPS); 2256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 2266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* we're now submitting commands at the start of 2276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the push buffer. 2286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 2296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs chan->dma.cur = 2306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs chan->dma.put = NOUVEAU_DMA_SKIPS; 2316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs } 2326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 2336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs /* engine fetching ahead of us, we have space up until the 2346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * current GET pointer. the "- 1" is to ensure there's 2356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * space left to emit a jump back to the beginning of the 2366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * push buffer if we require it. we can never get GET == PUT 2376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * here, so this is safe. 2386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */ 2396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs chan->dma.free = get - chan->dma.cur - 1; 2406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs } 2416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 2426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs return 0; 2436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs} 2446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs 245