blob: e721bb2163a066727bd306c8a4dca2f82f5dd2eb [file] [log] [blame]
Ben Skeggs5e120f62012-04-30 13:55:29 +10001/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
Ben Skeggs4dc28132016-05-20 09:22:55 +100025#include "nouveau_drv.h"
Ben Skeggsebb945a2012-07-20 08:17:34 +100026#include "nouveau_dma.h"
Ben Skeggs5e120f62012-04-30 13:55:29 +100027#include "nouveau_fence.h"
Ben Skeggs24e83752017-11-01 03:56:19 +100028#include "nouveau_vmm.h"
Ben Skeggs5e120f62012-04-30 13:55:29 +100029
Ben Skeggs77145f12012-07-31 16:16:21 +100030#include "nv50_display.h"
31
Ben Skeggs5e120f62012-04-30 13:55:29 +100032static int
Ben Skeggsbba98522013-02-14 09:37:35 +100033nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
Ben Skeggs5e120f62012-04-30 13:55:29 +100034{
Ben Skeggsbba98522013-02-14 09:37:35 +100035 int ret = RING_SPACE(chan, 8);
Ben Skeggs5e120f62012-04-30 13:55:29 +100036 if (ret == 0) {
37 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
Ben Skeggs0ad72862014-08-10 04:10:22 +100038 OUT_RING (chan, chan->vram.handle);
Ben Skeggse18c0802013-01-31 14:57:33 +100039 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
Ben Skeggsbba98522013-02-14 09:37:35 +100040 OUT_RING (chan, upper_32_bits(virtual));
41 OUT_RING (chan, lower_32_bits(virtual));
42 OUT_RING (chan, sequence);
Ben Skeggs5e120f62012-04-30 13:55:29 +100043 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
Ben Skeggse18c0802013-01-31 14:57:33 +100044 OUT_RING (chan, 0x00000000);
Ben Skeggs5e120f62012-04-30 13:55:29 +100045 FIRE_RING (chan);
46 }
47 return ret;
48}
49
50static int
Ben Skeggsbba98522013-02-14 09:37:35 +100051nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
Ben Skeggs5e120f62012-04-30 13:55:29 +100052{
Ben Skeggsbba98522013-02-14 09:37:35 +100053 int ret = RING_SPACE(chan, 7);
Ben Skeggs5e120f62012-04-30 13:55:29 +100054 if (ret == 0) {
55 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
Ben Skeggs0ad72862014-08-10 04:10:22 +100056 OUT_RING (chan, chan->vram.handle);
Ben Skeggs5e120f62012-04-30 13:55:29 +100057 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
Ben Skeggsbba98522013-02-14 09:37:35 +100058 OUT_RING (chan, upper_32_bits(virtual));
59 OUT_RING (chan, lower_32_bits(virtual));
60 OUT_RING (chan, sequence);
Ben Skeggs5e120f62012-04-30 13:55:29 +100061 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL);
62 FIRE_RING (chan);
63 }
64 return ret;
65}
66
Ben Skeggs264ce192013-02-14 13:43:21 +100067static int
Ben Skeggsbba98522013-02-14 09:37:35 +100068nv84_fence_emit(struct nouveau_fence *fence)
69{
70 struct nouveau_channel *chan = fence->channel;
Ben Skeggsbba98522013-02-14 09:37:35 +100071 struct nv84_fence_chan *fctx = chan->fence;
Ben Skeggs24e83752017-11-01 03:56:19 +100072 u64 addr = fctx->vma->addr + chan->chid * 16;
Ben Skeggs264ce192013-02-14 13:43:21 +100073
Maarten Lankhorst29ba89b2014-01-09 11:03:11 +010074 return fctx->base.emit32(chan, addr, fence->base.seqno);
Ben Skeggsbba98522013-02-14 09:37:35 +100075}
76
Ben Skeggs264ce192013-02-14 13:43:21 +100077static int
Ben Skeggsbba98522013-02-14 09:37:35 +100078nv84_fence_sync(struct nouveau_fence *fence,
79 struct nouveau_channel *prev, struct nouveau_channel *chan)
80{
Ben Skeggsbba98522013-02-14 09:37:35 +100081 struct nv84_fence_chan *fctx = chan->fence;
Ben Skeggs24e83752017-11-01 03:56:19 +100082 u64 addr = fctx->vma->addr + prev->chid * 16;
Ben Skeggs264ce192013-02-14 13:43:21 +100083
Maarten Lankhorst29ba89b2014-01-09 11:03:11 +010084 return fctx->base.sync32(chan, addr, fence->base.seqno);
Ben Skeggsbba98522013-02-14 09:37:35 +100085}
86
Ben Skeggs264ce192013-02-14 13:43:21 +100087static u32
Ben Skeggs5e120f62012-04-30 13:55:29 +100088nv84_fence_read(struct nouveau_channel *chan)
89{
Ben Skeggsebb945a2012-07-20 08:17:34 +100090 struct nv84_fence_priv *priv = chan->drm->fence;
Ben Skeggsbbf89062014-08-10 04:10:25 +100091 return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
Ben Skeggs5e120f62012-04-30 13:55:29 +100092}
93
Ben Skeggs264ce192013-02-14 13:43:21 +100094static void
Ben Skeggse193b1d2012-07-19 10:51:42 +100095nv84_fence_context_del(struct nouveau_channel *chan)
Ben Skeggs5e120f62012-04-30 13:55:29 +100096{
Ben Skeggsa34caf72013-02-14 09:28:37 +100097 struct nv84_fence_priv *priv = chan->drm->fence;
Ben Skeggse193b1d2012-07-19 10:51:42 +100098 struct nv84_fence_chan *fctx = chan->fence;
Ben Skeggsa34caf72013-02-14 09:28:37 +100099
Maarten Lankhorst1dadba82014-09-22 11:08:48 +0200100 nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
Ben Skeggs96692b02016-12-14 09:52:39 +1000101 mutex_lock(&priv->mutex);
Ben Skeggs24e83752017-11-01 03:56:19 +1000102 nouveau_vma_del(&fctx->vma);
Ben Skeggs96692b02016-12-14 09:52:39 +1000103 mutex_unlock(&priv->mutex);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000104 nouveau_fence_context_del(&fctx->base);
Ben Skeggse193b1d2012-07-19 10:51:42 +1000105 chan->fence = NULL;
Maarten Lankhorst15a996b2014-09-29 10:06:18 +0200106 nouveau_fence_context_free(&fctx->base);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000107}
108
Ben Skeggsa34caf72013-02-14 09:28:37 +1000109int
Ben Skeggse193b1d2012-07-19 10:51:42 +1000110nv84_fence_context_new(struct nouveau_channel *chan)
Ben Skeggs5e120f62012-04-30 13:55:29 +1000111{
Ben Skeggsa01ca782015-08-20 14:54:15 +1000112 struct nouveau_cli *cli = (void *)chan->user.client;
Ben Skeggsebb945a2012-07-20 08:17:34 +1000113 struct nv84_fence_priv *priv = chan->drm->fence;
Ben Skeggs5e120f62012-04-30 13:55:29 +1000114 struct nv84_fence_chan *fctx;
Ben Skeggse1ef6b42016-11-04 17:20:36 +1000115 int ret;
Ben Skeggs5e120f62012-04-30 13:55:29 +1000116
Ben Skeggse193b1d2012-07-19 10:51:42 +1000117 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000118 if (!fctx)
119 return -ENOMEM;
120
Maarten Lankhorst29ba89b2014-01-09 11:03:11 +0100121 nouveau_fence_context_new(chan, &fctx->base);
Ben Skeggs827520c2013-02-14 13:20:17 +1000122 fctx->base.emit = nv84_fence_emit;
123 fctx->base.sync = nv84_fence_sync;
124 fctx->base.read = nv84_fence_read;
125 fctx->base.emit32 = nv84_fence_emit32;
126 fctx->base.sync32 = nv84_fence_sync32;
Maarten Lankhorst29ba89b2014-01-09 11:03:11 +0100127 fctx->base.sequence = nv84_fence_read(chan);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000128
Ben Skeggs96692b02016-12-14 09:52:39 +1000129 mutex_lock(&priv->mutex);
Ben Skeggs24e83752017-11-01 03:56:19 +1000130 ret = nouveau_vma_new(priv->bo, &cli->vmm, &fctx->vma);
Ben Skeggs96692b02016-12-14 09:52:39 +1000131 mutex_unlock(&priv->mutex);
Ben Skeggsa34caf72013-02-14 09:28:37 +1000132
Ben Skeggs264ce192013-02-14 13:43:21 +1000133 if (ret)
134 nv84_fence_context_del(chan);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000135 return ret;
136}
137
Ben Skeggs264ce192013-02-14 13:43:21 +1000138static bool
Ben Skeggsa34caf72013-02-14 09:28:37 +1000139nv84_fence_suspend(struct nouveau_drm *drm)
140{
Ben Skeggsa34caf72013-02-14 09:28:37 +1000141 struct nv84_fence_priv *priv = drm->fence;
142 int i;
143
Kees Cook42bc47b2018-06-12 14:27:11 -0700144 priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan.nr));
Ben Skeggsa34caf72013-02-14 09:28:37 +1000145 if (priv->suspend) {
Ben Skeggseb47db42018-05-08 20:39:46 +1000146 for (i = 0; i < drm->chan.nr; i++)
Ben Skeggsa34caf72013-02-14 09:28:37 +1000147 priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
148 }
149
150 return priv->suspend != NULL;
151}
152
Ben Skeggs264ce192013-02-14 13:43:21 +1000153static void
Ben Skeggsa34caf72013-02-14 09:28:37 +1000154nv84_fence_resume(struct nouveau_drm *drm)
155{
Ben Skeggsa34caf72013-02-14 09:28:37 +1000156 struct nv84_fence_priv *priv = drm->fence;
157 int i;
158
159 if (priv->suspend) {
Ben Skeggseb47db42018-05-08 20:39:46 +1000160 for (i = 0; i < drm->chan.nr; i++)
Ben Skeggsa34caf72013-02-14 09:28:37 +1000161 nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
162 vfree(priv->suspend);
163 priv->suspend = NULL;
164 }
165}
166
Ben Skeggs264ce192013-02-14 13:43:21 +1000167static void
Ben Skeggsebb945a2012-07-20 08:17:34 +1000168nv84_fence_destroy(struct nouveau_drm *drm)
Ben Skeggs5e120f62012-04-30 13:55:29 +1000169{
Ben Skeggsebb945a2012-07-20 08:17:34 +1000170 struct nv84_fence_priv *priv = drm->fence;
Ben Skeggsa34caf72013-02-14 09:28:37 +1000171 nouveau_bo_unmap(priv->bo);
172 if (priv->bo)
173 nouveau_bo_unpin(priv->bo);
174 nouveau_bo_ref(NULL, &priv->bo);
Ben Skeggsebb945a2012-07-20 08:17:34 +1000175 drm->fence = NULL;
Ben Skeggs5e120f62012-04-30 13:55:29 +1000176 kfree(priv);
177}
178
179int
Ben Skeggsebb945a2012-07-20 08:17:34 +1000180nv84_fence_create(struct nouveau_drm *drm)
Ben Skeggs5e120f62012-04-30 13:55:29 +1000181{
Ben Skeggs5e120f62012-04-30 13:55:29 +1000182 struct nv84_fence_priv *priv;
Alexandre Courboteaecf032015-02-20 18:22:59 +0900183 u32 domain;
Ben Skeggs5e120f62012-04-30 13:55:29 +1000184 int ret;
185
Ben Skeggsebb945a2012-07-20 08:17:34 +1000186 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000187 if (!priv)
188 return -ENOMEM;
189
Ben Skeggse193b1d2012-07-19 10:51:42 +1000190 priv->base.dtor = nv84_fence_destroy;
Ben Skeggsa34caf72013-02-14 09:28:37 +1000191 priv->base.suspend = nv84_fence_suspend;
192 priv->base.resume = nv84_fence_resume;
Ben Skeggse193b1d2012-07-19 10:51:42 +1000193 priv->base.context_new = nv84_fence_context_new;
194 priv->base.context_del = nv84_fence_context_del;
Ben Skeggs5e120f62012-04-30 13:55:29 +1000195
Ben Skeggse18c0802013-01-31 14:57:33 +1000196 priv->base.uevent = true;
197
Ben Skeggs96692b02016-12-14 09:52:39 +1000198 mutex_init(&priv->mutex);
199
Alexandre Courboteaecf032015-02-20 18:22:59 +0900200 /* Use VRAM if there is any ; otherwise fallback to system memory */
Ben Skeggs1167c6b2016-05-18 13:57:42 +1000201 domain = drm->client.device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
Alexandre Courboteaecf032015-02-20 18:22:59 +0900202 /*
203 * fences created in sysmem must be non-cached or we
204 * will lose CPU/GPU coherency!
205 */
206 TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED;
Ben Skeggseb47db42018-05-08 20:39:46 +1000207 ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0,
Ben Skeggsbab7cc12016-05-24 17:26:48 +1000208 domain, 0, 0, NULL, NULL, &priv->bo);
Ben Skeggsa34caf72013-02-14 09:28:37 +1000209 if (ret == 0) {
Alexandre Courboteaecf032015-02-20 18:22:59 +0900210 ret = nouveau_bo_pin(priv->bo, domain, false);
Ben Skeggsa34caf72013-02-14 09:28:37 +1000211 if (ret == 0) {
212 ret = nouveau_bo_map(priv->bo);
213 if (ret)
214 nouveau_bo_unpin(priv->bo);
215 }
216 if (ret)
217 nouveau_bo_ref(NULL, &priv->bo);
218 }
219
Ben Skeggs5e120f62012-04-30 13:55:29 +1000220 if (ret)
Ben Skeggsebb945a2012-07-20 08:17:34 +1000221 nv84_fence_destroy(drm);
Ben Skeggs5e120f62012-04-30 13:55:29 +1000222 return ret;
223}