Commit f5650478 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/disp/nv50-: pass nvkm_memory objects for channel push buffers

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a9c44a88
...@@ -15,4 +15,6 @@ int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page, ...@@ -15,4 +15,6 @@ int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page,
int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page, int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page,
u64 size, void *argv, u32 argc, struct nvif_mem *); u64 size, void *argv, u32 argc, struct nvif_mem *);
void nvif_mem_fini(struct nvif_mem *); void nvif_mem_fini(struct nvif_mem *);
int nvif_mem_init_map(struct nvif_mmu *, u8 type, u64 size, struct nvif_mem *);
#endif #endif
...@@ -8,6 +8,7 @@ struct nvif_mmu { ...@@ -8,6 +8,7 @@ struct nvif_mmu {
u8 heap_nr; u8 heap_nr;
u8 type_nr; u8 type_nr;
u16 kind_nr; u16 kind_nr;
s32 mem;
struct { struct {
u64 size; u64 size;
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <nvif/mem.h>
#include <nvif/class.h> #include <nvif/class.h>
#include <nvif/cl0002.h> #include <nvif/cl0002.h>
#include <nvif/cl5070.h> #include <nvif/cl5070.h>
...@@ -400,7 +402,8 @@ struct nv50_dmac_ctxdma { ...@@ -400,7 +402,8 @@ struct nv50_dmac_ctxdma {
struct nv50_dmac { struct nv50_dmac {
struct nv50_chan base; struct nv50_chan base;
dma_addr_t handle;
struct nvif_mem push;
u32 *ptr; u32 *ptr;
struct nvif_object sync; struct nvif_object sync;
...@@ -482,9 +485,8 @@ nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb) ...@@ -482,9 +485,8 @@ nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb)
} }
static void static void
nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp) nv50_dmac_destroy(struct nv50_dmac *dmac)
{ {
struct nvif_device *device = dmac->base.device;
struct nv50_dmac_ctxdma *ctxdma, *ctxtmp; struct nv50_dmac_ctxdma *ctxdma, *ctxtmp;
list_for_each_entry_safe(ctxdma, ctxtmp, &dmac->ctxdma, head) { list_for_each_entry_safe(ctxdma, ctxtmp, &dmac->ctxdma, head) {
...@@ -496,10 +498,7 @@ nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp) ...@@ -496,10 +498,7 @@ nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp)
nv50_chan_destroy(&dmac->base); nv50_chan_destroy(&dmac->base);
if (dmac->ptr) { nvif_mem_fini(&dmac->push);
struct device *dev = nvxx_device(device)->dev;
dma_free_coherent(dev, PAGE_SIZE, dmac->ptr, dmac->handle);
}
} }
static int static int
...@@ -507,33 +506,24 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, ...@@ -507,33 +506,24 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf, const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf,
struct nv50_dmac *dmac) struct nv50_dmac *dmac)
{ {
struct nouveau_cli *cli = (void *)device->object.client;
struct nv50_disp_core_channel_dma_v0 *args = data; struct nv50_disp_core_channel_dma_v0 *args = data;
struct nvif_object pushbuf;
int ret; int ret;
mutex_init(&dmac->lock); mutex_init(&dmac->lock);
INIT_LIST_HEAD(&dmac->ctxdma); INIT_LIST_HEAD(&dmac->ctxdma);
dmac->ptr = dma_alloc_coherent(nvxx_device(device)->dev, PAGE_SIZE, ret = nvif_mem_init_map(&cli->mmu, NVIF_MEM_COHERENT, 0x1000,
&dmac->handle, GFP_KERNEL); &dmac->push);
if (!dmac->ptr)
return -ENOMEM;
ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY,
&(struct nv_dma_v0) {
.target = NV_DMA_V0_TARGET_PCI_US,
.access = NV_DMA_V0_ACCESS_RD,
.start = dmac->handle + 0x0000,
.limit = dmac->handle + 0x0fff,
}, sizeof(struct nv_dma_v0), &pushbuf);
if (ret) if (ret)
return ret; return ret;
args->pushbuf = nvif_handle(&pushbuf); dmac->ptr = dmac->push.object.map.ptr;
args->pushbuf = nvif_handle(&dmac->push.object);
ret = nv50_chan_create(device, disp, oclass, head, data, size, ret = nv50_chan_create(device, disp, oclass, head, data, size,
&dmac->base); &dmac->base);
nvif_object_fini(&pushbuf);
if (ret) if (ret)
return ret; return ret;
...@@ -574,9 +564,7 @@ static int ...@@ -574,9 +564,7 @@ static int
nv50_core_create(struct nvif_device *device, struct nvif_object *disp, nv50_core_create(struct nvif_device *device, struct nvif_object *disp,
u64 syncbuf, struct nv50_mast *core) u64 syncbuf, struct nv50_mast *core)
{ {
struct nv50_disp_core_channel_dma_v0 args = { struct nv50_disp_core_channel_dma_v0 args = {};
.pushbuf = 0xb0007d00,
};
static const s32 oclass[] = { static const s32 oclass[] = {
GP102_DISP_CORE_CHANNEL_DMA, GP102_DISP_CORE_CHANNEL_DMA,
GP100_DISP_CORE_CHANNEL_DMA, GP100_DISP_CORE_CHANNEL_DMA,
...@@ -612,7 +600,6 @@ nv50_base_create(struct nvif_device *device, struct nvif_object *disp, ...@@ -612,7 +600,6 @@ nv50_base_create(struct nvif_device *device, struct nvif_object *disp,
int head, u64 syncbuf, struct nv50_sync *base) int head, u64 syncbuf, struct nv50_sync *base)
{ {
struct nv50_disp_base_channel_dma_v0 args = { struct nv50_disp_base_channel_dma_v0 args = {
.pushbuf = 0xb0007c00 | head,
.head = head, .head = head,
}; };
static const s32 oclass[] = { static const s32 oclass[] = {
...@@ -643,7 +630,6 @@ nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, ...@@ -643,7 +630,6 @@ nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp,
int head, u64 syncbuf, struct nv50_ovly *ovly) int head, u64 syncbuf, struct nv50_ovly *ovly)
{ {
struct nv50_disp_overlay_channel_dma_v0 args = { struct nv50_disp_overlay_channel_dma_v0 args = {
.pushbuf = 0xb0007e00 | head,
.head = head, .head = head,
}; };
static const s32 oclass[] = { static const s32 oclass[] = {
...@@ -1472,9 +1458,8 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, ...@@ -1472,9 +1458,8 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
static void * static void *
nv50_base_dtor(struct nv50_wndw *wndw) nv50_base_dtor(struct nv50_wndw *wndw)
{ {
struct nv50_disp *disp = nv50_disp(wndw->plane.dev);
struct nv50_base *base = nv50_base(wndw); struct nv50_base *base = nv50_base(wndw);
nv50_dmac_destroy(&base->chan.base, disp->disp); nv50_dmac_destroy(&base->chan.base);
return base; return base;
} }
...@@ -2354,11 +2339,10 @@ nv50_head_reset(struct drm_crtc *crtc) ...@@ -2354,11 +2339,10 @@ nv50_head_reset(struct drm_crtc *crtc)
static void static void
nv50_head_destroy(struct drm_crtc *crtc) nv50_head_destroy(struct drm_crtc *crtc)
{ {
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nv50_head *head = nv50_head(crtc); struct nv50_head *head = nv50_head(crtc);
int i; int i;
nv50_dmac_destroy(&head->ovly.base, disp->disp); nv50_dmac_destroy(&head->ovly.base);
nv50_pioc_destroy(&head->oimm.base); nv50_pioc_destroy(&head->oimm.base);
for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++) for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++)
...@@ -4430,7 +4414,7 @@ nv50_display_destroy(struct drm_device *dev) ...@@ -4430,7 +4414,7 @@ nv50_display_destroy(struct drm_device *dev)
{ {
struct nv50_disp *disp = nv50_disp(dev); struct nv50_disp *disp = nv50_disp(dev);
nv50_dmac_destroy(&disp->mast.base, disp->disp); nv50_dmac_destroy(&disp->mast.base);
nouveau_bo_unmap(disp->sync); nouveau_bo_unmap(disp->sync);
if (disp->sync) if (disp->sync)
......
...@@ -24,6 +24,19 @@ ...@@ -24,6 +24,19 @@
#include <nvif/if000a.h> #include <nvif/if000a.h>
int
nvif_mem_init_map(struct nvif_mmu *mmu, u8 type, u64 size, struct nvif_mem *mem)
{
int ret = nvif_mem_init(mmu, mmu->mem, NVIF_MEM_MAPPABLE | type, 0,
size, NULL, 0, mem);
if (ret == 0) {
ret = nvif_object_map(&mem->object, NULL, 0);
if (ret)
nvif_mem_fini(mem);
}
return ret;
}
void void
nvif_mem_fini(struct nvif_mem *mem) nvif_mem_fini(struct nvif_mem *mem)
{ {
......
...@@ -36,6 +36,12 @@ nvif_mmu_fini(struct nvif_mmu *mmu) ...@@ -36,6 +36,12 @@ nvif_mmu_fini(struct nvif_mmu *mmu)
int int
nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu) nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
{ {
static const struct nvif_mclass mems[] = {
{ NVIF_CLASS_MEM_GF100, -1 },
{ NVIF_CLASS_MEM_NV50 , -1 },
{ NVIF_CLASS_MEM_NV04 , -1 },
{}
};
struct nvif_mmu_v0 args; struct nvif_mmu_v0 args;
int ret, i; int ret, i;
...@@ -54,6 +60,11 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu) ...@@ -54,6 +60,11 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
mmu->type_nr = args.type_nr; mmu->type_nr = args.type_nr;
mmu->kind_nr = args.kind_nr; mmu->kind_nr = args.kind_nr;
ret = nvif_mclass(&mmu->object, mems);
if (ret < 0)
goto done;
mmu->mem = mems[ret].oclass;
mmu->heap = kmalloc(sizeof(*mmu->heap) * mmu->heap_nr, GFP_KERNEL); mmu->heap = kmalloc(sizeof(*mmu->heap) * mmu->heap_nr, GFP_KERNEL);
mmu->type = kmalloc(sizeof(*mmu->type) * mmu->type_nr, GFP_KERNEL); mmu->type = kmalloc(sizeof(*mmu->type) * mmu->type_nr, GFP_KERNEL);
if (ret = -ENOMEM, !mmu->heap || !mmu->type) if (ret = -ENOMEM, !mmu->heap || !mmu->type)
......
...@@ -316,6 +316,7 @@ nv50_disp_chan_dtor(struct nvkm_object *object) ...@@ -316,6 +316,7 @@ nv50_disp_chan_dtor(struct nvkm_object *object)
struct nv50_disp *disp = chan->disp; struct nv50_disp *disp = chan->disp;
if (chan->chid.user >= 0) if (chan->chid.user >= 0)
disp->chan[chan->chid.user] = NULL; disp->chan[chan->chid.user] = NULL;
nvkm_memory_unref(&chan->memory);
return chan; return chan;
} }
......
...@@ -19,6 +19,7 @@ struct nv50_disp_chan { ...@@ -19,6 +19,7 @@ struct nv50_disp_chan {
struct nvkm_object object; struct nvkm_object object;
struct nvkm_memory *memory;
u64 push; u64 push;
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <core/client.h> #include <core/client.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <subdev/fb.h> #include <subdev/fb.h>
#include <subdev/mmu.h>
#include <subdev/timer.h> #include <subdev/timer.h>
#include <engine/dma.h> #include <engine/dma.h>
...@@ -37,7 +38,6 @@ nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, ...@@ -37,7 +38,6 @@ nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
struct nvkm_client *client = oclass->client; struct nvkm_client *client = oclass->client;
struct nvkm_dmaobj *dmaobj;
struct nv50_disp_chan *chan; struct nv50_disp_chan *chan;
int ret; int ret;
...@@ -47,24 +47,22 @@ nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, ...@@ -47,24 +47,22 @@ nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func,
if (ret) if (ret)
return ret; return ret;
dmaobj = nvkm_dmaobj_search(client, push); chan->memory = nvkm_umem_search(client, push);
if (IS_ERR(dmaobj)) if (IS_ERR(chan->memory))
return PTR_ERR(dmaobj); return PTR_ERR(chan->memory);
if (dmaobj->limit - dmaobj->start != 0xfff) if (nvkm_memory_size(chan->memory) < 0x1000)
return -EINVAL; return -EINVAL;
switch (dmaobj->target) { switch (nvkm_memory_target(chan->memory)) {
case NV_MEM_TARGET_VRAM: case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break;
chan->push = 0x00000001 | dmaobj->start >> 8; case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break;
break; case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break;
case NV_MEM_TARGET_PCI_NOSNOOP:
chan->push = 0x00000003 | dmaobj->start >> 8;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
chan->push |= nvkm_memory_addr(chan->memory) >> 8;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment