예제 #1
0
void
nvc0_instmem_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
	struct nouveau_vm *vm = NULL;

	nvc0_instmem_suspend(dev);

	nv_wr32(dev, 0x1704, 0x00000000);
	nv_wr32(dev, 0x1714, 0x00000000);

	nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
	nouveau_gpuobj_ref(NULL, &priv->chan_pgd);

	nvc0_channel_del(&priv->bar1);
	nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
	nouveau_gpuobj_ref(NULL, &priv->bar1_pgd);

	nvc0_channel_del(&priv->bar3);
	nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL);
	nouveau_vm_ref(NULL, &vm, priv->bar3_pgd);
	nouveau_gpuobj_ref(NULL, &priv->bar3_pgd);
	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);

	dev_priv->engine.instmem.priv = NULL;
	kfree(priv);
}
예제 #2
0
void
nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
{
	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
	nouveau_vm_ref(NULL, &fpriv->vm, NULL);
	kfree(fpriv);
}
static int
nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
		 struct nouveau_channel **pchan)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
	u32  fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200;
	struct nouveau_channel *chan;
	int ret, i;

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

	ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
	if (ret) {
		nv50_channel_del(&chan);
		return ret;
	}

	ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size);
	if (ret) {
		nv50_channel_del(&chan);
		return ret;
	}

	ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 :
				      chan->ramin->pinst + pgd,
				      chan->ramin->vinst + pgd,
				      0x4000, NVOBJ_FLAG_ZERO_ALLOC,
				      &chan->vm_pd);
	if (ret) {
		nv50_channel_del(&chan);
		return ret;
	}

	for (i = 0; i < 0x4000; i += 8) {
		nv_wo32(chan->vm_pd, i + 0, 0x00000000);
		nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe);
	}

	ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
	if (ret) {
		nv50_channel_del(&chan);
		return ret;
	}

	ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 :
				      chan->ramin->pinst + fc,
				      chan->ramin->vinst + fc, 0x100,
				      NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc);
	if (ret) {
		nv50_channel_del(&chan);
		return ret;
	}

	*pchan = chan;
	return 0;
}
예제 #4
0
static void
nv50_bar_dtor(struct nouveau_object *object)
{
	struct nv50_bar_priv *priv = (void *)object;
	nouveau_gpuobj_ref(NULL, &priv->bar1);
	nouveau_vm_ref(NULL, &priv->bar1_vm, priv->pgd);
	nouveau_gpuobj_ref(NULL, &priv->bar3);
	if (priv->bar3_vm) {
		nouveau_gpuobj_ref(NULL, &priv->bar3_vm->pgt[0].obj[0]);
		nouveau_vm_ref(NULL, &priv->bar3_vm, priv->pgd);
	}
	nouveau_gpuobj_ref(NULL, &priv->pgd);
	nouveau_gpuobj_ref(NULL, &priv->pad);
	nouveau_gpuobj_ref(NULL, &priv->mem);
	nouveau_bar_destroy(&priv->base);
}
예제 #5
0
static void
nouveau_cli_destroy(struct nouveau_cli *cli)
{
	nouveau_vm_ref(NULL, &nvkm_client(&cli->base)->vm, NULL);
	nvif_client_fini(&cli->base);
	usif_client_fini(cli);
}
예제 #6
0
파일: nouveau_drm.c 프로젝트: FoundYa/linux
static void
nouveau_cli_destroy(struct nouveau_cli *cli)
{
	struct nouveau_object *client = nv_object(cli);
	nouveau_vm_ref(NULL, &cli->base.vm, NULL);
	nouveau_client_fini(&cli->base, false);
	atomic_set(&client->refcount, 1);
	nouveau_object_ref(NULL, &client);
}
void
nv50_instmem_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
	struct nouveau_channel *chan = dev_priv->channels.ptr[0];
	int i;

	NV_DEBUG(dev, "\n");

	if (!priv)
		return;

	dev_priv->ramin_available = false;

	nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);

	for (i = 0x1700; i <= 0x1710; i += 4)
		nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]);

	nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj);
	nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj);

	nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd);
	dev_priv->channels.ptr[127] = 0;
	nv50_channel_del(&dev_priv->channels.ptr[0]);

	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);

	if (drm_mm_initialized(&dev_priv->ramin_heap))
		drm_mm_takedown(&dev_priv->ramin_heap);

	dev_priv->engine.instmem.priv = NULL;
	kfree(priv);
}
예제 #8
0
static void
nvc0_channel_del(struct nouveau_channel **pchan)
{
	struct nouveau_channel *chan;

	chan = *pchan;
	*pchan = NULL;
	if (!chan)
		return;

	nouveau_vm_ref(NULL, &chan->vm, NULL);
	if (chan->ramin_heap.free_stack.next)
		drm_mm_takedown(&chan->ramin_heap);
	nouveau_gpuobj_ref(NULL, &chan->ramin);
	kfree(chan);
}
static void
nv50_channel_del(struct nouveau_channel **pchan)
{
	struct nouveau_channel *chan;

	chan = *pchan;
	*pchan = NULL;
	if (!chan)
		return;

	nouveau_gpuobj_ref(NULL, &chan->ramfc);
	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
	if (drm_mm_initialized(&chan->ramin_heap))
		drm_mm_takedown(&chan->ramin_heap);
	nouveau_gpuobj_ref(NULL, &chan->ramin);
	kfree(chan);
}
예제 #10
0
static int
nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
		 struct nouveau_channel **pchan,
		 struct nouveau_gpuobj *pgd, u64 vm_size)
{
	struct nouveau_channel *chan;
	int ret;

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

	ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
	if (ret) {
		nvc0_channel_del(&chan);
		return ret;
	}

	ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000);
	if (ret) {
		nvc0_channel_del(&chan);
		return ret;
	}

	ret = nouveau_vm_ref(vm, &chan->vm, NULL);
	if (ret) {
		nvc0_channel_del(&chan);
		return ret;
	}

	nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst));
	nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst));
	nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1));
	nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1));

	*pchan = chan;
	return 0;
}
예제 #11
0
int
nvc0_instmem_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
	struct pci_dev *pdev = dev->pdev;
	struct nvc0_instmem_priv *priv;
	struct nouveau_vm *vm = NULL;
	int ret;

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

	/* BAR3 VM */
	ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0,
			     &dev_priv->bar3_vm);
	if (ret)
		goto error;

	ret = nouveau_gpuobj_new(dev, NULL,
				 (pci_resource_len(pdev, 3) >> 12) * 8, 0,
				 NVOBJ_FLAG_DONT_MAP |
				 NVOBJ_FLAG_ZERO_ALLOC,
				 &dev_priv->bar3_vm->pgt[0].obj[0]);
	if (ret)
		goto error;
	dev_priv->bar3_vm->pgt[0].refcount[0] = 1;

	nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);

	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
				 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd);
	if (ret)
		goto error;

	ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd);
	if (ret)
		goto error;
	nouveau_vm_ref(NULL, &vm, NULL);

	ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3,
			       priv->bar3_pgd, pci_resource_len(dev->pdev, 3));
	if (ret)
		goto error;

	/* BAR1 VM */
	ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm);
	if (ret)
		goto error;

	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
				 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd);
	if (ret)
		goto error;

	ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd);
	if (ret)
		goto error;
	nouveau_vm_ref(NULL, &vm, NULL);

	ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1,
			       priv->bar1_pgd, pci_resource_len(dev->pdev, 1));
	if (ret)
		goto error;

	/* channel vm */
	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
	if (ret)
		goto error;

	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
	if (ret)
		goto error;

	nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
	nouveau_vm_ref(NULL, &vm, NULL);

	nvc0_instmem_resume(dev);
	return 0;
