Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bfdde17 authored by Samuel Pitoiset's avatar Samuel Pitoiset Committed by Ben Skeggs
Browse files

drm/nouveau/pm: allow the userspace to schedule hardware counters



This adds a new method NVIF_PERFCTR_V0_INIT which starts a batch of
hardware counters for sampling. This will allow the userspace to start
a monitoring session using the INIT method and to stop it with SAMPLE,
for example before and after a frame is rendered.

This commit temporarily breaks nv_perfmon but this is going to be fixed
with the upcoming patch.

Signed-off-by: default avatarSamuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6f99c848
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -300,8 +300,12 @@ struct nvif_perfctr_v0 {
	__u8  pad06[4];
};

#define NVIF_PERFCTR_V0_SAMPLE                                             0x00
#define NVIF_PERFCTR_V0_READ                                               0x01
#define NVIF_PERFCTR_V0_INIT                                               0x00
#define NVIF_PERFCTR_V0_SAMPLE                                             0x01
#define NVIF_PERFCTR_V0_READ                                               0x02

struct nvif_perfctr_init {
};

struct nvif_perfctr_sample {
};
+41 −23
Original line number Diff line number Diff line
@@ -306,6 +306,36 @@ nvkm_perfmon_ofuncs = {
/*******************************************************************************
 * Perfctr object classes
 ******************************************************************************/
static int
nvkm_perfctr_init(struct nvkm_object *object, void *data, u32 size)
{
	union {
		struct nvif_perfctr_init none;
	} *args = data;
	struct nvkm_pm *ppm = (void *)object->engine;
	struct nvkm_perfctr *ctr = (void *)object;
	struct nvkm_perfdom *dom = ctr->dom;
	int ret;

	nv_ioctl(object, "perfctr init size %d\n", size);
	if (nvif_unvers(args->none)) {
		nv_ioctl(object, "perfctr init\n");
	} else
		return ret;

	ctr->slot = ffs(dom->quad) - 1;
	if (ctr->slot < 0) {
		/* no free slots are available */
		return -EINVAL;
	}
	dom->quad &= ~(QUAD_FREE << ctr->slot);
	dom->func->init(ppm, dom, ctr);

	/* start next batch of counters for sampling */
	dom->func->next(ppm, dom);
	return 0;
}

static int
nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size)
{
@@ -313,7 +343,7 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size)
		struct nvif_perfctr_sample none;
	} *args = data;
	struct nvkm_pm *ppm = (void *)object->engine;
	struct nvkm_perfctr *ctr, *tmp;
	struct nvkm_perfctr *ctr;
	struct nvkm_perfdom *dom;
	int ret;

@@ -328,32 +358,15 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size)
		/* sample previous batch of counters */
		if (dom->quad != QUAD_MASK) {
			dom->func->next(ppm, dom);
			tmp = NULL;
			while (!list_empty(&dom->list)) {
				ctr = list_first_entry(&dom->list,
						       typeof(*ctr), head);
				if (ctr->slot < 0) break;
				if ( tmp && tmp == ctr) break;
				if (!tmp) tmp = ctr;

			/* read counter values */
			list_for_each_entry(ctr, &dom->list, head) {
				dom->func->read(ppm, dom, ctr);
				ctr->slot = -1;
				list_move_tail(&ctr->head, &dom->list);
			}
			}

			dom->quad = QUAD_MASK;

		/* setup next batch of counters for sampling */
		list_for_each_entry(ctr, &dom->list, head) {
			ctr->slot = ffs(dom->quad) - 1;
			if (ctr->slot < 0)
				break;
			dom->quad &= ~(QUAD_FREE << ctr->slot);
			dom->func->init(ppm, dom, ctr);
		}

		if (dom->quad != QUAD_MASK)
			dom->func->next(ppm, dom);
	}

	return 0;
@@ -386,6 +399,8 @@ static int
nvkm_perfctr_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
	switch (mthd) {
	case NVIF_PERFCTR_V0_INIT:
		return nvkm_perfctr_init(object, data, size);
	case NVIF_PERFCTR_V0_SAMPLE:
		return nvkm_perfctr_sample(object, data, size);
	case NVIF_PERFCTR_V0_READ:
@@ -400,6 +415,8 @@ static void
nvkm_perfctr_dtor(struct nvkm_object *object)
{
	struct nvkm_perfctr *ctr = (void *)object;
	if (ctr->dom)
		ctr->dom->quad |= (QUAD_FREE << ctr->slot);
	if (ctr->head.next)
		list_del(&ctr->head);
	nvkm_object_destroy(&ctr->base);
@@ -441,6 +458,7 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	if (ret)
		return ret;

	ctr->dom = dom;
	ctr->slot = -1;
	ctr->logic_op = args->v0.logic_op;
	ctr->signal[0] = sig[0];
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ struct nvkm_perfctr {
	struct nvkm_object base;
	struct list_head head;
	struct nvkm_perfsig *signal[4];
	struct nvkm_perfdom *dom;
	int slot;
	u32 logic_op;
	u32 clk;