diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-20 18:03:54 -0400 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-22 20:10:36 -0400 |
| commit | 963b483691314ed174ceb883f2b9f13b3ef7fb33 (patch) | |
| tree | 14547cca5a646c19b5eb670143a90b28761b9462 /drivers | |
| parent | 13a05fd978a110d1efcda4a09e225aa156204ea3 (diff) | |
drm/i915: Do not mis-classify clean objects as purgeable
Whilst cleaning up the patches for submission, I mis-classified non-dirty
objects as purgeable. This was causing the backing pages for those
objects to be evicted under memory-pressure, discarding valid and
unreplaceable texture data.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 55 |
1 files changed, 26 insertions, 29 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8ecc75aa79b..c69f1fa38cc8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1530,6 +1530,23 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj) | |||
| 1530 | obj_priv->last_rendering_seqno = 0; | 1530 | obj_priv->last_rendering_seqno = 0; |
| 1531 | } | 1531 | } |
| 1532 | 1532 | ||
| 1533 | /* Immediately discard the backing storage */ | ||
| 1534 | static void | ||
| 1535 | i915_gem_object_truncate(struct drm_gem_object *obj) | ||
| 1536 | { | ||
| 1537 | struct inode *inode; | ||
| 1538 | |||
| 1539 | inode = obj->filp->f_path.dentry->d_inode; | ||
| 1540 | if (inode->i_op->truncate) | ||
| 1541 | inode->i_op->truncate (inode); | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | static inline int | ||
| 1545 | i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) | ||
| 1546 | { | ||
| 1547 | return obj_priv->madv == I915_MADV_DONTNEED; | ||
| 1548 | } | ||
| 1549 | |||
| 1533 | static void | 1550 | static void |
| 1534 | i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | 1551 | i915_gem_object_move_to_inactive(struct drm_gem_object *obj) |
| 1535 | { | 1552 | { |
| @@ -2018,17 +2035,14 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 2018 | if (!list_empty(&obj_priv->list)) | 2035 | if (!list_empty(&obj_priv->list)) |
| 2019 | list_del_init(&obj_priv->list); | 2036 | list_del_init(&obj_priv->list); |
| 2020 | 2037 | ||
| 2038 | if (i915_gem_object_is_purgeable(obj_priv)) | ||
| 2039 | i915_gem_object_truncate(obj); | ||
| 2040 | |||
| 2021 | trace_i915_gem_object_unbind(obj); | 2041 | trace_i915_gem_object_unbind(obj); |
| 2022 | 2042 | ||
| 2023 | return 0; | 2043 | return 0; |
| 2024 | } | 2044 | } |
| 2025 | 2045 | ||
| 2026 | static inline int | ||
| 2027 | i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) | ||
| 2028 | { | ||
| 2029 | return !obj_priv->dirty || obj_priv->madv == I915_MADV_DONTNEED; | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | static struct drm_gem_object * | 2046 | static struct drm_gem_object * |
| 2033 | i915_gem_find_inactive_object(struct drm_device *dev, int min_size) | 2047 | i915_gem_find_inactive_object(struct drm_device *dev, int min_size) |
| 2034 | { | 2048 | { |
| @@ -2041,7 +2055,8 @@ i915_gem_find_inactive_object(struct drm_device *dev, int min_size) | |||
| 2041 | list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { | 2055 | list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { |
| 2042 | struct drm_gem_object *obj = obj_priv->obj; | 2056 | struct drm_gem_object *obj = obj_priv->obj; |
| 2043 | if (obj->size >= min_size) { | 2057 | if (obj->size >= min_size) { |
| 2044 | if (i915_gem_object_is_purgeable(obj_priv) && | 2058 | if ((!obj_priv->dirty || |
| 2059 | i915_gem_object_is_purgeable(obj_priv)) && | ||
| 2045 | (!best || obj->size < best->size)) { | 2060 | (!best || obj->size < best->size)) { |
| 2046 | best = obj; | 2061 | best = obj; |
| 2047 | if (best->size == min_size) | 2062 | if (best->size == min_size) |
| @@ -4808,19 +4823,6 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv) | |||
| 4808 | mutex_unlock(&dev->struct_mutex); | 4823 | mutex_unlock(&dev->struct_mutex); |
| 4809 | } | 4824 | } |
| 4810 | 4825 | ||
| 4811 | /* Immediately discard the backing storage */ | ||
| 4812 | static void | ||
| 4813 | i915_gem_object_truncate(struct drm_gem_object *obj) | ||
| 4814 | { | ||
| 4815 | struct inode *inode; | ||
| 4816 | |||
| 4817 | inode = obj->filp->f_path.dentry->d_inode; | ||
| 4818 | |||
| 4819 | mutex_lock(&inode->i_mutex); | ||
| 4820 | truncate_inode_pages(inode->i_mapping, 0); | ||
| 4821 | mutex_unlock(&inode->i_mutex); | ||
| 4822 | } | ||
| 4823 | |||
| 4824 | static int | 4826 | static int |
| 4825 | i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) | 4827 | i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) |
| 4826 | { | 4828 | { |
| @@ -4866,10 +4868,7 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
| 4866 | &dev_priv->mm.inactive_list, | 4868 | &dev_priv->mm.inactive_list, |
| 4867 | list) { | 4869 | list) { |
| 4868 | if (i915_gem_object_is_purgeable(obj_priv)) { | 4870 | if (i915_gem_object_is_purgeable(obj_priv)) { |
| 4869 | struct drm_gem_object *obj = obj_priv->obj; | 4871 | i915_gem_object_unbind(obj_priv->obj); |
| 4870 | i915_gem_object_unbind(obj); | ||
| 4871 | i915_gem_object_truncate(obj); | ||
| 4872 | |||
| 4873 | if (--nr_to_scan <= 0) | 4872 | if (--nr_to_scan <= 0) |
| 4874 | break; | 4873 | break; |
| 4875 | } | 4874 | } |
| @@ -4878,6 +4877,8 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
| 4878 | spin_lock(&shrink_list_lock); | 4877 | spin_lock(&shrink_list_lock); |
| 4879 | mutex_unlock(&dev->struct_mutex); | 4878 | mutex_unlock(&dev->struct_mutex); |
| 4880 | 4879 | ||
| 4880 | would_deadlock = 0; | ||
| 4881 | |||
| 4881 | if (nr_to_scan <= 0) | 4882 | if (nr_to_scan <= 0) |
| 4882 | break; | 4883 | break; |
| 4883 | } | 4884 | } |
| @@ -4896,11 +4897,7 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
| 4896 | &dev_priv->mm.inactive_list, | 4897 | &dev_priv->mm.inactive_list, |
| 4897 | list) { | 4898 | list) { |
| 4898 | if (nr_to_scan > 0) { | 4899 | if (nr_to_scan > 0) { |
| 4899 | struct drm_gem_object *obj = obj_priv->obj; | 4900 | i915_gem_object_unbind(obj_priv->obj); |
| 4900 | i915_gem_object_unbind(obj); | ||
| 4901 | if (i915_gem_object_is_purgeable(obj_priv)) | ||
| 4902 | i915_gem_object_truncate(obj); | ||
| 4903 | |||
| 4904 | nr_to_scan--; | 4901 | nr_to_scan--; |
| 4905 | } else | 4902 | } else |
| 4906 | cnt++; | 4903 | cnt++; |
