0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/list.h>
0010
0011 #include <drm/drm_device.h>
0012 #include <drm/drm_gem_shmem_helper.h>
0013
0014 #include "panfrost_device.h"
0015 #include "panfrost_gem.h"
0016 #include "panfrost_mmu.h"
0017
0018 static unsigned long
0019 panfrost_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
0020 {
0021 struct panfrost_device *pfdev =
0022 container_of(shrinker, struct panfrost_device, shrinker);
0023 struct drm_gem_shmem_object *shmem;
0024 unsigned long count = 0;
0025
0026 if (!mutex_trylock(&pfdev->shrinker_lock))
0027 return 0;
0028
0029 list_for_each_entry(shmem, &pfdev->shrinker_list, madv_list) {
0030 if (drm_gem_shmem_is_purgeable(shmem))
0031 count += shmem->base.size >> PAGE_SHIFT;
0032 }
0033
0034 mutex_unlock(&pfdev->shrinker_lock);
0035
0036 return count;
0037 }
0038
0039 static bool panfrost_gem_purge(struct drm_gem_object *obj)
0040 {
0041 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
0042 struct panfrost_gem_object *bo = to_panfrost_bo(obj);
0043 bool ret = false;
0044
0045 if (atomic_read(&bo->gpu_usecount))
0046 return false;
0047
0048 if (!mutex_trylock(&bo->mappings.lock))
0049 return false;
0050
0051 if (!mutex_trylock(&shmem->pages_lock))
0052 goto unlock_mappings;
0053
0054 panfrost_gem_teardown_mappings_locked(bo);
0055 drm_gem_shmem_purge_locked(&bo->base);
0056 ret = true;
0057
0058 mutex_unlock(&shmem->pages_lock);
0059
0060 unlock_mappings:
0061 mutex_unlock(&bo->mappings.lock);
0062 return ret;
0063 }
0064
0065 static unsigned long
0066 panfrost_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
0067 {
0068 struct panfrost_device *pfdev =
0069 container_of(shrinker, struct panfrost_device, shrinker);
0070 struct drm_gem_shmem_object *shmem, *tmp;
0071 unsigned long freed = 0;
0072
0073 if (!mutex_trylock(&pfdev->shrinker_lock))
0074 return SHRINK_STOP;
0075
0076 list_for_each_entry_safe(shmem, tmp, &pfdev->shrinker_list, madv_list) {
0077 if (freed >= sc->nr_to_scan)
0078 break;
0079 if (drm_gem_shmem_is_purgeable(shmem) &&
0080 panfrost_gem_purge(&shmem->base)) {
0081 freed += shmem->base.size >> PAGE_SHIFT;
0082 list_del_init(&shmem->madv_list);
0083 }
0084 }
0085
0086 mutex_unlock(&pfdev->shrinker_lock);
0087
0088 if (freed > 0)
0089 pr_info_ratelimited("Purging %lu bytes\n", freed << PAGE_SHIFT);
0090
0091 return freed;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100 void panfrost_gem_shrinker_init(struct drm_device *dev)
0101 {
0102 struct panfrost_device *pfdev = dev->dev_private;
0103 pfdev->shrinker.count_objects = panfrost_gem_shrinker_count;
0104 pfdev->shrinker.scan_objects = panfrost_gem_shrinker_scan;
0105 pfdev->shrinker.seeks = DEFAULT_SEEKS;
0106 WARN_ON(register_shrinker(&pfdev->shrinker, "drm-panfrost"));
0107 }
0108
0109
0110
0111
0112
0113
0114
0115 void panfrost_gem_shrinker_cleanup(struct drm_device *dev)
0116 {
0117 struct panfrost_device *pfdev = dev->dev_private;
0118
0119 if (pfdev->shrinker.nr_deferred) {
0120 unregister_shrinker(&pfdev->shrinker);
0121 }
0122 }