[Nouveau] [RFC PATCH 3/8] nv50: allocate and map a notifier buffer object for PM

Samuel Pitoiset samuel.pitoiset at gmail.com
Sun Jun 28 00:42:29 PDT 2015



On 06/26/2015 01:02 AM, Ilia Mirkin wrote:
> On Mon, Jun 22, 2015 at 4:53 PM, Samuel Pitoiset
> <samuel.pitoiset at gmail.com> wrote:
>> This notifier buffer object will be used to read back global performance
>> counters results written by the kernel.
>>
>> For each domain, we will store the handle of the perfdom object, an
>> array of 4 counters and the number of cycles. Like the Gallium's HUD,
>> we keep a list of busy queries in a ring in order to prevent stalls
>> when reading queries.
>>
>> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
>> ---
>>   src/gallium/drivers/nouveau/nv50/nv50_screen.c | 29 ++++++++++++++++++++++++++
>>   src/gallium/drivers/nouveau/nv50/nv50_screen.h |  6 ++++++
>>   2 files changed, 35 insertions(+)
>>
>> diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
>> index c985344..3a99cc8 100644
>> --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
>> +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
>> @@ -368,6 +368,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
>>      nouveau_object_del(&screen->m2mf);
>>      nouveau_object_del(&screen->sync);
>>      nouveau_object_del(&screen->sw);
>> +   nouveau_object_del(&screen->query);
>>
>>      nouveau_screen_fini(&screen->base);
>>
>> @@ -699,9 +700,11 @@ nv50_screen_create(struct nouveau_device *dev)
>>      struct nv50_screen *screen;
>>      struct pipe_screen *pscreen;
>>      struct nouveau_object *chan;
>> +   struct nv04_fifo *fifo;
>>      uint64_t value;
>>      uint32_t tesla_class;
>>      unsigned stack_size;
>> +   uint32_t length;
>>      int ret;
>>
>>      screen = CALLOC_STRUCT(nv50_screen);
>> @@ -727,6 +730,7 @@ nv50_screen_create(struct nouveau_device *dev)
>>      screen->base.pushbuf->rsvd_kick = 5;
>>
>>      chan = screen->base.channel;
>> +   fifo = chan->data;
>>
>>      pscreen->destroy = nv50_screen_destroy;
>>      pscreen->context_create = nv50_create;
>> @@ -772,6 +776,23 @@ nv50_screen_create(struct nouveau_device *dev)
>>         goto fail;
>>      }
>>
>> +   /* Compute size (in bytes) of the notifier buffer object which is used
>> +    * in order to read back global performance counters results written
>> +    * by the kernel. For each domain, we store the handle of the perfdom
>> +    * object, an array of 4 counters and the number of cycles. Like for
>> +    * the Gallium's HUD, we keep a list of busy queries in a ring in order
>> +    * to prevent stalls when reading queries. */
>> +   length = (1 + (NV50_HW_PM_RING_BUFFER_NUM_DOMAINS * 6) *
>> +      NV50_HW_PM_RING_BUFFER_MAX_QUERIES) * 4;
> This calculation may become apparent to me later, but it certainly
> isn't now. What's the *6? You refer to an array of 4 counters...
> should that have been 6 counters? Or should this have been a 4?

This refers to the handle of the object, the array of 4 counters and the 
number of cycles.
In other words, for each domain we store: id, ctr0, ctr1, ctr2, ctr3, clk.

>
>> +
>> +   ret = nouveau_object_new(chan, 0xbeef0302, NOUVEAU_NOTIFIER_CLASS,
>> +                            &(struct nv04_notify){ .length = length },
>> +                            sizeof(struct nv04_notify), &screen->query);
>> +   if (ret) {
>> +       NOUVEAU_ERR("Failed to allocate notifier object for PM: %d\n", ret);
>> +       goto fail;
>> +   }
>> +
>>      ret = nouveau_object_new(chan, 0xbeef506e, 0x506e,
>>                               NULL, 0, &screen->sw);
>>      if (ret) {
>> @@ -845,6 +866,14 @@ nv50_screen_create(struct nouveau_device *dev)
>>      nouveau_heap_init(&screen->gp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2);
>>      nouveau_heap_init(&screen->fp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2);
>>
>> +   ret = nouveau_bo_wrap(screen->base.device, fifo->notify, &screen->notify_bo);
>> +   if (ret == 0)
>> +      nouveau_bo_map(screen->notify_bo, 0, screen->base.client);
> ret = ...

Good catch, thanks.

>
>> +   if (ret) {
>> +      NOUVEAU_ERR("Failed to map notifier object for PM: %d\n", ret);
>> +      goto fail;
>> +   }
>> +
>>      nouveau_getparam(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value);
>>
>>      screen->TPs = util_bitcount(value & 0xffff);
>> diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.h b/src/gallium/drivers/nouveau/nv50/nv50_screen.h
>> index 69fdfdb..71a5247 100644
>> --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.h
>> +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.h
>> @@ -59,6 +59,7 @@ struct nv50_screen {
>>      struct nouveau_bo *txc; /* TIC (offset 0) and TSC (65536) */
>>      struct nouveau_bo *stack_bo;
>>      struct nouveau_bo *tls_bo;
>> +   struct nouveau_bo *notify_bo;
>>
>>      unsigned TPs;
>>      unsigned MPsInTP;
>> @@ -89,6 +90,7 @@ struct nv50_screen {
>>      } fence;
>>
>>      struct nouveau_object *sync;
>> +   struct nouveau_object *query;
>>
>>      struct nouveau_object *tesla;
>>      struct nouveau_object *eng2d;
>> @@ -96,6 +98,10 @@ struct nv50_screen {
>>      struct nouveau_object *sw;
>>   };
>>
>> +/* Parameters of the ring buffer used to read back global PM counters. */
>> +#define NV50_HW_PM_RING_BUFFER_NUM_DOMAINS 8
>> +#define NV50_HW_PM_RING_BUFFER_MAX_QUERIES 9 /* HUD_NUM_QUERIES + 1 */
>> +
>>   static INLINE struct nv50_screen *
>>   nv50_screen(struct pipe_screen *screen)
>>   {
>> --
>> 2.4.4
>>
>> _______________________________________________
>> Nouveau mailing list
>> Nouveau at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/nouveau



More information about the Nouveau mailing list