Commit eb39c613 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: expose per-runlist CHID information



DRM uses this to setup fence-related items.

- nouveau_chan.runlist will always be "0" for the moment, not an issue
  as GPUs prior to ampere have system-wide channel IDs,

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 6de12538
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ struct nv_device_time_v0 {

/* Returns the number of available runlists. */
#define NV_DEVICE_HOST_RUNLISTS                       NV_DEVICE_HOST(0x00000000)
/* Returns the number of available channels. */
/* Returns the number of available channels (0 if per-runlist). */
#define NV_DEVICE_HOST_CHANNELS                       NV_DEVICE_HOST(0x00000001)

/* Returns a mask of available engine types on runlist(data). */
@@ -90,4 +90,6 @@ struct nv_device_time_v0 {
#define NV_DEVICE_HOST_RUNLIST_ENGINES_SEC2                          0x00004000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVDEC                         0x00008000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVENC                         0x00010000
/* Returns the number of available channels on runlist(data). */
#define NV_DEVICE_HOST_RUNLIST_CHANNELS               NV_DEVICE_HOST(0x00000101)
#endif
+43 −4
Original line number Diff line number Diff line
@@ -543,6 +543,12 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
	return ret;
}

void
nouveau_channels_fini(struct nouveau_drm *drm)
{
	kfree(drm->runl);
}

int
nouveau_channels_init(struct nouveau_drm *drm)
{
@@ -550,20 +556,53 @@ nouveau_channels_init(struct nouveau_drm *drm)
		struct nv_device_info_v1 m;
		struct {
			struct nv_device_info_v1_data channels;
			struct nv_device_info_v1_data runlists;
		} v;
	} args = {
		.m.version = 1,
		.m.count = sizeof(args.v) / sizeof(args.v.channels),
		.v.channels.mthd = NV_DEVICE_HOST_CHANNELS,
		.v.runlists.mthd = NV_DEVICE_HOST_RUNLISTS,
	};
	struct nvif_object *device = &drm->client.device.object;
	int ret;
	int ret, i;

	ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args));
	if (ret ||
	    args.v.runlists.mthd == NV_DEVICE_INFO_INVALID || !args.v.runlists.data ||
	    args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
		return -ENODEV;

	drm->chan_nr = drm->chan_total = args.v.channels.data;
	drm->runl_nr = fls64(args.v.runlists.data);
	drm->runl = kcalloc(drm->runl_nr, sizeof(*drm->runl), GFP_KERNEL);
	if (!drm->runl)
		return -ENOMEM;

	if (drm->chan_nr == 0) {
		for (i = 0; i < drm->runl_nr; i++) {
			if (!(args.v.runlists.data & BIT(i)))
				continue;

			args.v.channels.mthd = NV_DEVICE_HOST_RUNLIST_CHANNELS;
			args.v.channels.data = i;

			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);
			drm->runl[i].chan_nr = args.v.channels.data;
			drm->runl[i].chan_id_base = drm->chan_total;
			drm->runl[i].context_base = dma_fence_context_alloc(drm->runl[i].chan_nr);

			drm->chan_total += drm->runl[i].chan_nr;
		}
	} else {
		drm->runl[0].context_base = dma_fence_context_alloc(drm->chan_nr);
		for (i = 1; i < drm->runl_nr; i++)
			drm->runl[i].context_base = drm->runl[0].context_base;

	}

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ struct nouveau_channel {
	struct nouveau_drm *drm;
	struct nouveau_vmm *vmm;

	int runlist;
	int chid;
	u64 inst;
	u32 token;
@@ -55,6 +56,7 @@ struct nouveau_channel {
};

int nouveau_channels_init(struct nouveau_drm *);
void nouveau_channels_fini(struct nouveau_drm *);

int  nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u64 runm,
			 u32 vram, u32 gart, struct nouveau_channel **);
+1 −0
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ nouveau_accel_fini(struct nouveau_drm *drm)
	nouveau_accel_gr_fini(drm);
	if (drm->fence)
		nouveau_fence(drm)->dtor(drm);
	nouveau_channels_fini(drm);
}

static void
+6 −2
Original line number Diff line number Diff line
@@ -174,10 +174,14 @@ struct nouveau_drm {
	void *fence;

	/* Global channel management. */
	int chan_total; /* Number of channels across all runlists. */
	int chan_nr;	/* 0 if per-runlist CHIDs. */
	int runl_nr;
	struct {
		int nr;
		int chan_nr;
		int chan_id_base;
		u64 context_base;
	} chan;
	} *runl;

	/* context for accelerated drm-internal operations */
	struct nouveau_channel *cechan;
Loading