blob: a5cf1425457492523574159b9d4c2c3c6b94ddbf [file] [log] [blame]
Madan Mohan Koyyalamudie32d2192013-09-28 23:54:37 -07001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28//==============================================================================
29// Double-link list definitions (adapted from Atheros SDIO stack)
30//
31// Author(s): ="Atheros"
32//==============================================================================
33
34#ifndef __DL_LIST_H___
35#define __DL_LIST_H___
36
37#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
38 ((struct_type *)((char *)(address) - (char *)(&((struct_type *)0)->field_name)))
39
40/* list functions */
41/* pointers for the list */
42typedef struct _DL_LIST {
43 struct _DL_LIST *pPrev;
44 struct _DL_LIST *pNext;
45}DL_LIST, *PDL_LIST;
46/*
47 * DL_LIST_INIT , initialize doubly linked list
48*/
49#define DL_LIST_INIT(pList)\
50 {(pList)->pPrev = pList; (pList)->pNext = pList;}
51
52/* faster macro to init list and add a single item */
53#define DL_LIST_INIT_AND_ADD(pList,pItem) \
54{ (pList)->pPrev = (pItem); \
55 (pList)->pNext = (pItem); \
56 (pItem)->pNext = (pList); \
57 (pItem)->pPrev = (pList); \
58}
59
60#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
61#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
62#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
63/*
64 * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
65 * NOT: do not use this function if the items in the list are deleted inside the
66 * iteration loop
67*/
68#define ITERATE_OVER_LIST(pStart, pTemp) \
69 for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
70
71static __inline bool DL_ListIsEntryInList(const DL_LIST * pList, const DL_LIST * pEntry) {
72 const DL_LIST * pTmp;
73
74 if (pList == pEntry) return true;
75
76 ITERATE_OVER_LIST(pList, pTmp) {
77 if (pTmp == pEntry) {
78 return true;
79 }
80 }
81
82 return false;
83}
84
85/* safe iterate macro that allows the item to be removed from the list
86 * the iteration continues to the next item in the list
87 */
88#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
89{ \
90 PDL_LIST pTemp; \
91 pTemp = (pStart)->pNext; \
92 while (pTemp != (pStart)) { \
93 (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \
94 pTemp = pTemp->pNext; \
95
96#define ITERATE_IS_VALID(pStart) DL_ListIsEntryInList(pStart, pTemp)
97#define ITERATE_RESET(pStart) pTemp=(pStart)->pNext
98
99#define ITERATE_END }}
100
101/*
102 * DL_ListInsertTail - insert pAdd to the end of the list
103*/
104static __inline PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
105 /* insert at tail */
106 pAdd->pPrev = pList->pPrev;
107 pAdd->pNext = pList;
108 if (pList->pPrev) {
109 pList->pPrev->pNext = pAdd;
110 }
111 pList->pPrev = pAdd;
112 return pAdd;
113}
114
115/*
116 * DL_ListInsertHead - insert pAdd into the head of the list
117*/
118static __inline PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
119 /* insert at head */
120 pAdd->pPrev = pList;
121 pAdd->pNext = pList->pNext;
122 pList->pNext->pPrev = pAdd;
123 pList->pNext = pAdd;
124 return pAdd;
125}
126
127#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
128/*
129 * DL_ListRemove - remove pDel from list
130*/
131static __inline PDL_LIST DL_ListRemove(PDL_LIST pDel) {
132 if (pDel->pNext != NULL) {
133 pDel->pNext->pPrev = pDel->pPrev;
134 }
135 if (pDel->pPrev != NULL) {
136 pDel->pPrev->pNext = pDel->pNext;
137 }
138
139 /* point back to itself just to be safe, incase remove is called again */
140 pDel->pNext = pDel;
141 pDel->pPrev = pDel;
142 return pDel;
143}
144
145/*
146 * DL_ListRemoveItemFromHead - get a list item from the head
147*/
148static __inline PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
149 PDL_LIST pItem = NULL;
150 if (pList->pNext != pList) {
151 pItem = pList->pNext;
152 /* remove the first item from head */
153 DL_ListRemove(pItem);
154 }
155 return pItem;
156}
157
158static __inline PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
159 PDL_LIST pItem = NULL;
160 if (pList->pPrev != pList) {
161 pItem = pList->pPrev;
162 /* remove the item from tail */
163 DL_ListRemove(pItem);
164 }
165 return pItem;
166}
167
168/* transfer src list items to the tail of the destination list */
169static __inline void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) {
170 /* only concatenate if src is not empty */
171 if (!DL_LIST_IS_EMPTY(pSrc)) {
172 /* cut out circular list in src and re-attach to end of dest */
173 pSrc->pPrev->pNext = pDest;
174 pSrc->pNext->pPrev = pDest->pPrev;
175 pDest->pPrev->pNext = pSrc->pNext;
176 pDest->pPrev = pSrc->pPrev;
177 /* terminate src list, it is now empty */
178 pSrc->pPrev = pSrc;
179 pSrc->pNext = pSrc;
180 }
181}
182
183/* transfer src list items to the head of the destination list */
184static __inline void DL_ListTransferItemsToHead(PDL_LIST pDest, PDL_LIST pSrc) {
185 /* only concatenate if src is not empty */
186 if (!DL_LIST_IS_EMPTY(pSrc)) {
187 /* cut out circular list in src and re-attach to start of dest */
188 pSrc->pNext->pPrev = pDest;
189 pDest->pNext->pPrev = pSrc->pPrev;
190 pSrc->pPrev->pNext = pDest->pNext;
191 pDest->pNext = pSrc->pNext;
192 /* terminate src list, it is now empty */
193 pSrc->pPrev = pSrc;
194 pSrc->pNext = pSrc;
195 }
196}
197
198#endif /* __DL_LIST_H___ */