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