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_ */