Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / staging / otus / 80211core / queue.c
1 /*
2  * Copyright (c) 2007-2008 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*                                                                      */
17 /*  Module Name : queue.c                                               */
18 /*                                                                      */
19 /*  Abstract                                                            */
20 /*      This module contains queue management functions.                */
21 /*                                                                      */
22 /*  NOTES                                                               */
23 /*      None                                                            */
24 /*                                                                      */
25 /************************************************************************/
26 #include "cprecomp.h"
27 #include "queue.h"
28
29
30 struct zsQueue* zfQueueCreate(zdev_t* dev, u16_t size)
31 {
32     struct zsQueue* q;
33
34     if ((q = (struct zsQueue*)zfwMemAllocate(dev, sizeof(struct zsQueue)
35             + (sizeof(struct zsQueueCell)*(size-1)))) != NULL)
36     {
37         q->size = size;
38         q->sizeMask = size-1;
39         q->head = 0;
40         q->tail = 0;
41     }
42     return q;
43 }
44
45 void zfQueueDestroy(zdev_t* dev, struct zsQueue* q)
46 {
47     u16_t size = sizeof(struct zsQueue) + (sizeof(struct zsQueueCell)*(q->size-1));
48
49     zfQueueFlush(dev, q);
50     zfwMemFree(dev, q, size);
51
52     return;
53 }
54
55 u16_t zfQueuePutNcs(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
56 {
57     u16_t ret = ZM_ERR_QUEUE_FULL;
58
59     zm_msg0_mm(ZM_LV_1, "zfQueuePutNcs()");
60
61     if (((q->tail+1)&q->sizeMask) != q->head)
62     {
63         q->cell[q->tail].buf = buf;
64         q->cell[q->tail].tick = tick;
65         q->tail = (q->tail+1) & q->sizeMask;
66         ret = ZM_SUCCESS;
67     }
68
69     return ret;
70 }
71
72 u16_t zfQueuePut(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
73 {
74     u16_t ret;
75     zmw_declare_for_critical_section();
76
77     zmw_enter_critical_section(dev);
78
79     ret = zfQueuePutNcs(dev, q, buf, tick);
80
81     zmw_leave_critical_section(dev);
82
83     return ret;
84 }
85
86 zbuf_t* zfQueueGet(zdev_t* dev, struct zsQueue* q)
87 {
88     zbuf_t* buf = NULL;
89     zmw_declare_for_critical_section();
90
91     zmw_enter_critical_section(dev);
92
93     if (q->head != q->tail)
94     {
95         buf = q->cell[q->head].buf;
96         q->head = (q->head+1) & q->sizeMask;
97     }
98
99     zmw_leave_critical_section(dev);
100
101     return buf;
102 }
103
104 u16_t zfCompareDstwithBuf(zdev_t* dev, zbuf_t* buf, u8_t* addr)
105 {
106     u16_t i;
107     u8_t dst[6];
108
109     for (i=0; i<6; i++)
110     {
111         dst[i] = zmw_buf_readb(dev, buf, i);
112         if (dst[i] != addr[i])
113         {
114             return 1+i;
115         }
116     }
117
118     return 0;
119 }
120
121
122 zbuf_t* zfQueueGetWithMac(zdev_t* dev, struct zsQueue* q, u8_t* addr, u8_t* mb)
123 {
124     zbuf_t* buf;
125     zbuf_t* retBuf = NULL;
126     u16_t index, next;
127     zmw_declare_for_critical_section();
128
129     *mb = 0;
130
131     zmw_enter_critical_section(dev);
132
133     index = q->head;
134
135     while (1)
136     {
137         if (index != q->tail)
138         {
139             buf = q->cell[index].buf;
140
141             //if buf's detination address == input addr
142             if (zfCompareDstwithBuf(dev, buf, addr) == 0)
143             {
144                 retBuf = buf;
145                 //Get it, and trace the whole queue to calculate more bit
146                 while ((next =((index+1)&q->sizeMask)) != q->tail)
147                 {
148                     q->cell[index].buf = q->cell[next].buf;
149                     q->cell[index].tick = q->cell[next].tick;
150
151                     if ((*mb == 0) && (zfCompareDstwithBuf(dev,
152                             q->cell[next].buf, addr) == 0))
153                     {
154                         *mb = 1;
155                     }
156
157                     index = next;
158                 }
159                 q->tail = (q->tail-1) & q->sizeMask;
160
161                 zmw_leave_critical_section(dev);
162                 return retBuf;
163             }
164             index = (index + 1) & q->sizeMask;
165         } //if (index != q->tail)
166         else
167         {
168             break;
169         }
170     }
171
172     zmw_leave_critical_section(dev);
173
174     return retBuf;
175
176 }
177
178 void zfQueueFlush(zdev_t* dev, struct zsQueue* q)
179 {
180     zbuf_t* buf;
181
182     while ((buf = zfQueueGet(dev, q)) != NULL)
183     {
184         zfwBufFree(dev, buf, 0);
185     }
186
187     return;
188 }
189
190 void zfQueueAge(zdev_t* dev, struct zsQueue* q, u32_t tick, u32_t msAge)
191 {
192     zbuf_t* buf;
193     u32_t   buftick;
194     zmw_declare_for_critical_section();
195
196     while (1)
197     {
198         buf = NULL;
199         zmw_enter_critical_section(dev);
200
201         if (q->head != q->tail)
202         {
203             buftick = q->cell[q->head].tick;
204             if (((tick - buftick)*ZM_MS_PER_TICK) > msAge)
205             {
206                 buf = q->cell[q->head].buf;
207                 q->head = (q->head+1) & q->sizeMask;
208             }
209         }
210
211         zmw_leave_critical_section(dev);
212
213         if (buf != NULL)
214         {
215             zm_msg0_mm(ZM_LV_0, "Age frame in queue!");
216             zfwBufFree(dev, buf, 0);
217         }
218         else
219         {
220             break;
221         }
222     }
223     return;
224 }
225
226
227 u8_t zfQueueRemovewithIndex(zdev_t* dev, struct zsQueue* q, u16_t index, u8_t* addr)
228 {
229     u16_t next;
230     u8_t mb = 0;
231
232     //trace the whole queue to calculate more bit
233     while ((next =((index+1)&q->sizeMask)) != q->tail)
234     {
235         q->cell[index].buf = q->cell[next].buf;
236         q->cell[index].tick = q->cell[next].tick;
237
238         if ((mb == 0) && (zfCompareDstwithBuf(dev,
239                 q->cell[next].buf, addr) == 0))
240         {
241             mb = 1;
242         }
243
244         index = next;
245     }
246     q->tail = (q->tail-1) & q->sizeMask;
247
248     return mb;
249
250 }
251
252 void zfQueueGenerateUapsdTim(zdev_t* dev, struct zsQueue* q,
253         u8_t* uniBitMap, u16_t* highestByte)
254 {
255     zbuf_t* psBuf;
256     u8_t dst[6];
257     u16_t id, aid, index, i;
258     u16_t bitPosition;
259     u16_t bytePosition;
260     zmw_get_wlan_dev(dev);
261     zmw_declare_for_critical_section();
262
263     zmw_enter_critical_section(dev);
264
265     index = q->head;
266
267     while (index != q->tail)
268     {
269         psBuf = q->cell[index].buf;
270         for (i=0; i<6; i++)
271         {
272             dst[i] = zmw_buf_readb(dev, psBuf, i);
273         }
274         /* TODO : use u8_t* fot MAC address */
275         if (((id = zfApFindSta(dev, (u16_t*)dst)) != 0xffff)
276                 && (wd->ap.staTable[id].psMode != 0))
277         {
278             /* Calculate PVB only when all AC are delivery-enabled */
279             if ((wd->ap.staTable[id].qosInfo & 0xf) == 0xf)
280             {
281                 aid = id + 1;
282                 bitPosition = (1 << (aid & 0x7));
283                 bytePosition = (aid >> 3);
284                 uniBitMap[bytePosition] |= bitPosition;
285
286                 if (bytePosition>*highestByte)
287                 {
288                     *highestByte = bytePosition;
289                 }
290             }
291             index = (index+1) & q->sizeMask;
292         }
293         else
294         {
295             /* Free garbage UAPSD frame */
296             zfQueueRemovewithIndex(dev, q, index, dst);
297             zfwBufFree(dev, psBuf, 0);
298         }
299     }
300     zmw_leave_critical_section(dev);
301
302     return;
303 }