1 /**************************************************************************
2 * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
27 * An allocate-fence manager implementation intended for sets of base-registers
28 * or tiling-registers.
34 * Allocate a compatible register and put it on the unfenced list.
37 int drm_regs_alloc(struct drm_reg_manager *manager,
41 int interruptible, int no_wait, struct drm_reg **reg)
43 struct drm_reg *entry, *next_entry;
49 * Search the unfenced list.
52 list_for_each_entry(entry, &manager->unfenced, head) {
53 if (manager->reg_reusable(entry, data)) {
54 entry->new_fence_type |= fence_type;
60 * Search the lru list.
63 list_for_each_entry_safe(entry, next_entry, &manager->lru, head) {
64 struct drm_fence_object *fence = entry->fence;
65 if (fence->fence_class == fence_class &&
66 (entry->fence_type & fence_type) == entry->fence_type &&
67 manager->reg_reusable(entry, data)) {
68 list_del(&entry->head);
69 entry->new_fence_type = fence_type;
70 list_add_tail(&entry->head, &manager->unfenced);
76 * Search the free list.
79 list_for_each_entry(entry, &manager->free, head) {
80 list_del(&entry->head);
81 entry->new_fence_type = fence_type;
82 list_add_tail(&entry->head, &manager->unfenced);
90 * Go back to the lru list and try to expire fences.
93 list_for_each_entry_safe(entry, next_entry, &manager->lru, head) {
94 BUG_ON(!entry->fence);
95 ret = drm_fence_object_wait(entry->fence, 0, !interruptible,
100 drm_fence_usage_deref_unlocked(&entry->fence);
101 list_del(&entry->head);
102 entry->new_fence_type = fence_type;
103 list_add_tail(&entry->head, &manager->unfenced);
108 * Oops. All registers are used up :(.
116 EXPORT_SYMBOL(drm_regs_alloc);
118 void drm_regs_fence(struct drm_reg_manager *manager,
119 struct drm_fence_object *fence)
121 struct drm_reg *entry;
122 struct drm_reg *next_entry;
127 * Old fence (if any) is still valid.
128 * Put back on free and lru lists.
131 list_for_each_entry_safe_reverse(entry, next_entry,
132 &manager->unfenced, head) {
133 list_del(&entry->head);
134 list_add(&entry->head, (entry->fence) ?
135 &manager->lru : &manager->free);
140 * Fence with a new fence and put on lru list.
143 list_for_each_entry_safe(entry, next_entry, &manager->unfenced,
145 list_del(&entry->head);
147 drm_fence_usage_deref_unlocked(&entry->fence);
148 drm_fence_reference_unlocked(&entry->fence, fence);
150 entry->fence_type = entry->new_fence_type;
151 BUG_ON((entry->fence_type & fence->type) !=
154 list_add_tail(&entry->head, &manager->lru);
158 EXPORT_SYMBOL(drm_regs_fence);
160 void drm_regs_free(struct drm_reg_manager *manager)
162 struct drm_reg *entry;
163 struct drm_reg *next_entry;
165 drm_regs_fence(manager, NULL);
167 list_for_each_entry_safe(entry, next_entry, &manager->free, head) {
168 list_del(&entry->head);
169 manager->reg_destroy(entry);
172 list_for_each_entry_safe(entry, next_entry, &manager->lru, head) {
174 (void)drm_fence_object_wait(entry->fence, 1, 1,
176 list_del(&entry->head);
177 drm_fence_usage_deref_unlocked(&entry->fence);
178 manager->reg_destroy(entry);
181 EXPORT_SYMBOL(drm_regs_free);
183 void drm_regs_add(struct drm_reg_manager *manager, struct drm_reg *reg)
186 list_add_tail(®->head, &manager->free);
188 EXPORT_SYMBOL(drm_regs_add);
190 void drm_regs_init(struct drm_reg_manager *manager,
191 int (*reg_reusable) (const struct drm_reg *, const void *),
192 void (*reg_destroy) (struct drm_reg *))
194 INIT_LIST_HEAD(&manager->free);
195 INIT_LIST_HEAD(&manager->lru);
196 INIT_LIST_HEAD(&manager->unfenced);
197 manager->reg_reusable = reg_reusable;
198 manager->reg_destroy = reg_destroy;
200 EXPORT_SYMBOL(drm_regs_init);