diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-10-13 16:26:16 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-10-16 15:44:19 -0400 |
commit | 3d574a6bbb12a6c3bbeea807a1724b44a0f6ebbb (patch) | |
tree | 03aab19734eab1742c772553d93c71c759609ced | |
parent | f46250e4773149ab0fd8262cdc28764bb58a2d62 (diff) |
drm/i915: Remove walk over obj->vma_list for the shrinker
In the next patch, we want to reduce the lock coverage within the
shrinker, and one of the dangerous walks we have is over obj->vma_list.
We are only walking the obj->vma_list in order to check whether it has
been permanently pinned by HW access, typically via use on the scanout.
But we have a couple of other long term pins, the context objects for
which we currently have to check the individual vma pin_count. If we
instead mark these using obj->pin_display, we can forgo the dangerous
and sometimes slow list iteration.
v2: Rearrange code to try and avoid confusion from false associations
due to arrangement of whitespace along with rebasing on obj->pin_global.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171013202621.7276-4-chris@chris-wilson.co.uk
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_shrinker.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 8 |
3 files changed, 16 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index b5c87d89777b..575a6b735f39 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c | |||
@@ -71,25 +71,6 @@ static void shrinker_unlock(struct drm_i915_private *dev_priv, bool unlock) | |||
71 | mutex_unlock(&dev_priv->drm.struct_mutex); | 71 | mutex_unlock(&dev_priv->drm.struct_mutex); |
72 | } | 72 | } |
73 | 73 | ||
74 | static bool any_vma_pinned(struct drm_i915_gem_object *obj) | ||
75 | { | ||
76 | struct i915_vma *vma; | ||
77 | |||
78 | list_for_each_entry(vma, &obj->vma_list, obj_link) { | ||
79 | /* Only GGTT vma may be permanently pinned, and are always | ||
80 | * at the start of the list. We can stop hunting as soon | ||
81 | * as we see a ppGTT vma. | ||
82 | */ | ||
83 | if (!i915_vma_is_ggtt(vma)) | ||
84 | break; | ||
85 | |||
86 | if (i915_vma_is_pinned(vma)) | ||
87 | return true; | ||
88 | } | ||
89 | |||
90 | return false; | ||
91 | } | ||
92 | |||
93 | static bool swap_available(void) | 74 | static bool swap_available(void) |
94 | { | 75 | { |
95 | return get_nr_swap_pages() > 0; | 76 | return get_nr_swap_pages() > 0; |
@@ -115,7 +96,13 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) | |||
115 | if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count) | 96 | if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count) |
116 | return false; | 97 | return false; |
117 | 98 | ||
118 | if (any_vma_pinned(obj)) | 99 | /* If any vma are "permanently" pinned, it will prevent us from |
100 | * reclaiming the obj->mm.pages. We only allow scanout objects to claim | ||
101 | * a permanent pin, along with a few others like the context objects. | ||
102 | * To simplify the scan, and to avoid walking the list of vma under the | ||
103 | * object, we just check the count of its permanently pinned. | ||
104 | */ | ||
105 | if (obj->pin_global) | ||
119 | return false; | 106 | return false; |
120 | 107 | ||
121 | /* We can only return physical pages to the system if we can either | 108 | /* We can only return physical pages to the system if we can either |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 766552f2cfae..7f45dd7dc3e5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -1093,6 +1093,7 @@ execlists_context_pin(struct intel_engine_cs *engine, | |||
1093 | i915_ggtt_offset(ce->ring->vma); | 1093 | i915_ggtt_offset(ce->ring->vma); |
1094 | 1094 | ||
1095 | ce->state->obj->mm.dirty = true; | 1095 | ce->state->obj->mm.dirty = true; |
1096 | ce->state->obj->pin_global++; | ||
1096 | 1097 | ||
1097 | i915_gem_context_get(ctx); | 1098 | i915_gem_context_get(ctx); |
1098 | out: | 1099 | out: |
@@ -1120,6 +1121,7 @@ static void execlists_context_unpin(struct intel_engine_cs *engine, | |||
1120 | 1121 | ||
1121 | intel_ring_unpin(ce->ring); | 1122 | intel_ring_unpin(ce->ring); |
1122 | 1123 | ||
1124 | ce->state->obj->pin_global--; | ||
1123 | i915_gem_object_unpin_map(ce->state->obj); | 1125 | i915_gem_object_unpin_map(ce->state->obj); |
1124 | i915_vma_unpin(ce->state); | 1126 | i915_vma_unpin(ce->state); |
1125 | 1127 | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b2a6cb09c6e7..8da1bde442dd 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -1244,6 +1244,8 @@ int intel_ring_pin(struct intel_ring *ring, | |||
1244 | if (IS_ERR(addr)) | 1244 | if (IS_ERR(addr)) |
1245 | goto err; | 1245 | goto err; |
1246 | 1246 | ||
1247 | vma->obj->pin_global++; | ||
1248 | |||
1247 | ring->vaddr = addr; | 1249 | ring->vaddr = addr; |
1248 | return 0; | 1250 | return 0; |
1249 | 1251 | ||
@@ -1275,6 +1277,7 @@ void intel_ring_unpin(struct intel_ring *ring) | |||
1275 | i915_gem_object_unpin_map(ring->vma->obj); | 1277 | i915_gem_object_unpin_map(ring->vma->obj); |
1276 | ring->vaddr = NULL; | 1278 | ring->vaddr = NULL; |
1277 | 1279 | ||
1280 | ring->vma->obj->pin_global--; | ||
1278 | i915_vma_unpin(ring->vma); | 1281 | i915_vma_unpin(ring->vma); |
1279 | } | 1282 | } |
1280 | 1283 | ||
@@ -1439,6 +1442,7 @@ intel_ring_context_pin(struct intel_engine_cs *engine, | |||
1439 | goto err; | 1442 | goto err; |
1440 | 1443 | ||
1441 | ce->state->obj->mm.dirty = true; | 1444 | ce->state->obj->mm.dirty = true; |
1445 | ce->state->obj->pin_global++; | ||
1442 | } | 1446 | } |
1443 | 1447 | ||
1444 | /* The kernel context is only used as a placeholder for flushing the | 1448 | /* The kernel context is only used as a placeholder for flushing the |
@@ -1473,8 +1477,10 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine, | |||
1473 | if (--ce->pin_count) | 1477 | if (--ce->pin_count) |
1474 | return; | 1478 | return; |
1475 | 1479 | ||
1476 | if (ce->state) | 1480 | if (ce->state) { |
1481 | ce->state->obj->pin_global--; | ||
1477 | i915_vma_unpin(ce->state); | 1482 | i915_vma_unpin(ce->state); |
1483 | } | ||
1478 | 1484 | ||
1479 | i915_gem_context_put(ctx); | 1485 | i915_gem_context_put(ctx); |
1480 | } | 1486 | } |