aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-09-09 06:16:08 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-09-19 08:41:14 -0400
commit21ab4e746d4d455fef66e2bef8c0442eb369a1d4 (patch)
tree57d7d64809609c142e8fed7ff31be1615ab10d22 /drivers
parent344c5bbcb7a282cc59e2f111c8801106c4fe315c (diff)
drm/i915: Objects on the unbound list may still have an active reference
Due to the lazy retirement semantics, even though we have unbound an object, it may still hold onto an active reference. So in the debug code, play safe. v2: Export i915_gem_shrink() rather than opencoding it. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c34
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c111
3 files changed, 74 insertions, 77 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 2cbc85f3b237..063b44817e08 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3826,7 +3826,6 @@ i915_drop_caches_set(void *data, u64 val)
3826{ 3826{
3827 struct drm_device *dev = data; 3827 struct drm_device *dev = data;
3828 struct drm_i915_private *dev_priv = dev->dev_private; 3828 struct drm_i915_private *dev_priv = dev->dev_private;
3829 struct drm_i915_gem_object *obj, *next;
3830 int ret; 3829 int ret;
3831 3830
3832 DRM_DEBUG("Dropping caches: 0x%08llx\n", val); 3831 DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
@@ -3846,36 +3845,11 @@ i915_drop_caches_set(void *data, u64 val)
3846 if (val & (DROP_RETIRE | DROP_ACTIVE)) 3845 if (val & (DROP_RETIRE | DROP_ACTIVE))
3847 i915_gem_retire_requests(dev); 3846 i915_gem_retire_requests(dev);
3848 3847
3849 if (val & DROP_BOUND) { 3848 if (val & DROP_BOUND)
3850 list_for_each_entry_safe(obj, next, &dev_priv->mm.bound_list, 3849 i915_gem_shrink(dev_priv, LONG_MAX, I915_SHRINK_BOUND);
3851 global_list) {
3852 struct i915_vma *vma, *v;
3853 3850
3854 ret = 0; 3851 if (val & DROP_UNBOUND)
3855 drm_gem_object_reference(&obj->base); 3852 i915_gem_shrink(dev_priv, LONG_MAX, I915_SHRINK_UNBOUND);
3856 list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link) {
3857 if (vma->pin_count)
3858 continue;
3859
3860 ret = i915_vma_unbind(vma);
3861 if (ret)
3862 break;
3863 }
3864 drm_gem_object_unreference(&obj->base);
3865 if (ret)
3866 goto unlock;
3867 }
3868 }
3869
3870 if (val & DROP_UNBOUND) {
3871 list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
3872 global_list)
3873 if (obj->pages_pin_count == 0) {
3874 ret = i915_gem_object_put_pages(obj);
3875 if (ret)
3876 goto unlock;
3877 }
3878 }
3879 3853
3880unlock: 3854unlock:
3881 mutex_unlock(&dev->struct_mutex); 3855 mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 88a8b72b553e..17dfce0f4e68 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2368,6 +2368,12 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
2368int i915_gem_wait_ioctl(struct drm_device *dev, void *data, 2368int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
2369 struct drm_file *file_priv); 2369 struct drm_file *file_priv);
2370void i915_gem_load(struct drm_device *dev); 2370void i915_gem_load(struct drm_device *dev);
2371unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
2372 long target,
2373 unsigned flags);
2374#define I915_SHRINK_PURGEABLE 0x1
2375#define I915_SHRINK_UNBOUND 0x2
2376#define I915_SHRINK_BOUND 0x4
2371void *i915_gem_object_alloc(struct drm_device *dev); 2377void *i915_gem_object_alloc(struct drm_device *dev);
2372void i915_gem_object_free(struct drm_i915_gem_object *obj); 2378void i915_gem_object_free(struct drm_i915_gem_object *obj);
2373void i915_gem_object_init(struct drm_i915_gem_object *obj, 2379void i915_gem_object_init(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4ca3a6dcf10b..1ef6700e5d98 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -60,7 +60,6 @@ static unsigned long i915_gem_shrinker_scan(struct shrinker *shrinker,
60static int i915_gem_shrinker_oom(struct notifier_block *nb, 60static int i915_gem_shrinker_oom(struct notifier_block *nb,
61 unsigned long event, 61 unsigned long event,
62 void *ptr); 62 void *ptr);
63static unsigned long i915_gem_purge(struct drm_i915_private *dev_priv, long target);
64static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv); 63static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
65 64
66static bool cpu_cache_is_coherent(struct drm_device *dev, 65static bool cpu_cache_is_coherent(struct drm_device *dev,
@@ -1741,7 +1740,11 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
1741 * offsets on purgeable objects by truncating it and marking it purged, 1740 * offsets on purgeable objects by truncating it and marking it purged,
1742 * which prevents userspace from ever using that object again. 1741 * which prevents userspace from ever using that object again.
1743 */ 1742 */
1744 i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT); 1743 i915_gem_shrink(dev_priv,
1744 obj->base.size >> PAGE_SHIFT,
1745 I915_SHRINK_BOUND |
1746 I915_SHRINK_UNBOUND |
1747 I915_SHRINK_PURGEABLE);
1745 ret = drm_gem_create_mmap_offset(&obj->base); 1748 ret = drm_gem_create_mmap_offset(&obj->base);
1746 if (ret != -ENOSPC) 1749 if (ret != -ENOSPC)
1747 goto out; 1750 goto out;
@@ -1938,12 +1941,11 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
1938 return 0; 1941 return 0;
1939} 1942}
1940 1943
1941static unsigned long 1944unsigned long
1942__i915_gem_shrink(struct drm_i915_private *dev_priv, long target, 1945i915_gem_shrink(struct drm_i915_private *dev_priv,
1943 bool purgeable_only) 1946 long target, unsigned flags)
1944{ 1947{
1945 struct list_head still_in_list; 1948 const bool purgeable_only = flags & I915_SHRINK_PURGEABLE;
1946 struct drm_i915_gem_object *obj;
1947 unsigned long count = 0; 1949 unsigned long count = 0;
1948 1950
1949 /* 1951 /*
@@ -1965,62 +1967,68 @@ __i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
1965 * dev->struct_mutex and so we won't ever be able to observe an 1967 * dev->struct_mutex and so we won't ever be able to observe an
1966 * object on the bound_list with a reference count equals 0. 1968 * object on the bound_list with a reference count equals 0.
1967 */ 1969 */
1968 INIT_LIST_HEAD(&still_in_list); 1970 if (flags & I915_SHRINK_UNBOUND) {
1969 while (count < target && !list_empty(&dev_priv->mm.unbound_list)) { 1971 struct list_head still_in_list;
1970 obj = list_first_entry(&dev_priv->mm.unbound_list,
1971 typeof(*obj), global_list);
1972 list_move_tail(&obj->global_list, &still_in_list);
1973 1972
1974 if (!i915_gem_object_is_purgeable(obj) && purgeable_only) 1973 INIT_LIST_HEAD(&still_in_list);
1975 continue; 1974 while (count < target && !list_empty(&dev_priv->mm.unbound_list)) {
1975 struct drm_i915_gem_object *obj;
1976 1976
1977 drm_gem_object_reference(&obj->base); 1977 obj = list_first_entry(&dev_priv->mm.unbound_list,
1978 typeof(*obj), global_list);
1979 list_move_tail(&obj->global_list, &still_in_list);
1978 1980
1979 if (i915_gem_object_put_pages(obj) == 0) 1981 if (!i915_gem_object_is_purgeable(obj) && purgeable_only)
1980 count += obj->base.size >> PAGE_SHIFT; 1982 continue;
1981 1983
1982 drm_gem_object_unreference(&obj->base); 1984 drm_gem_object_reference(&obj->base);
1985
1986 if (i915_gem_object_put_pages(obj) == 0)
1987 count += obj->base.size >> PAGE_SHIFT;
1988
1989 drm_gem_object_unreference(&obj->base);
1990 }
1991 list_splice(&still_in_list, &dev_priv->mm.unbound_list);
1983 } 1992 }
1984 list_splice(&still_in_list, &dev_priv->mm.unbound_list);
1985 1993
1986 INIT_LIST_HEAD(&still_in_list); 1994 if (flags & I915_SHRINK_BOUND) {
1987 while (count < target && !list_empty(&dev_priv->mm.bound_list)) { 1995 struct list_head still_in_list;
1988 struct i915_vma *vma, *v;
1989 1996
1990 obj = list_first_entry(&dev_priv->mm.bound_list, 1997 INIT_LIST_HEAD(&still_in_list);
1991 typeof(*obj), global_list); 1998 while (count < target && !list_empty(&dev_priv->mm.bound_list)) {
1992 list_move_tail(&obj->global_list, &still_in_list); 1999 struct drm_i915_gem_object *obj;
2000 struct i915_vma *vma, *v;
1993 2001
1994 if (!i915_gem_object_is_purgeable(obj) && purgeable_only) 2002 obj = list_first_entry(&dev_priv->mm.bound_list,
1995 continue; 2003 typeof(*obj), global_list);
2004 list_move_tail(&obj->global_list, &still_in_list);
1996 2005
1997 drm_gem_object_reference(&obj->base); 2006 if (!i915_gem_object_is_purgeable(obj) && purgeable_only)
2007 continue;
1998 2008
1999 list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link) 2009 drm_gem_object_reference(&obj->base);
2000 if (i915_vma_unbind(vma))
2001 break;
2002 2010
2003 if (i915_gem_object_put_pages(obj) == 0) 2011 list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link)
2004 count += obj->base.size >> PAGE_SHIFT; 2012 if (i915_vma_unbind(vma))
2013 break;
2005 2014
2006 drm_gem_object_unreference(&obj->base); 2015 if (i915_gem_object_put_pages(obj) == 0)
2016 count += obj->base.size >> PAGE_SHIFT;
2017
2018 drm_gem_object_unreference(&obj->base);
2019 }
2020 list_splice(&still_in_list, &dev_priv->mm.bound_list);
2007 } 2021 }
2008 list_splice(&still_in_list, &dev_priv->mm.bound_list);
2009 2022
2010 return count; 2023 return count;
2011} 2024}
2012 2025
2013static unsigned long 2026static unsigned long
2014i915_gem_purge(struct drm_i915_private *dev_priv, long target)
2015{
2016 return __i915_gem_shrink(dev_priv, target, true);
2017}
2018
2019static unsigned long
2020i915_gem_shrink_all(struct drm_i915_private *dev_priv) 2027i915_gem_shrink_all(struct drm_i915_private *dev_priv)
2021{ 2028{
2022 i915_gem_evict_everything(dev_priv->dev); 2029 i915_gem_evict_everything(dev_priv->dev);
2023 return __i915_gem_shrink(dev_priv, LONG_MAX, false); 2030 return i915_gem_shrink(dev_priv, LONG_MAX,
2031 I915_SHRINK_BOUND | I915_SHRINK_UNBOUND);
2024} 2032}
2025 2033
2026static int 2034static int
@@ -2067,7 +2075,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
2067 for (i = 0; i < page_count; i++) { 2075 for (i = 0; i < page_count; i++) {
2068 page = shmem_read_mapping_page_gfp(mapping, i, gfp); 2076 page = shmem_read_mapping_page_gfp(mapping, i, gfp);
2069 if (IS_ERR(page)) { 2077 if (IS_ERR(page)) {
2070 i915_gem_purge(dev_priv, page_count); 2078 i915_gem_shrink(dev_priv,
2079 page_count,
2080 I915_SHRINK_BOUND |
2081 I915_SHRINK_UNBOUND |
2082 I915_SHRINK_PURGEABLE);
2071 page = shmem_read_mapping_page_gfp(mapping, i, gfp); 2083 page = shmem_read_mapping_page_gfp(mapping, i, gfp);
2072 } 2084 }
2073 if (IS_ERR(page)) { 2085 if (IS_ERR(page)) {
@@ -5261,11 +5273,16 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
5261 if (!i915_gem_shrinker_lock(dev, &unlock)) 5273 if (!i915_gem_shrinker_lock(dev, &unlock))
5262 return SHRINK_STOP; 5274 return SHRINK_STOP;
5263 5275
5264 freed = i915_gem_purge(dev_priv, sc->nr_to_scan); 5276 freed = i915_gem_shrink(dev_priv,
5277 sc->nr_to_scan,
5278 I915_SHRINK_BOUND |
5279 I915_SHRINK_UNBOUND |
5280 I915_SHRINK_PURGEABLE);
5265 if (freed < sc->nr_to_scan) 5281 if (freed < sc->nr_to_scan)
5266 freed += __i915_gem_shrink(dev_priv, 5282 freed += i915_gem_shrink(dev_priv,
5267 sc->nr_to_scan - freed, 5283 sc->nr_to_scan - freed,
5268 false); 5284 I915_SHRINK_BOUND |
5285 I915_SHRINK_UNBOUND);
5269 if (unlock) 5286 if (unlock)
5270 mutex_unlock(&dev->struct_mutex); 5287 mutex_unlock(&dev->struct_mutex);
5271 5288