aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Widawsky <ben@bwidawsk.net>2013-07-05 17:41:02 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-08 16:04:32 -0400
commitb3a070cccb9135f8bec63d9f194ddaa422136fb0 (patch)
tree64459a4af873cf5a1db2ddcd1d86d3bea24d7a38
parentb79480ba5074ae81d1c32073bce3981652e0f717 (diff)
drm: pre allocate node for create_block
For an upcoming patch where we introduce the i915 VMA, it's ideal to have the drm_mm_node as part of the VMA struct (ie. it's pre-allocated). Part of the conversion to VMAs is to kill off obj->gtt_space. Doing this will break a bunch of code, but amongst them are 2 callers of drm_mm_create_block(), both related to stolen memory. It also allows us to embed the drm_mm_node into the object currently which provides a nice transition over to the new code. v2: Reordered to do before ripping out obj->gtt_offset. Some minor cleanups made available because of reordering. v3: s/continue/break on failed stolen node allocation (David) Set obj->gtt_space on failed node allocation (David) Only unref stolen (fix double free) on failed create_stolen (David) Free node, and NULL it in failed create_stolen (David) Add back accidentally removed newline (David) CC: <dri-devel@lists.freedesktop.org> Reviewed-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Ben Widawsky <ben@bwidawsk.net> Acked-by: David Airlie <airlied@linux.ie> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_mm.c16
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c20
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c37
-rw-r--r--include/drm/drm_mm.h9
4 files changed, 53 insertions, 29 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 07cf99cc8862..9e8dfbc1955e 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -147,12 +147,10 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
147 } 147 }
148} 148}
149 149
150struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, 150int drm_mm_create_block(struct drm_mm *mm, struct drm_mm_node *node,
151 unsigned long start, 151 unsigned long start, unsigned long size)
152 unsigned long size,
153 bool atomic)
154{ 152{
155 struct drm_mm_node *hole, *node; 153 struct drm_mm_node *hole;
156 unsigned long end = start + size; 154 unsigned long end = start + size;
157 unsigned long hole_start; 155 unsigned long hole_start;
158 unsigned long hole_end; 156 unsigned long hole_end;
@@ -161,10 +159,6 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
161 if (hole_start > start || hole_end < end) 159 if (hole_start > start || hole_end < end)
162 continue; 160 continue;
163 161
164 node = drm_mm_kmalloc(mm, atomic);
165 if (unlikely(node == NULL))
166 return NULL;
167
168 node->start = start; 162 node->start = start;
169 node->size = size; 163 node->size = size;
170 node->mm = mm; 164 node->mm = mm;
@@ -184,11 +178,11 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
184 node->hole_follows = 1; 178 node->hole_follows = 1;
185 } 179 }
186 180
187 return node; 181 return 0;
188 } 182 }
189 183
190 WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size); 184 WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
191 return NULL; 185 return -ENOSPC;
192} 186}
193EXPORT_SYMBOL(drm_mm_create_block); 187EXPORT_SYMBOL(drm_mm_create_block);
194 188
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 66929eac6367..88180a597c0a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -629,14 +629,26 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
629 629
630 /* Mark any preallocated objects as occupied */ 630 /* Mark any preallocated objects as occupied */
631 list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { 631 list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
632 int ret;
632 DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n", 633 DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
633 obj->gtt_offset, obj->base.size); 634 obj->gtt_offset, obj->base.size);
634 635
635 BUG_ON(obj->gtt_space != I915_GTT_RESERVED); 636 BUG_ON(obj->gtt_space != I915_GTT_RESERVED);
636 obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space, 637 obj->gtt_space = kzalloc(sizeof(*obj->gtt_space), GFP_KERNEL);
637 obj->gtt_offset, 638 if (!obj->gtt_space) {
638 obj->base.size, 639 DRM_ERROR("Failed to preserve object at offset %x\n",
639 false); 640 obj->gtt_offset);
641 continue;
642 }
643 ret = drm_mm_create_block(&dev_priv->mm.gtt_space,
644 obj->gtt_space,
645 obj->gtt_offset,
646 obj->base.size);
647 if (ret) {
648 DRM_DEBUG_KMS("Reservation failed\n");
649 kfree(obj->gtt_space);
650 obj->gtt_space = NULL;
651 }
640 obj->has_global_gtt_mapping = 1; 652 obj->has_global_gtt_mapping = 1;
641 } 653 }
642 654
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 0f18d75fa9f8..2746ff2d846a 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -330,6 +330,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
330 struct drm_i915_private *dev_priv = dev->dev_private; 330 struct drm_i915_private *dev_priv = dev->dev_private;
331 struct drm_i915_gem_object *obj; 331 struct drm_i915_gem_object *obj;
332 struct drm_mm_node *stolen; 332 struct drm_mm_node *stolen;
333 int ret;
333 334
334 if (dev_priv->mm.stolen_base == 0) 335 if (dev_priv->mm.stolen_base == 0)
335 return NULL; 336 return NULL;
@@ -344,11 +345,15 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
344 if (WARN_ON(size == 0)) 345 if (WARN_ON(size == 0))
345 return NULL; 346 return NULL;
346 347
347 stolen = drm_mm_create_block(&dev_priv->mm.stolen, 348 stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
348 stolen_offset, size, 349 if (!stolen)
349 false); 350 return NULL;
350 if (stolen == NULL) { 351
352 ret = drm_mm_create_block(&dev_priv->mm.stolen, stolen, stolen_offset,
353 size);
354 if (ret) {
351 DRM_DEBUG_KMS("failed to allocate stolen space\n"); 355 DRM_DEBUG_KMS("failed to allocate stolen space\n");
356 kfree(stolen);
352 return NULL; 357 return NULL;
353 } 358 }
354 359
@@ -369,13 +374,18 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
369 * later. 374 * later.
370 */ 375 */
371 if (drm_mm_initialized(&dev_priv->mm.gtt_space)) { 376 if (drm_mm_initialized(&dev_priv->mm.gtt_space)) {
372 obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space, 377 obj->gtt_space = kzalloc(sizeof(*obj->gtt_space), GFP_KERNEL);
373 gtt_offset, size, 378 if (!obj->gtt_space) {
374 false); 379 DRM_DEBUG_KMS("-ENOMEM stolen GTT space\n");
375 if (obj->gtt_space == NULL) { 380 goto unref_out;
381 }
382
383 ret = drm_mm_create_block(&dev_priv->mm.gtt_space,
384 obj->gtt_space,
385 gtt_offset, size);
386 if (ret) {
376 DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); 387 DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
377 drm_gem_object_unreference(&obj->base); 388 goto free_out;
378 return NULL;
379 } 389 }
380 } else 390 } else
381 obj->gtt_space = I915_GTT_RESERVED; 391 obj->gtt_space = I915_GTT_RESERVED;
@@ -387,6 +397,13 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
387 list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); 397 list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
388 398
389 return obj; 399 return obj;
400
401free_out:
402 kfree(obj->gtt_space);
403 obj->gtt_space = NULL;
404unref_out:
405 drm_gem_object_unreference(&obj->base);
406 return NULL;
390} 407}
391 408
392void 409void
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 88591ef8fa24..d8b56b7d1839 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -138,10 +138,10 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
138/* 138/*
139 * Basic range manager support (drm_mm.c) 139 * Basic range manager support (drm_mm.c)
140 */ 140 */
141extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, 141extern int drm_mm_create_block(struct drm_mm *mm,
142 unsigned long start, 142 struct drm_mm_node *node,
143 unsigned long size, 143 unsigned long start,
144 bool atomic); 144 unsigned long size);
145extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, 145extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
146 unsigned long size, 146 unsigned long size,
147 unsigned alignment, 147 unsigned alignment,
@@ -155,6 +155,7 @@ extern struct drm_mm_node *drm_mm_get_block_range_generic(
155 unsigned long start, 155 unsigned long start,
156 unsigned long end, 156 unsigned long end,
157 int atomic); 157 int atomic);
158
158static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, 159static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
159 unsigned long size, 160 unsigned long size,
160 unsigned alignment) 161 unsigned alignment)