[go: nahoru, domu]

15e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs/*
25e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * Copyright 2012 Red Hat Inc.
35e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs *
45e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
55e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * copy of this software and associated documentation files (the "Software"),
65e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * to deal in the Software without restriction, including without limitation
75e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the
95e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * Software is furnished to do so, subject to the following conditions:
105e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs *
115e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * The above copyright notice and this permission notice shall be included in
125e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * all copies or substantial portions of the Software.
135e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs *
145e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
185e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
195e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
205e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE.
215e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs *
225e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs * Authors: Ben Skeggs
235e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs */
245e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
25ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs#include "nouveau_drm.h"
26ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs#include "nouveau_dma.h"
275e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs#include "nouveau_fence.h"
285e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
2977145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs#include "nv50_display.h"
3077145f1cbdf8d28b46ff8070ca749bad821e0774Ben Skeggs
31a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggsu64
32a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggsnv84_fence_crtc(struct nouveau_channel *chan, int crtc)
33a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs{
34a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	struct nv84_fence_chan *fctx = chan->fence;
35a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	return fctx->dispc_vma[crtc].offset;
36a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs}
375e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
385e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggsstatic int
39bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggsnv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
405e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
41bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs	int ret = RING_SPACE(chan, 8);
425e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	if (ret == 0) {
435e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
440ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs		OUT_RING  (chan, chan->vram.handle);
45e18c080fb8695d038f69c26c248f5ecbd9e8aa77Ben Skeggs		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
46bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, upper_32_bits(virtual));
47bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, lower_32_bits(virtual));
48bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, sequence);
495e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
50e18c080fb8695d038f69c26c248f5ecbd9e8aa77Ben Skeggs		OUT_RING  (chan, 0x00000000);
515e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		FIRE_RING (chan);
525e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	}
535e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	return ret;
545e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
555e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
565e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggsstatic int
57bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggsnv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
585e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
59bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs	int ret = RING_SPACE(chan, 7);
605e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	if (ret == 0) {
615e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
620ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs		OUT_RING  (chan, chan->vram.handle);
635e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
64bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, upper_32_bits(virtual));
65bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, lower_32_bits(virtual));
66bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		OUT_RING  (chan, sequence);
675e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL);
685e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		FIRE_RING (chan);
695e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	}
705e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	return ret;
715e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
725e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
73264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic int
74bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggsnv84_fence_emit(struct nouveau_fence *fence)
75bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs{
76bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs	struct nouveau_channel *chan = fence->channel;
77bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs	struct nv84_fence_chan *fctx = chan->fence;
78bbf8906b2cad17cf9530b06db7509d0e39b02d16Ben Skeggs	u64 addr = chan->chid * 16;
79264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs
80264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (fence->sysmem)
81264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		addr += fctx->vma_gart.offset;
82264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	else
83264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		addr += fctx->vma.offset;
84264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs
8529ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	return fctx->base.emit32(chan, addr, fence->base.seqno);
86bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs}
87bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs
88264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic int
89bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggsnv84_fence_sync(struct nouveau_fence *fence,
90bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs		struct nouveau_channel *prev, struct nouveau_channel *chan)
91bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs{
92bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs	struct nv84_fence_chan *fctx = chan->fence;
93bbf8906b2cad17cf9530b06db7509d0e39b02d16Ben Skeggs	u64 addr = prev->chid * 16;
94264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs
95264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (fence->sysmem)
96264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		addr += fctx->vma_gart.offset;
97264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	else
98264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		addr += fctx->vma.offset;
99264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs
10029ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	return fctx->base.sync32(chan, addr, fence->base.seqno);
101bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs}
102bba9852feedf3d38f963278e07bdd3db622090b9Ben Skeggs
103264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic u32
1045e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggsnv84_fence_read(struct nouveau_channel *chan)
1055e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
106ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs	struct nv84_fence_priv *priv = chan->drm->fence;
107bbf8906b2cad17cf9530b06db7509d0e39b02d16Ben Skeggs	return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
1085e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
1095e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
110264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic void
111e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggsnv84_fence_context_del(struct nouveau_channel *chan)
1125e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
113a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	struct drm_device *dev = chan->drm->dev;
114a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	struct nv84_fence_priv *priv = chan->drm->fence;
115e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	struct nv84_fence_chan *fctx = chan->fence;
116a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	int i;
117a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
118a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	for (i = 0; i < dev->mode_config.num_crtc; i++) {
119a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
120a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
121a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	}
122a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
1231dadba87cba20989c5a5a56f2a86fe6672e37c30Maarten Lankhorst	nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
124264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
125a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	nouveau_bo_vma_del(priv->bo, &fctx->vma);
1265e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	nouveau_fence_context_del(&fctx->base);
127e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	chan->fence = NULL;
12815a996bbb6978ae21c497aeadfe20deca6ddd07aMaarten Lankhorst	nouveau_fence_context_free(&fctx->base);
1295e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
1305e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
131a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggsint
132e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggsnv84_fence_context_new(struct nouveau_channel *chan)
1335e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
1340ad72863ea426d46b2786cba9430e122a40aad0bBen Skeggs	struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
135ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs	struct nv84_fence_priv *priv = chan->drm->fence;
1365e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	struct nv84_fence_chan *fctx;
137f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	int ret, i;
1385e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
139e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
1405e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	if (!fctx)
1415e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		return -ENOMEM;
1425e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
14329ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	nouveau_fence_context_new(chan, &fctx->base);
144827520ce06568f699dad275dcca61647cce08757Ben Skeggs	fctx->base.emit = nv84_fence_emit;
145827520ce06568f699dad275dcca61647cce08757Ben Skeggs	fctx->base.sync = nv84_fence_sync;
146827520ce06568f699dad275dcca61647cce08757Ben Skeggs	fctx->base.read = nv84_fence_read;
147827520ce06568f699dad275dcca61647cce08757Ben Skeggs	fctx->base.emit32 = nv84_fence_emit32;
148827520ce06568f699dad275dcca61647cce08757Ben Skeggs	fctx->base.sync32 = nv84_fence_sync32;
14929ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	fctx->base.sequence = nv84_fence_read(chan);
1505e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
1513ee6f5b5036be4fd4e64be4233f29ee1c552c005Ben Skeggs	ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
152264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (ret == 0) {
1533ee6f5b5036be4fd4e64be4233f29ee1c552c005Ben Skeggs		ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
154264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs					&fctx->vma_gart);
155264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	}
156ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs
157a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	/* map display semaphore buffers into channel's vm */
158a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
159a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
1603ee6f5b5036be4fd4e64be4233f29ee1c552c005Ben Skeggs		ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
161f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs	}
162f589be88caf32501a734e531180d5df5d6089ef3Ben Skeggs
163264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (ret)
164264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		nv84_fence_context_del(chan);
1655e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	return ret;
1665e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
1675e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
168264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic bool
169a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggsnv84_fence_suspend(struct nouveau_drm *drm)
170a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs{
171a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	struct nv84_fence_priv *priv = drm->fence;
172a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	int i;
173a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
17429ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	priv->suspend = vmalloc(priv->base.contexts * sizeof(u32));
175a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	if (priv->suspend) {
17629ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst		for (i = 0; i < priv->base.contexts; i++)
177a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs			priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
178a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	}
179a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
180a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	return priv->suspend != NULL;
181a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs}
182a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
183264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic void
184a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggsnv84_fence_resume(struct nouveau_drm *drm)
185a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs{
186a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	struct nv84_fence_priv *priv = drm->fence;
187a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	int i;
188a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
189a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	if (priv->suspend) {
19029ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst		for (i = 0; i < priv->base.contexts; i++)
191a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs			nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
192a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		vfree(priv->suspend);
193a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		priv->suspend = NULL;
194a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	}
195a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs}
196a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
197264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggsstatic void
198ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggsnv84_fence_destroy(struct nouveau_drm *drm)
1995e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
200ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs	struct nv84_fence_priv *priv = drm->fence;
201264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	nouveau_bo_unmap(priv->bo_gart);
202264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (priv->bo_gart)
203264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		nouveau_bo_unpin(priv->bo_gart);
204264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	nouveau_bo_ref(NULL, &priv->bo_gart);
205a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	nouveau_bo_unmap(priv->bo);
206a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	if (priv->bo)
207a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		nouveau_bo_unpin(priv->bo);
208a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	nouveau_bo_ref(NULL, &priv->bo);
209ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs	drm->fence = NULL;
2105e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	kfree(priv);
2115e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
2125e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
2135e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggsint
214ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggsnv84_fence_create(struct nouveau_drm *drm)
2155e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs{
216967e7bde8739fe3b215f7537e8f1f39c044902afBen Skeggs	struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
2175e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	struct nv84_fence_priv *priv;
2185e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	int ret;
2195e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
220ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs	priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
2215e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	if (!priv)
2225e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs		return -ENOMEM;
2235e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
224e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	priv->base.dtor = nv84_fence_destroy;
225a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	priv->base.suspend = nv84_fence_suspend;
226a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	priv->base.resume = nv84_fence_resume;
227e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	priv->base.context_new = nv84_fence_context_new;
228e193b1d42c390bf1bff7fa02a5a1202b98e75601Ben Skeggs	priv->base.context_del = nv84_fence_context_del;
2295e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs
23029ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	priv->base.contexts = pfifo->max + 1;
23129ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	priv->base.context_base = fence_context_alloc(priv->base.contexts);
232e18c080fb8695d038f69c26c248f5ecbd9e8aa77Ben Skeggs	priv->base.uevent = true;
233e18c080fb8695d038f69c26c248f5ecbd9e8aa77Ben Skeggs
23429ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst	ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
235bb6178b04f5ef6f62990306713fb6afdf5d8bc56Maarten Lankhorst			     TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo);
236a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	if (ret == 0) {
237a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
238a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		if (ret == 0) {
239a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs			ret = nouveau_bo_map(priv->bo);
240a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs			if (ret)
241a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs				nouveau_bo_unpin(priv->bo);
242a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		}
243a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs		if (ret)
244a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs			nouveau_bo_ref(NULL, &priv->bo);
245a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs	}
246a34caf78f26bda63869471cb3f46f354f4658758Ben Skeggs
247264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (ret == 0)
24829ba89b2371d466ca68973525816cf10debc2655Maarten Lankhorst		ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
249bb6178b04f5ef6f62990306713fb6afdf5d8bc56Maarten Lankhorst				     TTM_PL_FLAG_TT, 0, 0, NULL, NULL,
250264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs				     &priv->bo_gart);
251264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	if (ret == 0) {
252264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT);
253264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		if (ret == 0) {
254264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs			ret = nouveau_bo_map(priv->bo_gart);
255264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs			if (ret)
256264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs				nouveau_bo_unpin(priv->bo_gart);
257264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		}
258264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs		if (ret)
259264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs			nouveau_bo_ref(NULL, &priv->bo_gart);
260264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs	}
261264ce192b3e7f45d0adb37bfbab2b01a3fbe6c30Ben Skeggs
2625e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	if (ret)
263ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69Ben Skeggs		nv84_fence_destroy(drm);
2645e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs	return ret;
2655e120f6e4b3f35b741c5445dfc755f50128c3c44Ben Skeggs}
266