1 /*
2 * mr_sas_list.h: header for mr_sas
3 *
4 * Solaris MegaRAID driver for SAS2.0 controllers
5 * Copyright (c) 2008-20012, LSI Logic Corporation.
6 * All rights reserved.
7 */
8
9 #ifndef _MR_SAS_LIST_H_
10 #define _MR_SAS_LIST_H_
11
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15
16 /*
17 * Simple doubly linked list implementation.
18 *
19 * Some of the internal functions ("__xxx") are useful when
20 * manipulating whole lists rather than single entries, as
21 * sometimes we already know the next/prev entries and we can
22 * generate better code by using them directly rather than
23 * using the generic single-entry routines.
24 */
25
26 struct mlist_head {
27 struct mlist_head *next, *prev;
28 };
29
30 typedef struct mlist_head mlist_t;
31
32 #define LIST_HEAD_INIT(name) { &(name), &(name) }
33
34 #define LIST_HEAD(name) \
35 struct mlist_head name = LIST_HEAD_INIT(name)
36
37 #define INIT_LIST_HEAD(ptr) { \
38 (ptr)->next = (ptr); (ptr)->prev = (ptr); \
39 }
40
41
42 /*
43 * Insert a new entry between two known consecutive entries.
44 *
45 * This is only for internal list manipulation where we know
46 * the prev/next entries already!
47 */
48 static void __list_add(struct mlist_head *new,
49 struct mlist_head *prev,
50 struct mlist_head *next)
51 {
52 next->prev = new;
53 new->next = next;
54 new->prev = prev;
55 prev->next = new;
56 }
57
58
59 /*
60 * mlist_add - add a new entry
61 * @new: new entry to be added
62 * @head: list head to add it after
63 *
64 * Insert a new entry after the specified head.
65 * This is good for implementing stacks.
66 */
67 static void mlist_add(struct mlist_head *new, struct mlist_head *head)
68 {
69 __list_add(new, head, head->next);
70 }
71
72
73 /*
74 * mlist_add_tail - add a new entry
75 * @new: new entry to be added
76 * @head: list head to add it before
77 *
78 * Insert a new entry before the specified head.
79 * This is useful for implementing queues.
80 */
81 static void mlist_add_tail(struct mlist_head *new, struct mlist_head *head)
82 {
83 __list_add(new, head->prev, head);
84 }
85
86
87
88 /*
89 * Delete a list entry by making the prev/next entries
90 * point to each other.
91 *
92 * This is only for internal list manipulation where we know
93 * the prev/next entries already!
94 */
95 static void __list_del(struct mlist_head *prev,
96 struct mlist_head *next)
97 {
98 next->prev = prev;
99 prev->next = next;
100 }
101
102
103 #if 0
104 /*
105 * mlist_del - deletes entry from list.
106 * @entry: the element to delete from the list.
107 * Note: list_empty on entry does not return true after this, the entry
108 * is in an undefined state.
109 */
110
111 static void mlist_del(struct mlist_head *entry)
112 {
113 __list_del(entry->prev, entry->next);
114 entry->next = entry->prev = 0;
115 }
116 #endif
117
118 /*
119 * mlist_del_init - deletes entry from list and reinitialize it.
120 * @entry: the element to delete from the list.
121 */
122 static void mlist_del_init(struct mlist_head *entry)
123 {
124 __list_del(entry->prev, entry->next);
125 INIT_LIST_HEAD(entry);
126 }
127
128
129 /*
130 * mlist_empty - tests whether a list is empty
131 * @head: the list to test.
132 */
133 static int mlist_empty(struct mlist_head *head)
134 {
135 return (head->next == head);
136 }
137
138
139 /*
140 * mlist_splice - join two lists
141 * @list: the new list to add.
142 * @head: the place to add it in the first list.
143 */
144 static void mlist_splice(struct mlist_head *list, struct mlist_head *head)
145 {
146 struct mlist_head *first = list->next;
147
148 if (first != list) {
149 struct mlist_head *last = list->prev;
150 struct mlist_head *at = head->next;
151
152 first->prev = head;
153 head->next = first;
154
155 last->next = at;
156 at->prev = last;
157 }
158 }
159
160
161
162 /* TODO: set this */
163 #if 0
164 #pragma inline(list_add, list_add_tail, __list_del, list_del,
165 list_del_init, list_empty, list_splice)
166 #endif
167
168
169 /*
170 * mlist_entry - get the struct for this entry
171 * @ptr: the &struct mlist_head pointer.
172 * @type: the type of the struct this is embedded in.
173 * @member: the name of the list_struct within the struct.
174 */
175 #define mlist_entry(ptr, type, member) \
176 ((type *)((size_t)(ptr) - offsetof(type, member)))
177
178
179 /*
180 * mlist_for_each - iterate over a list
181 * @pos: the &struct mlist_head to use as a loop counter.
182 * @head: the head for your list.
183 */
184 #define mlist_for_each(pos, head) \
185 for (pos = (head)->next, prefetch(pos->next); pos != (head); \
186 pos = pos->next, prefetch(pos->next))
187
188
189 /*
190 * mlist_for_each_safe - iterate over a list safe against removal of list entry
191 * @pos: the &struct mlist_head to use as a loop counter.
192 * @n: another &struct mlist_head to use as temporary storage
193 * @head: the head for your list.
194 */
195 #define mlist_for_each_safe(pos, n, head) \
196 for (pos = (head)->next, n = pos->next; pos != (head); \
197 pos = n, n = pos->next)
198
199 #ifdef __cplusplus
200 }
201 #endif
202
203 #endif /* _MR_SAS_LIST_H_ */