22d22446d7a0bedbd11fca59610352e5fa2e267c
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_osk_list.h
1 /*
2  * Copyright (C) 2010-2015 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 /**
12  * @file mali_osk_list.h
13  * Implementation of the OS abstraction layer for the kernel device driver
14  */
15
16 #ifndef __MALI_OSK_LIST_H__
17 #define __MALI_OSK_LIST_H__
18
19 #include "mali_osk.h"
20 #include "mali_kernel_common.h"
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next)
27 {
28         next->prev = new_entry;
29         new_entry->next = next;
30         new_entry->prev = prev;
31         prev->next = new_entry;
32 }
33
34 MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next)
35 {
36         next->prev = prev;
37         prev->next = next;
38 }
39
40 /** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists
41  * @{ */
42
43 /** Reference implementations of Doubly-linked Circular Lists are provided.
44  * There is often no need to re-implement these.
45  *
46  * @note The implementation may differ subtly from any lists the OS provides.
47  * For this reason, these lists should not be mixed with OS-specific lists
48  * inside the OSK/UKK implementation. */
49
50 /** @brief Initialize a list to be a head of an empty list
51  * @param exp the list to initialize. */
52 #define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp)
53
54 /** @brief Define a list variable, which is uninitialized.
55  * @param exp the name of the variable that the list will be defined as. */
56 #define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp
57
58 /** @brief Define a list variable, which is initialized.
59  * @param exp the name of the variable that the list will be defined as. */
60 #define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp }
61
62 /** @brief Initialize a list element.
63  *
64  * All list elements must be initialized before use.
65  *
66  * Do not use on any list element that is present in a list without using
67  * _mali_osk_list_del first, otherwise this will break the list.
68  *
69  * @param list the list element to initialize
70  */
71 MALI_STATIC_INLINE void _mali_osk_list_init(_mali_osk_list_t *list)
72 {
73         list->next = list;
74         list->prev = list;
75 }
76
77 /** @brief Insert a single list element after an entry in a list
78  *
79  * As an example, if this is inserted to the head of a list, then this becomes
80  * the first element of the list.
81  *
82  * Do not use to move list elements from one list to another, as it will break
83  * the originating list.
84  *
85  *
86  * @param newlist the list element to insert
87  * @param list the list in which to insert. The new element will be the next
88  * entry in this list
89  */
90 MALI_STATIC_INLINE void _mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *list)
91 {
92         __mali_osk_list_add(new_entry, list, list->next);
93 }
94
95 /** @brief Insert a single list element before an entry in a list
96  *
97  * As an example, if this is inserted to the head of a list, then this becomes
98  * the last element of the list.
99  *
100  * Do not use to move list elements from one list to another, as it will break
101  * the originating list.
102  *
103  * @param newlist the list element to insert
104  * @param list the list in which to insert. The new element will be the previous
105  * entry in this list
106  */
107 MALI_STATIC_INLINE void _mali_osk_list_addtail(_mali_osk_list_t *new_entry, _mali_osk_list_t *list)
108 {
109         __mali_osk_list_add(new_entry, list->prev, list);
110 }
111
112 /** @brief Remove a single element from a list
113  *
114  * The element will no longer be present in the list. The removed list element
115  * will be uninitialized, and so should not be traversed. It must be
116  * initialized before further use.
117  *
118  * @param list the list element to remove.
119  */
120 MALI_STATIC_INLINE void _mali_osk_list_del(_mali_osk_list_t *list)
121 {
122         __mali_osk_list_del(list->prev, list->next);
123 }
124
125 /** @brief Remove a single element from a list, and re-initialize it
126  *
127  * The element will no longer be present in the list. The removed list element
128  * will initialized, and so can be used as normal.
129  *
130  * @param list the list element to remove and initialize.
131  */
132 MALI_STATIC_INLINE void _mali_osk_list_delinit(_mali_osk_list_t *list)
133 {
134         __mali_osk_list_del(list->prev, list->next);
135         _mali_osk_list_init(list);
136 }
137
138 /** @brief Determine whether a list is empty.
139  *
140  * An empty list is one that contains a single element that points to itself.
141  *
142  * @param list the list to check.
143  * @return non-zero if the list is empty, and zero otherwise.
144  */
145 MALI_STATIC_INLINE mali_bool _mali_osk_list_empty(_mali_osk_list_t *list)
146 {
147         return list->next == list;
148 }
149
150 /** @brief Move a list element from one list to another.
151  *
152  * The list element must be initialized.
153  *
154  * As an example, moving a list item to the head of a new list causes this item
155  * to be the first element in the new list.
156  *
157  * @param move the list element to move
158  * @param list the new list into which the element will be inserted, as the next
159  * element in the list.
160  */
161 MALI_STATIC_INLINE void _mali_osk_list_move(_mali_osk_list_t *move_entry, _mali_osk_list_t *list)
162 {
163         __mali_osk_list_del(move_entry->prev, move_entry->next);
164         _mali_osk_list_add(move_entry, list);
165 }
166
167 /** @brief Move an entire list
168  *
169  * The list element must be initialized.
170  *
171  * Allows you to move a list from one list head to another list head
172  *
173  * @param old_list The existing list head
174  * @param new_list The new list head (must be an empty list)
175  */
176 MALI_STATIC_INLINE void _mali_osk_list_move_list(_mali_osk_list_t *old_list, _mali_osk_list_t *new_list)
177 {
178         MALI_DEBUG_ASSERT(_mali_osk_list_empty(new_list));
179         if (!_mali_osk_list_empty(old_list)) {
180                 new_list->next = old_list->next;
181                 new_list->prev = old_list->prev;
182                 new_list->next->prev = new_list;
183                 new_list->prev->next = new_list;
184                 old_list->next = old_list;
185                 old_list->prev = old_list;
186         }
187 }
188
189 /** @brief Find the containing structure of a list
190  *
191  * When traversing a list, this is used to recover the containing structure,
192  * given that is contains a _mali_osk_list_t member.
193  *
194  * Each list must be of structures of one type, and must link the same members
195  * together, otherwise it will not be possible to correctly recover the
196  * sturctures that the lists link.
197  *
198  * @note no type or memory checking occurs to ensure that a structure does in
199  * fact exist for the list entry, and that it is being recovered with respect
200  * to the correct list member.
201  *
202  * @param ptr the pointer to the _mali_osk_list_t member in this structure
203  * @param type the type of the structure that contains the member
204  * @param member the member of the structure that ptr points to.
205  * @return a pointer to a \a type object which contains the _mali_osk_list_t
206  * \a member, as pointed to by the _mali_osk_list_t \a *ptr.
207  */
208 #define _MALI_OSK_LIST_ENTRY(ptr, type, member) \
209         _MALI_OSK_CONTAINER_OF(ptr, type, member)
210
211 /** @brief Enumerate a list safely
212  *
213  * With this macro, lists can be enumerated in a 'safe' manner. That is,
214  * entries can be deleted from the list without causing an error during
215  * enumeration. To achieve this, a 'temporary' pointer is required, which must
216  * be provided to the macro.
217  *
218  * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be
219  * followed by a statement or compound-statement which will be executed for
220  * each list entry.
221  *
222  * Upon loop completion, providing that an early out was not taken in the
223  * loop body, then it is guaranteed that ptr->member == list, even if the loop
224  * body never executed.
225  *
226  * @param ptr a pointer to an object of type 'type', which points to the
227  * structure that contains the currently enumerated list entry.
228  * @param tmp a pointer to an object of type 'type', which must not be used
229  * inside the list-execution statement.
230  * @param list a pointer to a _mali_osk_list_t, from which enumeration will
231  * begin
232  * @param type the type of the structure that contains the _mali_osk_list_t
233  * member that is part of the list to be enumerated.
234  * @param member the _mali_osk_list_t member of the structure that is part of
235  * the list to be enumerated.
236  */
237 #define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member)         \
238         for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member),      \
239              tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member);  \
240              &ptr->member != (list);                                      \
241              ptr = tmp,                                                   \
242              tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member))
243
244 /** @brief Enumerate a list in reverse order safely
245  *
246  * This macro is identical to @ref _MALI_OSK_LIST_FOREACHENTRY, except that
247  * entries are enumerated in reverse order.
248  *
249  * @param ptr a pointer to an object of type 'type', which points to the
250  * structure that contains the currently enumerated list entry.
251  * @param tmp a pointer to an object of type 'type', which must not be used
252  * inside the list-execution statement.
253  * @param list a pointer to a _mali_osk_list_t, from which enumeration will
254  * begin
255  * @param type the type of the structure that contains the _mali_osk_list_t
256  * member that is part of the list to be enumerated.
257  * @param member the _mali_osk_list_t member of the structure that is part of
258  * the list to be enumerated.
259  */
260 #define _MALI_OSK_LIST_FOREACHENTRY_REVERSE(ptr, tmp, list, type, member) \
261         for (ptr = _MALI_OSK_LIST_ENTRY((list)->prev, type, member),      \
262              tmp = _MALI_OSK_LIST_ENTRY(ptr->member.prev, type, member);  \
263              &ptr->member != (list);                                      \
264              ptr = tmp,                                                   \
265              tmp = _MALI_OSK_LIST_ENTRY(tmp->member.prev, type, member))
266
267 /** @} */ /* end group _mali_osk_list */
268
269 #ifdef __cplusplus
270 }
271 #endif
272
273 #endif /* __MALI_OSK_LIST_H__ */