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;
}
Example #2
0
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);
   }
}