drm_mm.h revision 235783
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#include <sys/cdefs.h>
30235783Skib__FBSDID("$FreeBSD: head/sys/dev/drm2/drm_mm.h 235783 2012-05-22 11:07:44Z kib $");
31235783Skib
32235783Skib/*
33235783Skib * Authors:
34235783Skib * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
35235783Skib */
36235783Skib
37235783Skib#ifndef _DRM_MM_H_
38235783Skib#define _DRM_MM_H_
39235783Skib
40235783Skib#include <dev/drm2/drm_linux_list.h>
41235783Skib
42235783Skibstruct drm_mm_node {
43235783Skib	struct list_head node_list;
44235783Skib	struct list_head hole_stack;
45235783Skib	unsigned hole_follows : 1;
46235783Skib	unsigned scanned_block : 1;
47235783Skib	unsigned scanned_prev_free : 1;
48235783Skib	unsigned scanned_next_free : 1;
49235783Skib	unsigned scanned_preceeds_hole : 1;
50235783Skib	unsigned allocated : 1;
51235783Skib	unsigned long start;
52235783Skib	unsigned long size;
53235783Skib	struct drm_mm *mm;
54235783Skib	void *private;
55235783Skib};
56235783Skib
57235783Skibstruct drm_mm {
58235783Skib	struct list_head hole_stack;
59235783Skib	struct drm_mm_node head_node;
60235783Skib	struct list_head unused_nodes;
61235783Skib	int num_unused;
62235783Skib	struct mtx unused_lock;
63235783Skib	unsigned int scan_check_range : 1;
64235783Skib	unsigned scan_alignment;
65235783Skib	unsigned long scan_size;
66235783Skib	unsigned long scan_hit_start;
67235783Skib	unsigned scan_hit_size;
68235783Skib	unsigned scanned_blocks;
69235783Skib	unsigned long scan_start;
70235783Skib	unsigned long scan_end;
71235783Skib	struct drm_mm_node *prev_scanned_node;
72235783Skib};
73235783Skib
74235783Skibstatic inline bool drm_mm_node_allocated(struct drm_mm_node *node)
75235783Skib{
76235783Skib	return node->allocated;
77235783Skib}
78235783Skib
79235783Skibstatic inline bool drm_mm_initialized(struct drm_mm *mm)
80235783Skib{
81235783Skib	return (mm->hole_stack.next != NULL);
82235783Skib}
83235783Skib#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
84235783Skib						&(mm)->head_node.node_list, \
85235783Skib						node_list)
86235783Skib#define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
87235783Skib	for (entry = (mm)->prev_scanned_node, \
88235783Skib		next = entry ? list_entry(entry->node_list.next, \
89235783Skib			struct drm_mm_node, node_list) : NULL; \
90235783Skib	     entry != NULL; entry = next, \
91235783Skib		next = entry ? list_entry(entry->node_list.next, \
92235783Skib			struct drm_mm_node, node_list) : NULL)
93235783Skib
94235783Skib/*
95235783Skib * Basic range manager support (drm_mm.c)
96235783Skib */
97235783Skibextern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
98235783Skib						    unsigned long size,
99235783Skib						    unsigned alignment,
100235783Skib						    int atomic);
101235783Skibextern struct drm_mm_node *drm_mm_get_block_range_generic(
102235783Skib						struct drm_mm_node *node,
103235783Skib						unsigned long size,
104235783Skib						unsigned alignment,
105235783Skib						unsigned long start,
106235783Skib						unsigned long end,
107235783Skib						int atomic);
108235783Skibstatic inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
109235783Skib						   unsigned long size,
110235783Skib						   unsigned alignment)
111235783Skib{
112235783Skib	return drm_mm_get_block_generic(parent, size, alignment, 0);
113235783Skib}
114235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
115235783Skib							  unsigned long size,
116235783Skib							  unsigned alignment)
117235783Skib{
118235783Skib	return drm_mm_get_block_generic(parent, size, alignment, 1);
119235783Skib}
120235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_range(
121235783Skib						struct drm_mm_node *parent,
122235783Skib						unsigned long size,
123235783Skib						unsigned alignment,
124235783Skib						unsigned long start,
125235783Skib						unsigned long end)
126235783Skib{
127235783Skib	return drm_mm_get_block_range_generic(parent, size, alignment,
128235783Skib						start, end, 0);
129235783Skib}
130235783Skibstatic inline struct drm_mm_node *drm_mm_get_block_atomic_range(
131235783Skib						struct drm_mm_node *parent,
132235783Skib						unsigned long size,
133235783Skib						unsigned alignment,
134235783Skib						unsigned long start,
135235783Skib						unsigned long end)
136235783Skib{
137235783Skib	return drm_mm_get_block_range_generic(parent, size, alignment,
138235783Skib						start, end, 1);
139235783Skib}
140235783Skibextern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
141235783Skib			      unsigned long size, unsigned alignment);
142235783Skibextern int drm_mm_insert_node_in_range(struct drm_mm *mm,
143235783Skib				       struct drm_mm_node *node,
144235783Skib				       unsigned long size, unsigned alignment,
145235783Skib				       unsigned long start, unsigned long end);
146235783Skibextern void drm_mm_put_block(struct drm_mm_node *cur);
147235783Skibextern void drm_mm_remove_node(struct drm_mm_node *node);
148235783Skibextern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
149235783Skibextern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
150235783Skib					      unsigned long size,
151235783Skib					      unsigned alignment,
152235783Skib					      int best_match);
153235783Skibextern struct drm_mm_node *drm_mm_search_free_in_range(
154235783Skib						const struct drm_mm *mm,
155235783Skib						unsigned long size,
156235783Skib						unsigned alignment,
157235783Skib						unsigned long start,
158235783Skib						unsigned long end,
159235783Skib						int best_match);
160235783Skibextern int drm_mm_init(struct drm_mm *mm, unsigned long start,
161235783Skib		       unsigned long size);
162235783Skibextern void drm_mm_takedown(struct drm_mm *mm);
163235783Skibextern int drm_mm_clean(struct drm_mm *mm);
164235783Skibextern unsigned long drm_mm_tail_space(struct drm_mm *mm);
165235783Skibextern int drm_mm_remove_space_from_tail(struct drm_mm *mm,
166235783Skib					 unsigned long size);
167235783Skibextern int drm_mm_add_space_to_tail(struct drm_mm *mm,
168235783Skib				    unsigned long size, int atomic);
169235783Skibextern int drm_mm_pre_get(struct drm_mm *mm);
170235783Skib
171235783Skibstatic inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
172235783Skib{
173235783Skib	return block->mm;
174235783Skib}
175235783Skib
176235783Skibvoid drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
177235783Skib		      unsigned alignment);
178235783Skibvoid drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
179235783Skib				 unsigned alignment,
180235783Skib				 unsigned long start,
181235783Skib				 unsigned long end);
182235783Skibint drm_mm_scan_add_block(struct drm_mm_node *node);
183235783Skibint drm_mm_scan_remove_block(struct drm_mm_node *node);
184235783Skib
185235783Skib#endif
186