dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm: Optionally create mm blocks from top-to-bottom
@ 2014-03-31 12:27 Lauri Kasanen
  2014-04-02  8:25 ` Daniel Vetter
  0 siblings, 1 reply; 2+ messages in thread
From: Lauri Kasanen @ 2014-03-31 12:27 UTC (permalink / raw)
  To: dri-devel

Clients like i915 need 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.

For other drivers, allocating small bos from one end and large ones
from the other helps improve the quality of fragmentation.

Original patch by Chris Wilson.

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 top of the many drm_mm changes since the original patches
Remove ATOMIC from allocator flags (Chris)
Reverse order of TOPDOWN and BOTTOMUP

v4 by Lauri:
Remove i915 parts, they don't apply
Respin on top of drm-next

Signed-off-by: Lauri Kasanen <cand@gmx.com>
---
 drivers/gpu/drm/drm_mm.c | 56 +++++++++++++++++++++++++++++++++++-------------
 include/drm/drm_mm.h     | 29 +++++++++++++++++++++----
 2 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index a2d45b74..1728bcc 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -102,7 +102,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
 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);
@@ -115,12 +116,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);
@@ -215,16 +226,17 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
 			       unsigned long size, unsigned alignment,
 			       unsigned long color,
-			       enum drm_mm_search_flags flags)
+			       enum drm_mm_search_flags sflags,
+			       enum drm_mm_allocator_flags aflags)
 {
 	struct drm_mm_node *hole_node;
 
 	hole_node = drm_mm_search_free_generic(mm, size, alignment,
-					       color, flags);
+					       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);
@@ -233,7 +245,8 @@ 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)
+				       unsigned long start, unsigned long end,
+				       enum drm_mm_allocator_flags flags)
 {
 	struct drm_mm *mm = hole_node->mm;
 	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
@@ -248,13 +261,20 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
 	if (adj_end > end)
 		adj_end = end;
 
+	if (flags & DRM_MM_CREATE_TOP)
+		adj_start = adj_end - size;
+
 	if (mm->color_adjust)
 		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
 
 	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;
+		}
 	}
 
 	if (adj_start == hole_start) {
@@ -271,6 +291,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
 	INIT_LIST_HEAD(&node->hole_stack);
 	list_add(&node->node_list, &hole_node->node_list);
 
+	BUG_ON(node->start < start);
+	BUG_ON(node->start < adj_start);
 	BUG_ON(node->start + node->size > adj_end);
 	BUG_ON(node->start + node->size > end);
 
@@ -298,21 +320,23 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
  * 0 on success, -ENOSPC if there's no suitable hole.
  */
 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,
-					enum drm_mm_search_flags flags)
+					enum drm_mm_search_flags sflags,
+					enum drm_mm_allocator_flags aflags)
 {
 	struct drm_mm_node *hole_node;
 
 	hole_node = drm_mm_search_free_in_range_generic(mm,
 							size, alignment, color,
-							start, end, flags);
+							start, end, sflags);
 	if (!hole_node)
 		return -ENOSPC;
 
 	drm_mm_insert_helper_range(hole_node, node,
 				   size, alignment, color,
-				   start, end);
+				   start, end, aflags);
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
@@ -391,7 +415,8 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
 	best = NULL;
 	best_size = ~0UL;
 
-	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
+	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
+			       flags & DRM_MM_SEARCH_BELOW) {
 		if (mm->color_adjust) {
 			mm->color_adjust(entry, color, &adj_start, &adj_end);
 			if (adj_end <= adj_start)
@@ -432,7 +457,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
 	best = NULL;
 	best_size = ~0UL;
 
-	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
+	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
+			       flags & DRM_MM_SEARCH_BELOW) {
 		if (adj_start < start)
 			adj_start = start;
 		if (adj_end > end)
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 8b6981a..f2bc79b 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -47,8 +47,17 @@
 enum drm_mm_search_flags {
 	DRM_MM_SEARCH_DEFAULT =		0,
 	DRM_MM_SEARCH_BEST =		1 << 0,
+	DRM_MM_SEARCH_BELOW =		1 << 1,
 };
 
+enum drm_mm_allocator_flags {
+	DRM_MM_CREATE_DEFAULT =		0,
+	DRM_MM_CREATE_TOP =		1 << 0,
+};
+
+#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT
+#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP
+
 struct drm_mm_node {
 	struct list_head node_list;
 	struct list_head hole_stack;
@@ -195,6 +204,14 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
 	     1 : 0; \
 	     entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
 
+#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
+	for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
+	     &entry->hole_stack != &(mm)->hole_stack ? \
+	     hole_start = drm_mm_hole_node_start(entry), \
+	     hole_end = drm_mm_hole_node_end(entry), \
+	     1 : 0; \
+	     entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
+
 /*
  * Basic range manager support (drm_mm.c)
  */
@@ -205,7 +222,8 @@ int drm_mm_insert_node_generic(struct drm_mm *mm,
 			       unsigned long size,
 			       unsigned alignment,
 			       unsigned long color,
-			       enum drm_mm_search_flags flags);
+			       enum drm_mm_search_flags sflags,
+			       enum drm_mm_allocator_flags aflags);
 /**
  * drm_mm_insert_node - search for space and insert @node
  * @mm: drm_mm to allocate from
@@ -228,7 +246,8 @@ static inline int drm_mm_insert_node(struct drm_mm *mm,
 				     unsigned alignment,
 				     enum drm_mm_search_flags flags)
 {
-	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags);
+	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags,
+					  DRM_MM_CREATE_DEFAULT);
 }
 
 int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
@@ -238,7 +257,8 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
 					unsigned long color,
 					unsigned long start,
 					unsigned long end,
-					enum drm_mm_search_flags flags);
+					enum drm_mm_search_flags sflags,
+					enum drm_mm_allocator_flags aflags);
 /**
  * drm_mm_insert_node_in_range - ranged search for space and insert @node
  * @mm: drm_mm to allocate from
@@ -266,7 +286,8 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
 					      enum drm_mm_search_flags flags)
 {
 	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
-						   0, start, end, flags);
+						   0, start, end, flags,
+						   DRM_MM_CREATE_DEFAULT);
 }
 
 void drm_mm_remove_node(struct drm_mm_node *node);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 1/4] drm: Optionally create mm blocks from top-to-bottom
  2014-03-31 12:27 [PATCH 1/4] drm: Optionally create mm blocks from top-to-bottom Lauri Kasanen
@ 2014-04-02  8:25 ` Daniel Vetter
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Vetter @ 2014-04-02  8:25 UTC (permalink / raw)
  To: Lauri Kasanen; +Cc: dri-devel

