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

Commit 6f99c848 authored by Samuel Pitoiset's avatar Samuel Pitoiset Committed by Ben Skeggs
Browse files

drm/nouveau/pm: implement NVIF_PERFMON_V0_QUERY_SOURCE method



This allows to query the ID, the mask and the user-readable name of
sources for each signal.

Signed-off-by: default avatarSamuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 50d138d7
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ struct gf110_dma_v0 {

#define NVIF_PERFMON_V0_QUERY_DOMAIN                                       0x00
#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x01
#define NVIF_PERFMON_V0_QUERY_SOURCE                                       0x02

struct nvif_perfmon_query_domain_v0 {
	__u8  version;
@@ -273,6 +274,17 @@ struct nvif_perfmon_query_signal_v0 {
	char  name[64];
};

struct nvif_perfmon_query_source_v0 {
	__u8  version;
	__u8  domain;
	__u8  signal;
	__u8  iter;
	__u8  pad04[4];
	__u32 source;
	__u32 mask;
	char  name[64];
};


/*******************************************************************************
 * perfctr
+77 −0
Original line number Diff line number Diff line
@@ -103,6 +103,31 @@ nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig)
	return source_nr;
}

static struct nvkm_perfsrc *
nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si)
{
	struct nvkm_perfsrc *src;
	bool found = false;
	int tmp = 1; /* Sources ID start from 1 */
	u8 i;

	for (i = 0; i < ARRAY_SIZE(sig->source) && sig->source[i]; i++) {
		if (sig->source[i] == si) {
			found = true;
			break;
		}
	}

	if (found) {
		list_for_each_entry(src, &ppm->sources, head) {
			if (tmp++ == si)
				return src;
		}
	}

	return NULL;
}

/*******************************************************************************
 * Perfmon object classes
 ******************************************************************************/
@@ -203,6 +228,56 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
	return 0;
}

static int
nvkm_perfmon_mthd_query_source(struct nvkm_object *object, void *data, u32 size)
{
	union {
		struct nvif_perfmon_query_source_v0 v0;
	} *args = data;
	struct nvkm_pm *ppm = (void *)object->engine;
	struct nvkm_perfdom *dom = NULL;
	struct nvkm_perfsig *sig;
	struct nvkm_perfsrc *src;
	u8 source_nr = 0;
	int si, ret;

	nv_ioctl(object, "perfmon query source size %d\n", size);
	if (nvif_unpack(args->v0, 0, 0, false)) {
		nv_ioctl(object,
			 "perfmon source vers %d dom %d sig %02x iter %02x\n",
			 args->v0.version, args->v0.domain, args->v0.signal,
			 args->v0.iter);
		si = (args->v0.iter & 0xff) - 1;
	} else
		return ret;

	sig = nvkm_perfsig_find(ppm, args->v0.domain, args->v0.signal, &dom);
	if (!sig)
		return -EINVAL;

	source_nr = nvkm_perfsig_count_perfsrc(sig);
	if (si >= (int)source_nr)
		return -EINVAL;

	if (si >= 0) {
		src = nvkm_perfsrc_find(ppm, sig, sig->source[si]);
		if (!src)
			return -EINVAL;

		args->v0.source = sig->source[si];
		args->v0.mask   = src->mask;
		strncpy(args->v0.name, src->name, sizeof(args->v0.name));
	}

	if (++si < source_nr) {
		args->v0.iter = ++si;
		return 0;
	}

	args->v0.iter = 0xff;
	return 0;
}

static int
nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
@@ -211,6 +286,8 @@ nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
		return nvkm_perfmon_mthd_query_domain(object, data, size);
	case NVIF_PERFMON_V0_QUERY_SIGNAL:
		return nvkm_perfmon_mthd_query_signal(object, data, size);
	case NVIF_PERFMON_V0_QUERY_SOURCE:
		return nvkm_perfmon_mthd_query_source(object, data, size);
	default:
		break;
	}