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