summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h5
-rw-r--r--linux-core/drm_mm.c19
-rw-r--r--linux-core/drm_ttm.c4
3 files changed, 22 insertions, 6 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 8044367f..b164e02c 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1095,10 +1095,11 @@ extern void drm_ttm_mm_init(drm_device_t *dev, drm_ttm_mm_t *mm, unsigned long s
* Basic memory manager support (drm_mm.c)
*/
-extern drm_mm_node_t * drm_mm_get_block_locked(drm_mm_node_t * parent, unsigned long size);
+extern drm_mm_node_t * drm_mm_get_block_locked(drm_mm_node_t * parent, unsigned long size,
+ unsigned alignment);
extern void drm_mm_put_block_locked(drm_mm_t *mm, drm_mm_node_t *cur);
extern drm_mm_node_t *drm_mm_search_free_locked(const drm_mm_t *mm, unsigned long size,
- int best_match);
+ unsigned alignment, int best_match);
extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
/* Inline replacements for DRM_IOREMAP macros */
diff --git a/linux-core/drm_mm.c b/linux-core/drm_mm.c
index 05d316ee..82bbf93d 100644
--- a/linux-core/drm_mm.c
+++ b/linux-core/drm_mm.c
@@ -30,16 +30,26 @@
* Generic simple memory manager implementation. Intended to be used as a base
* class implementation for more advanced memory managers. The mm.mm_lock spinlock
* needs to be explicitly taken by the client before calling any _locked function.
+ *
+ * Note that the algorithm used is quite simple and there might be substantial
+ * performance gains if a smarter free list is implemented. Currently it is just an
+ * unordered stack of free regions. Feel free to improve.
+ *
+ * Aligned allocations can also see some improvement.
*/
#include "drmP.h"
drm_mm_node_t *drm_mm_get_block_locked(drm_mm_node_t * parent,
- unsigned long size)
+ unsigned long size,
+ unsigned alignment)
{
drm_mm_node_t * child;
+ if (alignment)
+ size += alignment - 1;
+
if (parent->size == size) {
list_del_init(&parent->fl_entry);
parent->free = FALSE;
@@ -112,7 +122,9 @@ void drm_mm_put_block_locked(drm_mm_t * mm, drm_mm_node_t * cur)
}
drm_mm_node_t *drm_mm_search_free_locked(const drm_mm_t * mm,
- unsigned long size, int best_match)
+ unsigned long size,
+ unsigned alignment,
+ int best_match)
{
struct list_head *list;
const struct list_head *free_stack = &mm->root_node.fl_entry;
@@ -123,6 +135,9 @@ drm_mm_node_t *drm_mm_search_free_locked(const drm_mm_t * mm,
best = NULL;
best_size = ~0UL;
+ if (alignment)
+ size += alignment - 1;
+
list_for_each(list, free_stack) {
entry = list_entry(list, drm_mm_node_t, fl_entry);
if (entry->size >= size) {
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index c8048d12..03c81bb2 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -885,7 +885,7 @@ static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry,
while (!mm_node) {
mm_node =
drm_mm_search_free_locked(&entry->mm->mm, num_pages,
- 0);
+ 0, 0);
if (!mm_node) {
ret = drm_ttm_evict_lru_sl(entry, &have_fence, &cur_fence);
if (ret)
@@ -894,7 +894,7 @@ static int drm_validate_ttm_region(drm_ttm_backend_list_t * entry,
}
if (!entry->mm_node) {
- mm_node = drm_mm_get_block_locked(mm_node, num_pages);
+ mm_node = drm_mm_get_block_locked(mm_node, num_pages, 0);
mm_node->private = mm_priv;
mm_priv->region = entry;
entry->mm_node = mm_node;