static boolean nv50_hw_sm_begin_query(struct nv50_context *nv50, struct nv50_hw_query *hq) { struct nv50_screen *screen = nv50->screen; struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_hw_sm_query *hsq = nv50_hw_sm_query(hq); const struct nv50_hw_sm_query_cfg *cfg; uint16_t func; int i, c; cfg = nv50_hw_sm_query_get_cfg(nv50, hq); /* check if we have enough free counter slots */ if (screen->pm.num_hw_sm_active + cfg->num_counters > 4) { NOUVEAU_ERR("Not enough free MP counter slots !\n"); return false; } assert(cfg->num_counters <= 4); PUSH_SPACE(push, 4 * 4); /* set sequence field to 0 (used to check if result is available) */ for (i = 0; i < screen->MPsInTP; ++i) { const unsigned b = (0x14 / 4) * i; hq->data[b + 16] = 0; } hq->sequence++; for (i = 0; i < cfg->num_counters; i++) { screen->pm.num_hw_sm_active++; /* find free counter slots */ for (c = 0; c < 4; ++c) { if (!screen->pm.mp_counter[c]) { hsq->ctr[i] = c; screen->pm.mp_counter[c] = hsq; break; } } /* select func to aggregate counters */ func = nv50_hw_sm_get_func(c); /* configure and reset the counter(s) */ BEGIN_NV04(push, NV50_COMPUTE(MP_PM_CONTROL(c)), 1); PUSH_DATA (push, (cfg->ctr[i].sig << 24) | (func << 8) | cfg->ctr[i].unit | cfg->ctr[i].mode); BEGIN_NV04(push, NV50_COMPUTE(MP_PM_SET(c)), 1); PUSH_DATA (push, 0); } return true; }
void nve4_mp_pm_query_begin(struct nvc0_context *nvc0, struct nvc0_query *q) { struct nvc0_screen *screen = nvc0->screen; struct nouveau_pushbuf *push = nvc0->base.pushbuf; const struct nve4_mp_pm_query_cfg *cfg; unsigned i, c; unsigned num_ab[2] = { 0, 0 }; cfg = &nve4_mp_pm_queries[q->type - PIPE_QUERY_DRIVER_SPECIFIC]; /* check if we have enough free counter slots */ for (i = 0; i < cfg->num_counters; ++i) num_ab[cfg->ctr[i].sig_dom]++; if (screen->pm.num_mp_pm_active[0] + num_ab[0] > 4 || screen->pm.num_mp_pm_active[1] + num_ab[1] > 4) { NOUVEAU_ERR("Not enough free MP counter slots !\n"); return; } assert(cfg->num_counters <= 4); PUSH_SPACE(push, 4 * 8 + 6); if (!screen->pm.mp_counters_enabled) { screen->pm.mp_counters_enabled = TRUE; BEGIN_NVC0(push, SUBC_SW(0x06ac), 1); PUSH_DATA (push, 0x1fcb); } /* set sequence field to 0 (used to check if result is available) */ for (i = 0; i < screen->mp_count; ++i) q->data[i * 10 + 10] = 0; for (i = 0; i < cfg->num_counters; ++i) { const unsigned d = cfg->ctr[i].sig_dom; if (!screen->pm.num_mp_pm_active[d]) { uint32_t m = (1 << 22) | (1 << (7 + (8 * !d))); if (screen->pm.num_mp_pm_active[!d]) m |= 1 << (7 + (8 * d)); BEGIN_NVC0(push, SUBC_SW(0x0600), 1); PUSH_DATA (push, m); } screen->pm.num_mp_pm_active[d]++; for (c = d * 4; c < (d * 4 + 4); ++c) { if (!screen->pm.mp_counter[c]) { q->ctr[i] = c; screen->pm.mp_counter[c] = (struct pipe_query *)q; break; } } assert(c <= (d * 4 + 3)); /* must succeed, already checked for space */ /* configure and reset the counter(s) */ if (d == 0) BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_A_SIGSEL(c & 3)), 1); else BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_B_SIGSEL(c & 3)), 1); PUSH_DATA (push, cfg->ctr[i].sig_sel); BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_SRCSEL(c)), 1); PUSH_DATA (push, cfg->ctr[i].src_sel + 0x2108421 * (c & 3)); BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_FUNC(c)), 1); PUSH_DATA (push, (cfg->ctr[i].func << 4) | cfg->ctr[i].mode); BEGIN_NVC0(push, NVE4_COMPUTE(MP_PM_SET(c)), 1); PUSH_DATA (push, 0); } }