Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs <bskeggs@redhat.com>
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 }