16447Ssusans /*
26447Ssusans * list.h: header for mega_sas
36447Ssusans *
46447Ssusans * Solaris MegaRAID driver for SAS controllers
56447Ssusans * Copyright (c) 2004-2008, LSI Logic Corporation.
66447Ssusans * All rights reserved.
76447Ssusans *
86447Ssusans * Redistribution and use in source and binary forms, with or without
96447Ssusans * modification, are permitted provided that the following conditions are met:
106447Ssusans *
116447Ssusans * 1. Redistributions of source code must retain the above copyright notice,
126447Ssusans * this list of conditions and the following disclaimer.
136447Ssusans *
146447Ssusans * 2. Redistributions in binary form must reproduce the above copyright notice,
156447Ssusans * this list of conditions and the following disclaimer in the documentation
166447Ssusans * and/or other materials provided with the distribution.
176447Ssusans *
186447Ssusans * 3. Neither the name of the author nor the names of its contributors may be
196447Ssusans * used to endorse or promote products derived from this software without
206447Ssusans * specific prior written permission.
216447Ssusans *
226447Ssusans * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
236447Ssusans * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
246447Ssusans * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
256447Ssusans * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
266447Ssusans * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
276447Ssusans * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
286447Ssusans * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
296447Ssusans * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
306447Ssusans * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
316447Ssusans * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
326447Ssusans * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
336447Ssusans * DAMAGE.
346447Ssusans */
356447Ssusans
366447Ssusans /*
376447Ssusans * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
386447Ssusans * Use is subject to license terms.
396447Ssusans */
406447Ssusans
416447Ssusans #ifndef _LIST_H_
426447Ssusans #define _LIST_H_
436447Ssusans
446447Ssusans #ifdef __cplusplus
456447Ssusans extern "C" {
466447Ssusans #endif
476447Ssusans
486447Ssusans /*
496447Ssusans * Simple doubly linked list implementation.
506447Ssusans *
516447Ssusans * Some of the internal functions ("__xxx") are useful when
526447Ssusans * manipulating whole lists rather than single entries, as
536447Ssusans * sometimes we already know the next/prev entries and we can
546447Ssusans * generate better code by using them directly rather than
556447Ssusans * using the generic single-entry routines.
566447Ssusans */
576447Ssusans
586447Ssusans struct mlist_head {
596447Ssusans struct mlist_head *next, *prev;
606447Ssusans };
616447Ssusans
626447Ssusans typedef struct mlist_head mlist_t;
636447Ssusans
646447Ssusans #define LIST_HEAD_INIT(name) { &(name), &(name) }
656447Ssusans
666447Ssusans #define LIST_HEAD(name) \
676447Ssusans struct mlist_head name = LIST_HEAD_INIT(name)
686447Ssusans
696447Ssusans #define INIT_LIST_HEAD(ptr) { \
706447Ssusans (ptr)->next = (ptr); (ptr)->prev = (ptr); \
716447Ssusans }
726447Ssusans
736447Ssusans
746447Ssusans /*
756447Ssusans * Insert a new entry between two known consecutive entries.
766447Ssusans *
776447Ssusans * This is only for internal list manipulation where we know
786447Ssusans * the prev/next entries already!
796447Ssusans */
__list_add(struct mlist_head * new,struct mlist_head * prev,struct mlist_head * next)806447Ssusans static void __list_add(struct mlist_head *new,
816447Ssusans struct mlist_head *prev,
826447Ssusans struct mlist_head *next)
836447Ssusans {
846447Ssusans next->prev = new;
856447Ssusans new->next = next;
866447Ssusans new->prev = prev;
876447Ssusans prev->next = new;
886447Ssusans }
896447Ssusans
906447Ssusans
916447Ssusans /*
926447Ssusans * mlist_add - add a new entry
936447Ssusans * @new: new entry to be added
946447Ssusans * @head: list head to add it after
956447Ssusans *
966447Ssusans * Insert a new entry after the specified head.
976447Ssusans * This is good for implementing stacks.
986447Ssusans */
mlist_add(struct mlist_head * new,struct mlist_head * head)996447Ssusans static void mlist_add(struct mlist_head *new, struct mlist_head *head)
1006447Ssusans {
1016447Ssusans __list_add(new, head, head->next);
1026447Ssusans }
1036447Ssusans
1046447Ssusans
1056447Ssusans /*
1066447Ssusans * mlist_add_tail - add a new entry
1076447Ssusans * @new: new entry to be added
1086447Ssusans * @head: list head to add it before
1096447Ssusans *
1106447Ssusans * Insert a new entry before the specified head.
1116447Ssusans * This is useful for implementing queues.
1126447Ssusans */
mlist_add_tail(struct mlist_head * new,struct mlist_head * head)1136447Ssusans static void mlist_add_tail(struct mlist_head *new, struct mlist_head *head)
1146447Ssusans {
1156447Ssusans __list_add(new, head->prev, head);
1166447Ssusans }
1176447Ssusans
1186447Ssusans
1196447Ssusans
1206447Ssusans /*
1216447Ssusans * Delete a list entry by making the prev/next entries
1226447Ssusans * point to each other.
1236447Ssusans *
1246447Ssusans * This is only for internal list manipulation where we know
1256447Ssusans * the prev/next entries already!
1266447Ssusans */
__list_del(struct mlist_head * prev,struct mlist_head * next)1276447Ssusans static void __list_del(struct mlist_head *prev,
1286447Ssusans struct mlist_head *next)
1296447Ssusans {
1306447Ssusans next->prev = prev;
1316447Ssusans prev->next = next;
1326447Ssusans }
1336447Ssusans
1346447Ssusans
135*7698SSusan.Scheufele@Sun.COM #if 0
1366447Ssusans /*
1376447Ssusans * mlist_del - deletes entry from list.
1386447Ssusans * @entry: the element to delete from the list.
1396447Ssusans * Note: list_empty on entry does not return true after this, the entry
1406447Ssusans * is in an undefined state.
1416447Ssusans */
142*7698SSusan.Scheufele@Sun.COM
1436447Ssusans static void mlist_del(struct mlist_head *entry)
1446447Ssusans {
1456447Ssusans __list_del(entry->prev, entry->next);
1466447Ssusans entry->next = entry->prev = 0;
1476447Ssusans }
148*7698SSusan.Scheufele@Sun.COM #endif
1496447Ssusans
1506447Ssusans /*
1516447Ssusans * mlist_del_init - deletes entry from list and reinitialize it.
1526447Ssusans * @entry: the element to delete from the list.
1536447Ssusans */
mlist_del_init(struct mlist_head * entry)1546447Ssusans static void mlist_del_init(struct mlist_head *entry)
1556447Ssusans {
1566447Ssusans __list_del(entry->prev, entry->next);
1576447Ssusans INIT_LIST_HEAD(entry);
1586447Ssusans }
1596447Ssusans
1606447Ssusans
1616447Ssusans /*
1626447Ssusans * mlist_empty - tests whether a list is empty
1636447Ssusans * @head: the list to test.
1646447Ssusans */
mlist_empty(struct mlist_head * head)1656447Ssusans static int mlist_empty(struct mlist_head *head)
1666447Ssusans {
1676447Ssusans return (head->next == head);
1686447Ssusans }
1696447Ssusans
1706447Ssusans
1716447Ssusans /*
1726447Ssusans * mlist_splice - join two lists
1736447Ssusans * @list: the new list to add.
1746447Ssusans * @head: the place to add it in the first list.
1756447Ssusans */
mlist_splice(struct mlist_head * list,struct mlist_head * head)1766447Ssusans static void mlist_splice(struct mlist_head *list, struct mlist_head *head)
1776447Ssusans {
1786447Ssusans struct mlist_head *first = list->next;
1796447Ssusans
1806447Ssusans if (first != list) {
1816447Ssusans struct mlist_head *last = list->prev;
1826447Ssusans struct mlist_head *at = head->next;
1836447Ssusans
1846447Ssusans first->prev = head;
1856447Ssusans head->next = first;
1866447Ssusans
1876447Ssusans last->next = at;
1886447Ssusans at->prev = last;
1896447Ssusans }
1906447Ssusans }
1916447Ssusans
1926447Ssusans
1936447Ssusans
1946447Ssusans /* TODO: set this */
1956447Ssusans #if 0
1966447Ssusans #pragma inline(list_add, list_add_tail, __list_del, list_del,
1976447Ssusans list_del_init, list_empty, list_splice)
1986447Ssusans #endif
1996447Ssusans
2006447Ssusans
2016447Ssusans /*
2026447Ssusans * mlist_entry - get the struct for this entry
2036447Ssusans * @ptr: the &struct mlist_head pointer.
2046447Ssusans * @type: the type of the struct this is embedded in.
2056447Ssusans * @member: the name of the list_struct within the struct.
2066447Ssusans */
2076447Ssusans #define mlist_entry(ptr, type, member) \
208*7698SSusan.Scheufele@Sun.COM ((type *)((size_t)(ptr) - offsetof(type, member)))
2096447Ssusans
2106447Ssusans
2116447Ssusans /*
2126447Ssusans * mlist_for_each - iterate over a list
2136447Ssusans * @pos: the &struct mlist_head to use as a loop counter.
2146447Ssusans * @head: the head for your list.
2156447Ssusans */
2166447Ssusans #define mlist_for_each(pos, head) \
2176447Ssusans for (pos = (head)->next, prefetch(pos->next); pos != (head); \
2186447Ssusans pos = pos->next, prefetch(pos->next))
2196447Ssusans
2206447Ssusans
2216447Ssusans /*
2226447Ssusans * mlist_for_each_safe - iterate over a list safe against removal of list entry
2236447Ssusans * @pos: the &struct mlist_head to use as a loop counter.
2246447Ssusans * @n: another &struct mlist_head to use as temporary storage
2256447Ssusans * @head: the head for your list.
2266447Ssusans */
2276447Ssusans #define mlist_for_each_safe(pos, n, head) \
2286447Ssusans for (pos = (head)->next, n = pos->next; pos != (head); \
2296447Ssusans pos = n, n = pos->next)
2306447Ssusans
2316447Ssusans #ifdef __cplusplus
2326447Ssusans }
2336447Ssusans #endif
2346447Ssusans
2356447Ssusans #endif /* _LIST_H_ */
236