etnaviv: Use hash table to track BO indexes
authorMarek Vasut <marex@denx.de>
Mon, 3 Jun 2019 17:49:14 +0000 (19:49 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Wed, 14 Aug 2019 08:36:04 +0000 (10:36 +0200)
Use hash table instead of ad-hoc arrays.

Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
src/etnaviv/drm/etnaviv_bo.c
src/etnaviv/drm/etnaviv_cmd_stream.c
src/etnaviv/drm/etnaviv_priv.h

index 2b1fbbbc3c7f86fc66cc63b219cd878fb2c1a282..6436fea416244b46a1195b339922eb302fb7c8ca 100644 (file)
@@ -47,14 +47,14 @@ void _etna_bo_del(struct etna_bo *bo)
        if (bo->map)
                os_munmap(bo->map, bo->size);
 
-       if (bo->name)
-               _mesa_hash_table_remove_key(bo->dev->name_table, &bo->name);
-
        if (bo->handle) {
                struct drm_gem_close req = {
                        .handle = bo->handle,
                };
 
+               if (bo->name)
+                       _mesa_hash_table_remove_key(bo->dev->name_table, &bo->name);
+
                _mesa_hash_table_remove_key(bo->dev->handle_table, &bo->handle);
                drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
        }
index e591df297a3ea9068cbbd9b3a8c453e88fc308c3..894ad603c0808c09637e68def2cb8f4c8defd75c 100644 (file)
@@ -153,14 +153,20 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
        if (bo->current_stream == stream) {
                idx = bo->idx;
        } else {
-               /* slow-path: */
-               for (idx = 0; idx < priv->nr_bos; idx++)
-                       if (priv->bos[idx] == bo)
-                               break;
-               if (idx == priv->nr_bos) {
-                       /* not found */
+               void *val;
+
+               if (!priv->bo_table)
+                       priv->bo_table = drmHashCreate();
+
+               if (!drmHashLookup(priv->bo_table, bo->handle, &val)) {
+                       /* found */
+                       idx = (uint32_t)(uintptr_t)val;
+               } else {
                        idx = append_bo(stream, bo);
+                       val = (void *)(uintptr_t)idx;
+                       drmHashInsert(priv->bo_table, bo->handle, val);
                }
+
                bo->current_stream = stream;
                bo->idx = idx;
        }
@@ -217,6 +223,11 @@ static void flush(struct etna_cmd_stream *stream, int in_fence_fd,
                etna_bo_del(bo);
        }
 
+       if (priv->bo_table) {
+               drmHashDestroy(priv->bo_table);
+               priv->bo_table = NULL;
+       }
+
        if (out_fence_fd)
                *out_fence_fd = req.fence_fd;
 }
index 527cee30dc31d4fd150186a86507f0ab2d1d19e0..d8f053771e927ce0fcfd8ed087bcc2e1afef5a4d 100644 (file)
@@ -99,12 +99,10 @@ struct etna_bo {
        uint64_t        offset;         /* offset to mmap() */
        int             refcnt;
 
-       /* in the common case, a bo won't be referenced by more than a single
-        * command stream.  So to avoid looping over all the bo's in the
-        * reloc table to find the idx of a bo that might already be in the
-        * table, we cache the idx in the bo.  But in order to detect the
-        * slow-path where bo is ref'd in multiple streams, we also must track
-        * the current_stream for which the idx is valid.  See bo2idx().
+       /*
+        * To avoid excess hashtable lookups, cache the stream this bo was
+        * last emitted on (since that will probably also be the next ring
+        * it is emitted on).
         */
        struct etna_cmd_stream *current_stream;
        uint32_t idx;
@@ -154,6 +152,8 @@ struct etna_cmd_stream_priv {
        /* notify callback if buffer reset happened */
        void (*reset_notify)(struct etna_cmd_stream *stream, void *priv);
        void *reset_notify_priv;
+
+       void *bo_table;
 };
 
 struct etna_perfmon {