summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-06-08 18:17:41 +1000
committerBen Skeggs <bskeggs@redhat.com>2011-06-23 16:01:41 +1000
commit5de8037ab466d397df17ff72382c33a908f42f6c (patch)
treed9cb70739f15d39effafa3e205557ca82b16134b
parentad9ac437a500f8c0822bd5fe139af8ee2c132e15 (diff)
drm/nvc0: enable per-client address spaces
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c74
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_instmem.c14
3 files changed, 55 insertions, 40 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 115827133bb7..542b451c81f1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -690,46 +690,64 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
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);
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 91cc2a64d8e0..50507e7e3f58 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -787,7 +787,12 @@ nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
}
} else
if (dev_priv->card_type >= NV_C0) {
- nouveau_vm_ref(dev_priv->chan_vm, &fpriv->vm, NULL);
+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+ &fpriv->vm);
+ if (ret) {
+ kfree(fpriv);
+ return ret;
+ }
}
file_priv->driver_priv = fpriv;
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
index 82357d2df1f4..b701c439c92e 100644
--- a/drivers/gpu/drm/nouveau/nvc0_instmem.c
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -32,7 +32,6 @@ struct nvc0_instmem_priv {
struct nouveau_channel *bar1;
struct nouveau_gpuobj *bar3_pgd;
struct nouveau_channel *bar3;
- struct nouveau_gpuobj *chan_pgd;
};
int
@@ -181,17 +180,11 @@ nvc0_instmem_init(struct drm_device *dev)
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:
@@ -211,8 +204,7 @@ nvc0_instmem_takedown(struct drm_device *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);
+ 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);