panfrost: Add madvise support to BO cache
authorRob Herring <robh@kernel.org>
Wed, 31 Jul 2019 23:28:37 +0000 (23:28 +0000)
committerRob Herring <robh@kernel.org>
Tue, 20 Aug 2019 00:33:20 +0000 (19:33 -0500)
The kernel now supports madvise ioctl to indicate which BOs can be freed
when there is memory pressure. Mark BOs purgeable when they are in the
BO cache. The BOs must also be munmapped when they are in the cache or
they cannot be purged.

We could optimize avoiding the madvise ioctl on older kernels once the
driver version bump lands, but probably not worth it given the other
driver features also being added.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Rob Herring <robh@kernel.org>
src/gallium/drivers/panfrost/pan_bo_cache.c
src/gallium/drivers/panfrost/pan_drm.c

index 7378d0a8abea19ca1bb7ae195f027dc17c28b1f7..9dd6b694b725c08ddfd4f203dd524919ac310e50 100644 (file)
@@ -23,6 +23,8 @@
  * Authors (Collabora):
  *   Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
  */
+#include <xf86drm.h>
+#include "drm-uapi/panfrost_drm.h"
 
 #include "pan_screen.h"
 #include "util/u_math.h"
@@ -88,9 +90,21 @@ panfrost_bo_cache_fetch(
         list_for_each_entry_safe(struct panfrost_bo, entry, bucket, link) {
                 if (entry->size >= size &&
                     entry->flags == flags) {
+                        int ret;
+                        struct drm_panfrost_madvise madv;
+
                         /* This one works, splice it out of the cache */
                         list_del(&entry->link);
 
+                        madv.handle = entry->gem_handle;
+                        madv.madv = PANFROST_MADV_WILLNEED;
+                        madv.retained = 0;
+
+                        ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
+                        if (!ret && !madv.retained) {
+                                panfrost_drm_release_bo(screen, entry, false);
+                                continue;
+                        }
                         /* Let's go! */
                         return entry;
                 }
@@ -109,6 +123,13 @@ panfrost_bo_cache_put(
                 struct panfrost_bo *bo)
 {
         struct list_head *bucket = pan_bucket(screen, bo->size);
+        struct drm_panfrost_madvise madv;
+
+        madv.handle = bo->gem_handle;
+        madv.madv = PANFROST_MADV_DONTNEED;
+       madv.retained = 0;
+
+        drmIoctl(screen->fd, DRM_IOCTL_PANFROST_MADVISE, &madv);
 
         /* Add us to the bucket */
         list_addtail(&bo->link, bucket);
index 36a6b975680aaf4b68d8e7c2ca9cbe9b4ebea84b..28a4287202bd4b2aff397dd7d70ba342f33463b0 100644 (file)
@@ -163,6 +163,8 @@ panfrost_drm_release_bo(struct panfrost_screen *screen, struct panfrost_bo *bo,
         /* Rather than freeing the BO now, we'll cache the BO for later
          * allocations if we're allowed to */
 
+        panfrost_drm_munmap_bo(screen, bo);
+
         if (cacheable) {
                 bool cached = panfrost_bo_cache_put(screen, bo);
 
@@ -172,8 +174,6 @@ panfrost_drm_release_bo(struct panfrost_screen *screen, struct panfrost_bo *bo,
 
         /* Otherwise, if the BO wasn't cached, we'll legitimately free the BO */
 
-        panfrost_drm_munmap_bo(screen, bo);
-
         ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
         if (ret) {
                 fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %m\n");