mirror of https://gitee.com/openkylin/linux.git
drm/nouveau/fifo: support channel count query
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
6eb01aa898
commit
eb47db4f3b
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue