From eb47db4f3bb58b0143a911b29417e89f28e1b0c8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 8 May 2018 20:39:46 +1000 Subject: [PATCH] drm/nouveau/fifo: support channel count query Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/cl0080.h | 4 +++ drivers/gpu/drm/nouveau/include/nvif/device.h | 1 - drivers/gpu/drm/nouveau/nouveau_chan.c | 25 +++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_chan.h | 1 + drivers/gpu/drm/nouveau/nouveau_drm.c | 4 +++ drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +++++ drivers/gpu/drm/nouveau/nouveau_fence.c | 11 ++++---- drivers/gpu/drm/nouveau/nouveau_fence.h | 2 -- drivers/gpu/drm/nouveau/nv04_fence.c | 2 -- drivers/gpu/drm/nouveau/nv10_fence.c | 2 -- drivers/gpu/drm/nouveau/nv17_fence.c | 2 -- drivers/gpu/drm/nouveau/nv50_fence.c | 2 -- drivers/gpu/drm/nouveau/nv84_fence.c | 11 +++----- .../gpu/drm/nouveau/nvkm/engine/device/user.c | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 14 +++++++++++ 15 files changed, 64 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h index 6a54cda9613e..5af610ea260e 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h @@ -57,6 +57,7 @@ struct nv_device_time_v0 { #define NV_DEVICE_INFO_UNIT (0xffffffffULL << 32) #define NV_DEVICE_INFO(n) ((n) | (0x00000000ULL << 32)) +#define NV_DEVICE_FIFO(n) ((n) | (0x00000001ULL << 32)) /* This will be returned for unsupported queries. */ #define NV_DEVICE_INFO_INVALID ~0ULL @@ -79,4 +80,7 @@ struct nv_device_time_v0 { #define NV_DEVICE_INFO_ENGINE_SEC2 NV_DEVICE_INFO(0x0000000e) #define NV_DEVICE_INFO_ENGINE_NVDEC NV_DEVICE_INFO(0x0000000f) #define NV_DEVICE_INFO_ENGINE_NVENC NV_DEVICE_INFO(0x00000010) + +/* Returns the number of available channels. */ +#define NV_DEVICE_FIFO_CHANNELS NV_DEVICE_FIFO(0x00000000) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h index 6edb6266857e..216dbd9fa616 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/device.h +++ b/drivers/gpu/drm/nouveau/include/nvif/device.h @@ -67,6 +67,5 @@ u64 nvif_device_time(struct nvif_device *); #include #include -#define nvxx_fifo(a) nvxx_device(a)->fifo #define nvxx_gr(a) nvxx_device(a)->gr #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index af1116655910..db69d13f32a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -474,3 +474,28 @@ done: cli->base.super = super; return ret; } + +int +nouveau_channels_init(struct nouveau_drm *drm) +{ + struct { + struct nv_device_info_v1 m; + struct { + struct nv_device_info_v1_data channels; + } v; + } args = { + .m.version = 1, + .m.count = sizeof(args.v) / sizeof(args.v.channels), + .v.channels.mthd = NV_DEVICE_FIFO_CHANNELS, + }; + struct nvif_object *device = &drm->client.device.object; + int ret; + + ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args)); + if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID) + return -ENODEV; + + drm->chan.nr = args.v.channels.data; + drm->chan.context_base = dma_fence_context_alloc(drm->chan.nr); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 14607c16a2bd..64454c2ebd90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -45,6 +45,7 @@ struct nouveau_channel { atomic_t killed; }; +int nouveau_channels_init(struct nouveau_drm *); int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, u32 arg0, u32 arg1, struct nouveau_channel **); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index bbbf353682e1..dddd42592472 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -307,6 +307,10 @@ nouveau_accel_init(struct nouveau_drm *drm) if (nouveau_noaccel) return; + ret = nouveau_channels_init(drm); + if (ret) + return; + /* initialise synchronisation routines */ /*XXX: this is crap, but the fence/channel stuff is a little * backwards in some places. this will be fixed. diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 881b44b89a01..6e1acaec3400 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -170,6 +170,12 @@ struct nouveau_drm { /* synchronisation */ void *fence; + /* Global channel management. */ + struct { + int nr; + u64 context_base; + } chan; + /* context for accelerated drm-internal operations */ struct nouveau_channel *cechan; struct nouveau_channel *channel; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 503fa94dc06d..412d49bc6e56 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -74,15 +74,14 @@ nouveau_fence_signal(struct nouveau_fence *fence) } static struct nouveau_fence * -nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) { - struct nouveau_fence_priv *priv = (void*)drm->fence; - +nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) +{ if (fence->ops != &nouveau_fence_ops_legacy && fence->ops != &nouveau_fence_ops_uevent) return NULL; - if (fence->context < priv->context_base || - fence->context >= priv->context_base + priv->contexts) + if (fence->context < drm->chan.context_base || + fence->context >= drm->chan.context_base + drm->chan.nr) return NULL; return from_fence(fence); @@ -176,7 +175,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha INIT_LIST_HEAD(&fctx->flip); INIT_LIST_HEAD(&fctx->pending); spin_lock_init(&fctx->lock); - fctx->context = priv->context_base + chan->chid; + fctx->context = chan->drm->chan.context_base + chan->chid; if (chan == chan->drm->cechan) strcpy(fctx->name, "copy engine channel"); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 5bd8d30d1657..b999e6058046 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -55,8 +55,6 @@ struct nouveau_fence_priv { int (*context_new)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *); - u32 contexts; - u64 context_base; bool uevent; }; diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index fa8f2375c398..c41e82be4893 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -109,7 +109,5 @@ nv04_fence_create(struct nouveau_drm *drm) priv->base.dtor = nv04_fence_destroy; priv->base.context_new = nv04_fence_context_new; priv->base.context_del = nv04_fence_context_del; - priv->base.contexts = 15; - priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 2998bde29211..4476b712dc84 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -103,8 +103,6 @@ nv10_fence_create(struct nouveau_drm *drm) priv->base.dtor = nv10_fence_destroy; priv->base.context_new = nv10_fence_context_new; priv->base.context_del = nv10_fence_context_del; - priv->base.contexts = 31; - priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 6477b7069e14..5d613d43b84d 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -125,8 +125,6 @@ nv17_fence_create(struct nouveau_drm *drm) priv->base.resume = nv17_fence_resume; priv->base.context_new = nv17_fence_context_new; priv->base.context_del = nv10_fence_context_del; - priv->base.contexts = 31; - priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index a369d978e267..a00ecc3de053 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -78,8 +78,6 @@ nv50_fence_create(struct nouveau_drm *drm) priv->base.resume = nv17_fence_resume; priv->base.context_new = nv50_fence_context_new; priv->base.context_del = nv10_fence_context_del; - priv->base.contexts = 127; - priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); spin_lock_init(&priv->lock); ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 5f0c0c27d5dc..090664899247 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -141,9 +141,9 @@ nv84_fence_suspend(struct nouveau_drm *drm) struct nv84_fence_priv *priv = drm->fence; int i; - priv->suspend = vmalloc(priv->base.contexts * sizeof(u32)); + priv->suspend = vmalloc(drm->chan.nr * sizeof(u32)); if (priv->suspend) { - for (i = 0; i < priv->base.contexts; i++) + for (i = 0; i < drm->chan.nr; i++) priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); } @@ -157,7 +157,7 @@ nv84_fence_resume(struct nouveau_drm *drm) int i; if (priv->suspend) { - for (i = 0; i < priv->base.contexts; i++) + for (i = 0; i < drm->chan.nr; i++) nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); vfree(priv->suspend); priv->suspend = NULL; @@ -179,7 +179,6 @@ nv84_fence_destroy(struct nouveau_drm *drm) int nv84_fence_create(struct nouveau_drm *drm) { - struct nvkm_fifo *fifo = nvxx_fifo(&drm->client.device); struct nv84_fence_priv *priv; u32 domain; int ret; @@ -194,8 +193,6 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; - priv->base.contexts = fifo->nr; - priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); priv->base.uevent = true; mutex_init(&priv->mutex); @@ -207,7 +204,7 @@ nv84_fence_create(struct nouveau_drm *drm) * will lose CPU/GPU coherency! */ TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED; - ret = nouveau_bo_new(&drm->client, 16 * priv->base.contexts, 0, + ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0, domain, 0, 0, NULL, NULL, &priv->bo); if (ret == 0) { ret = nouveau_bo_pin(priv->bo, domain, false); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 42a552d314ef..600bdb870462 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -46,6 +46,7 @@ nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data) enum nvkm_devidx subidx; switch (mthd & NV_DEVICE_INFO_UNIT) { + case NV_DEVICE_FIFO(0): subidx = NVKM_ENGINE_FIFO; break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 64f6b7654a08..49b37a8a94b7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -30,6 +30,7 @@ #include #include +#include #include void @@ -270,6 +271,18 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) return 0; } +static int +nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + switch (mthd) { + case NV_DEVICE_FIFO_CHANNELS: *data = fifo->nr; return 0; + default: + break; + } + return -ENOSYS; +} + static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { @@ -311,6 +324,7 @@ nvkm_fifo = { .dtor = nvkm_fifo_dtor, .preinit = nvkm_fifo_preinit, .oneinit = nvkm_fifo_oneinit, + .info = nvkm_fifo_info, .init = nvkm_fifo_init, .fini = nvkm_fifo_fini, .intr = nvkm_fifo_intr, -- 2.30.2