summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath6kl/include/dl_list.h
blob: f07b41d7638abf3429ff9555b7d9523d249ad1cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//------------------------------------------------------------------------------
// <copyright file="dl_list.h" company="Atheros">
//    Copyright (c) 2004-2008 Atheros Corporation.  All rights reserved.
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation;
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Double-link list definitions (adapted from Atheros SDIO stack)
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef __DL_LIST_H___
#define __DL_LIST_H___

#include "a_osapi.h"

#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
            ((struct_type *)((A_UINT32)(address) - (A_UINT32)(&((struct_type *)0)->field_name)))

/* list functions */
/* pointers for the list */
typedef struct _DL_LIST {
    struct _DL_LIST *pPrev;
    struct _DL_LIST *pNext;
}DL_LIST, *PDL_LIST;
/*
 * DL_LIST_INIT , initialize doubly linked list
*/
#define DL_LIST_INIT(pList)\
    {(pList)->pPrev = pList; (pList)->pNext = pList;}

/* faster macro to init list and add a single item */    
#define DL_LIST_INIT_AND_ADD(pList,pItem) \
{   (pList)->pPrev = (pItem); \
    (pList)->pNext = (pItem); \
    (pItem)->pNext = (pList); \
    (pItem)->pPrev = (pList); \
}
    
#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
/*
 * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
 * NOT: do not use this function if the items in the list are deleted inside the
 * iteration loop
*/
#define ITERATE_OVER_LIST(pStart, pTemp) \
    for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)


/* safe iterate macro that allows the item to be removed from the list
 * the iteration continues to the next item in the list
 */
#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset)  \
{                                                       \
    PDL_LIST  pTemp;                                     \
    pTemp = (pStart)->pNext;                            \
    while (pTemp != (pStart)) {                         \
        (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset);   \
         pTemp = pTemp->pNext;                          \

#define ITERATE_END }}

/*
 * DL_ListInsertTail - insert pAdd to the end of the list
*/
static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
        /* insert at tail */
    pAdd->pPrev = pList->pPrev;
    pAdd->pNext = pList;
    pList->pPrev->pNext = pAdd;
    pList->pPrev = pAdd;
    return pAdd;
}

/*
 * DL_ListInsertHead - insert pAdd into the head of the list
*/
static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
        /* insert at head */
    pAdd->pPrev = pList;
    pAdd->pNext = pList->pNext;
    pList->pNext->pPrev = pAdd;
    pList->pNext = pAdd;
    return pAdd;
}

#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
/*
 * DL_ListRemove - remove pDel from list
*/
static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
    pDel->pNext->pPrev = pDel->pPrev;
    pDel->pPrev->pNext = pDel->pNext;
        /* point back to itself just to be safe, incase remove is called again */
    pDel->pNext = pDel;
    pDel->pPrev = pDel;
    return pDel;
}

/*
 * DL_ListRemoveItemFromHead - get a list item from the head
*/
static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
    PDL_LIST pItem = NULL;
    if (pList->pNext != pList) {
        pItem = pList->pNext;
            /* remove the first item from head */
        DL_ListRemove(pItem);
    }
    return pItem;
}

static INLINE PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
    PDL_LIST pItem = NULL;
    if (pList->pPrev != pList) {
        pItem = pList->pPrev;
            /* remove the item from tail */
        DL_ListRemove(pItem);
    }
    return pItem;
}

/* transfer src list items to the tail of the destination list */
static INLINE void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) {
        /* only concatenate if src is not empty */
    if (!DL_LIST_IS_EMPTY(pSrc)) {
            /* cut out circular list in src and re-attach to end of dest */
        pSrc->pPrev->pNext = pDest;
        pSrc->pNext->pPrev = pDest->pPrev;
        pDest->pPrev->pNext = pSrc->pNext; 
        pDest->pPrev = pSrc->pPrev;
            /* terminate src list, it is now empty */      
        pSrc->pPrev = pSrc;
        pSrc->pNext = pSrc;
    }
}

#endif /* __DL_LIST_H___ */