blob: be9970cf0a29e7da6dc23c6347b4bf7c51b372d0 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Manikandan Mohane3e209e2017-04-13 20:19:26 -07002 * Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
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
Manikandan Mohane3e209e2017-04-13 20:19:26 -070028/*=========================================================================== */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080029/* Double-link list definitions (adapted from Atheros SDIO stack) */
30/* */
31/* Author(s): ="Atheros" */
Manikandan Mohane3e209e2017-04-13 20:19:26 -070032/*=========================================================================== */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033
34#ifndef __DL_LIST_H___
35#define __DL_LIST_H___
36
37#define A_CONTAINING_STRUCT(address, struct_type, field_name) \
Manikandan Mohane3e209e2017-04-13 20:19:26 -070038 ((struct_type *)((char *)(address) - \
39 (char *)(&((struct_type *)0)->field_name)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040
41/* list functions */
42/* pointers for the list */
43typedef struct _DL_LIST {
44 struct _DL_LIST *pPrev;
45 struct _DL_LIST *pNext;
46} DL_LIST, *PDL_LIST;
47/*
48 * DL_LIST_INIT , initialize doubly linked list
49 */
50#define DL_LIST_INIT(pList) \
51 {(pList)->pPrev = pList; (pList)->pNext = pList; }
52
53/* faster macro to init list and add a single item */
Manikandan Mohane3e209e2017-04-13 20:19:26 -070054#define DL_LIST_INIT_AND_ADD(pList, pItem) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080055 { (pList)->pPrev = (pItem); \
56 (pList)->pNext = (pItem); \
57 (pItem)->pNext = (pList); \
58 (pItem)->pPrev = (pList); \
59 }
60
Manikandan Mohane3e209e2017-04-13 20:19:26 -070061#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && \
62 ((pList)->pNext == (pList)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
64#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
65/*
66 * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
67 * NOT: do not use this function if the items in the list are deleted inside the
68 * iteration loop
69 */
70#define ITERATE_OVER_LIST(pStart, pTemp) \
Manikandan Mohane3e209e2017-04-13 20:19:26 -070071 for ((pTemp) = (pStart)->pNext; pTemp != (pStart); \
72 (pTemp) = (pTemp)->pNext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073
Manikandan Mohane3e209e2017-04-13 20:19:26 -070074static inline bool dl_list_is_entry_in_list(const DL_LIST *pList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075 const DL_LIST *pEntry)
76{
77 const DL_LIST *pTmp;
78
79 if (pList == pEntry)
80 return true;
81
82 ITERATE_OVER_LIST(pList, pTmp) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -070083 if (pTmp == pEntry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080085 }
86
87 return false;
88}
89
90/* safe iterate macro that allows the item to be removed from the list
91 * the iteration continues to the next item in the list
92 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -070093#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart, pItem, st, offset) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094 { \
95 PDL_LIST pTemp; \
Manikandan Mohane3e209e2017-04-13 20:19:26 -070096 { pTemp = (pStart)->pNext; } \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097 while (pTemp != (pStart)) { \
Manikandan Mohane3e209e2017-04-13 20:19:26 -070098 { (pItem) = A_CONTAINING_STRUCT(pTemp, st, offset); } \
99 { pTemp = pTemp->pNext; } \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100
101#define ITERATE_IS_VALID(pStart) dl_list_is_entry_in_list(pStart, pTemp)
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700102#define ITERATE_RESET(pStart) { pTemp = (pStart)->pNext; }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103
104#define ITERATE_END }}
105
106/*
107 * dl_list_insert_tail - insert pAdd to the end of the list
108 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700109static inline PDL_LIST dl_list_insert_tail(PDL_LIST pList, PDL_LIST pAdd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110{
111 /* insert at tail */
112 pAdd->pPrev = pList->pPrev;
113 pAdd->pNext = pList;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700114 if (pList->pPrev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115 pList->pPrev->pNext = pAdd;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 pList->pPrev = pAdd;
117 return pAdd;
118}
119
120/*
121 * dl_list_insert_head - insert pAdd into the head of the list
122 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700123static inline PDL_LIST dl_list_insert_head(PDL_LIST pList, PDL_LIST pAdd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124{
125 /* insert at head */
126 pAdd->pPrev = pList;
127 pAdd->pNext = pList->pNext;
128 pList->pNext->pPrev = pAdd;
129 pList->pNext = pAdd;
130 return pAdd;
131}
132
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700133#define DL_ListAdd(pList, pItem) dl_list_insert_head((pList), (pItem))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134/*
135 * dl_list_remove - remove pDel from list
136 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700137static inline PDL_LIST dl_list_remove(PDL_LIST pDel)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138{
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700139 if (pDel->pNext != NULL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 pDel->pNext->pPrev = pDel->pPrev;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700141 if (pDel->pPrev != NULL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142 pDel->pPrev->pNext = pDel->pNext;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700143 /* point back to itself just to be safe, if remove is called again */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144 pDel->pNext = pDel;
145 pDel->pPrev = pDel;
146 return pDel;
147}
148
149/*
150 * dl_list_remove_item_from_head - get a list item from the head
151 */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700152static inline PDL_LIST dl_list_remove_item_from_head(PDL_LIST pList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153{
154 PDL_LIST pItem = NULL;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156 if (pList->pNext != pList) {
157 pItem = pList->pNext;
158 /* remove the first item from head */
159 dl_list_remove(pItem);
160 }
161 return pItem;
162}
163
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700164static inline PDL_LIST dl_list_remove_item_from_tail(PDL_LIST pList)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165{
166 PDL_LIST pItem = NULL;
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 if (pList->pPrev != pList) {
169 pItem = pList->pPrev;
170 /* remove the item from tail */
171 dl_list_remove(pItem);
172 }
173 return pItem;
174}
175
176/* transfer src list items to the tail of the destination list */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700177static inline void dl_list_transfer_items_to_tail(PDL_LIST pDest, PDL_LIST pSrc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178{
179 /* only concatenate if src is not empty */
180 if (!DL_LIST_IS_EMPTY(pSrc)) {
181 /* cut out circular list in src and re-attach to end of dest */
182 pSrc->pPrev->pNext = pDest;
183 pSrc->pNext->pPrev = pDest->pPrev;
184 pDest->pPrev->pNext = pSrc->pNext;
185 pDest->pPrev = pSrc->pPrev;
186 /* terminate src list, it is now empty */
187 pSrc->pPrev = pSrc;
188 pSrc->pNext = pSrc;
189 }
190}
191
192/* transfer src list items to the head of the destination list */
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700193static inline void dl_list_transfer_items_to_head(PDL_LIST pDest, PDL_LIST pSrc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194{
195 /* only concatenate if src is not empty */
196 if (!DL_LIST_IS_EMPTY(pSrc)) {
Manikandan Mohane3e209e2017-04-13 20:19:26 -0700197 /* cut out circular list in src and reattach to start of dest */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 pSrc->pNext->pPrev = pDest;
199 pDest->pNext->pPrev = pSrc->pPrev;
200 pSrc->pPrev->pNext = pDest->pNext;
201 pDest->pNext = pSrc->pNext;
202 /* terminate src list, it is now empty */
203 pSrc->pPrev = pSrc;
204 pSrc->pNext = pSrc;
205 }
206}
207
208#endif /* __DL_LIST_H___ */