xref: /illumos-gate/usr/src/uts/common/io/mr_sas/mr_sas_list.h (revision 56f33205c9ed776c3c909e07d52e94610a675740)
1 /*
2  * mr_sas_list.h: header for mr_sas
3  *
4  * Solaris MegaRAID driver for SAS2.0 controllers
5  * Copyright (c) 2008-2009, LSI Logic Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  *    this list of conditions and the following disclaimer in the documentation
16  *    and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the author nor the names of its contributors may be
19  *    used to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33  * DAMAGE.
34  */
35 
36 /*
37  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
38  * Use is subject to license terms.
39  */
40 
41 #ifndef	_MR_SAS_LIST_H_
42 #define	_MR_SAS_LIST_H_
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /*
49  * Simple doubly linked list implementation.
50  *
51  * Some of the internal functions ("__xxx") are useful when
52  * manipulating whole lists rather than single entries, as
53  * sometimes we already know the next/prev entries and we can
54  * generate better code by using them directly rather than
55  * using the generic single-entry routines.
56  */
57 
58 struct mlist_head {
59 	struct mlist_head *next, *prev;
60 };
61 
62 typedef struct mlist_head mlist_t;
63 
64 #define	LIST_HEAD_INIT(name) { &(name), &(name) }
65 
66 #define	LIST_HEAD(name) \
67 	struct mlist_head name = LIST_HEAD_INIT(name)
68 
69 #define	INIT_LIST_HEAD(ptr) { \
70 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
71 }
72 
73 #ifndef	KMDB_MODULE
74 /*
75  * Insert a new entry between two known consecutive entries.
76  *
77  * This is only for internal list manipulation where we know
78  * the prev/next entries already!
79  */
80 static void __list_add(struct mlist_head *new,
81 	struct mlist_head *prev,
82 	struct mlist_head *next)
83 {
84 	next->prev = new;
85 	new->next = next;
86 	new->prev = prev;
87 	prev->next = new;
88 }
89 
90 
91 /*
92  * mlist_add - add a new entry
93  * @new: new entry to be added
94  * @head: list head to add it after
95  *
96  * Insert a new entry after the specified head.
97  * This is good for implementing stacks.
98  */
99 static void mlist_add(struct mlist_head *new, struct mlist_head *head)
100 {
101 	__list_add(new, head, head->next);
102 }
103 
104 
105 /*
106  * mlist_add_tail - add a new entry
107  * @new: new entry to be added
108  * @head: list head to add it before
109  *
110  * Insert a new entry before the specified head.
111  * This is useful for implementing queues.
112  */
113 static void mlist_add_tail(struct mlist_head *new, struct mlist_head *head)
114 {
115 	__list_add(new, head->prev, head);
116 }
117 
118 
119 
120 /*
121  * Delete a list entry by making the prev/next entries
122  * point to each other.
123  *
124  * This is only for internal list manipulation where we know
125  * the prev/next entries already!
126  */
127 static void __list_del(struct mlist_head *prev,
128 			struct mlist_head *next)
129 {
130 	next->prev = prev;
131 	prev->next = next;
132 }
133 
134 
135 /*
136  * mlist_del_init - deletes entry from list and reinitialize it.
137  * @entry: the element to delete from the list.
138  */
139 static void mlist_del_init(struct mlist_head *entry)
140 {
141 	__list_del(entry->prev, entry->next);
142 	INIT_LIST_HEAD(entry);
143 }
144 
145 
146 /*
147  * mlist_empty - tests whether a list is empty
148  * @head: the list to test.
149  */
150 static int mlist_empty(struct mlist_head *head)
151 {
152 	return (head->next == head);
153 }
154 
155 
156 /*
157  * mlist_splice - join two lists
158  * @list: the new list to add.
159  * @head: the place to add it in the first list.
160  */
161 static void mlist_splice(struct mlist_head *list, struct mlist_head *head)
162 {
163 	struct mlist_head *first = list->next;
164 
165 	if (first != list) {
166 		struct mlist_head *last = list->prev;
167 		struct mlist_head *at = head->next;
168 
169 		first->prev = head;
170 		head->next = first;
171 
172 		last->next = at;
173 		at->prev = last;
174 	}
175 }
176 #endif /* KMDB_MODULE */
177 
178 /*
179  * mlist_entry - get the struct for this entry
180  * @ptr:	the &struct mlist_head pointer.
181  * @type:	the type of the struct this is embedded in.
182  * @member:	the name of the list_struct within the struct.
183  */
184 #define	mlist_entry(ptr, type, member) \
185 	((type *)((size_t)(ptr) - offsetof(type, member)))
186 
187 
188 /*
189  * mlist_for_each	-	iterate over a list
190  * @pos:	the &struct mlist_head to use as a loop counter.
191  * @head:	the head for your list.
192  */
193 #define	mlist_for_each(pos, head) \
194 	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
195 		pos = pos->next, prefetch(pos->next))
196 
197 
198 /*
199  * mlist_for_each_safe - iterate over a list safe against removal of list entry
200  * @pos:	the &struct mlist_head to use as a loop counter.
201  * @n:		another &struct mlist_head to use as temporary storage
202  * @head:	the head for your list.
203  */
204 #define	mlist_for_each_safe(pos, n, head) \
205 	for (pos = (head)->next, n = pos->next; pos != (head); \
206 		pos = n, n = pos->next)
207 
208 #ifdef __cplusplus
209 }
210 #endif
211 
212 #endif /* _MR_SAS_LIST_H_ */
213