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

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
...@@ -300,8 +300,12 @@ struct nvif_perfctr_v0 { ...@@ -300,8 +300,12 @@ struct nvif_perfctr_v0 {
__u8 pad06[4]; __u8 pad06[4];
}; };
#define NVIF_PERFCTR_V0_SAMPLE 0x00 #define NVIF_PERFCTR_V0_INIT 0x00
#define NVIF_PERFCTR_V0_READ 0x01 #define NVIF_PERFCTR_V0_SAMPLE 0x01
#define NVIF_PERFCTR_V0_READ 0x02
struct nvif_perfctr_init {
};
struct nvif_perfctr_sample { struct nvif_perfctr_sample {
}; };
......
...@@ -306,6 +306,36 @@ nvkm_perfmon_ofuncs = { ...@@ -306,6 +306,36 @@ nvkm_perfmon_ofuncs = {
/******************************************************************************* /*******************************************************************************
* Perfctr object classes * 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 static int
nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size) 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) ...@@ -313,7 +343,7 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size)
struct nvif_perfctr_sample none; struct nvif_perfctr_sample none;
} *args = data; } *args = data;
struct nvkm_pm *ppm = (void *)object->engine; struct nvkm_pm *ppm = (void *)object->engine;
struct nvkm_perfctr *ctr, *tmp; struct nvkm_perfctr *ctr;
struct nvkm_perfdom *dom; struct nvkm_perfdom *dom;
int ret; int ret;
...@@ -328,32 +358,15 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size) ...@@ -328,32 +358,15 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size)
/* sample previous batch of counters */ /* sample previous batch of counters */
if (dom->quad != QUAD_MASK) { if (dom->quad != QUAD_MASK) {
dom->func->next(ppm, dom); dom->func->next(ppm, dom);
tmp = NULL;
while (!list_empty(&dom->list)) { /* read counter values */
ctr = list_first_entry(&dom->list, list_for_each_entry(ctr, &dom->list, head) {
typeof(*ctr), head);
if (ctr->slot < 0) break;
if ( tmp && tmp == ctr) break;
if (!tmp) tmp = ctr;
dom->func->read(ppm, dom, ctr); dom->func->read(ppm, dom, ctr);
ctr->slot = -1; ctr->slot = -1;
list_move_tail(&ctr->head, &dom->list);
} }
}
dom->quad = QUAD_MASK;
/* setup next batch of counters for sampling */ dom->quad = QUAD_MASK;
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; return 0;
...@@ -386,6 +399,8 @@ static int ...@@ -386,6 +399,8 @@ static int
nvkm_perfctr_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) nvkm_perfctr_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{ {
switch (mthd) { switch (mthd) {
case NVIF_PERFCTR_V0_INIT:
return nvkm_perfctr_init(object, data, size);
case NVIF_PERFCTR_V0_SAMPLE: case NVIF_PERFCTR_V0_SAMPLE:
return nvkm_perfctr_sample(object, data, size); return nvkm_perfctr_sample(object, data, size);
case NVIF_PERFCTR_V0_READ: case NVIF_PERFCTR_V0_READ:
...@@ -400,6 +415,8 @@ static void ...@@ -400,6 +415,8 @@ static void
nvkm_perfctr_dtor(struct nvkm_object *object) nvkm_perfctr_dtor(struct nvkm_object *object)
{ {
struct nvkm_perfctr *ctr = (void *)object; struct nvkm_perfctr *ctr = (void *)object;
if (ctr->dom)
ctr->dom->quad |= (QUAD_FREE << ctr->slot);
if (ctr->head.next) if (ctr->head.next)
list_del(&ctr->head); list_del(&ctr->head);
nvkm_object_destroy(&ctr->base); nvkm_object_destroy(&ctr->base);
...@@ -441,6 +458,7 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ...@@ -441,6 +458,7 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret) if (ret)
return ret; return ret;
ctr->dom = dom;
ctr->slot = -1; ctr->slot = -1;
ctr->logic_op = args->v0.logic_op; ctr->logic_op = args->v0.logic_op;
ctr->signal[0] = sig[0]; ctr->signal[0] = sig[0];
......
...@@ -6,6 +6,7 @@ struct nvkm_perfctr { ...@@ -6,6 +6,7 @@ struct nvkm_perfctr {
struct nvkm_object base; struct nvkm_object base;
struct list_head head; struct list_head head;
struct nvkm_perfsig *signal[4]; struct nvkm_perfsig *signal[4];
struct nvkm_perfdom *dom;
int slot; int slot;
u32 logic_op; u32 logic_op;
u32 clk; u32 clk;
......
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