예제 #1
0
void
nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
              int delta, int length)
{
    struct nouveau_bo *pb = chan->push.buffer;
    struct nouveau_vma *vma;
    int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
    u64 offset;

    vma = nouveau_bo_vma_find(bo, nv_client(chan->cli)->vm);
    BUG_ON(!vma);
    offset = vma->offset + delta;

    BUG_ON(chan->dma.ib_free < 1);

    nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
    nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);

    chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;

    mb();
    /* Flush writes. */
    nouveau_bo_rd32(pb, 0);

    nv_wo32(chan->object, 0x8c, chan->dma.ib_put);
    chan->dma.ib_free--;
}
예제 #2
0
static int
nouveau_fbcon_sync(struct fb_info *info)
{
	struct nouveau_fbdev *nfbdev = info->par;
	struct drm_device *dev = nfbdev->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->channel;
	int ret, i;

	if (!chan || !chan->accel_done || in_interrupt() ||
	    info->state != FBINFO_STATE_RUNNING ||
	    info->flags & FBINFO_HWACCEL_DISABLED)
		return 0;

	if (!mutex_trylock(&chan->mutex))
		return 0;

	ret = RING_SPACE(chan, 4);
	if (ret) {
		mutex_unlock(&chan->mutex);
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	if (dev_priv->card_type >= NV_C0) {
		BEGIN_NVC0(chan, 2, NvSub2D, 0x010c, 1);
		OUT_RING  (chan, 0);
		BEGIN_NVC0(chan, 2, NvSub2D, 0x0100, 1);
		OUT_RING  (chan, 0);
	} else {
		BEGIN_RING(chan, 0, 0x0104, 1);
		OUT_RING  (chan, 0);
		BEGIN_RING(chan, 0, 0x0100, 1);
		OUT_RING  (chan, 0);
	}

	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3, 0xffffffff);
	FIRE_RING(chan);
	mutex_unlock(&chan->mutex);

	ret = -EBUSY;
	for (i = 0; i < 100000; i++) {
		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3)) {
			ret = 0;
			break;
		}
		DRM_UDELAY(1);
	}

	if (ret) {
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	chan->accel_done = false;
	return 0;
}
예제 #3
0
파일: nv84_fence.c 프로젝트: 020gzh/linux
static void
nv84_fence_resume(struct nouveau_drm *drm)
{
	struct nv84_fence_priv *priv = drm->fence;
	int i;

	if (priv->suspend) {
		for (i = 0; i < priv->base.contexts; i++)
			nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
		vfree(priv->suspend);
		priv->suspend = NULL;
	}
}
예제 #4
0
static void
nv84_fence_resume(struct nouveau_drm *drm)
{
	struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
	struct nv84_fence_priv *priv = drm->fence;
	int i;

	if (priv->suspend) {
		for (i = 0; i <= pfifo->max; i++)
			nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
		vfree(priv->suspend);
		priv->suspend = NULL;
	}
}
예제 #5
0
파일: nouveau_dma.c 프로젝트: Lyude/linux
void
nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
{
	struct nvif_user *user = &chan->drm->client.device.user;
	struct nouveau_bo *pb = chan->push.buffer;
	int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;

	BUG_ON(chan->dma.ib_free < 1);

	nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
	nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);

	chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;

	mb();
	/* Flush writes. */
	nouveau_bo_rd32(pb, 0);

	nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
	if (user->func && user->func->doorbell)
		user->func->doorbell(user, chan->chid);
	chan->dma.ib_free--;
}
예제 #6
0
static void
nv84_fence_context_del(struct nouveau_channel *chan)
{
	struct nv84_fence_priv *priv = chan->drm->fence;
	struct nv84_fence_chan *fctx = chan->fence;

	nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
	mutex_lock(&priv->mutex);
	nouveau_vma_del(&fctx->vma);
	mutex_unlock(&priv->mutex);
	nouveau_fence_context_del(&fctx->base);
	chan->fence = NULL;
	nouveau_fence_context_free(&fctx->base);
}
예제 #7
0
파일: nouveau_fbcon.c 프로젝트: wucan/pscnv
static int
nouveau_fbcon_sync(struct fb_info *info)
{
#if 0
	struct nouveau_fbdev *nfbdev = info->par;
	struct drm_device *dev = nfbdev->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->channel;
	int ret, i;

	if (!chan || !chan->accel_done ||
	    info->state != FBINFO_STATE_RUNNING ||
	    info->flags & FBINFO_HWACCEL_DISABLED)
		return 0;

	if (RING_SPACE(chan, 4)) {
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	BEGIN_RING(chan, 0, 0x0104, 1);
	OUT_RING(chan, 0);
	BEGIN_RING(chan, 0, 0x0100, 1);
	OUT_RING(chan, 0);
	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
	FIRE_RING(chan);

	ret = -EBUSY;
	for (i = 0; i < 100000; i++) {
		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) {
			ret = 0;
			break;
		}
		DRM_UDELAY(1);
	}

	if (ret) {
		nouveau_fbcon_gpu_lockup(info);
		return 0;
	}

	chan->accel_done = false;
#endif
	return 0;
}
예제 #8
0
int
nv10_fence_create(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nv10_fence_priv *priv;
	int ret = 0;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->base.engine.destroy = nv10_fence_destroy;
	priv->base.engine.init = nv10_fence_init;
	priv->base.engine.fini = nv10_fence_fini;
	priv->base.engine.context_new = nv10_fence_context_new;
	priv->base.engine.context_del = nv10_fence_context_del;
	priv->base.emit = nv10_fence_emit;
	priv->base.read = nv10_fence_read;
	priv->base.sync = nv10_fence_sync;
	dev_priv->eng[NVOBJ_ENGINE_FENCE] = &priv->base.engine;
	spin_lock_init(&priv->lock);

	if (dev_priv->chipset >= 0x17) {
		ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
				     0, 0x0000, NULL, &priv->bo);
		if (!ret) {
			ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
			if (!ret)
				ret = nouveau_bo_map(priv->bo);
			if (ret)
				nouveau_bo_ref(NULL, &priv->bo);
		}

		if (ret == 0) {
			nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
			priv->base.sync = nv17_fence_sync;
		}
	}

	if (ret)
		nv10_fence_destroy(dev, NVOBJ_ENGINE_FENCE);
	return ret;
}
예제 #9
0
파일: nv84_fence.c 프로젝트: 020gzh/linux
static void
nv84_fence_context_del(struct nouveau_channel *chan)
{
	struct drm_device *dev = chan->drm->dev;
	struct nv84_fence_priv *priv = chan->drm->fence;
	struct nv84_fence_chan *fctx = chan->fence;
	int i;

	for (i = 0; i < dev->mode_config.num_crtc; i++) {
		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
		nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
	}

	nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
	nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
	nouveau_bo_vma_del(priv->bo, &fctx->vma);
	nouveau_fence_context_del(&fctx->base);
	chan->fence = NULL;
	nouveau_fence_context_free(&fctx->base);
}
예제 #10
0
int
nv84_fence_context_new(struct nouveau_channel *chan)
{
	struct nouveau_fifo_chan *fifo = (void *)chan->object;
	struct nouveau_client *client = nouveau_client(fifo);
	struct nv84_fence_priv *priv = chan->drm->fence;
	struct nv84_fence_chan *fctx;
	int ret, i;

	fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
	if (!fctx)
		return -ENOMEM;

	nouveau_fence_context_new(&fctx->base);
	fctx->base.emit = nv84_fence_emit;
	fctx->base.sync = nv84_fence_sync;
	fctx->base.read = nv84_fence_read;
	fctx->base.emit32 = nv84_fence_emit32;
	fctx->base.sync32 = nv84_fence_sync32;

	ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
	if (ret == 0) {
		ret = nouveau_bo_vma_add(priv->bo_gart, client->vm,
					&fctx->vma_gart);
	}

	/* map display semaphore buffers into channel's vm */
	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
		struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
		ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]);
	}

	nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);

	if (ret)
		nv84_fence_context_del(chan);
	return ret;
}