summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_chan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_chan.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c123
1 files changed, 66 insertions, 57 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 0589babc506e..ff5e59db49db 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -24,6 +24,7 @@
#include <nvif/os.h>
#include <nvif/class.h>
+#include <nvif/ioctl.h>
/*XXX*/
#include <core/client.h>
@@ -42,20 +43,26 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
int
nouveau_channel_idle(struct nouveau_channel *chan)
{
- struct nouveau_cli *cli = (void *)nvif_client(chan->object);
- struct nouveau_fence *fence = NULL;
- int ret;
+ if (likely(chan && chan->fence)) {
+ struct nouveau_cli *cli = (void *)chan->user.client;
+ struct nouveau_fence *fence = NULL;
+ int ret;
+
+ ret = nouveau_fence_new(chan, false, &fence);
+ if (!ret) {
+ ret = nouveau_fence_wait(fence, false, false);
+ nouveau_fence_unref(&fence);
+ }
- ret = nouveau_fence_new(chan, false, &fence);
- if (!ret) {
- ret = nouveau_fence_wait(fence, false, false);
- nouveau_fence_unref(&fence);
+ if (ret) {
+ NV_PRINTK(err, cli, "failed to idle channel "
+ "0x%08x [%s]\n",
+ chan->user.handle,
+ nvxx_client(&cli->base)->name);
+ return ret;
+ }
}
-
- if (ret)
- NV_PRINTK(error, cli, "failed to idle channel 0x%08x [%s]\n",
- chan->object->handle, nvxx_client(&cli->base)->name);
- return ret;
+ return 0;
}
void
@@ -63,21 +70,18 @@ nouveau_channel_del(struct nouveau_channel **pchan)
{
struct nouveau_channel *chan = *pchan;
if (chan) {
- if (chan->fence) {
- nouveau_channel_idle(chan);
+ if (chan->fence)
nouveau_fence(chan->drm)->context_del(chan);
- }
nvif_object_fini(&chan->nvsw);
nvif_object_fini(&chan->gart);
nvif_object_fini(&chan->vram);
- nvif_object_ref(NULL, &chan->object);
+ nvif_object_fini(&chan->user);
nvif_object_fini(&chan->push.ctxdma);
nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma);
nouveau_bo_unmap(chan->push.buffer);
if (chan->push.buffer && chan->push.buffer->pin_refcnt)
nouveau_bo_unpin(chan->push.buffer);
nouveau_bo_ref(NULL, &chan->push.buffer);
- nvif_device_ref(NULL, &chan->device);
kfree(chan);
}
*pchan = NULL;
@@ -87,7 +91,7 @@ static int
nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
u32 handle, u32 size, struct nouveau_channel **pchan)
{
- struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+ struct nouveau_cli *cli = (void *)device->object.client;
struct nvkm_mmu *mmu = nvxx_mmu(device);
struct nv_dma_v0 args = {};
struct nouveau_channel *chan;
@@ -98,7 +102,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
if (!chan)
return -ENOMEM;
- nvif_device_ref(device, &chan->device);
+ chan->device = device;
chan->drm = drm;
/* allocate memory for dma push buffer */
@@ -146,7 +150,8 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
*/
args.target = NV_DMA_V0_TARGET_PCI;
args.access = NV_DMA_V0_ACCESS_RDWR;
- args.start = nv_device_resource_start(nvxx_device(device), 1);
+ args.start = nvxx_device(device)->func->
+ resource_addr(nvxx_device(device), 1);
args.limit = args.start + device->info.ram_user - 1;
} else {
args.target = NV_DMA_V0_TARGET_VRAM;
@@ -155,7 +160,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
args.limit = device->info.ram_user - 1;
}
} else {
- if (chan->drm->agp.stat == ENABLED) {
+ if (chan->drm->agp.bridge) {
args.target = NV_DMA_V0_TARGET_AGP;
args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = chan->drm->agp.base;
@@ -169,7 +174,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
}
}
- ret = nvif_object_init(nvif_object(device), NULL, NVDRM_PUSH |
+ ret = nvif_object_init(&device->object, NVDRM_PUSH |
(handle & 0xffff), NV_DMA_FROM_MEMORY,
&args, sizeof(args), &chan->push.ctxdma);
if (ret) {
@@ -193,8 +198,9 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
const u16 *oclass = oclasses;
union {
struct nv50_channel_gpfifo_v0 nv50;
+ struct fermi_channel_gpfifo_v0 fermi;
struct kepler_channel_gpfifo_a_v0 kepler;
- } args, *retn;
+ } args;
struct nouveau_channel *chan;
u32 size;
int ret;
@@ -210,26 +216,36 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
args.kepler.version = 0;
args.kepler.engine = engine;
- args.kepler.pushbuf = chan->push.ctxdma.handle;
args.kepler.ilength = 0x02000;
args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
+ args.kepler.vm = 0;
size = sizeof(args.kepler);
+ } else
+ if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
+ args.fermi.version = 0;
+ args.fermi.ilength = 0x02000;
+ args.fermi.ioffset = 0x10000 + chan->push.vma.offset;
+ args.fermi.vm = 0;
+ size = sizeof(args.fermi);
} else {
args.nv50.version = 0;
- args.nv50.pushbuf = chan->push.ctxdma.handle;
args.nv50.ilength = 0x02000;
args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
+ args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
+ args.nv50.vm = 0;
size = sizeof(args.nv50);
}
- ret = nvif_object_new(nvif_object(device), handle, *oclass++,
- &args, size, &chan->object);
+ ret = nvif_object_init(&device->object, handle, *oclass++,
+ &args, size, &chan->user);
if (ret == 0) {
- retn = chan->object->data;
- if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A)
- chan->chid = retn->kepler.chid;
+ if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A)
+ chan->chid = args.kepler.chid;
+ else
+ if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO)
+ chan->chid = args.fermi.chid;
else
- chan->chid = retn->nv50.chid;
+ chan->chid = args.nv50.chid;
return ret;
}
} while (*oclass);
@@ -248,7 +264,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
NV03_CHANNEL_DMA,
0 };
const u16 *oclass = oclasses;
- struct nv03_channel_dma_v0 args, *retn;
+ struct nv03_channel_dma_v0 args;
struct nouveau_channel *chan;
int ret;
@@ -260,15 +276,14 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
/* create channel object */
args.version = 0;
- args.pushbuf = chan->push.ctxdma.handle;
+ args.pushbuf = nvif_handle(&chan->push.ctxdma);
args.offset = chan->push.vma.offset;
do {
- ret = nvif_object_new(nvif_object(device), handle, *oclass++,
- &args, sizeof(args), &chan->object);
+ ret = nvif_object_init(&device->object, handle, *oclass++,
+ &args, sizeof(args), &chan->user);
if (ret == 0) {
- retn = chan->object->data;
- chan->chid = retn->chid;
+ chan->chid = args.chid;
return ret;
}
} while (ret && *oclass);
@@ -281,13 +296,12 @@ static int
nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
{
struct nvif_device *device = chan->device;
- struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+ struct nouveau_cli *cli = (void *)chan->user.client;
struct nvkm_mmu *mmu = nvxx_mmu(device);
- struct nvkm_sw_chan *swch;
struct nv_dma_v0 args = {};
int ret, i;
- nvif_object_map(chan->object);
+ nvif_object_map(&chan->user);
/* allocate dma objects to cover all allowed vram, and gart */
if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
@@ -303,9 +317,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
args.limit = device->info.ram_user - 1;
}
- ret = nvif_object_init(chan->object, NULL, vram,
- NV_DMA_IN_MEMORY, &args,
- sizeof(args), &chan->vram);
+ ret = nvif_object_init(&chan->user, vram, NV_DMA_IN_MEMORY,
+ &args, sizeof(args), &chan->vram);
if (ret)
return ret;
@@ -315,7 +328,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
args.start = 0;
args.limit = cli->vm->mmu->limit - 1;
} else
- if (chan->drm->agp.stat == ENABLED) {
+ if (chan->drm->agp.bridge) {
args.target = NV_DMA_V0_TARGET_AGP;
args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = chan->drm->agp.base;
@@ -328,15 +341,14 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
args.limit = mmu->limit - 1;
}
- ret = nvif_object_init(chan->object, NULL, gart,
- NV_DMA_IN_MEMORY, &args,
- sizeof(args), &chan->gart);
+ ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY,
+ &args, sizeof(args), &chan->gart);
if (ret)
return ret;
}
/* initialise dma tracking parameters */
- switch (chan->object->oclass & 0x00ff) {
+ switch (chan->user.oclass & 0x00ff) {
case 0x006b:
case 0x006e:
chan->user_put = 0x40;
@@ -368,15 +380,12 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
/* allocate software object class (used for fences on <= nv05) */
if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
- ret = nvif_object_init(chan->object, NULL, 0x006e, 0x006e,
+ ret = nvif_object_init(&chan->user, 0x006e,
+ NVIF_IOCTL_NEW_V0_SW_NV04,
NULL, 0, &chan->nvsw);
if (ret)
return ret;
- swch = (void *)nvxx_object(&chan->nvsw)->parent;
- swch->flip = nouveau_flip_complete;
- swch->flip_data = chan;
-
ret = RING_SPACE(chan, 2);
if (ret)
return ret;
@@ -395,7 +404,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
u32 handle, u32 arg0, u32 arg1,
struct nouveau_channel **pchan)
{
- struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+ struct nouveau_cli *cli = (void *)device->object.client;
bool super;
int ret;
@@ -405,17 +414,17 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
ret = nouveau_channel_ind(drm, device, handle, arg0, pchan);
if (ret) {
- NV_PRINTK(debug, cli, "ib channel create, %d\n", ret);
+ NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
ret = nouveau_channel_dma(drm, device, handle, pchan);
if (ret) {
- NV_PRINTK(debug, cli, "dma channel create, %d\n", ret);
+ NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
goto done;
}
}
ret = nouveau_channel_init(*pchan, arg0, arg1);
if (ret) {
- NV_PRINTK(error, cli, "channel failed to initialise, %d\n", ret);
+ NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
nouveau_channel_del(pchan);
}