Commit 31e5d7c6 authored by David Herrmann's avatar David Herrmann Committed by Dave Airlie

drm/mm: add "best_match" flag to drm_mm_insert_node()

Add a "best_match" flag similar to the drm_mm_search_*() helpers so we
can convert TTM to use them in follow up patches. We can also inline the
non-generic helpers and move them into the header to allow compile-time
optimizations.

To make calls to drm_mm_{search,insert}_node() more readable, this
converts the boolean argument to a flagset. There are pending patches that
add additional flags for top-down allocators and more.

v2:
 - use flag parameter instead of boolean "best_match"
 - convert *_search_free() helpers to also use flags argument
Signed-off-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 7fc65eb7
...@@ -212,12 +212,13 @@ EXPORT_SYMBOL(drm_mm_get_block_generic); ...@@ -212,12 +212,13 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
*/ */
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
unsigned long size, unsigned alignment, unsigned long size, unsigned alignment,
unsigned long color) unsigned long color,
enum drm_mm_search_flags flags)
{ {
struct drm_mm_node *hole_node; struct drm_mm_node *hole_node;
hole_node = drm_mm_search_free_generic(mm, size, alignment, hole_node = drm_mm_search_free_generic(mm, size, alignment,
color, 0); color, flags);
if (!hole_node) if (!hole_node)
return -ENOSPC; return -ENOSPC;
...@@ -226,13 +227,6 @@ int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, ...@@ -226,13 +227,6 @@ int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
} }
EXPORT_SYMBOL(drm_mm_insert_node_generic); EXPORT_SYMBOL(drm_mm_insert_node_generic);
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
unsigned long size, unsigned alignment)
{
return drm_mm_insert_node_generic(mm, node, size, alignment, 0);
}
EXPORT_SYMBOL(drm_mm_insert_node);
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned alignment, unsigned long size, unsigned alignment,
...@@ -313,13 +307,14 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic); ...@@ -313,13 +307,14 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic);
*/ */
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
unsigned long size, unsigned alignment, unsigned long color, unsigned long size, unsigned alignment, unsigned long color,
unsigned long start, unsigned long end) unsigned long start, unsigned long end,
enum drm_mm_search_flags flags)
{ {
struct drm_mm_node *hole_node; struct drm_mm_node *hole_node;
hole_node = drm_mm_search_free_in_range_generic(mm, hole_node = drm_mm_search_free_in_range_generic(mm,
size, alignment, color, size, alignment, color,
start, end, 0); start, end, flags);
if (!hole_node) if (!hole_node)
return -ENOSPC; return -ENOSPC;
...@@ -330,14 +325,6 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *n ...@@ -330,14 +325,6 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *n
} }
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
unsigned long size, unsigned alignment,
unsigned long start, unsigned long end)
{
return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
}
EXPORT_SYMBOL(drm_mm_insert_node_in_range);
/** /**
* Remove a memory node from the allocator. * Remove a memory node from the allocator.
*/ */
...@@ -413,7 +400,7 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -413,7 +400,7 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
unsigned long color, unsigned long color,
bool best_match) enum drm_mm_search_flags flags)
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
...@@ -436,7 +423,7 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -436,7 +423,7 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
if (!check_free_hole(adj_start, adj_end, size, alignment)) if (!check_free_hole(adj_start, adj_end, size, alignment))
continue; continue;
if (!best_match) if (!(flags & DRM_MM_SEARCH_BEST))
return entry; return entry;
if (entry->size < best_size) { if (entry->size < best_size) {
...@@ -455,7 +442,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, ...@@ -455,7 +442,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
unsigned long color, unsigned long color,
unsigned long start, unsigned long start,
unsigned long end, unsigned long end,
bool best_match) enum drm_mm_search_flags flags)
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
...@@ -483,7 +470,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, ...@@ -483,7 +470,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
if (!check_free_hole(adj_start, adj_end, size, alignment)) if (!check_free_hole(adj_start, adj_end, size, alignment))
continue; continue;
if (!best_match) if (!(flags & DRM_MM_SEARCH_BEST))
return entry; return entry;
if (entry->size < best_size) { if (entry->size < best_size) {
...@@ -629,8 +616,8 @@ EXPORT_SYMBOL(drm_mm_scan_add_block); ...@@ -629,8 +616,8 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
* corrupted. * corrupted.
* *
* When the scan list is empty, the selected memory nodes can be freed. An * When the scan list is empty, the selected memory nodes can be freed. An
* immediately following drm_mm_search_free with best_match = 0 will then return * immediately following drm_mm_search_free with !DRM_MM_SEARCH_BEST will then
* the just freed block (because its at the top of the free_stack list). * return the just freed block (because its at the top of the free_stack list).
* *
* Returns one if this block should be evicted, zero otherwise. Will always * Returns one if this block should be evicted, zero otherwise. Will always
* return zero when no hole has been found. * return zero when no hole has been found.
......
...@@ -241,8 +241,8 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr, ...@@ -241,8 +241,8 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
goto out_unlock; goto out_unlock;
} }
ret = drm_mm_insert_node_generic(&mgr->vm_addr_space_mm, ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node,
&node->vm_node, pages, 0, 0); pages, 0, DRM_MM_SEARCH_DEFAULT);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
......
...@@ -3085,7 +3085,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, ...@@ -3085,7 +3085,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space,
&obj->gtt_space, &obj->gtt_space,
size, alignment, size, alignment,
obj->cache_level, 0, gtt_max); obj->cache_level, 0, gtt_max,
DRM_MM_SEARCH_DEFAULT);
if (ret) { if (ret) {
ret = i915_gem_evict_something(dev, size, alignment, ret = i915_gem_evict_something(dev, size, alignment,
obj->cache_level, obj->cache_level,
......
...@@ -115,10 +115,12 @@ static int i915_setup_compression(struct drm_device *dev, int size) ...@@ -115,10 +115,12 @@ static int i915_setup_compression(struct drm_device *dev, int size)
/* Try to over-allocate to reduce reallocations and fragmentation */ /* Try to over-allocate to reduce reallocations and fragmentation */
compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
size <<= 1, 4096, 0); size <<= 1, 4096,
DRM_MM_SEARCH_DEFAULT);
if (!compressed_fb) if (!compressed_fb)
compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
size >>= 1, 4096, 0); size >>= 1, 4096,
DRM_MM_SEARCH_DEFAULT);
if (compressed_fb) if (compressed_fb)
compressed_fb = drm_mm_get_block(compressed_fb, size, 4096); compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
if (!compressed_fb) if (!compressed_fb)
...@@ -130,7 +132,8 @@ static int i915_setup_compression(struct drm_device *dev, int size) ...@@ -130,7 +132,8 @@ static int i915_setup_compression(struct drm_device *dev, int size)
I915_WRITE(DPFC_CB_BASE, compressed_fb->start); I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
} else { } else {
compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen, compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
4096, 4096, 0); 4096, 4096,
DRM_MM_SEARCH_DEFAULT);
if (compressed_llb) if (compressed_llb)
compressed_llb = drm_mm_get_block(compressed_llb, compressed_llb = drm_mm_get_block(compressed_llb,
4096, 4096); 4096, 4096);
...@@ -328,7 +331,8 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size) ...@@ -328,7 +331,8 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
if (size == 0) if (size == 0)
return NULL; return NULL;
stolen = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0); stolen = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096,
DRM_MM_SEARCH_DEFAULT);
if (stolen) if (stolen)
stolen = drm_mm_get_block(stolen, size, 4096); stolen = drm_mm_get_block(stolen, size, 4096);
if (stolen == NULL) if (stolen == NULL)
......
...@@ -109,7 +109,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, ...@@ -109,7 +109,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
if (pool == AGP_TYPE) { if (pool == AGP_TYPE) {
retval = drm_mm_insert_node(&dev_priv->agp_mm, retval = drm_mm_insert_node(&dev_priv->agp_mm,
&item->mm_node, &item->mm_node,
mem->size, 0); mem->size, 0,
DRM_MM_SEARCH_DEFAULT);
offset = item->mm_node.start; offset = item->mm_node.start;
} else { } else {
#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
...@@ -121,7 +122,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, ...@@ -121,7 +122,8 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
#else #else
retval = drm_mm_insert_node(&dev_priv->vram_mm, retval = drm_mm_insert_node(&dev_priv->vram_mm,
&item->mm_node, &item->mm_node,
mem->size, 0); mem->size, 0,
DRM_MM_SEARCH_DEFAULT);
offset = item->mm_node.start; offset = item->mm_node.start;
#endif #endif
} }
......
...@@ -69,7 +69,8 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, ...@@ -69,7 +69,8 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
spin_lock(&rman->lock); spin_lock(&rman->lock);
node = drm_mm_search_free_in_range(mm, node = drm_mm_search_free_in_range(mm,
mem->num_pages, mem->page_alignment, mem->num_pages, mem->page_alignment,
placement->fpfn, lpfn, 1); placement->fpfn, lpfn,
DRM_MM_SEARCH_BEST);
if (unlikely(node == NULL)) { if (unlikely(node == NULL)) {
spin_unlock(&rman->lock); spin_unlock(&rman->lock);
return 0; return 0;
......
...@@ -140,11 +140,11 @@ int via_mem_alloc(struct drm_device *dev, void *data, ...@@ -140,11 +140,11 @@ int via_mem_alloc(struct drm_device *dev, void *data,
if (mem->type == VIA_MEM_AGP) if (mem->type == VIA_MEM_AGP)
retval = drm_mm_insert_node(&dev_priv->agp_mm, retval = drm_mm_insert_node(&dev_priv->agp_mm,
&item->mm_node, &item->mm_node,
tmpSize, 0); tmpSize, 0, DRM_MM_SEARCH_DEFAULT);
else else
retval = drm_mm_insert_node(&dev_priv->vram_mm, retval = drm_mm_insert_node(&dev_priv->vram_mm,
&item->mm_node, &item->mm_node,
tmpSize, 0); tmpSize, 0, DRM_MM_SEARCH_DEFAULT);
if (retval) if (retval)
goto fail_alloc; goto fail_alloc;
......
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#endif #endif
enum drm_mm_search_flags {
DRM_MM_SEARCH_DEFAULT = 0,
DRM_MM_SEARCH_BEST = 1 << 0,
};
struct drm_mm_node { struct drm_mm_node {
struct list_head node_list; struct list_head node_list;
struct list_head hole_stack; struct list_head hole_stack;
...@@ -189,28 +194,41 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( ...@@ -189,28 +194,41 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
start, end, 1); start, end, 1);
} }
extern int drm_mm_insert_node(struct drm_mm *mm, extern int drm_mm_insert_node_generic(struct drm_mm *mm,
struct drm_mm_node *node,
unsigned long size,
unsigned alignment);
extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
unsigned long start, unsigned long color,
unsigned long end); enum drm_mm_search_flags flags);
extern int drm_mm_insert_node_generic(struct drm_mm *mm, static inline int drm_mm_insert_node(struct drm_mm *mm,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
unsigned long color); enum drm_mm_search_flags flags)
{
return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags);
}
extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
unsigned long color, unsigned long color,
unsigned long start, unsigned long start,
unsigned long end); unsigned long end,
enum drm_mm_search_flags flags);
static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
struct drm_mm_node *node,
unsigned long size,
unsigned alignment,
unsigned long start,
unsigned long end,
enum drm_mm_search_flags flags)
{
return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
0, start, end, flags);
}
extern void drm_mm_put_block(struct drm_mm_node *cur); extern void drm_mm_put_block(struct drm_mm_node *cur);
extern void drm_mm_remove_node(struct drm_mm_node *node); extern void drm_mm_remove_node(struct drm_mm_node *node);
extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
...@@ -218,7 +236,7 @@ extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -218,7 +236,7 @@ extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
unsigned long color, unsigned long color,
bool best_match); enum drm_mm_search_flags flags);
extern struct drm_mm_node *drm_mm_search_free_in_range_generic( extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
const struct drm_mm *mm, const struct drm_mm *mm,
unsigned long size, unsigned long size,
...@@ -226,13 +244,13 @@ extern struct drm_mm_node *drm_mm_search_free_in_range_generic( ...@@ -226,13 +244,13 @@ extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
unsigned long color, unsigned long color,
unsigned long start, unsigned long start,
unsigned long end, unsigned long end,
bool best_match); enum drm_mm_search_flags flags);
static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
bool best_match) enum drm_mm_search_flags flags)
{ {
return drm_mm_search_free_generic(mm,size, alignment, 0, best_match); return drm_mm_search_free_generic(mm,size, alignment, 0, flags);
} }
static inline struct drm_mm_node *drm_mm_search_free_in_range( static inline struct drm_mm_node *drm_mm_search_free_in_range(
const struct drm_mm *mm, const struct drm_mm *mm,
...@@ -240,10 +258,10 @@ static inline struct drm_mm_node *drm_mm_search_free_in_range( ...@@ -240,10 +258,10 @@ static inline struct drm_mm_node *drm_mm_search_free_in_range(
unsigned alignment, unsigned alignment,
unsigned long start, unsigned long start,
unsigned long end, unsigned long end,
bool best_match) enum drm_mm_search_flags flags)
{ {
return drm_mm_search_free_in_range_generic(mm, size, alignment, 0, return drm_mm_search_free_in_range_generic(mm, size, alignment, 0,
start, end, best_match); start, end, flags);
} }
extern void drm_mm_init(struct drm_mm *mm, extern void drm_mm_init(struct drm_mm *mm,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment