From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: Re: [PATCH 1/3] drm: Add colouring to the range allocator Date: Tue, 10 Jul 2012 11:21:57 +0200 Message-ID: <20120710092157.GB5108@phenom.ffwll.local> References: <1341833679-11614-1-git-send-email-chris@chris-wilson.co.uk> <1341833679-11614-2-git-send-email-chris@chris-wilson.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail-bk0-f49.google.com (mail-bk0-f49.google.com [209.85.214.49]) by gabe.freedesktop.org (Postfix) with ESMTP id D3FEAA0958 for ; Tue, 10 Jul 2012 02:21:58 -0700 (PDT) Received: by bkcji2 with SMTP id ji2so6187457bkc.36 for ; Tue, 10 Jul 2012 02:21:58 -0700 (PDT) Content-Disposition: inline In-Reply-To: <1341833679-11614-2-git-send-email-chris@chris-wilson.co.uk> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: Chris Wilson Cc: Benjamin Herrenschmidt , intel-gfx@lists.freedesktop.org, Jerome Glisse , Ben Skeggs , Daniel Vetter , Alex Deucher List-Id: intel-gfx@lists.freedesktop.org On Mon, Jul 09, 2012 at 12:34:37PM +0100, Chris Wilson wrote: > 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: Benjamin Herrenschmidt > Cc: Ben Skeggs > Cc: Jerome Glisse > Cc: Alex Deucher > Cc: Daniel Vetter Two little bikesheds: - Do we really need 64bits of colour? Especially since we have quite a few bits of space left ... - I think we could add a new insert_color helper that always takes a range (we can select the right rang in the driver). That way this patch wouldn't need to touch the drivers, and we could take the opportunity to embed the gtt_space mm_node into our gem object ... Besides that this looks good and I like it, but I think I've mentioned that way back when this patch first popped up ;-) -Daniel > > 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); > -- > 1.7.10 > -- Daniel Vetter Mail: daniel@ffwll.ch Mobile: +41 (0)79 365 57 48