1235783Skib/************************************************************************** 2235783Skib * 3235783Skib * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA. 4235783Skib * All Rights Reserved. 5235783Skib * 6235783Skib * Permission is hereby granted, free of charge, to any person obtaining a 7235783Skib * copy of this software and associated documentation files (the 8235783Skib * "Software"), to deal in the Software without restriction, including 9235783Skib * without limitation the rights to use, copy, modify, merge, publish, 10235783Skib * distribute, sub license, and/or sell copies of the Software, and to 11235783Skib * permit persons to whom the Software is furnished to do so, subject to 12235783Skib * the following conditions: 13235783Skib * 14235783Skib * The above copyright notice and this permission notice (including the 15235783Skib * next paragraph) shall be included in all copies or substantial portions 16235783Skib * of the Software. 17235783Skib * 18235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21235783Skib * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22235783Skib * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23235783Skib * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24235783Skib * USE OR OTHER DEALINGS IN THE SOFTWARE. 25235783Skib * 26235783Skib * 27235783Skib **************************************************************************/ 28235783Skib/* 29235783Skib * Authors: 30235783Skib * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> 31235783Skib */ 32235783Skib 33282199Sdumbbell#include <sys/cdefs.h> 34282199Sdumbbell__FBSDID("$FreeBSD$"); 35282199Sdumbbell 36235783Skib#ifndef _DRM_MM_H_ 37235783Skib#define _DRM_MM_H_ 38235783Skib 39282199Sdumbbell/* 40282199Sdumbbell * Generic range manager structs 41282199Sdumbbell */ 42235783Skib#include <dev/drm2/drm_linux_list.h> 43235783Skib 44235783Skibstruct drm_mm_node { 45235783Skib struct list_head node_list; 46235783Skib struct list_head hole_stack; 47235783Skib unsigned hole_follows : 1; 48235783Skib unsigned scanned_block : 1; 49235783Skib unsigned scanned_prev_free : 1; 50235783Skib unsigned scanned_next_free : 1; 51235783Skib unsigned scanned_preceeds_hole : 1; 52235783Skib unsigned allocated : 1; 53282199Sdumbbell unsigned long color; 54235783Skib unsigned long start; 55235783Skib unsigned long size; 56235783Skib struct drm_mm *mm; 57235783Skib}; 58235783Skib 59235783Skibstruct drm_mm { 60282199Sdumbbell /* List of all memory nodes that immediately precede a free hole. */ 61235783Skib struct list_head hole_stack; 62282199Sdumbbell /* head_node.node_list is the list of all memory nodes, ordered 63282199Sdumbbell * according to the (increasing) start address of the memory node. */ 64235783Skib struct drm_mm_node head_node; 65235783Skib struct list_head unused_nodes; 66235783Skib int num_unused; 67235783Skib struct mtx unused_lock; 68235783Skib unsigned int scan_check_range : 1; 69235783Skib unsigned scan_alignment; 70282199Sdumbbell unsigned long scan_color; 71235783Skib unsigned long scan_size; 72235783Skib unsigned long scan_hit_start; 73282199Sdumbbell unsigned long scan_hit_end; 74235783Skib unsigned scanned_blocks; 75235783Skib unsigned long scan_start; 76235783Skib unsigned long scan_end; 77235783Skib struct drm_mm_node *prev_scanned_node; 78282199Sdumbbell 79282199Sdumbbell void (*color_adjust)(struct drm_mm_node *node, unsigned long color, 80282199Sdumbbell unsigned long *start, unsigned long *end); 81235783Skib}; 82235783Skib 83235783Skibstatic inline bool drm_mm_node_allocated(struct drm_mm_node *node) 84235783Skib{ 85235783Skib return node->allocated; 86235783Skib} 87235783Skib 88235783Skibstatic inline bool drm_mm_initialized(struct drm_mm *mm) 89235783Skib{ 90282199Sdumbbell return mm->hole_stack.next; 91235783Skib} 92235783Skib#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ 93235783Skib &(mm)->head_node.node_list, \ 94235783Skib node_list) 95235783Skib#define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \ 96235783Skib for (entry = (mm)->prev_scanned_node, \ 97235783Skib next = entry ? list_entry(entry->node_list.next, \ 98235783Skib struct drm_mm_node, node_list) : NULL; \ 99235783Skib entry != NULL; entry = next, \ 100235783Skib next = entry ? list_entry(entry->node_list.next, \ 101282199Sdumbbell struct drm_mm_node, node_list) : NULL) \ 102235783Skib/* 103235783Skib * Basic range manager support (drm_mm.c) 104235783Skib */ 105235783Skibextern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, 106235783Skib unsigned long size, 107235783Skib unsigned alignment, 108282199Sdumbbell unsigned long color, 109235783Skib int atomic); 110235783Skibextern struct drm_mm_node *drm_mm_get_block_range_generic( 111235783Skib struct drm_mm_node *node, 112235783Skib unsigned long size, 113235783Skib unsigned alignment, 114282199Sdumbbell unsigned long color, 115235783Skib unsigned long start, 116235783Skib unsigned long end, 117235783Skib int atomic); 118235783Skibstatic inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, 119235783Skib unsigned long size, 120235783Skib unsigned alignment) 121235783Skib{ 122282199Sdumbbell return drm_mm_get_block_generic(parent, size, alignment, 0, 0); 123235783Skib} 124235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, 125235783Skib unsigned long size, 126235783Skib unsigned alignment) 127235783Skib{ 128282199Sdumbbell return drm_mm_get_block_generic(parent, size, alignment, 0, 1); 129235783Skib} 130235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_range( 131235783Skib struct drm_mm_node *parent, 132235783Skib unsigned long size, 133235783Skib unsigned alignment, 134235783Skib unsigned long start, 135235783Skib unsigned long end) 136235783Skib{ 137282199Sdumbbell return drm_mm_get_block_range_generic(parent, size, alignment, 0, 138282199Sdumbbell start, end, 0); 139235783Skib} 140282199Sdumbbellstatic inline struct drm_mm_node *drm_mm_get_color_block_range( 141282199Sdumbbell struct drm_mm_node *parent, 142282199Sdumbbell unsigned long size, 143282199Sdumbbell unsigned alignment, 144282199Sdumbbell unsigned long color, 145282199Sdumbbell unsigned long start, 146282199Sdumbbell unsigned long end) 147282199Sdumbbell{ 148282199Sdumbbell return drm_mm_get_block_range_generic(parent, size, alignment, color, 149282199Sdumbbell start, end, 0); 150282199Sdumbbell} 151235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_atomic_range( 152235783Skib struct drm_mm_node *parent, 153235783Skib unsigned long size, 154235783Skib unsigned alignment, 155235783Skib unsigned long start, 156235783Skib unsigned long end) 157235783Skib{ 158282199Sdumbbell return drm_mm_get_block_range_generic(parent, size, alignment, 0, 159235783Skib start, end, 1); 160235783Skib} 161282199Sdumbbell 162282199Sdumbbellextern int drm_mm_insert_node(struct drm_mm *mm, 163282199Sdumbbell struct drm_mm_node *node, 164282199Sdumbbell unsigned long size, 165282199Sdumbbell unsigned alignment); 166235783Skibextern int drm_mm_insert_node_in_range(struct drm_mm *mm, 167235783Skib struct drm_mm_node *node, 168282199Sdumbbell unsigned long size, 169282199Sdumbbell unsigned alignment, 170282199Sdumbbell unsigned long start, 171282199Sdumbbell unsigned long end); 172282199Sdumbbellextern int drm_mm_insert_node_generic(struct drm_mm *mm, 173282199Sdumbbell struct drm_mm_node *node, 174282199Sdumbbell unsigned long size, 175282199Sdumbbell unsigned alignment, 176282199Sdumbbell unsigned long color); 177282199Sdumbbellextern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, 178282199Sdumbbell struct drm_mm_node *node, 179282199Sdumbbell unsigned long size, 180282199Sdumbbell unsigned alignment, 181282199Sdumbbell unsigned long color, 182282199Sdumbbell unsigned long start, 183282199Sdumbbell unsigned long end); 184235783Skibextern void drm_mm_put_block(struct drm_mm_node *cur); 185235783Skibextern void drm_mm_remove_node(struct drm_mm_node *node); 186235783Skibextern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); 187282199Sdumbbellextern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, 188282199Sdumbbell unsigned long size, 189282199Sdumbbell unsigned alignment, 190282199Sdumbbell unsigned long color, 191282199Sdumbbell bool best_match); 192282199Sdumbbellextern struct drm_mm_node *drm_mm_search_free_in_range_generic( 193235783Skib const struct drm_mm *mm, 194235783Skib unsigned long size, 195235783Skib unsigned alignment, 196282199Sdumbbell unsigned long color, 197235783Skib unsigned long start, 198235783Skib unsigned long end, 199282199Sdumbbell bool best_match); 200282199Sdumbbellstatic inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, 201282199Sdumbbell unsigned long size, 202282199Sdumbbell unsigned alignment, 203282199Sdumbbell bool best_match) 204282199Sdumbbell{ 205282199Sdumbbell return drm_mm_search_free_generic(mm,size, alignment, 0, best_match); 206282199Sdumbbell} 207282199Sdumbbellstatic inline struct drm_mm_node *drm_mm_search_free_in_range( 208282199Sdumbbell const struct drm_mm *mm, 209282199Sdumbbell unsigned long size, 210282199Sdumbbell unsigned alignment, 211282199Sdumbbell unsigned long start, 212282199Sdumbbell unsigned long end, 213282199Sdumbbell bool best_match) 214282199Sdumbbell{ 215282199Sdumbbell return drm_mm_search_free_in_range_generic(mm, size, alignment, 0, 216282199Sdumbbell start, end, best_match); 217282199Sdumbbell} 218282199Sdumbbellstatic inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm, 219282199Sdumbbell unsigned long size, 220282199Sdumbbell unsigned alignment, 221282199Sdumbbell unsigned long color, 222282199Sdumbbell bool best_match) 223282199Sdumbbell{ 224282199Sdumbbell return drm_mm_search_free_generic(mm,size, alignment, color, best_match); 225282199Sdumbbell} 226282199Sdumbbellstatic inline struct drm_mm_node *drm_mm_search_free_in_range_color( 227282199Sdumbbell const struct drm_mm *mm, 228282199Sdumbbell unsigned long size, 229282199Sdumbbell unsigned alignment, 230282199Sdumbbell unsigned long color, 231282199Sdumbbell unsigned long start, 232282199Sdumbbell unsigned long end, 233282199Sdumbbell bool best_match) 234282199Sdumbbell{ 235282199Sdumbbell return drm_mm_search_free_in_range_generic(mm, size, alignment, color, 236282199Sdumbbell start, end, best_match); 237282199Sdumbbell} 238282199Sdumbbellextern int drm_mm_init(struct drm_mm *mm, 239282199Sdumbbell unsigned long start, 240235783Skib unsigned long size); 241235783Skibextern void drm_mm_takedown(struct drm_mm *mm); 242235783Skibextern int drm_mm_clean(struct drm_mm *mm); 243235783Skibextern int drm_mm_pre_get(struct drm_mm *mm); 244235783Skib 245235783Skibstatic inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) 246235783Skib{ 247235783Skib return block->mm; 248235783Skib} 249235783Skib 250282199Sdumbbellvoid drm_mm_init_scan(struct drm_mm *mm, 251282199Sdumbbell unsigned long size, 252282199Sdumbbell unsigned alignment, 253282199Sdumbbell unsigned long color); 254282199Sdumbbellvoid drm_mm_init_scan_with_range(struct drm_mm *mm, 255282199Sdumbbell unsigned long size, 256235783Skib unsigned alignment, 257282199Sdumbbell unsigned long color, 258235783Skib unsigned long start, 259235783Skib unsigned long end); 260235783Skibint drm_mm_scan_add_block(struct drm_mm_node *node); 261235783Skibint drm_mm_scan_remove_block(struct drm_mm_node *node); 262235783Skib 263282199Sdumbbellextern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); 264247833Skib 265235783Skib#endif 266