error:
	nvc0_instmem_takedown(dev);
	return ret;
}
예제 #12
0
파일: nvc0.c 프로젝트: 174high/dell-driver
static int
nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
	      struct nouveau_oclass *oclass, void *data, u32 size,
	      struct nouveau_object **pobject)
{
	struct nouveau_device *device = nv_device(parent);
	struct pci_dev *pdev = device->pdev;
	struct nvc0_bar_priv *priv;
	struct nouveau_gpuobj *mem;
	struct nouveau_vm *vm;
	int ret;

	ret = nouveau_bar_create(parent, engine, oclass, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	/* BAR3 */
	ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[0].mem);
	mem = priv->bar[0].mem;
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[0].pgd);
	if (ret)
		return ret;

	ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(parent, NULL,
				 (pci_resource_len(pdev, 3) >> 12) * 8,
				 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
				 &vm->pgt[0].obj[0]);
	vm->pgt[0].refcount[0] = 1;
	if (ret)
		return ret;

	ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd);
	nouveau_vm_ref(NULL, &vm, NULL);
	if (ret)
		return ret;

	nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
	nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
	nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1));
	nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1));

	/* BAR1 */
	ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[1].mem);
	mem = priv->bar[1].mem;
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[1].pgd);
	if (ret)
		return ret;

	ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm);
	if (ret)
		return ret;

	ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd);
	nouveau_vm_ref(NULL, &vm, NULL);
	if (ret)
		return ret;

	nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
	nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
	nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1));
	nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1));

	priv->base.alloc = nouveau_bar_alloc;
	priv->base.kmap = nvc0_bar_kmap;
	priv->base.umap = nvc0_bar_umap;
	priv->base.unmap = nvc0_bar_unmap;
	priv->base.flush = nv84_bar_flush;
	spin_lock_init(&priv->lock);
	return 0;
}
예제 #13
0
static int
nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
	      struct nouveau_oclass *oclass, void *data, u32 size,
	      struct nouveau_object **pobject)
{
	struct nouveau_device *device = nv_device(parent);
	struct nouveau_object *heap;
	struct nouveau_vm *vm;
	struct nv50_bar_priv *priv;
	u64 start, limit;
	int ret;

