summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2015-06-07 22:40:27 +0200
committerBen Skeggs <bskeggs@redhat.com>2015-06-14 12:09:48 +1000
commit507598d0b60816903a062f9b488f72065d7e63a6 (patch)
tree0cc5e72694fe578cc84d36194a0d9f317ebd5135
parent3935063afe9c50bb6a11b662c8004a8da21f55a5 (diff)
pm: allow the userspace to configure sources
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drm/nouveau/include/nvif/class.h1
-rw-r--r--drm/nouveau/nvkm/engine/pm/base.c102
-rw-r--r--drm/nouveau/nvkm/engine/pm/priv.h2
3 files changed, 95 insertions, 10 deletions
diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h
index 1a76a7fe..3b7f49f8 100644
--- a/drm/nouveau/include/nvif/class.h
+++ b/drm/nouveau/include/nvif/class.h
@@ -297,6 +297,7 @@ struct nvif_perfdom_v0 {
__u8 pad03[1];
struct {
__u8 signal[4];
+ __u64 source[4][8];
__u16 logic_op;
} ctr[4];
};
diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c
index 8960bf4f..a4bb6fe5 100644
--- a/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drm/nouveau/nvkm/engine/pm/base.c
@@ -125,6 +125,66 @@ nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si)
return NULL;
}
+static int
+nvkm_perfsrc_enable(struct nvkm_pm *ppm, struct nvkm_perfctr *ctr)
+{
+ struct nvkm_perfdom *dom = NULL;
+ struct nvkm_perfsig *sig;
+ struct nvkm_perfsrc *src;
+ u32 mask, value;
+ int i, j;
+
+ for (i = 0; i < 4 && ctr->signal[i]; i++) {
+ for (j = 0; j < 8 && ctr->source[i][j]; j++) {
+ sig = nvkm_perfsig_find(ppm, ctr->domain,
+ ctr->signal[i], &dom);
+ if (!sig)
+ return -EINVAL;
+
+ src = nvkm_perfsrc_find(ppm, sig, ctr->source[i][j]);
+ if (!src)
+ return -EINVAL;
+
+ /* set enable bit if needed */
+ mask = value = 0x00000000;
+ if (src->enable)
+ mask = value = 0x80000000;
+ mask |= (src->mask << src->shift);
+ value |= ((ctr->source[i][j] >> 32) << src->shift);
+
+ /* enable the source */
+ nv_mask(ppm, src->addr, mask, value);
+ }
+ }
+ return 0;
+}
+
+static int
+nvkm_perfsrc_disable(struct nvkm_pm *ppm, struct nvkm_perfctr *ctr)
+{
+ struct nvkm_perfdom *dom = NULL;
+ struct nvkm_perfsig *sig;
+ struct nvkm_perfsrc *src;
+ int i, j;
+
+ for (i = 0; i < 4 && ctr->signal[i]; i++) {
+ for (j = 0; j < 8 && ctr->source[i][j]; j++) {
+ sig = nvkm_perfsig_find(ppm, ctr->domain,
+ ctr->signal[i], &dom);
+ if (!sig)
+ return -EINVAL;
+
+ src = nvkm_perfsrc_find(ppm, sig, ctr->source[i][j]);
+ if (!src)
+ return -EINVAL;
+
+ /* disable the source */
+ nv_mask(ppm, src->addr, src->mask << src->shift, 0);
+ }
+ }
+ return 0;
+}
+
/*******************************************************************************
* Perfmon object classes
******************************************************************************/
@@ -319,10 +379,15 @@ nvkm_perfdom_init(struct nvkm_object *object, void *data, u32 size)
} else
return ret;
- for (i = 0; i < 4; i++)
- if (dom->ctr[i])
+ for (i = 0; i < 4; i++) {
+ if (dom->ctr[i]) {
dom->func->init(ppm, dom, dom->ctr[i]);
+ /* enable sources */
+ nvkm_perfsrc_enable(ppm, dom->ctr[i]);
+ }
+ }
+
/* start next batch of counters for sampling */
dom->func->next(ppm, dom);
return 0;
@@ -402,13 +467,17 @@ nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
static void
nvkm_perfdom_dtor(struct nvkm_object *object)
{
+ struct nvkm_pm *ppm = (void *)object->engine;
struct nvkm_perfdom *dom = (void *)object;
int i;
for (i = 0; i < 4; i++) {
struct nvkm_perfctr *ctr = dom->ctr[i];
- if (ctr && ctr->head.next)
- list_del(&ctr->head);
+ if (ctr) {
+ nvkm_perfsrc_disable(ppm, ctr);
+ if (ctr->head.next)
+ list_del(&ctr->head);
+ }
kfree(ctr);
}
nvkm_object_destroy(&dom->base);
@@ -416,11 +485,11 @@ nvkm_perfdom_dtor(struct nvkm_object *object)
static int
nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot,
- struct nvkm_perfsig *signal[4], uint16_t logic_op,
- struct nvkm_perfctr **pctr)
+ struct nvkm_perfsig *signal[4], uint64_t source[4][8],
+ uint16_t logic_op, struct nvkm_perfctr **pctr)
{
struct nvkm_perfctr *ctr;
- int i;
+ int i, j;
if (!dom)
return -EINVAL;
@@ -432,8 +501,11 @@ nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot,
ctr->logic_op = logic_op;
ctr->slot = slot;
for (i = 0; i < 4; i++) {
- if (signal[i])
+ if (signal[i]) {
ctr->signal[i] = signal[i] - dom->signal;
+ for (j = 0; j < 8; j++)
+ ctr->source[i][j] = source[i][j];
+ }
}
list_add_tail(&ctr->head, &dom->list);
@@ -452,7 +524,7 @@ nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_perfdom *sdom = NULL;
struct nvkm_perfctr *ctr[4] = {};
struct nvkm_perfdom *dom;
- int c, s;
+ int c, s, m;
int ret;
nv_ioctl(parent, "create perfdom size %d\n", size);
@@ -464,18 +536,28 @@ nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
for (c = 0; c < ARRAY_SIZE(args->v0.ctr); c++) {
struct nvkm_perfsig *sig[4] = {};
+ u64 src[4][8];
+
for (s = 0; s < ARRAY_SIZE(args->v0.ctr[c].signal); s++) {
sig[s] = nvkm_perfsig_find(ppm, args->v0.domain,
args->v0.ctr[c].signal[s],
&sdom);
if (args->v0.ctr[c].signal[s] && !sig[s])
return -EINVAL;
+
+ for (m = 0; m < 8; m++) {
+ src[s][m] = args->v0.ctr[c].source[s][m];
+ if (src[s][m] && !nvkm_perfsrc_find(ppm, sig[s],
+ src[s][m]))
+ return -EINVAL;
+ }
}
- ret = nvkm_perfctr_new(sdom, c, sig,
+ ret = nvkm_perfctr_new(sdom, c, sig, src,
args->v0.ctr[c].logic_op, &ctr[c]);
if (ret)
return ret;
+ ctr[c]->domain = args->v0.domain;
}
if (!sdom)
diff --git a/drm/nouveau/nvkm/engine/pm/priv.h b/drm/nouveau/nvkm/engine/pm/priv.h
index 38adeb73..da419c1d 100644
--- a/drm/nouveau/nvkm/engine/pm/priv.h
+++ b/drm/nouveau/nvkm/engine/pm/priv.h
@@ -4,7 +4,9 @@
struct nvkm_perfctr {
struct list_head head;
+ u8 domain;
u8 signal[4];
+ u64 source[4][8];
int slot;
u32 logic_op;
u32 ctr;