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

Commit 45f0f94d authored by Samuel Pitoiset's avatar Samuel Pitoiset Committed by Ben Skeggs
Browse files

drm/nouveau/pm: implement NVIF_PERFMON_V0_QUERY_DOMAIN method



This allows to query the number of available domains, including the
number of hardware counter and the number of signals per domain.

Signed-off-by: default avatarSamuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 44d9de58
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -251,7 +251,16 @@ struct gf110_dma_v0 {
 * perfmon
 * perfmon
 ******************************************************************************/
 ******************************************************************************/


#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x00
#define NVIF_PERFMON_V0_QUERY_DOMAIN                                       0x00
#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x01

struct nvif_perfmon_query_domain_v0 {
	__u8  version;
	__u8  id;
	__u8  counter_nr;
	__u8  iter;
	__u32 signal_nr;
};


struct nvif_perfmon_query_signal_v0 {
struct nvif_perfmon_query_signal_v0 {
	__u8  version;
	__u8  version;
+86 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,45 @@
#define QUAD_MASK 0x0f
#define QUAD_MASK 0x0f
#define QUAD_FREE 0x01
#define QUAD_FREE 0x01


static u8
nvkm_pm_count_perfdom(struct nvkm_pm *ppm)
{
	struct nvkm_perfdom *dom;
	u8 domain_nr = 0;

	list_for_each_entry(dom, &ppm->domains, head)
		domain_nr++;
	return domain_nr;
}

static u32
nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom)
{
	u32 signal_nr = 0;
	int i;

	if (dom) {
		for (i = 0; i < dom->signal_nr; i++) {
			if (dom->signal[i].name)
				signal_nr++;
		}
	}
	return signal_nr;
}

static struct nvkm_perfdom *
nvkm_perfdom_find(struct nvkm_pm *ppm, int di)
{
	struct nvkm_perfdom *dom;
	int tmp = 0;

	list_for_each_entry(dom, &ppm->domains, head) {
		if (tmp++ == di)
			return dom;
	}
	return NULL;
}

static struct nvkm_perfsig *
static struct nvkm_perfsig *
nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size)
nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size)
{
{
@@ -82,6 +121,51 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size,
/*******************************************************************************
/*******************************************************************************
 * Perfmon object classes
 * Perfmon object classes
 ******************************************************************************/
 ******************************************************************************/
static int
nvkm_perfmon_mthd_query_domain(struct nvkm_object *object, void *data, u32 size)
{
	union {
		struct nvif_perfmon_query_domain_v0 v0;
	} *args = data;
	struct nvkm_pm *ppm = (void *)object->engine;
	struct nvkm_perfdom *dom;
	u8 domain_nr;
	int di, ret;

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

	domain_nr = nvkm_pm_count_perfdom(ppm);
	if (di >= (int)domain_nr)
		return -EINVAL;

	if (di >= 0) {
		dom = nvkm_perfdom_find(ppm, di);
		if (dom == NULL)
			return -EINVAL;

		args->v0.id         = di;
		args->v0.signal_nr  = nvkm_perfdom_count_perfsig(dom);

		/* Currently only global counters (PCOUNTER) are implemented
		 * but this will be different for local counters (MP). */
		args->v0.counter_nr = 4;
	}

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

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

static int
static int
nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
{
{
@@ -145,6 +229,8 @@ static int
nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
{
	switch (mthd) {
	switch (mthd) {
	case NVIF_PERFMON_V0_QUERY_DOMAIN:
		return nvkm_perfmon_mthd_query_domain(object, data, size);
	case NVIF_PERFMON_V0_QUERY_SIGNAL:
	case NVIF_PERFMON_V0_QUERY_SIGNAL:
		return nvkm_perfmon_mthd_query_signal(object, data, size);
		return nvkm_perfmon_mthd_query_signal(object, data, size);
	default:
	default: