History

drm/i915/gem: Defer obj->base.resv fini until RCU callback

Since reservation_object_fini() does an immediate free, rather than kfree_rcu as normal, we have to delay the release until after the RCU grace period has elapsed (i.e. from the rcu cleanup callback) so that we can rely on the RCU protected access to the fences while the object is a zombie. i915_gem_busy_ioctl relies on having an RCU barrier to protect the reservation in order to avoid having to take a reference and strong memory barriers. v2: Order is important; only release after putting the pages!

Chris Wilson committed 7 years ago

Commit 0c159ff1 parent 21de5a94 files · +12 −13Browse files

Unified · Split

4 files
  1. drivers/gpu/drm/i915/gem/i915_gem_object.c +5 −4
  2. drivers/gpu/drm/i915/gem/i915_gem_phys.c +0 −7
  3. drivers/gpu/drm/i915/gem/i915_gem_shmem.c +7 −0
  4. drivers/gpu/drm/i915/gem/i915_gem_stolen.c +0 −2
drivers/gpu/drm/i915/gem/i915_gem_object.c+5−4
@@ -152,6 +152,7 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head) · 151 unmodified lines
152 container_of(head, typeof(*obj), rcu);152 container_of(head, typeof(*obj), rcu);
153 struct drm_i915_private *i915 = to_i915(obj->base.dev);153 struct drm_i915_private *i915 = to_i915(obj->base.dev);
154 154
155 reservation_object_fini(&obj->base._resv);
155 i915_gem_object_free(obj);156 i915_gem_object_free(obj);
156 157
157 GEM_BUG_ON(!atomic_read(&i915->mm.free_count));158 GEM_BUG_ON(!atomic_read(&i915->mm.free_count));
@@ -187,9 +188,6 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, · 29 unmodified lines
187 GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));188 GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
188 GEM_BUG_ON(!list_empty(&obj->lut_list));189 GEM_BUG_ON(!list_empty(&obj->lut_list));
189 190
190 if (obj->ops->release)
191 obj->ops->release(obj);
192
193 atomic_set(&obj->mm.pages_pin_count, 0);191 atomic_set(&obj->mm.pages_pin_count, 0);
194 __i915_gem_object_put_pages(obj, I915_MM_NORMAL);192 __i915_gem_object_put_pages(obj, I915_MM_NORMAL);
195 GEM_BUG_ON(i915_gem_object_has_pages(obj));193 GEM_BUG_ON(i915_gem_object_has_pages(obj));
@@ -198,7 +196,10 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, · 2 unmodified lines
198 if (obj->base.import_attach)196 if (obj->base.import_attach)
199 drm_prime_gem_destroy(&obj->base, NULL);197 drm_prime_gem_destroy(&obj->base, NULL);
200 198
201 drm_gem_object_release(&obj->base);199 drm_gem_free_mmap_offset(&obj->base);
200
201 if (obj->ops->release)
202 obj->ops->release(obj);
202 203
203 /* But keep the pointer alive for RCU-protected lookups */204 /* But keep the pointer alive for RCU-protected lookups */
204 call_rcu(&obj->rcu, __i915_gem_free_object_rcu);205 call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
drivers/gpu/drm/i915/gem/i915_gem_phys.c+0−7
@@ -133,16 +133,9 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, · 132 unmodified lines
133 drm_pci_free(obj->base.dev, obj->phys_handle);133 drm_pci_free(obj->base.dev, obj->phys_handle);
134}134}
135 135
136static void
137i915_gem_object_release_phys(struct drm_i915_gem_object *obj)
138{
139 i915_gem_object_unpin_pages(obj);
140}
141
142static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {136static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {
143 .get_pages = i915_gem_object_get_pages_phys,137 .get_pages = i915_gem_object_get_pages_phys,
144 .put_pages = i915_gem_object_put_pages_phys,138 .put_pages = i915_gem_object_put_pages_phys,
145 .release = i915_gem_object_release_phys,
146};139};
147 140
148int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)141int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
drivers/gpu/drm/i915/gem/i915_gem_shmem.c+7−0
@@ -414,6 +414,11 @@ shmem_pwrite(struct drm_i915_gem_object *obj, · 413 unmodified lines
414 return 0;414 return 0;
415}415}
416 416
417static void shmem_release(struct drm_i915_gem_object *obj)
418{
419 fput(obj->base.filp);
420}
421
417const struct drm_i915_gem_object_ops i915_gem_shmem_ops = {422const struct drm_i915_gem_object_ops i915_gem_shmem_ops = {
418 .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |423 .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
419 I915_GEM_OBJECT_IS_SHRINKABLE,424 I915_GEM_OBJECT_IS_SHRINKABLE,
@@ -424,6 +429,8 @@ const struct drm_i915_gem_object_ops i915_gem_shmem_ops = { · 4 unmodified lines
424 .writeback = shmem_writeback,429 .writeback = shmem_writeback,
425 430
426 .pwrite = shmem_pwrite,431 .pwrite = shmem_pwrite,
432
433 .release = shmem_release,
427};434};
428 435
429static int create_shmem(struct drm_i915_private *i915,436static int create_shmem(struct drm_i915_private *i915,
drivers/gpu/drm/i915/gem/i915_gem_stolen.c+0−2
@@ -529,8 +529,6 @@ i915_gem_object_release_stolen(struct drm_i915_gem_object *obj) · 528 unmodified lines
529 529
530 GEM_BUG_ON(!stolen);530 GEM_BUG_ON(!stolen);
531 531
532 __i915_gem_object_unpin_pages(obj);
533
534 i915_gem_stolen_remove_node(dev_priv, stolen);532 i915_gem_stolen_remove_node(dev_priv, stolen);
535 kfree(stolen);533 kfree(stolen);
536}534}