Beispiel #1
0
void
nvc0_default_flush_notify(struct nouveau_channel *chan)
{
   struct nvc0_screen *screen = chan->user_private;

   if (!screen)
      return;

   nouveau_fence_update(&screen->base, TRUE);
   nouveau_fence_next(&screen->base);
}
Beispiel #2
0
void
nv50_default_kick_notify(struct nouveau_pushbuf *push)
{
   struct nv50_screen *screen = push->user_priv;

   if (screen) {
      nouveau_fence_next(&screen->base);
      nouveau_fence_update(&screen->base, TRUE);
      if (screen->cur_ctx)
         screen->cur_ctx->state.flushed = TRUE;
   }
}
Beispiel #3
0
void
nvc0_default_kick_notify(struct nouveau_pushbuf *push)
{
    struct nvc0_screen *screen = push->user_priv;

    if (screen) {
        nouveau_fence_next(&screen->base);
        nouveau_fence_update(&screen->base, true);
        if (screen->cur_ctx)
            screen->cur_ctx->state.flushed = true;
        NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
    }
}
Beispiel #4
0
void
nouveau_channel_idle(struct nouveau_channel *chan)
{
	struct drm_device *dev = chan->dev;
	struct nouveau_fence *fence = NULL;
	int ret;

	nouveau_fence_update(chan);

	if (chan->fence.sequence != chan->fence.sequence_ack) {
		ret = nouveau_fence_new(chan, &fence, true);
		if (!ret) {
			ret = nouveau_fence_wait(fence, false, false);
			nouveau_fence_unref(&fence);
		}

		if (ret)
			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
	}
}
Beispiel #5
0
static int
nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
{
	struct nouveau_fence_chan *fctx =
		container_of(notify, typeof(*fctx), notify);
	unsigned long flags;
	int ret = NVIF_NOTIFY_KEEP;

	spin_lock_irqsave(&fctx->lock, flags);
	if (!list_empty(&fctx->pending)) {
		struct nouveau_fence *fence;
		struct nouveau_channel *chan;

		fence = list_entry(fctx->pending.next, typeof(*fence), head);
		chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
		if (nouveau_fence_update(fence->channel, fctx))
			ret = NVIF_NOTIFY_DROP;
	}
	spin_unlock_irqrestore(&fctx->lock, flags);

	return ret;
}
/* stops a fifo */
void
nouveau_channel_free(struct nouveau_channel *chan)
{
	struct drm_device *dev = chan->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
	unsigned long flags;
	int ret;

	NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id);

	nouveau_debugfs_channel_fini(chan);

	/* Give outstanding push buffers a chance to complete */
	spin_lock_irqsave(&chan->fence.lock, flags);
	nouveau_fence_update(chan);
	spin_unlock_irqrestore(&chan->fence.lock, flags);
	if (chan->fence.sequence != chan->fence.sequence_ack) {
		struct nouveau_fence *fence = NULL;

		ret = nouveau_fence_new(chan, &fence, true);
		if (ret == 0) {
			ret = nouveau_fence_wait(fence, NULL, false, false);
			nouveau_fence_unref((void *)&fence);
		}

		if (ret)
			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
	}

	/* Ensure all outstanding fences are signaled.  They should be if the
	 * above attempts at idling were OK, but if we failed this'll tell TTM
	 * we're done with the buffers.
	 */
	nouveau_fence_fini(chan);

	/* Ensure the channel is no longer active on the GPU */
	pfifo->reassign(dev, false);

	pgraph->fifo_access(dev, false);
	if (pgraph->channel(dev) == chan)
		pgraph->unload_context(dev);
	pgraph->destroy_context(chan);
	pgraph->fifo_access(dev, true);

	if (pfifo->channel_id(dev) == chan->id) {
		pfifo->disable(dev);
		pfifo->unload_context(dev);
		pfifo->enable(dev);
	}
	pfifo->destroy_context(chan);

	pfifo->reassign(dev, true);

	/* Release the channel's resources */
	nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
	if (chan->pushbuf_bo) {
		nouveau_bo_unpin(chan->pushbuf_bo);
		nouveau_bo_ref(NULL, &chan->pushbuf_bo);
	}
	nouveau_gpuobj_channel_takedown(chan);
	nouveau_notifier_takedown_channel(chan);
	if (chan->user)
		iounmap(chan->user);

	dev_priv->fifos[chan->id] = NULL;
	dev_priv->fifo_alloc_count--;
	kfree(chan);
}