On Mon, Mar 31, 2014 at 03:27:54PM +0300, Lauri Kasanen wrote:
> Clients like i915 need 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.
> 
> For other drivers, allocating small bos from one end and large ones
> from the other helps improve the quality of fragmentation.
> 
> Original patch by Chris Wilson.
> 
> 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 top of the many drm_mm changes since the original patches
> Remove ATOMIC from allocator flags (Chris)
> Reverse order of TOPDOWN and BOTTOMUP
> 
> v4 by Lauri:
> Remove i915 parts, they don't apply
> Respin on top of drm-next
> 
> Signed-off-by: Lauri Kasanen <cand@gmx.com>

Please also update the kerneldoc we now have in drm-next, thanks.
-Daniel

> ---
>  drivers/gpu/drm/drm_mm.c | 56 +++++++++++++++++++++++++++++++++++-------------
>  include/drm/drm_mm.h     | 29 +++++++++++++++++++++----
>  2 files changed, 66 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
> index a2d45b74..1728bcc 100644
> --- a/drivers/gpu/drm/drm_mm.c
> +++ b/drivers/gpu/drm/drm_mm.c
> @@ -102,7 +102,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
>  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);
> @@ -115,12 +116,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);
> @@ -215,16 +226,17 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
>  int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
>  			       unsigned long size, unsigned alignment,
>  			       unsigned long color,
> -			       enum drm_mm_search_flags flags)
> +			       enum drm_mm_search_flags sflags,
> +			       enum drm_mm_allocator_flags aflags)
>  {
>  	struct drm_mm_node *hole_node;
>  
>  	hole_node = drm_mm_search_free_generic(mm, size, alignment,
> -					       color, flags);
> +					       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);
> @@ -233,7 +245,8 @@ 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)
> +				       unsigned long start, unsigned long end,
> +				       enum drm_mm_allocator_flags flags)
>  {
>  	struct drm_mm *mm = hole_node->mm;
>  	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
> @@ -248,13 +261,20 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
>  	if (adj_end > end)
>  		adj_end = end;
>  
> +	if (flags & DRM_MM_CREATE_TOP)
> +		adj_start = adj_end - size;
> +
>  	if (mm->color_adjust)
>  		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
>  
>  	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;
> +		}
>  	}
>  
>  	if (adj_start == hole_start) {
> @@ -271,6 +291,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
>  	INIT_LIST_HEAD(&node->hole_stack);
>  	list_add(&node->node_list, &hole_node->node_list);
>  
> +	BUG_ON(node->start < start);
> +	BUG_ON(node->start < adj_start);
>  	BUG_ON(node->start + node->size > adj_end);
>  	BUG_ON(node->start + node->size > end);
>  
> @@ -298,21 +320,23 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
>   * 0 on success, -ENOSPC if there's no suitable hole.
>   */
>  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,
> -					enum drm_mm_search_flags flags)
> +					enum drm_mm_search_flags sflags,
> +					enum drm_mm_allocator_flags aflags)
>  {
>  	struct drm_mm_node *hole_node;
>  
>  	hole_node = drm_mm_search_free_in_range_generic(mm,
>  							size, alignment, color,
> -							start, end, flags);
> +							start, end, sflags);
>  	if (!hole_node)
>  		return -ENOSPC;
>  
>  	drm_mm_insert_helper_range(hole_node, node,
>  				   size, alignment, color,
> -				   start, end);
> +				   start, end, aflags);
>  	return 0;
>  }
>  EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
> @@ -391,7 +415,8 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
>  	best = NULL;
>  	best_size = ~0UL;
>  
> -	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
> +	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
> +			       flags & DRM_MM_SEARCH_BELOW) {
>  		if (mm->color_adjust) {
>  			mm->color_adjust(entry, color, &adj_start, &adj_end);
>  			if (adj_end <= adj_start)
> @@ -432,7 +457,8 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
>  	best = NULL;
>  	best_size = ~0UL;
>  
> -	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
> +	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
> +			       flags & DRM_MM_SEARCH_BELOW) {
>  		if (adj_start < start)
>  			adj_start = start;
>  		if (adj_end > end)
> diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
> index 8b6981a..f2bc79b 100644
> --- a/include/drm/drm_mm.h
> +++ b/include/drm/drm_mm.h
> @@ -47,8 +47,17 @@
>  enum drm_mm_search_flags {
>  	DRM_MM_SEARCH_DEFAULT =		0,
>  	DRM_MM_SEARCH_BEST =		1 << 0,
> +	DRM_MM_SEARCH_BELOW =		1 << 1,
>  };
>  
> +enum drm_mm_allocator_flags {
> +	DRM_MM_CREATE_DEFAULT =		0,
> +	DRM_MM_CREATE_TOP =		1 << 0,
> +};
> +
> +#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT
> +#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP
> +
>  struct drm_mm_node {
>  	struct list_head node_list;
>  	struct list_head hole_stack;
> @@ -195,6 +204,14 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
>  	     1 : 0; \
>  	     entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
>  
> +#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
> +	for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
> +	     &entry->hole_stack != &(mm)->hole_stack ? \
> +	     hole_start = drm_mm_hole_node_start(entry), \
> +	     hole_end = drm_mm_hole_node_end(entry), \
> +	     1 : 0; \
> +	     entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
> +
>  /*
>   * Basic range manager support (drm_mm.c)
>   */
> @@ -205,7 +222,8 @@ int drm_mm_insert_node_generic(struct drm_mm *mm,
>  			       unsigned long size,
>  			       unsigned alignment,
>  			       unsigned long color,
> -			       enum drm_mm_search_flags flags);
> +			       enum drm_mm_search_flags sflags,
> +			       enum drm_mm_allocator_flags aflags);
>  /**
>   * drm_mm_insert_node - search for space and insert @node
>   * @mm: drm_mm to allocate from
> @@ -228,7 +246,8 @@ static inline int drm_mm_insert_node(struct drm_mm *mm,
>  				     unsigned alignment,
>  				     enum drm_mm_search_flags flags)
>  {
> -	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags);
> +	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags,
> +					  DRM_MM_CREATE_DEFAULT);
>  }
>  
>  int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
> @@ -238,7 +257,8 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
>  					unsigned long color,
>  					unsigned long start,
>  					unsigned long end,
> -					enum drm_mm_search_flags flags);
> +					enum drm_mm_search_flags sflags,
> +					enum drm_mm_allocator_flags aflags);
>  /**
>   * drm_mm_insert_node_in_range - ranged search for space and insert @node
>   * @mm: drm_mm to allocate from
> @@ -266,7 +286,8 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
>  					      enum drm_mm_search_flags flags)
>  {
>  	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
> -						   0, start, end, flags);
> +						   0, start, end, flags,
> +						   DRM_MM_CREATE_DEFAULT);
>  }
>  
>  void drm_mm_remove_node(struct drm_mm_node *node);
> -- 
> 1.8.3.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-04-02  8:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-31 12:27 [PATCH 1/4] drm: Optionally create mm blocks from top-to-bottom Lauri Kasanen
2014-04-02  8:25 ` Daniel Vetter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox