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