summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_gem.h
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2021-04-01 04:27:19 +0300
committerRob Clark <robdclark@chromium.org>2021-04-07 21:05:42 +0300
commitcc8a4d5a1bd84a37ff1827e2902c459e9b2d4e25 (patch)
tree7de47a94da6e7aee4f9d19cf7be12351b926035a /drivers/gpu/drm/msm/msm_gem.h
parentbc90dc33c46c8b98843f33f40446b7fdb0ba8f1c (diff)
downloadlinux-cc8a4d5a1bd84a37ff1827e2902c459e9b2d4e25.tar.xz
drm/msm: Avoid mutex in shrinker_count()
When the system is under heavy memory pressure, we can end up with lots of concurrent calls into the shrinker. Keeping a running tab on what we can shrink avoids grabbing a lock in shrinker->count(), and avoids shrinker->scan() getting called when not profitable. Also, we can keep purged objects in their own list to avoid re-traversing them to help cut down time in the critical section further. Signed-off-by: Rob Clark <robdclark@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Link: https://lore.kernel.org/r/20210401012722.527712-3-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem.h')
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h53
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 7a9107cf1818..13aabfe92dac 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -51,17 +51,23 @@ struct msm_gem_object {
uint8_t madv;
/**
+ * Is object on inactive_dontneed list (ie. counted in priv->shrinkable_count)?
+ */
+ bool dontneed : 1;
+
+ /**
* count of active vmap'ing
*/
uint8_t vmap_count;
- /* And object is either:
- * inactive - on priv->inactive_list
+ /**
+ * An object is either:
+ * inactive - on priv->inactive_dontneed/willneed/purged depending
+ * on status
* active - on one one of the gpu's active_list.. well, at
* least for now we don't have (I don't think) hw sync between
* 2d and 3d one devices which have both, meaning we need to
* block on submit if a bo is already on other ring
- *
*/
struct list_head mm_list;
@@ -186,10 +192,16 @@ static inline bool is_active(struct msm_gem_object *msm_obj)
return msm_obj->active_count;
}
+/* imported/exported objects are not purgable: */
+static inline bool is_unpurgable(struct msm_gem_object *msm_obj)
+{
+ return msm_obj->base.dma_buf && msm_obj->base.import_attach;
+}
+
static inline bool is_purgeable(struct msm_gem_object *msm_obj)
{
return (msm_obj->madv == MSM_MADV_DONTNEED) && msm_obj->sgt &&
- !msm_obj->base.dma_buf && !msm_obj->base.import_attach;
+ !is_unpurgable(msm_obj);
}
static inline bool is_vunmapable(struct msm_gem_object *msm_obj)
@@ -198,6 +210,39 @@ static inline bool is_vunmapable(struct msm_gem_object *msm_obj)
return (msm_obj->vmap_count == 0) && msm_obj->vaddr;
}
+static inline void mark_purgable(struct msm_gem_object *msm_obj)
+{
+ struct msm_drm_private *priv = msm_obj->base.dev->dev_private;
+
+ WARN_ON(!mutex_is_locked(&priv->mm_lock));
+
+ if (is_unpurgable(msm_obj))
+ return;
+
+ if (WARN_ON(msm_obj->dontneed))
+ return;
+
+ priv->shrinkable_count += msm_obj->base.size >> PAGE_SHIFT;
+ msm_obj->dontneed = true;
+}
+
+static inline void mark_unpurgable(struct msm_gem_object *msm_obj)
+{
+ struct msm_drm_private *priv = msm_obj->base.dev->dev_private;
+
+ WARN_ON(!mutex_is_locked(&priv->mm_lock));
+
+ if (is_unpurgable(msm_obj))
+ return;
+
+ if (WARN_ON(!msm_obj->dontneed))
+ return;
+
+ priv->shrinkable_count -= msm_obj->base.size >> PAGE_SHIFT;
+ WARN_ON(priv->shrinkable_count < 0);
+ msm_obj->dontneed = false;
+}
+
void msm_gem_purge(struct drm_gem_object *obj);
void msm_gem_vunmap(struct drm_gem_object *obj);