0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "nouveau_drv.h"
0025 #include "nouveau_dma.h"
0026 #include "nv10_fence.h"
0027
0028 #include <nvif/push006c.h>
0029
0030 #include <nvif/class.h>
0031 #include <nvif/cl0002.h>
0032
0033 #include <nvhw/class/cl176e.h>
0034
0035 int
0036 nv17_fence_sync(struct nouveau_fence *fence,
0037 struct nouveau_channel *prev, struct nouveau_channel *chan)
0038 {
0039 struct nouveau_cli *cli = (void *)prev->user.client;
0040 struct nv10_fence_priv *priv = chan->drm->fence;
0041 struct nv10_fence_chan *fctx = chan->fence;
0042 struct nvif_push *ppush = prev->chan.push;
0043 struct nvif_push *npush = chan->chan.push;
0044 u32 value;
0045 int ret;
0046
0047 if (!mutex_trylock(&cli->mutex))
0048 return -EBUSY;
0049
0050 spin_lock(&priv->lock);
0051 value = priv->sequence;
0052 priv->sequence += 2;
0053 spin_unlock(&priv->lock);
0054
0055 ret = PUSH_WAIT(ppush, 5);
0056 if (!ret) {
0057 PUSH_MTHD(ppush, NV176E, SET_CONTEXT_DMA_SEMAPHORE, fctx->sema.handle,
0058 SEMAPHORE_OFFSET, 0,
0059 SEMAPHORE_ACQUIRE, value + 0,
0060 SEMAPHORE_RELEASE, value + 1);
0061 PUSH_KICK(ppush);
0062 }
0063
0064 if (!ret && !(ret = PUSH_WAIT(npush, 5))) {
0065 PUSH_MTHD(npush, NV176E, SET_CONTEXT_DMA_SEMAPHORE, fctx->sema.handle,
0066 SEMAPHORE_OFFSET, 0,
0067 SEMAPHORE_ACQUIRE, value + 1,
0068 SEMAPHORE_RELEASE, value + 2);
0069 PUSH_KICK(npush);
0070 }
0071
0072 mutex_unlock(&cli->mutex);
0073 return 0;
0074 }
0075
0076 static int
0077 nv17_fence_context_new(struct nouveau_channel *chan)
0078 {
0079 struct nv10_fence_priv *priv = chan->drm->fence;
0080 struct ttm_resource *reg = priv->bo->bo.resource;
0081 struct nv10_fence_chan *fctx;
0082 u32 start = reg->start * PAGE_SIZE;
0083 u32 limit = start + priv->bo->bo.base.size - 1;
0084 int ret = 0;
0085
0086 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
0087 if (!fctx)
0088 return -ENOMEM;
0089
0090 nouveau_fence_context_new(chan, &fctx->base);
0091 fctx->base.emit = nv10_fence_emit;
0092 fctx->base.read = nv10_fence_read;
0093 fctx->base.sync = nv17_fence_sync;
0094
0095 ret = nvif_object_ctor(&chan->user, "fenceCtxDma", NvSema,
0096 NV_DMA_FROM_MEMORY,
0097 &(struct nv_dma_v0) {
0098 .target = NV_DMA_V0_TARGET_VRAM,
0099 .access = NV_DMA_V0_ACCESS_RDWR,
0100 .start = start,
0101 .limit = limit,
0102 }, sizeof(struct nv_dma_v0),
0103 &fctx->sema);
0104 if (ret)
0105 nv10_fence_context_del(chan);
0106 return ret;
0107 }
0108
0109 void
0110 nv17_fence_resume(struct nouveau_drm *drm)
0111 {
0112 struct nv10_fence_priv *priv = drm->fence;
0113
0114 nouveau_bo_wr32(priv->bo, 0, priv->sequence);
0115 }
0116
0117 int
0118 nv17_fence_create(struct nouveau_drm *drm)
0119 {
0120 struct nv10_fence_priv *priv;
0121 int ret = 0;
0122
0123 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
0124 if (!priv)
0125 return -ENOMEM;
0126
0127 priv->base.dtor = nv10_fence_destroy;
0128 priv->base.resume = nv17_fence_resume;
0129 priv->base.context_new = nv17_fence_context_new;
0130 priv->base.context_del = nv10_fence_context_del;
0131 spin_lock_init(&priv->lock);
0132
0133 ret = nouveau_bo_new(&drm->client, 4096, 0x1000,
0134 NOUVEAU_GEM_DOMAIN_VRAM,
0135 0, 0x0000, NULL, NULL, &priv->bo);
0136 if (!ret) {
0137 ret = nouveau_bo_pin(priv->bo, NOUVEAU_GEM_DOMAIN_VRAM, false);
0138 if (!ret) {
0139 ret = nouveau_bo_map(priv->bo);
0140 if (ret)
0141 nouveau_bo_unpin(priv->bo);
0142 }
0143 if (ret)
0144 nouveau_bo_ref(NULL, &priv->bo);
0145 }
0146
0147 if (ret) {
0148 nv10_fence_destroy(drm);
0149 return ret;
0150 }
0151
0152 nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
0153 return ret;
0154 }