Home | History | Annotate | Line # | Download | only in drm
drm_mm.h revision 1.1
      1 /**************************************************************************
      2  *
      3  * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  *
     27  **************************************************************************/
     28 /*
     29  * Authors:
     30  * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
     31  */
     32 
     33 #ifndef _DRM_MM_H_
     34 #define _DRM_MM_H_
     35 
     36 /*
     37  * Generic range manager structs
     38  */
     39 #include <linux/list.h>
     40 #ifdef CONFIG_DEBUG_FS
     41 #include <linux/seq_file.h>
     42 #endif
     43 
     44 struct drm_mm_node {
     45 	struct list_head node_list;
     46 	struct list_head hole_stack;
     47 	unsigned hole_follows : 1;
     48 	unsigned scanned_block : 1;
     49 	unsigned scanned_prev_free : 1;
     50 	unsigned scanned_next_free : 1;
     51 	unsigned scanned_preceeds_hole : 1;
     52 	unsigned allocated : 1;
     53 	unsigned long color;
     54 	unsigned long start;
     55 	unsigned long size;
     56 	struct drm_mm *mm;
     57 };
     58 
     59 struct drm_mm {
     60 	/* List of all memory nodes that immediately precede a free hole. */
     61 	struct list_head hole_stack;
     62 	/* head_node.node_list is the list of all memory nodes, ordered
     63 	 * according to the (increasing) start address of the memory node. */
     64 	struct drm_mm_node head_node;
     65 	struct list_head unused_nodes;
     66 	int num_unused;
     67 	spinlock_t unused_lock;
     68 	unsigned int scan_check_range : 1;
     69 	unsigned scan_alignment;
     70 	unsigned long scan_color;
     71 	unsigned long scan_size;
     72 	unsigned long scan_hit_start;
     73 	unsigned long scan_hit_end;
     74 	unsigned scanned_blocks;
     75 	unsigned long scan_start;
     76 	unsigned long scan_end;
     77 	struct drm_mm_node *prev_scanned_node;
     78 
     79 	void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
     80 			     unsigned long *start, unsigned long *end);
     81 };
     82 
     83 static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
     84 {
     85 	return node->allocated;
     86 }
     87 
     88 static inline bool drm_mm_initialized(struct drm_mm *mm)
     89 {
     90 	return mm->hole_stack.next;
     91 }
     92 #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
     93 						&(mm)->head_node.node_list, \
     94 						node_list)
     95 #define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
     96 	for (entry = (mm)->prev_scanned_node, \
     97 		next = entry ? list_entry(entry->node_list.next, \
     98 			struct drm_mm_node, node_list) : NULL; \
     99 	     entry != NULL; entry = next, \
    100 		next = entry ? list_entry(entry->node_list.next, \
    101 			struct drm_mm_node, node_list) : NULL) \
    102 /*
    103  * Basic range manager support (drm_mm.c)
    104  */
    105 extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
    106 						    unsigned long size,
    107 						    unsigned alignment,
    108 						    unsigned long color,
    109 						    int atomic);
    110 extern struct drm_mm_node *drm_mm_get_block_range_generic(
    111 						struct drm_mm_node *node,
    112 						unsigned long size,
    113 						unsigned alignment,
    114 						unsigned long color,
    115 						unsigned long start,
    116 						unsigned long end,
    117 						int atomic);
    118 static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
    119 						   unsigned long size,
    120 						   unsigned alignment)
    121 {
    122 	return drm_mm_get_block_generic(parent, size, alignment, 0, 0);
    123 }
    124 static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
    125 							  unsigned long size,
    126 							  unsigned alignment)
    127 {
    128 	return drm_mm_get_block_generic(parent, size, alignment, 0, 1);
    129 }
    130 static inline struct drm_mm_node *drm_mm_get_block_range(
    131 						struct drm_mm_node *parent,
    132 						unsigned long size,
    133 						unsigned alignment,
    134 						unsigned long start,
    135 						unsigned long end)
    136 {
    137 	return drm_mm_get_block_range_generic(parent, size, alignment, 0,
    138 					      start, end, 0);
    139 }
    140 static inline struct drm_mm_node *drm_mm_get_color_block_range(
    141 						struct drm_mm_node *parent,
    142 						unsigned long size,
    143 						unsigned alignment,
    144 						unsigned long color,
    145 						unsigned long start,
    146 						unsigned long end)
    147 {
    148 	return drm_mm_get_block_range_generic(parent, size, alignment, color,
    149 					      start, end, 0);
    150 }
    151 static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
    152 						struct drm_mm_node *parent,
    153 						unsigned long size,
    154 						unsigned alignment,
    155 						unsigned long start,
    156 						unsigned long end)
    157 {
    158 	return drm_mm_get_block_range_generic(parent, size, alignment, 0,
    159 						start, end, 1);
    160 }
    161 
    162 extern int drm_mm_insert_node(struct drm_mm *mm,
    163 			      struct drm_mm_node *node,
    164 			      unsigned long size,
    165 			      unsigned alignment);
    166 extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
    167 				       struct drm_mm_node *node,
    168 				       unsigned long size,
    169 				       unsigned alignment,
    170 				       unsigned long start,
    171 				       unsigned long end);
    172 extern int drm_mm_insert_node_generic(struct drm_mm *mm,
    173 				      struct drm_mm_node *node,
    174 				      unsigned long size,
    175 				      unsigned alignment,
    176 				      unsigned long color);
    177 extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
    178 				       struct drm_mm_node *node,
    179 				       unsigned long size,
    180 				       unsigned alignment,
    181 				       unsigned long color,
    182 				       unsigned long start,
    183 				       unsigned long end);
    184 extern void drm_mm_put_block(struct drm_mm_node *cur);
    185 extern void drm_mm_remove_node(struct drm_mm_node *node);
    186 extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
    187 extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
    188 						      unsigned long size,
    189 						      unsigned alignment,
    190 						      unsigned long color,
    191 						      bool best_match);
    192 extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
    193 						const struct drm_mm *mm,
    194 						unsigned long size,
    195 						unsigned alignment,
    196 						unsigned long color,
    197 						unsigned long start,
    198 						unsigned long end,
    199 						bool best_match);
    200 static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
    201 						     unsigned long size,
    202 						     unsigned alignment,
    203 						     bool best_match)
    204 {
    205 	return drm_mm_search_free_generic(mm,size, alignment, 0, best_match);
    206 }
    207 static inline  struct drm_mm_node *drm_mm_search_free_in_range(
    208 						const struct drm_mm *mm,
    209 						unsigned long size,
    210 						unsigned alignment,
    211 						unsigned long start,
    212 						unsigned long end,
    213 						bool best_match)
    214 {
    215 	return drm_mm_search_free_in_range_generic(mm, size, alignment, 0,
    216 						   start, end, best_match);
    217 }
    218 static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm,
    219 							   unsigned long size,
    220 							   unsigned alignment,
    221 							   unsigned long color,
    222 							   bool best_match)
    223 {
    224 	return drm_mm_search_free_generic(mm,size, alignment, color, best_match);
    225 }
    226 static inline  struct drm_mm_node *drm_mm_search_free_in_range_color(
    227 						const struct drm_mm *mm,
    228 						unsigned long size,
    229 						unsigned alignment,
    230 						unsigned long color,
    231 						unsigned long start,
    232 						unsigned long end,
    233 						bool best_match)
    234 {
    235 	return drm_mm_search_free_in_range_generic(mm, size, alignment, color,
    236 						   start, end, best_match);
    237 }
    238 extern int drm_mm_init(struct drm_mm *mm,
    239 		       unsigned long start,
    240 		       unsigned long size);
    241 extern void drm_mm_takedown(struct drm_mm *mm);
    242 extern int drm_mm_clean(struct drm_mm *mm);
    243 extern int drm_mm_pre_get(struct drm_mm *mm);
    244 
    245 static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
    246 {
    247 	return block->mm;
    248 }
    249 
    250 void drm_mm_init_scan(struct drm_mm *mm,
    251 		      unsigned long size,
    252 		      unsigned alignment,
    253 		      unsigned long color);
    254 void drm_mm_init_scan_with_range(struct drm_mm *mm,
    255 				 unsigned long size,
    256 				 unsigned alignment,
    257 				 unsigned long color,
    258 				 unsigned long start,
    259 				 unsigned long end);
    260 int drm_mm_scan_add_block(struct drm_mm_node *node);
    261 int drm_mm_scan_remove_block(struct drm_mm_node *node);
    262 
    263 extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
    264 #ifdef CONFIG_DEBUG_FS
    265 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm);
    266 #endif
    267 
    268 #endif
    269