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 {
#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
......@@ -67,6 +67,5 @@ u64 nvif_device_time(struct nvif_device *);
#include <engine/fifo.h>
#include <engine/gr.h>
#define nvxx_fifo(a) nvxx_device(a)->fifo
#define nvxx_gr(a) nvxx_device(a)->gr
#endif
......@@ -474,3 +474,28 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
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;
}
......@@ -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 **);
......
......@@ -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.
......
......@@ -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;
......
......@@ -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");
......
......@@ -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;
};
......
......@@ -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;
}
......@@ -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;
}
......@@ -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,
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -30,6 +30,7 @@
#include <subdev/mc.h>
#include <nvif/event.h>
#include <nvif/cl0080.h>
#include <nvif/unpack.h>
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,
......
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