From patchwork Mon Jul 9 11:34:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 1172581 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id F0BE640B18 for ; Mon, 9 Jul 2012 11:38:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C51EC9E940 for ; Mon, 9 Jul 2012 04:38:01 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (smtp.fireflyinternet.com [109.228.6.236]) by gabe.freedesktop.org (Postfix) with ESMTP id 82B9A9F5A0 for ; Mon, 9 Jul 2012 04:36:00 -0700 (PDT) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.66.37; Received: from arrandale.alporthouse.com (unverified [78.156.66.37]) by fireflyinternet.com (Firefly Internet SMTP) with ESMTP id 117856676-1500050 for multiple; Mon, 09 Jul 2012 12:35:31 +0100 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Mon, 9 Jul 2012 12:34:37 +0100 Message-Id: <1341833679-11614-2-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1341833679-11614-1-git-send-email-chris@chris-wilson.co.uk> References: <1341833679-11614-1-git-send-email-chris@chris-wilson.co.uk> X-Originating-IP: 78.156.66.37 Cc: Benjamin Herrenschmidt , Jerome Glisse , Ben Skeggs , Daniel Vetter , Alex Deucher Subject: [Intel-gfx] [PATCH 1/3] drm: Add colouring to the range allocator X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org In order to support snoopable memory on non-LLC architectures (so that we can bind vgem objects into the i915 GATT for example), we have to avoid the prefetcher on the GPU from crossing memory domains and so prevent allocation of a snoopable PTE immediately following an uncached PTE. To do that, we need to extend the range allocator with support for tracking and segregating different node colours. This will be used by i915 to segregate memory domains within the GTT. Signed-off-by: Chris Wilson Cc: Dave Airlie Cc: Ben Skeggs Cc: Jerome Glisse Cc: Alex Deucher Cc: Daniel Vetter Conflicts: drivers/gpu/drm/i915/i915_gem_stolen.c --- drivers/gpu/drm/drm_gem.c | 2 +- drivers/gpu/drm/drm_mm.c | 151 +++++++++++++++++----------- drivers/gpu/drm/i915/i915_gem.c | 6 +- drivers/gpu/drm/i915/i915_gem_evict.c | 9 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 5 +- drivers/gpu/drm/nouveau/nouveau_notifier.c | 4 +- drivers/gpu/drm/nouveau/nouveau_object.c | 2 +- drivers/gpu/drm/nouveau/nv04_instmem.c | 2 +- drivers/gpu/drm/nouveau/nv20_fb.c | 2 +- drivers/gpu/drm/nouveau/nv50_vram.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/ttm/ttm_bo_manager.c | 4 +- include/drm/drm_mm.h | 38 +++++-- 13 files changed, 143 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d58e69d..961ccd8 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -354,7 +354,7 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj) /* Get a DRM GEM mmap offset allocated... */ list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->size / PAGE_SIZE, 0, 0); + obj->size / PAGE_SIZE, 0, 0, false); if (!list->file_offset_node) { DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 961fb54..0311dba 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -118,45 +118,53 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) static void drm_mm_insert_helper(struct drm_mm_node *hole_node, struct drm_mm_node *node, - unsigned long size, unsigned alignment) + unsigned long size, unsigned alignment, + unsigned long color) { struct drm_mm *mm = hole_node->mm; - unsigned long tmp = 0, wasted = 0; unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); + unsigned long adj_start = hole_start; + unsigned long adj_end = hole_end; BUG_ON(!hole_node->hole_follows || node->allocated); - if (alignment) - tmp = hole_start % alignment; + if (mm->color_adjust) + mm->color_adjust(hole_node, color, &adj_start, &adj_end); - if (!tmp) { + if (alignment) { + unsigned tmp = adj_start % alignment; + if (tmp) + adj_start += alignment - tmp; + } + + if (adj_start == hole_start) { hole_node->hole_follows = 0; - list_del_init(&hole_node->hole_stack); - } else - wasted = alignment - tmp; + list_del(&hole_node->hole_stack); + } - node->start = hole_start + wasted; + node->start = adj_start; node->size = size; node->mm = mm; + node->color = color; node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); - BUG_ON(node->start + node->size > hole_end); + BUG_ON(node->start + node->size > adj_end); + node->hole_follows = 0; if (node->start + node->size < hole_end) { list_add(&node->hole_stack, &mm->hole_stack); node->hole_follows = 1; - } else { - node->hole_follows = 0; } } struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, unsigned long size, unsigned alignment, + unsigned long color, int atomic) { struct drm_mm_node *node; @@ -165,7 +173,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, if (unlikely(node == NULL)) return NULL; - drm_mm_insert_helper(hole_node, node, size, alignment); + drm_mm_insert_helper(hole_node, node, size, alignment, color); return node; } @@ -181,11 +189,11 @@ int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, { struct drm_mm_node *hole_node; - hole_node = drm_mm_search_free(mm, size, alignment, 0); + hole_node = drm_mm_search_free(mm, size, alignment, 0, false); if (!hole_node) return -ENOSPC; - drm_mm_insert_helper(hole_node, node, size, alignment); + drm_mm_insert_helper(hole_node, node, size, alignment, 0); return 0; } @@ -194,50 +202,57 @@ EXPORT_SYMBOL(drm_mm_insert_node); static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, struct drm_mm_node *node, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end) { struct drm_mm *mm = hole_node->mm; - unsigned long tmp = 0, wasted = 0; unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); + unsigned long adj_start = hole_start; + unsigned long adj_end = hole_end; BUG_ON(!hole_node->hole_follows || node->allocated); - if (hole_start < start) - wasted += start - hole_start; - if (alignment) - tmp = (hole_start + wasted) % alignment; + if (mm->color_adjust) + mm->color_adjust(hole_node, color, &adj_start, &adj_end); - if (tmp) - wasted += alignment - tmp; + if (adj_start < start) + adj_start = start; - if (!wasted) { + if (alignment) { + unsigned tmp = adj_start % alignment; + if (tmp) + adj_start += alignment - tmp; + } + + if (adj_start == hole_start) { hole_node->hole_follows = 0; - list_del_init(&hole_node->hole_stack); + list_del(&hole_node->hole_stack); } - node->start = hole_start + wasted; + node->start = adj_start; node->size = size; node->mm = mm; + node->color = color; node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); - BUG_ON(node->start + node->size > hole_end); + BUG_ON(node->start + node->size > adj_end); BUG_ON(node->start + node->size > end); + node->hole_follows = 0; if (node->start + node->size < hole_end) { list_add(&node->hole_stack, &mm->hole_stack); node->hole_follows = 1; - } else { - node->hole_follows = 0; } } struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end, int atomic) @@ -248,7 +263,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node if (unlikely(node == NULL)) return NULL; - drm_mm_insert_helper_range(hole_node, node, size, alignment, + drm_mm_insert_helper_range(hole_node, node, size, alignment, color, start, end); return node; @@ -266,12 +281,12 @@ int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, { struct drm_mm_node *hole_node; - hole_node = drm_mm_search_free_in_range(mm, size, alignment, - start, end, 0); + hole_node = drm_mm_search_free_in_range(mm, size, alignment, 0, + start, end, false); if (!hole_node) return -ENOSPC; - drm_mm_insert_helper_range(hole_node, node, size, alignment, + drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, start, end); return 0; @@ -336,27 +351,23 @@ EXPORT_SYMBOL(drm_mm_put_block); static int check_free_hole(unsigned long start, unsigned long end, unsigned long size, unsigned alignment) { - unsigned wasted = 0; - if (end - start < size) return 0; if (alignment) { unsigned tmp = start % alignment; if (tmp) - wasted = alignment - tmp; - } - - if (end >= start + size + wasted) { - return 1; + start += alignment - tmp; } - return 0; + return end >= start + size; } struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size, - unsigned alignment, int best_match) + unsigned alignment, + unsigned long color, + bool best_match) { struct drm_mm_node *entry; struct drm_mm_node *best; @@ -368,10 +379,17 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, best_size = ~0UL; list_for_each_entry(entry, &mm->hole_stack, hole_stack) { + unsigned long adj_start = drm_mm_hole_node_start(entry); + unsigned long adj_end = drm_mm_hole_node_end(entry); + + if (mm->color_adjust) { + mm->color_adjust(entry, color, &adj_start, &adj_end); + if (adj_end <= adj_start) + continue; + } + BUG_ON(!entry->hole_follows); - if (!check_free_hole(drm_mm_hole_node_start(entry), - drm_mm_hole_node_end(entry), - size, alignment)) + if (!check_free_hole(adj_start, adj_end, size, alignment)) continue; if (!best_match) @@ -390,9 +408,10 @@ EXPORT_SYMBOL(drm_mm_search_free); struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end, - int best_match) + bool best_match) { struct drm_mm_node *entry; struct drm_mm_node *best; @@ -410,6 +429,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, end : drm_mm_hole_node_end(entry); BUG_ON(!entry->hole_follows); + + if (mm->color_adjust) { + mm->color_adjust(entry, color, &adj_start, &adj_end); + if (adj_end <= adj_start) + continue; + } + if (!check_free_hole(adj_start, adj_end, size, alignment)) continue; @@ -437,6 +463,7 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) new->mm = old->mm; new->start = old->start; new->size = old->size; + new->color = old->color; old->allocated = 0; new->allocated = 1; @@ -452,9 +479,12 @@ EXPORT_SYMBOL(drm_mm_replace_node); * Warning: As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, - unsigned alignment) +void drm_mm_init_scan(struct drm_mm *mm, + unsigned long size, + unsigned alignment, + unsigned long color) { + mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; mm->scanned_blocks = 0; @@ -474,11 +504,14 @@ EXPORT_SYMBOL(drm_mm_init_scan); * Warning: As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, +void drm_mm_init_scan_with_range(struct drm_mm *mm, + unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end) { + mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; mm->scanned_blocks = 0; @@ -522,17 +555,21 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) hole_start = drm_mm_hole_node_start(prev_node); hole_end = drm_mm_hole_node_end(prev_node); + + adj_start = hole_start; + adj_end = hole_end; + + if (mm->color_adjust) + mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); + if (mm->scan_check_range) { - adj_start = hole_start < mm->scan_start ? - mm->scan_start : hole_start; - adj_end = hole_end > mm->scan_end ? - mm->scan_end : hole_end; - } else { - adj_start = hole_start; - adj_end = hole_end; + if (adj_start < mm->scan_start) + adj_start = mm->scan_start; + if (adj_end > mm->scan_end) + adj_end = mm->scan_end; } - if (check_free_hole(adj_start , adj_end, + if (check_free_hole(adj_start, adj_end, mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = hole_start; mm->scan_hit_size = hole_end; @@ -616,6 +653,8 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) mm->head_node.size = start - mm->head_node.start; list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); + mm->color_adjust = NULL; + return 0; } EXPORT_SYMBOL(drm_mm_init); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index db438f0..cad56dd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2756,18 +2756,18 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, free_space = drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, size, alignment, 0, - dev_priv->mm.gtt_mappable_end, + 0, dev_priv->mm.gtt_mappable_end, 0); else free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, - size, alignment, 0); + size, alignment, 0, 0); if (free_space != NULL) { if (map_and_fenceable) obj->gtt_space = drm_mm_get_block_range_generic(free_space, size, alignment, 0, - dev_priv->mm.gtt_mappable_end, + 0, dev_priv->mm.gtt_mappable_end, 0); else obj->gtt_space = diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index ae7c24e..eba0308 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -78,11 +78,12 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, INIT_LIST_HEAD(&unwind_list); if (mappable) - drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size, - alignment, 0, - dev_priv->mm.gtt_mappable_end); + drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, + min_size, alignment, 0, + 0, dev_priv->mm.gtt_mappable_end); else - drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); + drm_mm_init_scan(&dev_priv->mm.gtt_space, + min_size, alignment, 0); /* First see if there is a large enough contiguous idle region... */ list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index ada2e90..dba13cf 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -111,7 +111,8 @@ static void i915_setup_compression(struct drm_device *dev, int size) /* Just in case the BIOS is doing something questionable. */ intel_disable_fbc(dev); - compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0); + compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, + size, 4096, 0, 0); if (compressed_fb) compressed_fb = drm_mm_get_block(compressed_fb, size, 4096); if (!compressed_fb) @@ -123,7 +124,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) { compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen, - 4096, 4096, 0); + 4096, 4096, 0, 0); if (compressed_llb) compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096); diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 2ef883c..65c64b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c @@ -118,10 +118,10 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, uint64_t offset; int target, ret; - mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0, + mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0, 0, start, end, 0); if (mem) - mem = drm_mm_get_block_range(mem, size, 0, start, end); + mem = drm_mm_get_block_range(mem, size, 0, 0, start, end); if (!mem) { NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index b190cc0..15d5d97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -163,7 +163,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, spin_unlock(&dev_priv->ramin_lock); if (!(flags & NVOBJ_FLAG_VM) && chan) { - ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); + ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0, 0); if (ramin) ramin = drm_mm_get_block(ramin, size, align); if (!ramin) { diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index ef7a934..ce57bcd 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -149,7 +149,7 @@ nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, return -ENOMEM; spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0, 0); if (ramin == NULL) { spin_unlock(&dev_priv->ramin_lock); return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/nv20_fb.c b/drivers/gpu/drm/nouveau/nv20_fb.c index 19bd640..754f47f 100644 --- a/drivers/gpu/drm/nouveau/nv20_fb.c +++ b/drivers/gpu/drm/nouveau/nv20_fb.c @@ -16,7 +16,7 @@ nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) return NULL; spin_lock(&dev_priv->tile.lock); - mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); + mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0, 0); if (mem) mem = drm_mm_get_block_atomic(mem, size, 0); spin_unlock(&dev_priv->tile.lock); diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 9ed9ae39..6c8ea3f 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/nv50_vram.c @@ -105,7 +105,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; int n = (size >> 4) * comp; - mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); + mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0, 0); if (mem->tag) mem->tag = drm_mm_get_block(mem->tag, n, 0); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 36f4b28..76ee39f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1686,7 +1686,7 @@ retry_pre_get: write_lock(&bdev->vm_lock); bo->vm_node = drm_mm_search_free(&bdev->addr_space_mm, - bo->mem.num_pages, 0, 0); + bo->mem.num_pages, 0, 0, 0); if (unlikely(bo->vm_node == NULL)) { ret = -ENOMEM; diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 038e947..b426b29 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -68,14 +68,14 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, spin_lock(&rman->lock); node = drm_mm_search_free_in_range(mm, - mem->num_pages, mem->page_alignment, + mem->num_pages, mem->page_alignment, 0, placement->fpfn, lpfn, 1); if (unlikely(node == NULL)) { spin_unlock(&rman->lock); return 0; } node = drm_mm_get_block_atomic_range(node, mem->num_pages, - mem->page_alignment, + mem->page_alignment, 0, placement->fpfn, lpfn); spin_unlock(&rman->lock); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 564b14a..04a9554 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -50,6 +50,7 @@ struct drm_mm_node { unsigned scanned_next_free : 1; unsigned scanned_preceeds_hole : 1; unsigned allocated : 1; + unsigned long color; unsigned long start; unsigned long size; struct drm_mm *mm; @@ -66,6 +67,7 @@ struct drm_mm { spinlock_t unused_lock; unsigned int scan_check_range : 1; unsigned scan_alignment; + unsigned long scan_color; unsigned long scan_size; unsigned long scan_hit_start; unsigned scan_hit_size; @@ -73,6 +75,9 @@ struct drm_mm { unsigned long scan_start; unsigned long scan_end; struct drm_mm_node *prev_scanned_node; + + void (*color_adjust)(struct drm_mm_node *node, unsigned long color, + unsigned long *start, unsigned long *end); }; static inline bool drm_mm_node_allocated(struct drm_mm_node *node) @@ -100,11 +105,13 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, unsigned long size, unsigned alignment, + unsigned long color, int atomic); extern struct drm_mm_node *drm_mm_get_block_range_generic( struct drm_mm_node *node, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end, int atomic); @@ -112,32 +119,34 @@ static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, unsigned long size, unsigned alignment) { - return drm_mm_get_block_generic(parent, size, alignment, 0); + return drm_mm_get_block_generic(parent, size, alignment, 0, 0); } static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, unsigned long size, unsigned alignment) { - return drm_mm_get_block_generic(parent, size, alignment, 1); + return drm_mm_get_block_generic(parent, size, alignment, 0, 1); } static inline struct drm_mm_node *drm_mm_get_block_range( struct drm_mm_node *parent, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end) { - return drm_mm_get_block_range_generic(parent, size, alignment, - start, end, 0); + return drm_mm_get_block_range_generic(parent, size, alignment, color, + start, end, 0); } static inline struct drm_mm_node *drm_mm_get_block_atomic_range( struct drm_mm_node *parent, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end) { - return drm_mm_get_block_range_generic(parent, size, alignment, + return drm_mm_get_block_range_generic(parent, size, alignment, color, start, end, 1); } extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, @@ -152,15 +161,18 @@ extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size, unsigned alignment, - int best_match); + unsigned long color, + bool best_match); extern struct drm_mm_node *drm_mm_search_free_in_range( const struct drm_mm *mm, unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end, - int best_match); -extern int drm_mm_init(struct drm_mm *mm, unsigned long start, + bool best_match); +extern int drm_mm_init(struct drm_mm *mm, + unsigned long start, unsigned long size); extern void drm_mm_takedown(struct drm_mm *mm); extern int drm_mm_clean(struct drm_mm *mm); @@ -171,10 +183,14 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) return block->mm; } -void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, - unsigned alignment); -void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, +void drm_mm_init_scan(struct drm_mm *mm, + unsigned long size, + unsigned alignment, + unsigned long color); +void drm_mm_init_scan_with_range(struct drm_mm *mm, + unsigned long size, unsigned alignment, + unsigned long color, unsigned long start, unsigned long end); int drm_mm_scan_add_block(struct drm_mm_node *node);