	ret = nouveau_bar_create(parent, engine, oclass, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x20000, 0,
				 NVOBJ_FLAG_HEAP, &priv->mem);
	heap = nv_object(priv->mem);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(nv_object(priv), heap,
				(device->chipset == 0x50) ? 0x1400 : 0x0200,
				 0, 0, &priv->pad);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(nv_object(priv), heap, 0x4000, 0,
				 0, &priv->pgd);
	if (ret)
		return ret;

	/* BAR3 */
	start = 0x0100000000ULL;
	limit = start + nv_device_resource_len(device, 3);

	ret = nouveau_vm_new(device, start, limit, start, &vm);
	if (ret)
		return ret;

	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);

	ret = nouveau_gpuobj_new(nv_object(priv), heap,
				 ((limit-- - start) >> 12) * 8, 0x1000,
				 NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]);
	vm->pgt[0].refcount[0] = 1;
	if (ret)
		return ret;

	ret = nouveau_vm_ref(vm, &priv->bar3_vm, priv->pgd);
	nouveau_vm_ref(NULL, &vm, NULL);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar3);
	if (ret)
		return ret;

	nv_wo32(priv->bar3, 0x00, 0x7fc00000);
	nv_wo32(priv->bar3, 0x04, lower_32_bits(limit));
	nv_wo32(priv->bar3, 0x08, lower_32_bits(start));
	nv_wo32(priv->bar3, 0x0c, upper_32_bits(limit) << 24 |
				  upper_32_bits(start));
	nv_wo32(priv->bar3, 0x10, 0x00000000);
	nv_wo32(priv->bar3, 0x14, 0x00000000);

	/* BAR1 */
	start = 0x0000000000ULL;
	limit = start + nv_device_resource_len(device, 1);

	ret = nouveau_vm_new(device, start, limit--, start, &vm);
	if (ret)
		return ret;

	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);

	ret = nouveau_vm_ref(vm, &priv->bar1_vm, priv->pgd);
	nouveau_vm_ref(NULL, &vm, NULL);
	if (ret)
		return ret;

	ret = nouveau_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar1);
	if (ret)
		return ret;

	nv_wo32(priv->bar1, 0x00, 0x7fc00000);
	nv_wo32(priv->bar1, 0x04, lower_32_bits(limit));
	nv_wo32(priv->bar1, 0x08, lower_32_bits(start));
	nv_wo32(priv->bar1, 0x0c, upper_32_bits(limit) << 24 |
				  upper_32_bits(start));
	nv_wo32(priv->bar1, 0x10, 0x00000000);
	nv_wo32(priv->bar1, 0x14, 0x00000000);

	priv->base.alloc = nouveau_bar_alloc;
	priv->base.kmap = nv50_bar_kmap;
	priv->base.umap = nv50_bar_umap;
	priv->base.unmap = nv50_bar_unmap;
	if (device->chipset == 0x50)
		priv->base.flush = nv50_bar_flush;
	else
		priv->base.flush = nv84_bar_flush;
	spin_lock_init(&priv->lock);
	return 0;
}
예제 #14
0
int
nv50_instmem_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nv50_instmem_priv *priv;
	struct nouveau_channel *chan;
	struct nouveau_vm *vm;
	int ret, i;
	u32 tmp;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	dev_priv->engine.instmem.priv = priv;

	/*                                       */
	for (i = 0x1700; i <= 0x1710; i += 4)
		priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i);

	/*                    */
	ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size);
	if (ret) {
		NV_ERROR(dev, "Failed to init RAMIN heap\n");
		goto error;
	}

	/*      */
	ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE,
			     &dev_priv->bar3_vm);
	if (ret)
		goto error;

	ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8,
				 0x1000, NVOBJ_FLAG_DONT_MAP |
				 NVOBJ_FLAG_ZERO_ALLOC,
				 &dev_priv->bar3_vm->pgt[0].obj[0]);
	if (ret)
		goto error;
	dev_priv->bar3_vm->pgt[0].refcount[0] = 1;

	nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);

	ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan);
	if (ret)
		goto error;
	dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan;

	ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE,
				  NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
				  NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
				  &priv->bar3_dmaobj);
	if (ret)
		goto error;

	nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12));
	nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12));
	nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4));

	dev_priv->engine.instmem.flush(dev);
	dev_priv->ramin_available = true;

	tmp = nv_ro32(chan->ramin, 0);
	nv_wo32(chan->ramin, 0, ~tmp);
	if (nv_ro32(chan->ramin, 0) != ~tmp) {
		NV_ERROR(dev, "PRAMIN readback failed\n");
		ret = -EIO;
		goto error;
	}
	nv_wo32(chan->ramin, 0, tmp);

	/*      */
	ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm);
	if (ret)
		goto error;

	ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd);
	if (ret)
		goto error;
	nouveau_vm_ref(NULL, &vm, NULL);

	ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE,
				  NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
				  NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
				  &priv->bar1_dmaobj);
	if (ret)
		goto error;

	nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4));
	for (i = 0; i < 8; i++)
		nv_wr32(dev, 0x1900 + (i*4), 0);

	/*                                                             
                                      
  */
	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
			     &dev_priv->chan_vm);
	if (ret)
		return ret;

	return 0;

error:
	nv50_instmem_takedown(dev);
	return ret;
}