summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_gem_shrinker.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2021-04-05 20:45:31 +0300
committerRob Clark <robdclark@chromium.org>2021-04-07 21:05:48 +0300
commit63f17ef834284d9a1fa72b548a86fee1ccd01a45 (patch)
treeecad9c18cd959f43749edce9edede2091670892a /drivers/gpu/drm/msm/msm_gem_shrinker.c
parent81d4d597d4faadb1d4eb6d464362f675b5775289 (diff)
downloadlinux-63f17ef834284d9a1fa72b548a86fee1ccd01a45.tar.xz
drm/msm: Support evicting GEM objects to swap
Now that tracking is wired up for potentially evictable GEM objects, wire up shrinker and the remaining GEM bits for unpinning backing pages of inactive objects. Disabled by default for now, with an 'enable_eviction' module param to enable so that we can get some more testing on the range of generations (and iommu pairings) supported. Signed-off-by: Rob Clark <robdclark@chromium.org> Link: https://lore.kernel.org/r/20210405174532.1441497-9-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem_shrinker.c')
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index a4d85955cbd9..1187ecf9d647 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -9,12 +9,29 @@
#include "msm_gpu.h"
#include "msm_gpu_trace.h"
+/* Default disabled for now until it has some more testing on the different
+ * iommu combinations that can be paired with the driver:
+ */
+bool enable_eviction = false;
+MODULE_PARM_DESC(enable_eviction, "Enable swappable GEM buffers");
+module_param(enable_eviction, bool, 0600);
+
+static bool can_swap(void)
+{
+ return enable_eviction && get_nr_swap_pages() > 0;
+}
+
static unsigned long
msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
struct msm_drm_private *priv =
container_of(shrinker, struct msm_drm_private, shrinker);
- return priv->shrinkable_count;
+ unsigned count = priv->shrinkable_count;
+
+ if (can_swap())
+ count += priv->evictable_count;
+
+ return count;
}
static bool
@@ -32,6 +49,17 @@ purge(struct msm_gem_object *msm_obj)
return true;
}
+static bool
+evict(struct msm_gem_object *msm_obj)
+{
+ if (is_unevictable(msm_obj))
+ return false;
+
+ msm_gem_evict(&msm_obj->base);
+
+ return true;
+}
+
static unsigned long
scan(struct msm_drm_private *priv, unsigned nr_to_scan, struct list_head *list,
bool (*shrink)(struct msm_gem_object *msm_obj))
@@ -104,6 +132,16 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
if (freed > 0)
trace_msm_gem_purge(freed << PAGE_SHIFT);
+ if (can_swap() && freed < sc->nr_to_scan) {
+ int evicted = scan(priv, sc->nr_to_scan - freed,
+ &priv->inactive_willneed, evict);
+
+ if (evicted > 0)
+ trace_msm_gem_evict(evicted << PAGE_SHIFT);
+
+ freed += evicted;
+ }
+
return (freed > 0) ? freed : SHRINK_STOP;
}