blob: 998321299a0e370e1a6ebc356c6749a53ded62c9 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/** ------------------------------------------------------------------------- *
43 ------------------------------------------------------------------------- *
44 \file csrLinkList.c
45
46 Implementation for the Common link list interfaces.
47
48
49 Copyright (C) 2006 Airgo Networks, Incorporated
50 ========================================================================== */
51
52#include "palApi.h"
53#include "csrLinkList.h"
54#include "vos_lock.h"
55#include "vos_memory.h"
56#include "vos_trace.h"
57
58ANI_INLINE_FUNCTION void csrListInit(tListElem *pList)
59{
60 pList->last = pList->next = pList;
61}
62
63
64ANI_INLINE_FUNCTION void csrListRemoveEntry(tListElem *pEntry)
65{
66 tListElem *pLast;
67 tListElem *pNext;
68
69 pLast = pEntry->last;
70 pNext = pEntry->next;
71 pLast->next = pNext;
72 pNext->last = pLast;
73}
74
75
76ANI_INLINE_FUNCTION tListElem * csrListRemoveHead(tListElem *pHead)
77{
78 tListElem *pEntry;
79 tListElem *pNext;
80
81 pEntry = pHead->next;
82 pNext = pEntry->next;
83 pHead->next = pNext;
84 pNext->last = pHead;
85
86 return (pEntry);
87}
88
89
90
91ANI_INLINE_FUNCTION tListElem * csrListRemoveTail(tListElem *pHead)
92{
93 tListElem *pEntry;
94 tListElem *pLast;
95
96 pEntry = pHead->last;
97 pLast = pEntry->last;
98 pHead->last = pLast;
99 pLast->next = pHead;
100
101 return (pEntry);
102}
103
104
105ANI_INLINE_FUNCTION void csrListInsertTail(tListElem *pHead, tListElem *pEntry)
106{
107 tListElem *pLast;
108
109 pLast = pHead->last;
110 pEntry->last = pLast;
111 pEntry->next = pHead;
112 pLast->next = pEntry;
113 pHead->last = pEntry;
114}
115
116
117ANI_INLINE_FUNCTION void csrListInsertHead(tListElem *pHead, tListElem *pEntry)
118{
119 tListElem *pNext;
120
121 pNext = pHead->next;
122 pEntry->next = pNext;
123 pEntry->last = pHead;
124 pNext->last = pEntry;
125 pHead->next = pEntry;
126}
127
128
129//Insert pNewEntry before pEntry
130void csrListInsertEntry(tListElem *pEntry, tListElem *pNewEntry)
131{
132 tListElem *pLast;
133 if( !pEntry)
134 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700135 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pEntry is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700136 return;
137 }
138
139 pLast = pEntry->last;
140 pLast->next = pNewEntry;
141 pEntry->last = pNewEntry;
142 pNewEntry->next = pEntry;
143 pNewEntry->last = pLast;
144}
145
146tANI_U32 csrLLCount( tDblLinkList *pList )
147{
148 tANI_U32 c = 0;
149
150
151 if( !pList)
152 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700153 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700154 return c;
155 }
156
157 if ( pList && ( LIST_FLAG_OPEN == pList->Flag ) )
158 {
159 c = pList->Count;
160 }
161
162 return( c );
163}
164
165
166void csrLLLock( tDblLinkList *pList )
167{
168
169
170 if( !pList)
171 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700172 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700173 return ;
174 }
175
176 if ( LIST_FLAG_OPEN == pList->Flag )
177 {
178 vos_lock_acquire(&pList->Lock);
179 }
180}
181
182
183void csrLLUnlock( tDblLinkList *pList )
184{
185
186 if( !pList)
187 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700188 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700189 return ;
190 }
191
192 if ( LIST_FLAG_OPEN == pList->Flag )
193 {
194 vos_lock_release(&pList->Lock);
195 }
196}
197
198
199tANI_BOOLEAN csrLLIsListEmpty( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
200{
201 tANI_BOOLEAN fEmpty = eANI_BOOLEAN_TRUE;
202
203
204 if( !pList)
205 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700206 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 return fEmpty ;
208 }
209
210 if ( LIST_FLAG_OPEN == pList->Flag )
211 {
212 if(fInterlocked)
213 {
214 csrLLLock(pList);
215 }
216
217 fEmpty = csrIsListEmpty( &pList->ListHead );
218
219 if(fInterlocked)
220 {
221 csrLLUnlock(pList);
222 }
223 }
224 return( fEmpty );
225}
226
227
228
229tANI_BOOLEAN csrLLFindEntry( tDblLinkList *pList, tListElem *pEntryToFind )
230{
231 tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE;
232 tListElem *pEntry;
233
234
235 if( !pList)
236 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700237 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 return fFound ;
239 }
240
241 if ( LIST_FLAG_OPEN == pList->Flag )
242 {
243 pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK);
244
245 // Have to make sure we don't loop back to the head of the list, which will
246 // happen if the entry is NOT on the list...
247
248 while( pEntry && ( pEntry != &pList->ListHead ) )
249 {
250 if ( pEntry == pEntryToFind )
251 {
252 fFound = eANI_BOOLEAN_TRUE;
253 break;
254 }
255 pEntry = pEntry->next;
256 }
257
258 }
259 return( fFound );
260}
261
262
263eHalStatus csrLLOpen( tHddHandle hHdd, tDblLinkList *pList )
264{
265 eHalStatus status = eHAL_STATUS_SUCCESS;
266 VOS_STATUS vosStatus;
267
268 if( !pList)
269 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700270 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 return eHAL_STATUS_FAILURE ;
272 }
273
274 if ( LIST_FLAG_OPEN != pList->Flag )
275 {
276 pList->Count = 0;
277
278 vosStatus = vos_lock_init(&pList->Lock);
279
280 if(VOS_IS_STATUS_SUCCESS(vosStatus))
281 {
282 csrListInit( &pList->ListHead );
283 pList->Flag = LIST_FLAG_OPEN;
284 pList->hHdd = hHdd;
285 }
286 else
287 {
288 status = eHAL_STATUS_FAILURE;
289 }
290 }
291 return (status);
292}
293
294void csrLLClose( tDblLinkList *pList )
295{
296 if( !pList)
297 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700298 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700299 return ;
300 }
301
302 if ( LIST_FLAG_OPEN == pList->Flag )
303 {
304 // Make sure the list is empty...
305 csrLLPurge( pList, LL_ACCESS_LOCK );
306 vos_lock_destroy( &pList->Lock );
307 pList->Flag = LIST_FLAG_CLOSE;
308 }
309}
310
311void csrLLInsertTail( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
312{
313 if( !pList)
314 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700315 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700316 return;
317 }
318
319 if ( LIST_FLAG_OPEN == pList->Flag )
320 {
321 if(fInterlocked)
322 {
323 csrLLLock(pList);
324 }
325 csrListInsertTail( &pList->ListHead, pEntry );
326 pList->Count++;
327 if(fInterlocked)
328 {
329 csrLLUnlock(pList);
330 }
331 }
332}
333
334
335
336void csrLLInsertHead( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
337{
338
339 if( !pList)
340 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700341 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700342 return;
343 }
344
345 if ( LIST_FLAG_OPEN == pList->Flag )
346 {
347 if(fInterlocked)
348 {
349 csrLLLock(pList);
350 }
351 csrListInsertHead( &pList->ListHead, pEntry );
352 pList->Count++;
353 if(fInterlocked)
354 {
355 csrLLUnlock(pList);
356 }
357 }
358}
359
360
361void csrLLInsertEntry( tDblLinkList *pList, tListElem *pEntry, tListElem *pNewEntry, tANI_BOOLEAN fInterlocked )
362{
363 if( !pList)
364 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700365 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700366 return ;
367 }
368
369 if ( LIST_FLAG_OPEN == pList->Flag )
370 {
371 if(fInterlocked)
372 {
373 csrLLLock(pList);
374 }
375 csrListInsertEntry( pEntry, pNewEntry );
376 pList->Count++;
377 if(fInterlocked)
378 {
379 csrLLUnlock(pList);
380 }
381 }
382}
383
384
385
386tListElem *csrLLRemoveTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
387{
388 tListElem *pEntry = NULL;
389
390 if( !pList)
391 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700392 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700393 return pEntry ;
394 }
395
396 if ( LIST_FLAG_OPEN == pList->Flag )
397 {
398 if ( fInterlocked )
399 {
400 csrLLLock( pList );
401 }
402
403 if ( !csrIsListEmpty(&pList->ListHead) )
404 {
405
406 pEntry = csrListRemoveTail( &pList->ListHead );
407 pList->Count--;
408 }
409 if ( fInterlocked )
410 {
411 csrLLUnlock( pList );
412 }
413 }
414
415 return( pEntry );
416}
417
418
419tListElem *csrLLPeekTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
420{
421 tListElem *pEntry = NULL;
422
423
424 if( !pList)
425 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700426 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700427 return pEntry ;
428 }
429
430 if ( LIST_FLAG_OPEN == pList->Flag )
431 {
432 if ( fInterlocked )
433 {
434 csrLLLock( pList );
435 }
436
437 if ( !csrIsListEmpty(&pList->ListHead) )
438 {
439 pEntry = pList->ListHead.last;
440 }
441 if ( fInterlocked )
442 {
443 csrLLUnlock( pList );
444 }
445 }
446
447 return( pEntry );
448}
449
450
451
452tListElem *csrLLRemoveHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
453{
454 tListElem *pEntry = NULL;
455
456
457 if( !pList)
458 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700459 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 return pEntry ;
461 }
462
463 if ( LIST_FLAG_OPEN == pList->Flag )
464 {
465 if ( fInterlocked )
466 {
467 csrLLLock( pList );
468 }
469
470 if ( !csrIsListEmpty(&pList->ListHead) )
471 {
472 pEntry = csrListRemoveHead( &pList->ListHead );
473 pList->Count--;
474 }
475
476 if ( fInterlocked )
477 {
478 csrLLUnlock( pList );
479 }
480 }
481
482 return( pEntry );
483}
484
485
486tListElem *csrLLPeekHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
487{
488 tListElem *pEntry = NULL;
489
490 if( !pList)
491 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700492 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700493 return pEntry ;
494 }
495
496 if ( LIST_FLAG_OPEN == pList->Flag )
497 {
498 if ( fInterlocked )
499 {
500 csrLLLock( pList );
501 }
502
503 if ( !csrIsListEmpty(&pList->ListHead) )
504 {
505 pEntry = pList->ListHead.next;
506 }
507 if ( fInterlocked )
508 {
509 csrLLUnlock( pList );
510 }
511 }
512
513 return( pEntry );
514}
515
516
517
518void csrLLPurge( tDblLinkList *pList, tANI_BOOLEAN fInterlocked )
519{
520 tListElem *pEntry;
521
522 if( !pList)
523 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700524 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700525 return ;
526 }
527
528 if ( LIST_FLAG_OPEN == pList->Flag )
529 {
530 if ( fInterlocked )
531 {
532 csrLLLock( pList );
533 }
534 while( (pEntry = csrLLRemoveHead( pList, LL_ACCESS_NOLOCK )) )
535 {
536 // just remove everything from the list until
537 // nothing left on the list.
538 }
539 if ( fInterlocked )
540 {
541 csrLLUnlock( pList );
542 }
543 }
544}
545
546
547tANI_BOOLEAN csrLLRemoveEntry( tDblLinkList *pList, tListElem *pEntryToRemove, tANI_BOOLEAN fInterlocked )
548{
549 tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE;
550 tListElem *pEntry;
551
552 if( !pList)
553 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700554 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700555 return fFound;
556 }
557
558 if ( LIST_FLAG_OPEN == pList->Flag )
559 {
560 if ( fInterlocked )
561 {
562 csrLLLock( pList );
563 }
564
565 pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK );
566
567 // Have to make sure we don't loop back to the head of the list, which will
568 // happen if the entry is NOT on the list...
569 while( pEntry && ( pEntry != &pList->ListHead ) )
570 {
571 if ( pEntry == pEntryToRemove )
572 {
573 csrListRemoveEntry( pEntry );
574 pList->Count--;
575
576 fFound = eANI_BOOLEAN_TRUE;
577 break;
578 }
579
580 pEntry = pEntry->next;
581 }
582 if ( fInterlocked )
583 {
584 csrLLUnlock( pList );
585 }
586 }
587
588 return( fFound );
589}
590
591
592
593tListElem *csrLLNext( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
594{
595 tListElem *pNextEntry = NULL;
596
597 if( !pList)
598 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700599 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700600 return pNextEntry ;
601 }
602
603 if ( LIST_FLAG_OPEN == pList->Flag )
604 {
605 if ( fInterlocked )
606 {
607 csrLLLock( pList );
608 }
609
610 if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) )
611 {
612 pNextEntry = pEntry->next;
613 //Make sure we don't walk past the head
614 if ( pNextEntry == &pList->ListHead )
615 {
616 pNextEntry = NULL;
617 }
618 }
619
620 if ( fInterlocked )
621 {
622 csrLLUnlock( pList );
623 }
624 }
625
626 return( pNextEntry );
627}
628
629
630tListElem *csrLLPrevious( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked )
631{
632 tListElem *pNextEntry = NULL;
633
634 if( !pList)
635 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700636 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700637 return pNextEntry ;
638 }
639
640 if ( LIST_FLAG_OPEN == pList->Flag )
641 {
642 if ( fInterlocked )
643 {
644 csrLLLock( pList );
645 }
646
647 if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) )
648 {
649 pNextEntry = pEntry->last;
650 //Make sure we don't walk past the head
651 if ( pNextEntry == &pList->ListHead )
652 {
653 pNextEntry = NULL;
654 }
655 }
656
657 if ( fInterlocked )
658 {
659 csrLLUnlock( pList );
660 }
661 }
662
663 return( pNextEntry );
664}
665
666
667
668