Commit 6137b5a7 authored by Samuel Pitoiset's avatar Samuel Pitoiset Committed by Ben Skeggs

drm/nouveau/pm: allow the userspace to configure sources

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 0f380436
...@@ -297,6 +297,7 @@ struct nvif_perfdom_v0 { ...@@ -297,6 +297,7 @@ struct nvif_perfdom_v0 {
__u8 pad03[1]; __u8 pad03[1];
struct { struct {
__u8 signal[4]; __u8 signal[4];
__u64 source[4][8];
__u16 logic_op; __u16 logic_op;
} ctr[4]; } ctr[4];
}; };
......
...@@ -125,6 +125,66 @@ nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si) ...@@ -125,6 +125,66 @@ nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si)
return NULL; 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 * Perfmon object classes
******************************************************************************/ ******************************************************************************/
...@@ -319,10 +379,15 @@ nvkm_perfdom_init(struct nvkm_object *object, void *data, u32 size) ...@@ -319,10 +379,15 @@ nvkm_perfdom_init(struct nvkm_object *object, void *data, u32 size)
} else } else
return ret; return ret;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++) {
if (dom->ctr[i]) if (dom->ctr[i]) {
dom->func->init(ppm, dom, 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 */ /* start next batch of counters for sampling */
dom->func->next(ppm, dom); dom->func->next(ppm, dom);
return 0; return 0;
...@@ -402,13 +467,17 @@ nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) ...@@ -402,13 +467,17 @@ nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
static void static void
nvkm_perfdom_dtor(struct nvkm_object *object) nvkm_perfdom_dtor(struct nvkm_object *object)
{ {
struct nvkm_pm *ppm = (void *)object->engine;
struct nvkm_perfdom *dom = (void *)object; struct nvkm_perfdom *dom = (void *)object;
int i; int i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
struct nvkm_perfctr *ctr = dom->ctr[i]; struct nvkm_perfctr *ctr = dom->ctr[i];
if (ctr && ctr->head.next) if (ctr) {
nvkm_perfsrc_disable(ppm, ctr);
if (ctr->head.next)
list_del(&ctr->head); list_del(&ctr->head);
}
kfree(ctr); kfree(ctr);
} }
nvkm_object_destroy(&dom->base); nvkm_object_destroy(&dom->base);
...@@ -416,11 +485,11 @@ nvkm_perfdom_dtor(struct nvkm_object *object) ...@@ -416,11 +485,11 @@ nvkm_perfdom_dtor(struct nvkm_object *object)
static int static int
nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot, nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot,
struct nvkm_perfsig *signal[4], uint16_t logic_op, struct nvkm_perfsig *signal[4], uint64_t source[4][8],
struct nvkm_perfctr **pctr) uint16_t logic_op, struct nvkm_perfctr **pctr)
{ {
struct nvkm_perfctr *ctr; struct nvkm_perfctr *ctr;
int i; int i, j;
if (!dom) if (!dom)
return -EINVAL; return -EINVAL;
...@@ -432,8 +501,11 @@ nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot, ...@@ -432,8 +501,11 @@ nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot,
ctr->logic_op = logic_op; ctr->logic_op = logic_op;
ctr->slot = slot; ctr->slot = slot;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (signal[i]) if (signal[i]) {
ctr->signal[i] = signal[i] - dom->signal; 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); list_add_tail(&ctr->head, &dom->list);
...@@ -452,7 +524,7 @@ nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ...@@ -452,7 +524,7 @@ nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_perfdom *sdom = NULL; struct nvkm_perfdom *sdom = NULL;
struct nvkm_perfctr *ctr[4] = {}; struct nvkm_perfctr *ctr[4] = {};
struct nvkm_perfdom *dom; struct nvkm_perfdom *dom;
int c, s; int c, s, m;
int ret; int ret;
nv_ioctl(parent, "create perfdom size %d\n", size); nv_ioctl(parent, "create perfdom size %d\n", size);
...@@ -464,18 +536,28 @@ nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ...@@ -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++) { for (c = 0; c < ARRAY_SIZE(args->v0.ctr); c++) {
struct nvkm_perfsig *sig[4] = {}; struct nvkm_perfsig *sig[4] = {};
u64 src[4][8];
for (s = 0; s < ARRAY_SIZE(args->v0.ctr[c].signal); s++) { for (s = 0; s < ARRAY_SIZE(args->v0.ctr[c].signal); s++) {
sig[s] = nvkm_perfsig_find(ppm, args->v0.domain, sig[s] = nvkm_perfsig_find(ppm, args->v0.domain,
args->v0.ctr[c].signal[s], args->v0.ctr[c].signal[s],
&sdom); &sdom);
if (args->v0.ctr[c].signal[s] && !sig[s]) if (args->v0.ctr[c].signal[s] && !sig[s])
return -EINVAL; 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]); args->v0.ctr[c].logic_op, &ctr[c]);
if (ret) if (ret)
return ret; return ret;
ctr[c]->domain = args->v0.domain;
} }
if (!sdom) if (!sdom)
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
struct nvkm_perfctr { struct nvkm_perfctr {
struct list_head head; struct list_head head;
u8 domain;
u8 signal[4]; u8 signal[4];
u64 source[4][8];
int slot; int slot;
u32 logic_op; u32 logic_op;
u32 ctr; u32 ctr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment