[PATCH 9/9] drm: Optionally create mm blocks from top-to-bottom

2013-07-05 Thread Ben Widawsky
From: Chris Wilson 

Clients like i915 needs to segregate cache domains within the GTT which
can lead to small amounts of fragmentation. By allocating the uncached
buffers from the bottom and the cacheable buffers from the top, we can
reduce the amount of wasted space and also optimize allocation of the
mappable portion of the GTT to only those buffers that require CPU
access through the GTT.

v2 by Ben:
Update callers in i915_gem_object_bind_to_gtt()
Turn search flags and allocation flags into separate enums
Make checkpatch happy where logical/easy

v3: by Ben:
Rebased on create_block removal

v4: by Ben:
Rebased on reserve_node addition.

Signed-off-by: Chris Wilson 
CC: 
Signed-off-by: Ben Widawsky 

Conflicts:
drivers/gpu/drm/drm_mm.c
include/drm/drm_mm.h

Conflicts:
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
include/drm/drm_mm.h
---
 drivers/gpu/drm/drm_mm.c| 118 +--
 drivers/gpu/drm/i915/i915_gem.c |   4 +-
 include/drm/drm_mm.h| 149 +++-
 3 files changed, 169 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index fe304f9..5037b1a 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -49,7 +49,7 @@

 #define MM_UNUSED_TARGET 4

-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
+static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, bool atomic)
 {
struct drm_mm_node *child;

@@ -105,7 +105,8 @@ EXPORT_SYMBOL(drm_mm_pre_get);
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 struct drm_mm_node *node,
 unsigned long size, unsigned alignment,
-unsigned long color)
+unsigned long color,
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm *mm = hole_node->mm;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -118,12 +119,22 @@ static void drm_mm_insert_helper(struct drm_mm_node 
*hole_node,
if (mm->color_adjust)
mm->color_adjust(hole_node, color, _start, _end);

+   if (flags & DRM_MM_CREATE_TOP)
+   adj_start = adj_end - size;
+
if (alignment) {
unsigned tmp = adj_start % alignment;
-   if (tmp)
-   adj_start += alignment - tmp;
+   if (tmp) {
+   if (flags & DRM_MM_CREATE_TOP)
+   adj_start -= tmp;
+   else
+   adj_start += alignment - tmp;
+   }
}

+   BUG_ON(adj_start < hole_start);
+   BUG_ON(adj_end > hole_end);
+
if (adj_start == hole_start) {
hole_node->hole_follows = 0;
list_del(_node->hole_stack);
@@ -191,15 +202,15 @@ 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)
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm_node *node;

-   node = drm_mm_kmalloc(hole_node->mm, atomic);
+   node = drm_mm_kmalloc(hole_node->mm, flags & DRM_MM_CREATE_ATOMIC);
if (unlikely(node == NULL))
return NULL;

-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, flags);

return node;
 }
@@ -212,32 +223,28 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
   unsigned long size, unsigned alignment,
-  unsigned long color)
+  unsigned long color,
+  enum drm_mm_allocator_flags aflags,
+  enum drm_mm_search_flags sflags)
 {
struct drm_mm_node *hole_node;

hole_node = drm_mm_search_free_generic(mm, size, alignment,
-  color, 0);
+  color, sflags);
if (!hole_node)
return -ENOSPC;

-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags);
return 0;
 }
 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 

[PATCH 9/9] drm: Optionally create mm blocks from top-to-bottom

2013-07-05 Thread Ben Widawsky
From: Chris Wilson 

Clients like i915 needs to segregate cache domains within the GTT which
can lead to small amounts of fragmentation. By allocating the uncached
buffers from the bottom and the cacheable buffers from the top, we can
reduce the amount of wasted space and also optimize allocation of the
mappable portion of the GTT to only those buffers that require CPU
access through the GTT.

v2 by Ben:
Update callers in i915_gem_object_bind_to_gtt()
Turn search flags and allocation flags into separate enums
Make checkpatch happy where logical/easy

v3: by Ben:
Rebased on create_block removal

v4: by Ben:
Rebased on reserve_node addition.

Signed-off-by: Chris Wilson 
CC: 
Signed-off-by: Ben Widawsky 

Conflicts:
drivers/gpu/drm/drm_mm.c
include/drm/drm_mm.h

Conflicts:
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
include/drm/drm_mm.h
---
 drivers/gpu/drm/drm_mm.c| 118 +--
 drivers/gpu/drm/i915/i915_gem.c |   4 +-
 include/drm/drm_mm.h| 149 +++-
 3 files changed, 169 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index fe304f9..5037b1a 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -49,7 +49,7 @@

 #define MM_UNUSED_TARGET 4

-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
+static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, bool atomic)
 {
struct drm_mm_node *child;

@@ -105,7 +105,8 @@ EXPORT_SYMBOL(drm_mm_pre_get);
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 struct drm_mm_node *node,
 unsigned long size, unsigned alignment,
-unsigned long color)
+unsigned long color,
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm *mm = hole_node->mm;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -118,12 +119,22 @@ static void drm_mm_insert_helper(struct drm_mm_node 
*hole_node,
if (mm->color_adjust)
mm->color_adjust(hole_node, color, _start, _end);

+   if (flags & DRM_MM_CREATE_TOP)
+   adj_start = adj_end - size;
+
if (alignment) {
unsigned tmp = adj_start % alignment;
-   if (tmp)
-   adj_start += alignment - tmp;
+   if (tmp) {
+   if (flags & DRM_MM_CREATE_TOP)
+   adj_start -= tmp;
+   else
+   adj_start += alignment - tmp;
+   }
}

+   BUG_ON(adj_start < hole_start);
+   BUG_ON(adj_end > hole_end);
+
if (adj_start == hole_start) {
hole_node->hole_follows = 0;
list_del(_node->hole_stack);
@@ -191,15 +202,15 @@ 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)
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm_node *node;

-   node = drm_mm_kmalloc(hole_node->mm, atomic);
+   node = drm_mm_kmalloc(hole_node->mm, flags & DRM_MM_CREATE_ATOMIC);
if (unlikely(node == NULL))
return NULL;

-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, flags);

return node;
 }
@@ -212,32 +223,28 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
   unsigned long size, unsigned alignment,
-  unsigned long color)
+  unsigned long color,
+  enum drm_mm_allocator_flags aflags,
+  enum drm_mm_search_flags sflags)
 {
struct drm_mm_node *hole_node;

hole_node = drm_mm_search_free_generic(mm, size, alignment,
-  color, 0);
+  color, sflags);
if (!hole_node)
return -ENOSPC;

-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags);
return 0;
 }
 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 

[PATCH 9/9] drm: Optionally create mm blocks from top-to-bottom

2013-07-05 Thread Ben Widawsky
From: Chris Wilson ch...@chris-wilson.co.uk

Clients like i915 needs to segregate cache domains within the GTT which
can lead to small amounts of fragmentation. By allocating the uncached
buffers from the bottom and the cacheable buffers from the top, we can
reduce the amount of wasted space and also optimize allocation of the
mappable portion of the GTT to only those buffers that require CPU
access through the GTT.

v2 by Ben:
Update callers in i915_gem_object_bind_to_gtt()
Turn search flags and allocation flags into separate enums
Make checkpatch happy where logical/easy

v3: by Ben:
Rebased on create_block removal

v4: by Ben:
Rebased on reserve_node addition.

Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Ben Widawsky b...@bwidawsk.net

Conflicts:
drivers/gpu/drm/drm_mm.c
include/drm/drm_mm.h

Conflicts:
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
include/drm/drm_mm.h
---
 drivers/gpu/drm/drm_mm.c| 118 +--
 drivers/gpu/drm/i915/i915_gem.c |   4 +-
 include/drm/drm_mm.h| 149 +++-
 3 files changed, 169 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index fe304f9..5037b1a 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -49,7 +49,7 @@
 
 #define MM_UNUSED_TARGET 4
 
-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
+static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, bool atomic)
 {
struct drm_mm_node *child;
 
@@ -105,7 +105,8 @@ EXPORT_SYMBOL(drm_mm_pre_get);
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 struct drm_mm_node *node,
 unsigned long size, unsigned alignment,
-unsigned long color)
+unsigned long color,
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm *mm = hole_node-mm;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -118,12 +119,22 @@ static void drm_mm_insert_helper(struct drm_mm_node 
*hole_node,
if (mm-color_adjust)
mm-color_adjust(hole_node, color, adj_start, adj_end);
 
+   if (flags  DRM_MM_CREATE_TOP)
+   adj_start = adj_end - size;
+
if (alignment) {
unsigned tmp = adj_start % alignment;
-   if (tmp)
-   adj_start += alignment - tmp;
+   if (tmp) {
+   if (flags  DRM_MM_CREATE_TOP)
+   adj_start -= tmp;
+   else
+   adj_start += alignment - tmp;
+   }
}
 
+   BUG_ON(adj_start  hole_start);
+   BUG_ON(adj_end  hole_end);
+
if (adj_start == hole_start) {
hole_node-hole_follows = 0;
list_del(hole_node-hole_stack);
@@ -191,15 +202,15 @@ 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)
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm_node *node;
 
-   node = drm_mm_kmalloc(hole_node-mm, atomic);
+   node = drm_mm_kmalloc(hole_node-mm, flags  DRM_MM_CREATE_ATOMIC);
if (unlikely(node == NULL))
return NULL;
 
-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, flags);
 
return node;
 }
@@ -212,32 +223,28 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
   unsigned long size, unsigned alignment,
-  unsigned long color)
+  unsigned long color,
+  enum drm_mm_allocator_flags aflags,
+  enum drm_mm_search_flags sflags)
 {
struct drm_mm_node *hole_node;
 
hole_node = drm_mm_search_free_generic(mm, size, alignment,
-  color, 0);
+  color, sflags);
if (!hole_node)
return -ENOSPC;
 
-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags);
return 0;
 }
 EXPORT_SYMBOL(drm_mm_insert_node_generic);
 
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-  

[PATCH 9/9] drm: Optionally create mm blocks from top-to-bottom

2013-07-05 Thread Ben Widawsky
From: Chris Wilson ch...@chris-wilson.co.uk

Clients like i915 needs to segregate cache domains within the GTT which
can lead to small amounts of fragmentation. By allocating the uncached
buffers from the bottom and the cacheable buffers from the top, we can
reduce the amount of wasted space and also optimize allocation of the
mappable portion of the GTT to only those buffers that require CPU
access through the GTT.

v2 by Ben:
Update callers in i915_gem_object_bind_to_gtt()
Turn search flags and allocation flags into separate enums
Make checkpatch happy where logical/easy

v3: by Ben:
Rebased on create_block removal

v4: by Ben:
Rebased on reserve_node addition.

Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
CC: dri-devel@lists.freedesktop.org
Signed-off-by: Ben Widawsky b...@bwidawsk.net

Conflicts:
drivers/gpu/drm/drm_mm.c
include/drm/drm_mm.h

Conflicts:
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
include/drm/drm_mm.h
---
 drivers/gpu/drm/drm_mm.c| 118 +--
 drivers/gpu/drm/i915/i915_gem.c |   4 +-
 include/drm/drm_mm.h| 149 +++-
 3 files changed, 169 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index fe304f9..5037b1a 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -49,7 +49,7 @@
 
 #define MM_UNUSED_TARGET 4
 
-static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
+static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, bool atomic)
 {
struct drm_mm_node *child;
 
@@ -105,7 +105,8 @@ EXPORT_SYMBOL(drm_mm_pre_get);
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 struct drm_mm_node *node,
 unsigned long size, unsigned alignment,
-unsigned long color)
+unsigned long color,
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm *mm = hole_node-mm;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -118,12 +119,22 @@ static void drm_mm_insert_helper(struct drm_mm_node 
*hole_node,
if (mm-color_adjust)
mm-color_adjust(hole_node, color, adj_start, adj_end);
 
+   if (flags  DRM_MM_CREATE_TOP)
+   adj_start = adj_end - size;
+
if (alignment) {
unsigned tmp = adj_start % alignment;
-   if (tmp)
-   adj_start += alignment - tmp;
+   if (tmp) {
+   if (flags  DRM_MM_CREATE_TOP)
+   adj_start -= tmp;
+   else
+   adj_start += alignment - tmp;
+   }
}
 
+   BUG_ON(adj_start  hole_start);
+   BUG_ON(adj_end  hole_end);
+
if (adj_start == hole_start) {
hole_node-hole_follows = 0;
list_del(hole_node-hole_stack);
@@ -191,15 +202,15 @@ 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)
+enum drm_mm_allocator_flags flags)
 {
struct drm_mm_node *node;
 
-   node = drm_mm_kmalloc(hole_node-mm, atomic);
+   node = drm_mm_kmalloc(hole_node-mm, flags  DRM_MM_CREATE_ATOMIC);
if (unlikely(node == NULL))
return NULL;
 
-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, flags);
 
return node;
 }
@@ -212,32 +223,28 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
   unsigned long size, unsigned alignment,
-  unsigned long color)
+  unsigned long color,
+  enum drm_mm_allocator_flags aflags,
+  enum drm_mm_search_flags sflags)
 {
struct drm_mm_node *hole_node;
 
hole_node = drm_mm_search_free_generic(mm, size, alignment,
-  color, 0);
+  color, sflags);
if (!hole_node)
return -ENOSPC;
 
-   drm_mm_insert_helper(hole_node, node, size, alignment, color);
+   drm_mm_insert_helper(hole_node, node, size, alignment, color, aflags);
return 0;
 }
 EXPORT_SYMBOL(drm_mm_insert_node_generic);
 
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-