• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * HND generic pktq operation primitives
3  *
4  * Copyright (C) 1999-2019, Broadcom.
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions
16  * of the license of that module.  An independent module is a module which is
17  * not derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  * $Id: hnd_pktq.c 698847 2017-05-11 00:10:48Z $
28  */
29 
30 #include <typedefs.h>
31 #include <osl.h>
32 #include <osl_ext.h>
33 #include <bcmutils.h>
34 #include <hnd_pktq.h>
35 
36 /* mutex macros for thread safe */
37 #ifdef HND_PKTQ_THREAD_SAFE
38 #define HND_PKTQ_MUTEX_CREATE(name, mutex) osl_ext_mutex_create(name, mutex)
39 #define HND_PKTQ_MUTEX_DELETE(mutex) osl_ext_mutex_delete(mutex)
40 #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) osl_ext_mutex_acquire(mutex, msec)
41 #define HND_PKTQ_MUTEX_RELEASE(mutex) osl_ext_mutex_release(mutex)
42 #else
43 #define HND_PKTQ_MUTEX_CREATE(name, mutex) OSL_EXT_SUCCESS
44 #define HND_PKTQ_MUTEX_DELETE(mutex) OSL_EXT_SUCCESS
45 #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) OSL_EXT_SUCCESS
46 #define HND_PKTQ_MUTEX_RELEASE(mutex) OSL_EXT_SUCCESS
47 #endif /* HND_PKTQ_THREAD_SAFE */
48 
49 /* status during txfifo sync */
50 #if defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS)
51 #define TXQ_PKT_DEL 0x01
52 #define HEAD_PKT_FLUSHED 0xFF
53 #endif /* defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) */
54 /*
55  * osl multiple-precedence packet queue
56  * hi_prec is always >= the number of the highest non-empty precedence
57  */
pktq_penq(struct pktq * pq,int prec,void * p)58 void *BCMFASTPATH pktq_penq(struct pktq *pq, int prec, void *p)
59 {
60     struct pktq_prec *q;
61 
62     /* protect shared resource */
63     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
64         OSL_EXT_SUCCESS) {
65         return NULL;
66     }
67 
68     ASSERT(prec >= 0 && prec < pq->num_prec);
69     ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
70 
71     ASSERT(!pktq_full(pq));
72     ASSERT(!pktqprec_full(pq, prec));
73 
74     q = &pq->q[prec];
75 
76     if (q->head) {
77         PKTSETLINK(q->tail, p);
78     } else {
79         q->head = p;
80     }
81 
82     q->tail = p;
83     q->n_pkts++;
84 
85     pq->n_pkts_tot++;
86 
87     if (pq->hi_prec < prec) {
88         pq->hi_prec = (uint8)prec;
89     }
90 
91     /* protect shared resource */
92     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
93         return NULL;
94     }
95 
96     return p;
97 }
98 
99 /*
100  * osl simple, non-priority packet queue
101  */
spktq_enq(struct spktq * spq,void * p)102 void *BCMFASTPATH spktq_enq(struct spktq *spq, void *p)
103 {
104     struct pktq_prec *q;
105 
106     /* protect shared resource */
107     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
108         OSL_EXT_SUCCESS) {
109         return NULL;
110     }
111 
112     ASSERT(!spktq_full(spq));
113 
114     PKTSETLINK(p, NULL);
115 
116     q = &spq->q;
117 
118     if (q->head) {
119         PKTSETLINK(q->tail, p);
120     } else {
121         q->head = p;
122     }
123 
124     q->tail = p;
125     q->n_pkts++;
126 
127     /* protect shared resource */
128     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
129         return NULL;
130     }
131 
132     return p;
133 }
134 
pktq_penq_head(struct pktq * pq,int prec,void * p)135 void *BCMFASTPATH pktq_penq_head(struct pktq *pq, int prec, void *p)
136 {
137     struct pktq_prec *q;
138 
139     /* protect shared resource */
140     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
141         OSL_EXT_SUCCESS) {
142         return NULL;
143     }
144 
145     ASSERT(prec >= 0 && prec < pq->num_prec);
146     ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
147 
148     ASSERT(!pktq_full(pq));
149     ASSERT(!pktqprec_full(pq, prec));
150 
151     q = &pq->q[prec];
152 
153     if (q->head == NULL) {
154         q->tail = p;
155     }
156 
157     PKTSETLINK(p, q->head);
158     q->head = p;
159     q->n_pkts++;
160 
161     pq->n_pkts_tot++;
162 
163     if (pq->hi_prec < prec) {
164         pq->hi_prec = (uint8)prec;
165     }
166 
167     /* protect shared resource */
168     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
169         return NULL;
170     }
171 
172     return p;
173 }
174 
spktq_enq_head(struct spktq * spq,void * p)175 void *BCMFASTPATH spktq_enq_head(struct spktq *spq, void *p)
176 {
177     struct pktq_prec *q;
178 
179     /* protect shared resource */
180     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
181         OSL_EXT_SUCCESS) {
182         return NULL;
183     }
184 
185     ASSERT(!spktq_full(spq));
186 
187     PKTSETLINK(p, NULL);
188 
189     q = &spq->q;
190 
191     if (q->head == NULL) {
192         q->tail = p;
193     }
194 
195     PKTSETLINK(p, q->head);
196     q->head = p;
197     q->n_pkts++;
198 
199     /* protect shared resource */
200     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
201         return NULL;
202     }
203 
204     return p;
205 }
206 
pktq_pdeq(struct pktq * pq,int prec)207 void *BCMFASTPATH pktq_pdeq(struct pktq *pq, int prec)
208 {
209     struct pktq_prec *q;
210     void *p;
211 
212     /* protect shared resource */
213     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
214         OSL_EXT_SUCCESS) {
215         return NULL;
216     }
217 
218     ASSERT(prec >= 0 && prec < pq->num_prec);
219 
220     q = &pq->q[prec];
221 
222     if ((p = q->head) == NULL) {
223         goto done;
224     }
225 
226     if ((q->head = PKTLINK(p)) == NULL) {
227         q->tail = NULL;
228     }
229 
230     q->n_pkts--;
231 
232     pq->n_pkts_tot--;
233 
234 #ifdef WL_TXQ_STALL
235     q->dequeue_count++;
236 #endif // endif
237 
238     PKTSETLINK(p, NULL);
239 
240 done:
241     /* protect shared resource */
242     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
243         return NULL;
244     }
245 
246     return p;
247 }
248 
spktq_deq(struct spktq * spq)249 void *BCMFASTPATH spktq_deq(struct spktq *spq)
250 {
251     struct pktq_prec *q;
252     void *p;
253 
254     /* protect shared resource */
255     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
256         OSL_EXT_SUCCESS) {
257         return NULL;
258     }
259 
260     q = &spq->q;
261 
262     if ((p = q->head) == NULL) {
263         goto done;
264     }
265 
266     if ((q->head = PKTLINK(p)) == NULL) {
267         q->tail = NULL;
268     }
269 
270     q->n_pkts--;
271 
272 #ifdef WL_TXQ_STALL
273     q->dequeue_count++;
274 #endif // endif
275 
276     PKTSETLINK(p, NULL);
277 
278 done:
279     /* protect shared resource */
280     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
281         return NULL;
282     }
283 
284     return p;
285 }
286 
pktq_pdeq_tail(struct pktq * pq,int prec)287 void *BCMFASTPATH pktq_pdeq_tail(struct pktq *pq, int prec)
288 {
289     struct pktq_prec *q;
290     void *p, *prev;
291 
292     /* protect shared resource */
293     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
294         OSL_EXT_SUCCESS) {
295         return NULL;
296     }
297 
298     ASSERT(prec >= 0 && prec < pq->num_prec);
299 
300     q = &pq->q[prec];
301 
302     if ((p = q->head) == NULL) {
303         goto done;
304     }
305 
306     for (prev = NULL; p != q->tail; p = PKTLINK(p)) {
307         prev = p;
308     }
309 
310     if (prev) {
311         PKTSETLINK(prev, NULL);
312     } else {
313         q->head = NULL;
314     }
315 
316     q->tail = prev;
317     q->n_pkts--;
318 
319     pq->n_pkts_tot--;
320 
321 #ifdef WL_TXQ_STALL
322     q->dequeue_count++;
323 #endif // endif
324 done:
325     /* protect shared resource */
326     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
327         return NULL;
328     }
329 
330     return p;
331 }
332 
spktq_deq_tail(struct spktq * spq)333 void *BCMFASTPATH spktq_deq_tail(struct spktq *spq)
334 {
335     struct pktq_prec *q;
336     void *p, *prev;
337 
338     /* protect shared resource */
339     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
340         OSL_EXT_SUCCESS) {
341         return NULL;
342     }
343 
344     q = &spq->q;
345 
346     if ((p = q->head) == NULL) {
347         goto done;
348     }
349 
350     for (prev = NULL; p != q->tail; p = PKTLINK(p)) {
351         prev = p;
352     }
353 
354     if (prev) {
355         PKTSETLINK(prev, NULL);
356     } else {
357         q->head = NULL;
358     }
359 
360     q->tail = prev;
361     q->n_pkts--;
362 
363 #ifdef WL_TXQ_STALL
364     q->dequeue_count++;
365 #endif // endif
366 done:
367     /* protect shared resource */
368     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
369         return NULL;
370     }
371 
372     return p;
373 }
374 
pktq_peek_tail(struct pktq * pq,int * prec_out)375 void *pktq_peek_tail(struct pktq *pq, int *prec_out)
376 {
377     int prec;
378     void *p = NULL;
379 
380     /* protect shared resource */
381     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
382         OSL_EXT_SUCCESS) {
383         return NULL;
384     }
385 
386     if (pq->n_pkts_tot == 0) {
387         goto done;
388     }
389 
390     for (prec = 0; prec < pq->hi_prec; prec++) {
391         if (pq->q[prec].head) {
392             break;
393         }
394     }
395 
396     if (prec_out) {
397         *prec_out = prec;
398     }
399 
400     p = pq->q[prec].tail;
401 
402 done:
403     /* protect shared resource */
404     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
405         return NULL;
406     }
407 
408     return p;
409 }
410 
411 /*
412  * Append spktq 'list' to the tail of pktq 'pq'
413  */
pktq_append(struct pktq * pq,int prec,struct spktq * list)414 void BCMFASTPATH pktq_append(struct pktq *pq, int prec, struct spktq *list)
415 {
416     struct pktq_prec *q;
417     struct pktq_prec *list_q;
418 
419     /* protect shared resource */
420     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
421         OSL_EXT_SUCCESS) {
422         return;
423     }
424 
425     list_q = &list->q;
426 
427     /* empty list check */
428     if (list_q->head == NULL) {
429         goto done;
430     }
431 
432     ASSERT(prec >= 0 && prec < pq->num_prec);
433     ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
434 
435     ASSERT(!pktq_full(pq));
436     ASSERT(!pktqprec_full(pq, prec));
437 
438     q = &pq->q[prec];
439 
440     if (q->head) {
441         PKTSETLINK(q->tail, list_q->head);
442     } else {
443         q->head = list_q->head;
444     }
445 
446     q->tail = list_q->tail;
447     q->n_pkts += list_q->n_pkts;
448     pq->n_pkts_tot += list_q->n_pkts;
449 
450     if (pq->hi_prec < prec) {
451         pq->hi_prec = (uint8)prec;
452     }
453 
454 #ifdef WL_TXQ_STALL
455     list_q->dequeue_count += list_q->n_pkts;
456 #endif // endif
457 
458     list_q->head = NULL;
459     list_q->tail = NULL;
460     list_q->n_pkts = 0;
461 
462 done:
463     /* protect shared resource */
464     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
465         return;
466     }
467 }
468 
469 /*
470  * Append spktq 'list' to the tail of spktq 'spq'
471  */
spktq_append(struct spktq * spq,struct spktq * list)472 void BCMFASTPATH spktq_append(struct spktq *spq, struct spktq *list)
473 {
474     struct pktq_prec *q;
475     struct pktq_prec *list_q;
476 
477     /* protect shared resource */
478     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
479         OSL_EXT_SUCCESS) {
480         return;
481     }
482 
483     list_q = &list->q;
484 
485     /* empty list check */
486     if (list_q->head == NULL) {
487         goto done;
488     }
489 
490     ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
491 
492     ASSERT(!spktq_full(spq));
493 
494     q = &spq->q;
495 
496     if (q->head) {
497         PKTSETLINK(q->tail, list_q->head);
498     } else {
499         q->head = list_q->head;
500     }
501 
502     q->tail = list_q->tail;
503     q->n_pkts += list_q->n_pkts;
504 
505 #ifdef WL_TXQ_STALL
506     list_q->dequeue_count += list_q->n_pkts;
507 #endif // endif
508 
509     list_q->head = NULL;
510     list_q->tail = NULL;
511     list_q->n_pkts = 0;
512 
513 done:
514     /* protect shared resource */
515     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
516         return;
517     }
518 }
519 
520 /*
521  * Prepend spktq 'list' to the head of pktq 'pq'
522  */
pktq_prepend(struct pktq * pq,int prec,struct spktq * list)523 void BCMFASTPATH pktq_prepend(struct pktq *pq, int prec, struct spktq *list)
524 {
525     struct pktq_prec *q;
526     struct pktq_prec *list_q;
527 
528     /* protect shared resource */
529     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
530         OSL_EXT_SUCCESS) {
531         return;
532     }
533 
534     list_q = &list->q;
535 
536     /* empty list check */
537     if (list_q->head == NULL) {
538         goto done;
539     }
540 
541     ASSERT(prec >= 0 && prec < pq->num_prec);
542     ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
543 
544     ASSERT(!pktq_full(pq));
545     ASSERT(!pktqprec_full(pq, prec));
546 
547     q = &pq->q[prec];
548 
549     /* set the tail packet of list to point at the former pq head */
550     PKTSETLINK(list_q->tail, q->head);
551     /* the new q head is the head of list */
552     q->head = list_q->head;
553 
554     /* If the q tail was non-null, then it stays as is.
555      * If the q tail was null, it is now the tail of list
556      */
557     if (q->tail == NULL) {
558         q->tail = list_q->tail;
559     }
560 
561     q->n_pkts += list_q->n_pkts;
562     pq->n_pkts_tot += list_q->n_pkts;
563 
564     if (pq->hi_prec < prec) {
565         pq->hi_prec = (uint8)prec;
566     }
567 
568 #ifdef WL_TXQ_STALL
569     list_q->dequeue_count += list_q->n_pkts;
570 #endif // endif
571 
572     list_q->head = NULL;
573     list_q->tail = NULL;
574     list_q->n_pkts = 0;
575 
576 done:
577     /* protect shared resource */
578     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
579         return;
580     }
581 }
582 
583 /*
584  * Prepend spktq 'list' to the head of spktq 'spq'
585  */
spktq_prepend(struct spktq * spq,struct spktq * list)586 void BCMFASTPATH spktq_prepend(struct spktq *spq, struct spktq *list)
587 {
588     struct pktq_prec *q;
589     struct pktq_prec *list_q;
590 
591     /* protect shared resource */
592     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
593         OSL_EXT_SUCCESS) {
594         return;
595     }
596 
597     list_q = &list->q;
598 
599     /* empty list check */
600     if (list_q->head == NULL) {
601         goto done;
602     }
603 
604     ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
605 
606     ASSERT(!spktq_full(spq));
607 
608     q = &spq->q;
609 
610     /* set the tail packet of list to point at the former pq head */
611     PKTSETLINK(list_q->tail, q->head);
612     /* the new q head is the head of list */
613     q->head = list_q->head;
614 
615     /* If the q tail was non-null, then it stays as is.
616      * If the q tail was null, it is now the tail of list
617      */
618     if (q->tail == NULL) {
619         q->tail = list_q->tail;
620     }
621 
622     q->n_pkts += list_q->n_pkts;
623 
624 #ifdef WL_TXQ_STALL
625     list_q->dequeue_count += list_q->n_pkts;
626 #endif // endif
627 
628     list_q->head = NULL;
629     list_q->tail = NULL;
630     list_q->n_pkts = 0;
631 
632 done:
633     /* protect shared resource */
634     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
635         return;
636     }
637 }
638 
pktq_pdeq_prev(struct pktq * pq,int prec,void * prev_p)639 void *BCMFASTPATH pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
640 {
641     struct pktq_prec *q;
642     void *p = NULL;
643 
644     /* protect shared resource */
645     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
646         OSL_EXT_SUCCESS) {
647         return NULL;
648     }
649 
650     ASSERT(prec >= 0 && prec < pq->num_prec);
651 
652     q = &pq->q[prec];
653 
654     if (prev_p == NULL) {
655         goto done;
656     }
657 
658     if ((p = PKTLINK(prev_p)) == NULL) {
659         goto done;
660     }
661 
662     q->n_pkts--;
663 
664     pq->n_pkts_tot--;
665 
666 #ifdef WL_TXQ_STALL
667     q->dequeue_count++;
668 #endif // endif
669     PKTSETLINK(prev_p, PKTLINK(p));
670     PKTSETLINK(p, NULL);
671 
672 done:
673     /* protect shared resource */
674     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
675         return NULL;
676     }
677 
678     return p;
679 }
680 
pktq_pdeq_with_fn(struct pktq * pq,int prec,ifpkt_cb_t fn,int arg)681 void *BCMFASTPATH pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn,
682                                     int arg)
683 {
684     struct pktq_prec *q;
685     void *p, *prev = NULL;
686 
687     /* protect shared resource */
688     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
689         OSL_EXT_SUCCESS) {
690         return NULL;
691     }
692 
693     ASSERT(prec >= 0 && prec < pq->num_prec);
694 
695     q = &pq->q[prec];
696     p = q->head;
697 
698     while (p) {
699         if (fn == NULL || (*fn)(p, arg)) {
700             break;
701         } else {
702             prev = p;
703             p = PKTLINK(p);
704         }
705     }
706     if (p == NULL) {
707         goto done;
708     }
709 
710     if (prev == NULL) {
711         if ((q->head = PKTLINK(p)) == NULL) {
712             q->tail = NULL;
713         }
714     } else {
715         PKTSETLINK(prev, PKTLINK(p));
716         if (q->tail == p) {
717             q->tail = prev;
718         }
719     }
720 
721     q->n_pkts--;
722 
723     pq->n_pkts_tot--;
724 
725 #ifdef WL_TXQ_STALL
726     q->dequeue_count++;
727 #endif // endif
728     PKTSETLINK(p, NULL);
729 
730 done:
731     /* protect shared resource */
732     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
733         return NULL;
734     }
735 
736     return p;
737 }
738 
pktq_pdel(struct pktq * pq,void * pktbuf,int prec)739 bool BCMFASTPATH pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
740 {
741     bool ret = FALSE;
742     struct pktq_prec *q;
743     void *p = NULL;
744 
745     /* protect shared resource */
746     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
747         OSL_EXT_SUCCESS) {
748         return FALSE;
749     }
750 
751     ASSERT(prec >= 0 && prec < pq->num_prec);
752 
753     /* Should this just assert pktbuf? */
754     if (!pktbuf) {
755         goto done;
756     }
757 
758     q = &pq->q[prec];
759 
760     if (q->head == pktbuf) {
761         if ((q->head = PKTLINK(pktbuf)) == NULL) {
762             q->tail = NULL;
763         }
764     } else {
765         for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) {
766             ;
767         }
768         if (p == NULL) {
769             goto done;
770         }
771 
772         PKTSETLINK(p, PKTLINK(pktbuf));
773         if (q->tail == pktbuf) {
774             q->tail = p;
775         }
776     }
777 
778     q->n_pkts--;
779     pq->n_pkts_tot--;
780 
781 #ifdef WL_TXQ_STALL
782     q->dequeue_count++;
783 #endif // endif
784 
785     PKTSETLINK(pktbuf, NULL);
786     ret = TRUE;
787 
788 done:
789     /* protect shared resource */
790     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
791         return FALSE;
792     }
793 
794     return ret;
795 }
796 
_pktq_pfilter(struct pktq * pq,int prec,pktq_filter_t fltr,void * fltr_ctx,defer_free_pkt_fn_t defer,void * defer_ctx)797 static void _pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr,
798                           void *fltr_ctx, defer_free_pkt_fn_t defer,
799                           void *defer_ctx)
800 {
801     struct pktq_prec wq;
802     struct pktq_prec *q;
803     void *p;
804 
805     /* protect shared resource */
806     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
807         OSL_EXT_SUCCESS) {
808         return;
809     }
810 
811     /* move the prec queue aside to a work queue */
812     q = &pq->q[prec];
813 
814     wq = *q;
815 
816     q->head = NULL;
817     q->tail = NULL;
818     q->n_pkts = 0;
819 
820 #ifdef WL_TXQ_STALL
821     q->dequeue_count += wq.n_pkts;
822 #endif // endif
823 
824     pq->n_pkts_tot -= wq.n_pkts;
825 
826     /* protect shared resource */
827     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
828         return;
829     }
830 
831     /* start with the head of the work queue */
832     while ((p = wq.head) != NULL) {
833         /* unlink the current packet from the list */
834         wq.head = PKTLINK(p);
835         PKTSETLINK(p, NULL);
836         wq.n_pkts--;
837 
838 #ifdef WL_TXQ_STALL
839         wq.dequeue_count++;
840 #endif // endif
841 
842         /* call the filter function on current packet */
843         ASSERT(fltr != NULL);
844         switch ((*fltr)(fltr_ctx, p)) {
845             case PKT_FILTER_NOACTION:
846                 /* put this packet back */
847                 pktq_penq(pq, prec, p);
848                 break;
849 
850             case PKT_FILTER_DELETE:
851                 /* delete this packet */
852                 ASSERT(defer != NULL);
853                 (*defer)(defer_ctx, p);
854                 break;
855 
856             case PKT_FILTER_REMOVE:
857                 /* pkt already removed from list */
858                 break;
859 
860             default:
861                 ASSERT(0);
862                 break;
863         }
864     }
865 
866     ASSERT(wq.n_pkts == 0);
867 }
868 
pktq_pfilter(struct pktq * pq,int prec,pktq_filter_t fltr,void * fltr_ctx,defer_free_pkt_fn_t defer,void * defer_ctx,flush_free_pkt_fn_t flush,void * flush_ctx)869 void pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void *fltr_ctx,
870                   defer_free_pkt_fn_t defer, void *defer_ctx,
871                   flush_free_pkt_fn_t flush, void *flush_ctx)
872 {
873     _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx);
874 
875     ASSERT(flush != NULL);
876     (*flush)(flush_ctx);
877 }
878 
pktq_filter(struct pktq * pq,pktq_filter_t fltr,void * fltr_ctx,defer_free_pkt_fn_t defer,void * defer_ctx,flush_free_pkt_fn_t flush,void * flush_ctx)879 void pktq_filter(struct pktq *pq, pktq_filter_t fltr, void *fltr_ctx,
880                  defer_free_pkt_fn_t defer, void *defer_ctx,
881                  flush_free_pkt_fn_t flush, void *flush_ctx)
882 {
883     bool filter = FALSE;
884 
885     /* protect shared resource */
886     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
887         OSL_EXT_SUCCESS) {
888         return;
889     }
890 
891     /* Optimize if pktq n_pkts = 0, just return.
892      * pktq len of 0 means pktq's prec q's are all empty.
893      */
894     if (pq->n_pkts_tot > 0) {
895         filter = TRUE;
896     }
897 
898     /* protect shared resource */
899     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
900         return;
901     }
902 
903     if (filter) {
904         int prec;
905 
906         PKTQ_PREC_ITER(pq, prec)
907         {
908             _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx);
909         }
910 
911         ASSERT(flush != NULL);
912         (*flush)(flush_ctx);
913     }
914 }
915 
spktq_filter(struct spktq * spq,pktq_filter_t fltr,void * fltr_ctx,defer_free_pkt_fn_t defer,void * defer_ctx,flush_free_pkt_fn_t flush,void * flush_ctx)916 void spktq_filter(struct spktq *spq, pktq_filter_t fltr, void *fltr_ctx,
917                   defer_free_pkt_fn_t defer, void *defer_ctx,
918                   flush_free_pkt_fn_t flush, void *flush_ctx)
919 {
920     struct pktq_prec wq;
921     struct pktq_prec *q;
922     void *p = NULL;
923 
924     /* protect shared resource */
925     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
926         OSL_EXT_SUCCESS) {
927         return;
928     }
929 
930     q = &spq->q;
931 
932     /* Optimize if pktq_prec n_pkts = 0, just return. */
933     if (q->n_pkts == 0) {
934         (void)HND_PKTQ_MUTEX_RELEASE(&spq->mutex);
935         return;
936     }
937 
938     wq = *q;
939 
940     q->head = NULL;
941     q->tail = NULL;
942     q->n_pkts = 0;
943 
944 #ifdef WL_TXQ_STALL
945     q->dequeue_count += wq.n_pkts;
946 #endif // endif
947 
948     /* protect shared resource */
949     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
950         return;
951     }
952 
953     /* start with the head of the work queue */
954 
955     while ((p = wq.head) != NULL) {
956         /* unlink the current packet from the list */
957         wq.head = PKTLINK(p);
958         PKTSETLINK(p, NULL);
959         wq.n_pkts--;
960 
961 #ifdef WL_TXQ_STALL
962         wq.dequeue_count++;
963 #endif // endif
964 
965         /* call the filter function on current packet */
966         ASSERT(fltr != NULL);
967         switch ((*fltr)(fltr_ctx, p)) {
968             case PKT_FILTER_NOACTION:
969                 /* put this packet back */
970                 spktq_enq(spq, p);
971                 break;
972 
973             case PKT_FILTER_DELETE:
974                 /* delete this packet */
975                 ASSERT(defer != NULL);
976                 (*defer)(defer_ctx, p);
977                 break;
978 
979             case PKT_FILTER_REMOVE:
980                 /* pkt already removed from list */
981                 break;
982 
983             default:
984                 ASSERT(0);
985                 break;
986         }
987     }
988 
989     ASSERT(wq.n_pkts == 0);
990 
991     ASSERT(flush != NULL);
992     (*flush)(flush_ctx);
993 }
994 
pktq_init(struct pktq * pq,int num_prec,int max_pkts)995 bool pktq_init(struct pktq *pq, int num_prec, int max_pkts)
996 {
997     int prec;
998 
999     ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
1000 
1001     /* pq is variable size; only zero out what's requested */
1002     bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
1003 
1004     if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS) {
1005         return FALSE;
1006     }
1007 
1008     pq->num_prec = (uint16)num_prec;
1009 
1010     pq->max_pkts = (uint16)max_pkts;
1011 
1012     for (prec = 0; prec < num_prec; prec++) {
1013         pq->q[prec].max_pkts = pq->max_pkts;
1014     }
1015 
1016     return TRUE;
1017 }
1018 
spktq_init(struct spktq * spq,int max_pkts)1019 bool spktq_init(struct spktq *spq, int max_pkts)
1020 {
1021     bzero(spq, sizeof(struct spktq));
1022 
1023     if (HND_PKTQ_MUTEX_CREATE("spktq", &spq->mutex) != OSL_EXT_SUCCESS) {
1024         return FALSE;
1025     }
1026 
1027     spq->q.max_pkts = (uint16)max_pkts;
1028 
1029     return TRUE;
1030 }
1031 
pktq_deinit(struct pktq * pq)1032 bool pktq_deinit(struct pktq *pq)
1033 {
1034     BCM_REFERENCE(pq);
1035     if (HND_PKTQ_MUTEX_DELETE(&pq->mutex) != OSL_EXT_SUCCESS) {
1036         return FALSE;
1037     }
1038 
1039     return TRUE;
1040 }
1041 
spktq_deinit(struct spktq * spq)1042 bool spktq_deinit(struct spktq *spq)
1043 {
1044     BCM_REFERENCE(spq);
1045     if (HND_PKTQ_MUTEX_DELETE(&spq->mutex) != OSL_EXT_SUCCESS) {
1046         return FALSE;
1047     }
1048 
1049     return TRUE;
1050 }
1051 
pktq_set_max_plen(struct pktq * pq,int prec,int max_pkts)1052 void pktq_set_max_plen(struct pktq *pq, int prec, int max_pkts)
1053 {
1054     ASSERT(prec >= 0 && prec < pq->num_prec);
1055 
1056     /* protect shared resource */
1057     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1058         OSL_EXT_SUCCESS) {
1059         return;
1060     }
1061 
1062     if (prec < pq->num_prec) {
1063         pq->q[prec].max_pkts = (uint16)max_pkts;
1064     }
1065 
1066     /* protect shared resource */
1067     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1068         return;
1069     }
1070 }
1071 
pktq_deq(struct pktq * pq,int * prec_out)1072 void *BCMFASTPATH pktq_deq(struct pktq *pq, int *prec_out)
1073 {
1074     struct pktq_prec *q;
1075     void *p = NULL;
1076     int prec;
1077 
1078     /* protect shared resource */
1079     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1080         OSL_EXT_SUCCESS) {
1081         return NULL;
1082     }
1083 
1084     if (pq->n_pkts_tot == 0) {
1085         goto done;
1086     }
1087 
1088     while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) {
1089         pq->hi_prec--;
1090     }
1091 
1092     q = &pq->q[prec];
1093 
1094     if ((p = q->head) == NULL) {
1095         goto done;
1096     }
1097 
1098     if ((q->head = PKTLINK(p)) == NULL) {
1099         q->tail = NULL;
1100     }
1101 
1102     q->n_pkts--;
1103 
1104     pq->n_pkts_tot--;
1105 
1106 #ifdef WL_TXQ_STALL
1107     q->dequeue_count++;
1108 #endif // endif
1109 
1110     if (prec_out) {
1111         *prec_out = prec;
1112     }
1113 
1114     PKTSETLINK(p, NULL);
1115 
1116 done:
1117     /* protect shared resource */
1118     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1119         return NULL;
1120     }
1121 
1122     return p;
1123 }
1124 
pktq_deq_tail(struct pktq * pq,int * prec_out)1125 void *BCMFASTPATH pktq_deq_tail(struct pktq *pq, int *prec_out)
1126 {
1127     struct pktq_prec *q;
1128     void *p = NULL, *prev;
1129     int prec;
1130 
1131     /* protect shared resource */
1132     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1133         OSL_EXT_SUCCESS) {
1134         return NULL;
1135     }
1136 
1137     if (pq->n_pkts_tot == 0) {
1138         goto done;
1139     }
1140 
1141     for (prec = 0; prec < pq->hi_prec; prec++) {
1142         if (pq->q[prec].head) {
1143             break;
1144         }
1145     }
1146 
1147     q = &pq->q[prec];
1148 
1149     if ((p = q->head) == NULL) {
1150         goto done;
1151     }
1152 
1153     for (prev = NULL; p != q->tail; p = PKTLINK(p)) {
1154         prev = p;
1155     }
1156 
1157     if (prev) {
1158         PKTSETLINK(prev, NULL);
1159     } else {
1160         q->head = NULL;
1161     }
1162 
1163     q->tail = prev;
1164     q->n_pkts--;
1165 
1166     pq->n_pkts_tot--;
1167 
1168 #ifdef WL_TXQ_STALL
1169     q->dequeue_count++;
1170 #endif // endif
1171 
1172     if (prec_out) {
1173         *prec_out = prec;
1174     }
1175 
1176     PKTSETLINK(p, NULL);
1177 
1178 done:
1179     /* protect shared resource */
1180     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1181         return NULL;
1182     }
1183 
1184     return p;
1185 }
1186 
pktq_peek(struct pktq * pq,int * prec_out)1187 void *pktq_peek(struct pktq *pq, int *prec_out)
1188 {
1189     int prec;
1190     void *p = NULL;
1191 
1192     /* protect shared resource */
1193     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1194         OSL_EXT_SUCCESS) {
1195         return NULL;
1196     }
1197 
1198     if (pq->n_pkts_tot == 0) {
1199         goto done;
1200     }
1201 
1202     while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) {
1203         pq->hi_prec--;
1204     }
1205 
1206     if (prec_out) {
1207         *prec_out = prec;
1208     }
1209 
1210     p = pq->q[prec].head;
1211 
1212 done:
1213     /* protect shared resource */
1214     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1215         return NULL;
1216     }
1217 
1218     return p;
1219 }
1220 
spktq_peek(struct spktq * spq)1221 void *spktq_peek(struct spktq *spq)
1222 {
1223     void *p = NULL;
1224 
1225     /* protect shared resource */
1226     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
1227         OSL_EXT_SUCCESS) {
1228         return NULL;
1229     }
1230 
1231     if (spq->q.n_pkts == 0) {
1232         goto done;
1233     }
1234 
1235     p = spq->q.head;
1236 
1237 done:
1238     /* protect shared resource */
1239     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
1240         return NULL;
1241     }
1242 
1243     return p;
1244 }
1245 
pktq_pflush(osl_t * osh,struct pktq * pq,int prec,bool dir)1246 void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir)
1247 {
1248     void *p;
1249 
1250     /* no need for a mutex protection! */
1251 
1252     /* start with the head of the list */
1253     while ((p = pktq_pdeq(pq, prec)) != NULL) {
1254         /* delete this packet */
1255         PKTFREE(osh, p, dir);
1256     }
1257 }
1258 
spktq_flush(osl_t * osh,struct spktq * spq,bool dir)1259 void spktq_flush(osl_t *osh, struct spktq *spq, bool dir)
1260 {
1261     void *p;
1262 
1263     /* no need for a mutex protection! */
1264 
1265     /* start with the head of the list */
1266     while ((p = spktq_deq(spq)) != NULL) {
1267         /* delete this packet */
1268         PKTFREE(osh, p, dir);
1269     }
1270 }
1271 
pktq_flush(osl_t * osh,struct pktq * pq,bool dir)1272 void pktq_flush(osl_t *osh, struct pktq *pq, bool dir)
1273 {
1274     bool flush = FALSE;
1275 
1276     /* protect shared resource */
1277     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1278         OSL_EXT_SUCCESS) {
1279         return;
1280     }
1281 
1282     /* Optimize flush, if pktq n_pkts_tot = 0, just return.
1283      * pktq len of 0 means pktq's prec q's are all empty.
1284      */
1285     if (pq->n_pkts_tot > 0) {
1286         flush = TRUE;
1287     }
1288 
1289     /* protect shared resource */
1290     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1291         return;
1292     }
1293 
1294     if (flush) {
1295         int prec;
1296 
1297         PKTQ_PREC_ITER(pq, prec)
1298         {
1299             pktq_pflush(osh, pq, prec, dir);
1300         }
1301     }
1302 }
1303 
1304 /* Return sum of lengths of a specific set of precedences */
pktq_mlen(struct pktq * pq,uint prec_bmp)1305 int pktq_mlen(struct pktq *pq, uint prec_bmp)
1306 {
1307     int prec, len;
1308 
1309     /* protect shared resource */
1310     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1311         OSL_EXT_SUCCESS) {
1312         return 0;
1313     }
1314 
1315     len = 0;
1316 
1317     for (prec = 0; prec <= pq->hi_prec; prec++) {
1318         if (prec_bmp & (1 << prec)) {
1319             len += pq->q[prec].n_pkts;
1320         }
1321     }
1322 
1323     /* protect shared resource */
1324     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1325         return 0;
1326     }
1327 
1328     return len;
1329 }
1330 
1331 /* Priority peek from a specific set of precedences */
pktq_mpeek(struct pktq * pq,uint prec_bmp,int * prec_out)1332 void *BCMFASTPATH pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
1333 {
1334     struct pktq_prec *q;
1335     void *p = NULL;
1336     int prec;
1337 
1338     /* protect shared resource */
1339     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1340         OSL_EXT_SUCCESS) {
1341         return NULL;
1342     }
1343 
1344     if (pq->n_pkts_tot == 0) {
1345         goto done;
1346     }
1347 
1348     while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) {
1349         pq->hi_prec--;
1350     }
1351 
1352     while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) {
1353         if (prec-- == 0) {
1354             goto done;
1355         }
1356     }
1357 
1358     q = &pq->q[prec];
1359 
1360     if ((p = q->head) == NULL) {
1361         goto done;
1362     }
1363 
1364     if (prec_out) {
1365         *prec_out = prec;
1366     }
1367 
1368 done:
1369     /* protect shared resource */
1370     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1371         return NULL;
1372     }
1373 
1374     return p;
1375 }
1376 /* Priority dequeue from a specific set of precedences */
pktq_mdeq(struct pktq * pq,uint prec_bmp,int * prec_out)1377 void *BCMFASTPATH pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
1378 {
1379     struct pktq_prec *q;
1380     void *p = NULL;
1381     int prec;
1382 
1383     /* protect shared resource */
1384     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1385         OSL_EXT_SUCCESS) {
1386         return NULL;
1387     }
1388 
1389     if (pq->n_pkts_tot == 0) {
1390         goto done;
1391     }
1392 
1393     while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) {
1394         pq->hi_prec--;
1395     }
1396 
1397     while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) {
1398         if (prec-- == 0) {
1399             goto done;
1400         }
1401     }
1402 
1403     q = &pq->q[prec];
1404 
1405     if ((p = q->head) == NULL) {
1406         goto done;
1407     }
1408 
1409     if ((q->head = PKTLINK(p)) == NULL) {
1410         q->tail = NULL;
1411     }
1412 
1413     q->n_pkts--;
1414 
1415     // terence 20150308: fix for non-null pointer of skb->prev sent from
1416     // ndo_start_xmit
1417     if (q->n_pkts == 0) {
1418         q->head = NULL;
1419         q->tail = NULL;
1420     }
1421 
1422 #ifdef WL_TXQ_STALL
1423     q->dequeue_count++;
1424 #endif // endif
1425 
1426     if (prec_out) {
1427         *prec_out = prec;
1428     }
1429 
1430     pq->n_pkts_tot--;
1431 
1432     PKTSETLINK(p, NULL);
1433 
1434 done:
1435     /* protect shared resource */
1436     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1437         return NULL;
1438     }
1439 
1440     return p;
1441 }
1442 
1443 #ifdef HND_PKTQ_THREAD_SAFE
pktqprec_avail_pkts(struct pktq * pq,int prec)1444 int pktqprec_avail_pkts(struct pktq *pq, int prec)
1445 {
1446     int ret;
1447 
1448     /* protect shared resource */
1449     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1450         OSL_EXT_SUCCESS) {
1451         return 0;
1452     }
1453 
1454     ASSERT(prec >= 0 && prec < pq->num_prec);
1455 
1456     ret = pq->q[prec].max_pkts - pq->q[prec].n_pkts;
1457 
1458     /* protect shared resource */
1459     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1460         return 0;
1461     }
1462 
1463     return ret;
1464 }
1465 
pktqprec_full(struct pktq * pq,int prec)1466 bool pktqprec_full(struct pktq *pq, int prec)
1467 {
1468     bool ret;
1469 
1470     /* protect shared resource */
1471     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1472         OSL_EXT_SUCCESS) {
1473         return FALSE;
1474     }
1475 
1476     ASSERT(prec >= 0 && prec < pq->num_prec);
1477 
1478     ret = pq->q[prec].n_pkts >= pq->q[prec].max_pkts;
1479 
1480     /* protect shared resource */
1481     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1482         return FALSE;
1483     }
1484 
1485     return ret;
1486 }
1487 
pktq_avail(struct pktq * pq)1488 int pktq_avail(struct pktq *pq)
1489 {
1490     int ret;
1491 
1492     /* protect shared resource */
1493     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1494         OSL_EXT_SUCCESS) {
1495         return 0;
1496     }
1497 
1498     ret = pq->max_pkts - pq->n_pkts_tot;
1499 
1500     /* protect shared resource */
1501     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1502         return 0;
1503     }
1504 
1505     return ret;
1506 }
1507 
spktq_avail(struct spktq * spq)1508 int spktq_avail(struct spktq *spq)
1509 {
1510     int ret;
1511 
1512     /* protect shared resource */
1513     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
1514         OSL_EXT_SUCCESS) {
1515         return 0;
1516     }
1517 
1518     ret = spq->q.max_pkts - spq->q.n_pkts;
1519 
1520     /* protect shared resource */
1521     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
1522         return 0;
1523     }
1524 
1525     return ret;
1526 }
1527 
pktq_full(struct pktq * pq)1528 bool pktq_full(struct pktq *pq)
1529 {
1530     bool ret;
1531 
1532     /* protect shared resource */
1533     if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) !=
1534         OSL_EXT_SUCCESS) {
1535         return FALSE;
1536     }
1537 
1538     ret = pq->n_pkts_tot >= pq->max_pkts;
1539 
1540     /* protect shared resource */
1541     if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) {
1542         return FALSE;
1543     }
1544 
1545     return ret;
1546 }
1547 
spktq_full(struct spktq * spq)1548 bool spktq_full(struct spktq *spq)
1549 {
1550     bool ret;
1551 
1552     /* protect shared resource */
1553     if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) !=
1554         OSL_EXT_SUCCESS) {
1555         return FALSE;
1556     }
1557 
1558     ret = spq->q.n_pkts >= spq->q.max_pkts;
1559 
1560     /* protect shared resource */
1561     if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) {
1562         return FALSE;
1563     }
1564 
1565     return ret;
1566 }
1567 
1568 #endif /* HND_PKTQ_THREAD_SAFE */
1569