]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/libdrm.git/blob - linux-core/drm_regman.c
Use headers copied from kernel instead of shared-core
[glsdk/libdrm.git] / linux-core / drm_regman.c
1 /**************************************************************************
2  * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
3  * All Rights Reserved.
4  *
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:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
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.
24  *
25  **************************************************************************/
26 /*
27  * An allocate-fence manager implementation intended for sets of base-registers
28  * or tiling-registers.
29  */
31 #include "drmP.h"
33 /*
34  * Allocate a compatible register and put it on the unfenced list.
35  */
37 int drm_regs_alloc(struct drm_reg_manager *manager,
38                    const void *data,
39                    uint32_t fence_class,
40                    uint32_t fence_type,
41                    int interruptible, int no_wait, struct drm_reg **reg)
42 {
43         struct drm_reg *entry, *next_entry;
44         int ret;
46         *reg = NULL;
48         /*
49          * Search the unfenced list.
50          */
52         list_for_each_entry(entry, &manager->unfenced, head) {
53                 if (manager->reg_reusable(entry, data)) {
54                         entry->new_fence_type |= fence_type;
55                         goto out;
56                 }
57         }
59         /*
60          * Search the lru list.
61          */
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);
71                         goto out;
72                 }
73         }
75         /*
76          * Search the free list.
77          */
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);
83                 goto out;
84         }
86         if (no_wait)
87                 return -EBUSY;
89         /*
90          * Go back to the lru list and try to expire fences.
91          */
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,
96                                             entry->fence_type);
97                 if (ret)
98                         return ret;
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);
104                 goto out;
105         }
107         /*
108          * Oops. All registers are used up :(.
109          */
111         return -EBUSY;
112 out:
113         *reg = entry;
114         return 0;
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;
124         if (!fence) {
126                 /*
127                  * Old fence (if any) is still valid.
128                  * Put back on free and lru lists.
129                  */
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);
136                 }
137         } else {
139                 /*
140                  * Fence with a new fence and put on lru list.
141                  */
143                 list_for_each_entry_safe(entry, next_entry, &manager->unfenced,
144                                          head) {
145                         list_del(&entry->head);
146                         if (entry->fence)
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) !=
152                                entry->fence_type);
154                         list_add_tail(&entry->head, &manager->lru);
155                 }
156         }
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);
170         }
172         list_for_each_entry_safe(entry, next_entry, &manager->lru, head) {
174                 (void)drm_fence_object_wait(entry->fence, 1, 1,
175                                             entry->fence_type);
176                 list_del(&entry->head);
177                 drm_fence_usage_deref_unlocked(&entry->fence);
178                 manager->reg_destroy(entry);
179         }
181 EXPORT_SYMBOL(drm_regs_free);
183 void drm_regs_add(struct drm_reg_manager *manager, struct drm_reg *reg)
185         reg->fence = NULL;
186         list_add_tail(&reg->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);