Commit eb47db4f authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo: support channel count query

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6eb01aa8
...@@ -57,6 +57,7 @@ struct nv_device_time_v0 { ...@@ -57,6 +57,7 @@ struct nv_device_time_v0 {
#define NV_DEVICE_INFO_UNIT (0xffffffffULL << 32) #define NV_DEVICE_INFO_UNIT (0xffffffffULL << 32)
#define NV_DEVICE_INFO(n) ((n) | (0x00000000ULL << 32)) #define NV_DEVICE_INFO(n) ((n) | (0x00000000ULL << 32))
#define NV_DEVICE_FIFO(n) ((n) | (0x00000001ULL << 32))
/* This will be returned for unsupported queries. */ /* This will be returned for unsupported queries. */
#define NV_DEVICE_INFO_INVALID ~0ULL #define NV_DEVICE_INFO_INVALID ~0ULL
...@@ -79,4 +80,7 @@ struct nv_device_time_v0 { ...@@ -79,4 +80,7 @@ struct nv_device_time_v0 {
#define NV_DEVICE_INFO_ENGINE_SEC2 NV_DEVICE_INFO(0x0000000e) #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_NVDEC NV_DEVICE_INFO(0x0000000f)
#define NV_DEVICE_INFO_ENGINE_NVENC NV_DEVICE_INFO(0x00000010) #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 #endif
...@@ -67,6 +67,5 @@ u64 nvif_device_time(struct nvif_device *); ...@@ -67,6 +67,5 @@ u64 nvif_device_time(struct nvif_device *);
#include <engine/fifo.h> #include <engine/fifo.h>
#include <engine/gr.h> #include <engine/gr.h>
#define nvxx_fifo(a) nvxx_device(a)->fifo
#define nvxx_gr(a) nvxx_device(a)->gr #define nvxx_gr(a) nvxx_device(a)->gr
#endif #endif
...@@ -474,3 +474,28 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -474,3 +474,28 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
cli->base.super = super; cli->base.super = super;
return ret; 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;
}
...@@ -45,6 +45,7 @@ struct nouveau_channel { ...@@ -45,6 +45,7 @@ struct nouveau_channel {
atomic_t killed; atomic_t killed;
}; };
int nouveau_channels_init(struct nouveau_drm *);
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
u32 arg0, u32 arg1, struct nouveau_channel **); u32 arg0, u32 arg1, struct nouveau_channel **);
......
...@@ -307,6 +307,10 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -307,6 +307,10 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (nouveau_noaccel) if (nouveau_noaccel)
return; return;
ret = nouveau_channels_init(drm);
if (ret)
return;
/* initialise synchronisation routines */ /* initialise synchronisation routines */
/*XXX: this is crap, but the fence/channel stuff is a little /*XXX: this is crap, but the fence/channel stuff is a little
* backwards in some places. this will be fixed. * backwards in some places. this will be fixed.
......
...@@ -170,6 +170,12 @@ struct nouveau_drm { ...@@ -170,6 +170,12 @@ struct nouveau_drm {
/* synchronisation */ /* synchronisation */
void *fence; void *fence;
/* Global channel management. */
struct {
int nr;
u64 context_base;
} chan;
/* context for accelerated drm-internal operations */ /* context for accelerated drm-internal operations */
struct nouveau_channel *cechan; struct nouveau_channel *cechan;
struct nouveau_channel *channel; struct nouveau_channel *channel;
......
...@@ -74,15 +74,14 @@ nouveau_fence_signal(struct nouveau_fence *fence) ...@@ -74,15 +74,14 @@ nouveau_fence_signal(struct nouveau_fence *fence)
} }
static struct nouveau_fence * static struct nouveau_fence *
nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) { nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm)
struct nouveau_fence_priv *priv = (void*)drm->fence; {
if (fence->ops != &nouveau_fence_ops_legacy && if (fence->ops != &nouveau_fence_ops_legacy &&
fence->ops != &nouveau_fence_ops_uevent) fence->ops != &nouveau_fence_ops_uevent)
return NULL; return NULL;
if (fence->context < priv->context_base || if (fence->context < drm->chan.context_base ||
fence->context >= priv->context_base + priv->contexts) fence->context >= drm->chan.context_base + drm->chan.nr)
return NULL; return NULL;
return from_fence(fence); return from_fence(fence);
...@@ -176,7 +175,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha ...@@ -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->flip);
INIT_LIST_HEAD(&fctx->pending); INIT_LIST_HEAD(&fctx->pending);
spin_lock_init(&fctx->lock); 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) if (chan == chan->drm->cechan)
strcpy(fctx->name, "copy engine channel"); strcpy(fctx->name, "copy engine channel");
......
...@@ -55,8 +55,6 @@ struct nouveau_fence_priv { ...@@ -55,8 +55,6 @@ struct nouveau_fence_priv {
int (*context_new)(struct nouveau_channel *); int (*context_new)(struct nouveau_channel *);
void (*context_del)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *);
u32 contexts;
u64 context_base;
bool uevent; bool uevent;
}; };
......
...@@ -109,7 +109,5 @@ nv04_fence_create(struct nouveau_drm *drm) ...@@ -109,7 +109,5 @@ nv04_fence_create(struct nouveau_drm *drm)
priv->base.dtor = nv04_fence_destroy; priv->base.dtor = nv04_fence_destroy;
priv->base.context_new = nv04_fence_context_new; priv->base.context_new = nv04_fence_context_new;
priv->base.context_del = nv04_fence_context_del; 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; return 0;
} }
...@@ -103,8 +103,6 @@ nv10_fence_create(struct nouveau_drm *drm) ...@@ -103,8 +103,6 @@ nv10_fence_create(struct nouveau_drm *drm)
priv->base.dtor = nv10_fence_destroy; priv->base.dtor = nv10_fence_destroy;
priv->base.context_new = nv10_fence_context_new; priv->base.context_new = nv10_fence_context_new;
priv->base.context_del = nv10_fence_context_del; 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); spin_lock_init(&priv->lock);
return 0; return 0;
} }
...@@ -125,8 +125,6 @@ nv17_fence_create(struct nouveau_drm *drm) ...@@ -125,8 +125,6 @@ nv17_fence_create(struct nouveau_drm *drm)
priv->base.resume = nv17_fence_resume; priv->base.resume = nv17_fence_resume;
priv->base.context_new = nv17_fence_context_new; priv->base.context_new = nv17_fence_context_new;
priv->base.context_del = nv10_fence_context_del; 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); spin_lock_init(&priv->lock);
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
......
...@@ -78,8 +78,6 @@ nv50_fence_create(struct nouveau_drm *drm) ...@@ -78,8 +78,6 @@ nv50_fence_create(struct nouveau_drm *drm)
priv->base.resume = nv17_fence_resume; priv->base.resume = nv17_fence_resume;
priv->base.context_new = nv50_fence_context_new; priv->base.context_new = nv50_fence_context_new;
priv->base.context_del = nv10_fence_context_del; 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); spin_lock_init(&priv->lock);
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
......
...@@ -141,9 +141,9 @@ nv84_fence_suspend(struct nouveau_drm *drm) ...@@ -141,9 +141,9 @@ nv84_fence_suspend(struct nouveau_drm *drm)
struct nv84_fence_priv *priv = drm->fence; struct nv84_fence_priv *priv = drm->fence;
int i; int i;
priv->suspend = vmalloc(priv->base.contexts * sizeof(u32)); priv->suspend = vmalloc(drm->chan.nr * sizeof(u32));
if (priv->suspend) { 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); priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
} }
...@@ -157,7 +157,7 @@ nv84_fence_resume(struct nouveau_drm *drm) ...@@ -157,7 +157,7 @@ nv84_fence_resume(struct nouveau_drm *drm)
int i; int i;
if (priv->suspend) { 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]); nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
vfree(priv->suspend); vfree(priv->suspend);
priv->suspend = NULL; priv->suspend = NULL;
...@@ -179,7 +179,6 @@ nv84_fence_destroy(struct nouveau_drm *drm) ...@@ -179,7 +179,6 @@ nv84_fence_destroy(struct nouveau_drm *drm)
int int
nv84_fence_create(struct nouveau_drm *drm) nv84_fence_create(struct nouveau_drm *drm)
{ {
struct nvkm_fifo *fifo = nvxx_fifo(&drm->client.device);
struct nv84_fence_priv *priv; struct nv84_fence_priv *priv;
u32 domain; u32 domain;
int ret; int ret;
...@@ -194,8 +193,6 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -194,8 +193,6 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv84_fence_context_new; priv->base.context_new = nv84_fence_context_new;
priv->base.context_del = nv84_fence_context_del; 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; priv->base.uevent = true;
mutex_init(&priv->mutex); mutex_init(&priv->mutex);
...@@ -207,7 +204,7 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -207,7 +204,7 @@ nv84_fence_create(struct nouveau_drm *drm)
* will lose CPU/GPU coherency! * will lose CPU/GPU coherency!
*/ */
TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED; 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); domain, 0, 0, NULL, NULL, &priv->bo);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_pin(priv->bo, domain, false); ret = nouveau_bo_pin(priv->bo, domain, false);
......
...@@ -46,6 +46,7 @@ nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data) ...@@ -46,6 +46,7 @@ nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data)
enum nvkm_devidx subidx; enum nvkm_devidx subidx;
switch (mthd & NV_DEVICE_INFO_UNIT) { switch (mthd & NV_DEVICE_INFO_UNIT) {
case NV_DEVICE_FIFO(0): subidx = NVKM_ENGINE_FIFO; break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <subdev/mc.h> #include <subdev/mc.h>
#include <nvif/event.h> #include <nvif/event.h>
#include <nvif/cl0080.h>
#include <nvif/unpack.h> #include <nvif/unpack.h>
void void
...@@ -270,6 +271,18 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) ...@@ -270,6 +271,18 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
return 0; 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 static int
nvkm_fifo_oneinit(struct nvkm_engine *engine) nvkm_fifo_oneinit(struct nvkm_engine *engine)
{ {
...@@ -311,6 +324,7 @@ nvkm_fifo = { ...@@ -311,6 +324,7 @@ nvkm_fifo = {
.dtor = nvkm_fifo_dtor, .dtor = nvkm_fifo_dtor,
.preinit = nvkm_fifo_preinit, .preinit = nvkm_fifo_preinit,
.oneinit = nvkm_fifo_oneinit, .oneinit = nvkm_fifo_oneinit,
.info = nvkm_fifo_info,
.init = nvkm_fifo_init, .init = nvkm_fifo_init,
.fini = nvkm_fifo_fini, .fini = nvkm_fifo_fini,
.intr = nvkm_fifo_intr, .intr = nvkm_fifo_intr,
......
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