return 0;
}
-int
-nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
- uint32_t vram_h, uint32_t tt_h)
+static int
+nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
{
struct drm_device *dev = chan->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
- struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
- struct nouveau_gpuobj *vram = NULL, *tt = NULL;
+ struct nouveau_gpuobj *pgd = NULL;
+ struct nouveau_vm_pgd *vpgd;
int ret, i;
- NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
- if (dev_priv->card_type == NV_C0) {
- struct nouveau_vm_pgd *vpgd;
+ ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin);
+ if (ret)
+ return ret;
- ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
- &chan->ramin);
+ /* create page directory for this vm if none currently exists,
+ * will be destroyed automagically when last reference to the
+ * vm is removed
+ */
+ if (list_empty(&vm->pgd_list)) {
+ ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd);
if (ret)
return ret;
+ }
+ nouveau_vm_ref(vm, &chan->vm, pgd);
+ nouveau_gpuobj_ref(NULL, &pgd);
- nouveau_vm_ref(vm, &chan->vm, NULL);
+ /* point channel at vm's page directory */
+ vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
+ nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
+ nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
+ nv_wo32(chan->ramin, 0x0208, 0xffffffff);
+ nv_wo32(chan->ramin, 0x020c, 0x000000ff);
- vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
- nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
- nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
- nv_wo32(chan->ramin, 0x0208, 0xffffffff);
- nv_wo32(chan->ramin, 0x020c, 0x000000ff);
+ /* map display semaphore buffers into channel's vm */
+ for (i = 0; i < 2; i++) {
+ struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
- for (i = 0; i < 2; i++) {
- struct nv50_display_crtc *dispc =
- &nv50_display(dev)->crtc[i];
+ ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
+ &chan->dispc_vma[i]);
+ if (ret)
+ return ret;
+ }
- ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
- &chan->dispc_vma[i]);
- if (ret)
- return ret;
- }
+ return 0;
+}
- return 0;
- }
+int
+nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
+ uint32_t vram_h, uint32_t tt_h)
+{
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
+ struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
+ struct nouveau_gpuobj *vram = NULL, *tt = NULL;
+ int ret, i;
+
+ NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
+ if (dev_priv->card_type == NV_C0)
+ return nvc0_gpuobj_channel_init(chan, vm);
/* Allocate a chunk of memory for per-channel object storage */
ret = nouveau_gpuobj_channel_init_pramin(chan);
struct nouveau_channel *bar1;
struct nouveau_gpuobj *bar3_pgd;
struct nouveau_channel *bar3;
- struct nouveau_gpuobj *chan_pgd;
};
int
goto error;
/* channel vm */
- ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+ &dev_priv->chan_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:
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);
+ nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
nvc0_channel_del(&priv->bar1);
nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);