[Nouveau] [PATCH RFC 15/20] pm: allow the userspace to schedule hardware counters
Samuel Pitoiset
samuel.pitoiset at gmail.com
Sun Jun 7 13:40:25 PDT 2015
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 at gmail.com>
---
drm/nouveau/include/nvif/class.h | 8 +++--
drm/nouveau/nvkm/engine/pm/base.c | 64 +++++++++++++++++++++++++--------------
drm/nouveau/nvkm/engine/pm/priv.h | 1 +
3 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h
index d85fb0d..528eac8 100644
--- a/drm/nouveau/include/nvif/class.h
+++ b/drm/nouveau/include/nvif/class.h
@@ -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 {
};
diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c
index ec02abf..5dbb3b4 100644
--- a/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drm/nouveau/nvkm/engine/pm/base.c
@@ -307,13 +307,43 @@ 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)
{
union {
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;
- /* 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);
+ dom->quad = QUAD_MASK;
}
-
- 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];
diff --git a/drm/nouveau/nvkm/engine/pm/priv.h b/drm/nouveau/nvkm/engine/pm/priv.h
index f954c98..4ed77ff 100644
--- a/drm/nouveau/nvkm/engine/pm/priv.h
+++ b/drm/nouveau/nvkm/engine/pm/priv.h
@@ -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;
--
2.4.2
More information about the Nouveau
mailing list