From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:50 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux driver --- kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hnd_pktq.c | 1029 +++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 782 insertions(+), 247 deletions(-) diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hnd_pktq.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hnd_pktq.c index bbf3189..c305cce 100644 --- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hnd_pktq.c +++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hnd_pktq.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0 */ /* * HND generic pktq operation primitives * - * Copyright (C) 1999-2019, Broadcom Corporation - * + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation + * + * Copyright (C) 1999-2017, Broadcom Corporation + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -17,7 +18,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -25,7 +26,7 @@ * * <<Broadcom-WL-IPTag/Open:>> * - * $Id: $ + * $Id: hnd_pktq.c 698847 2017-05-11 00:10:48Z $ */ #include <typedefs.h> @@ -45,8 +46,13 @@ #define HND_PKTQ_MUTEX_DELETE(mutex) OSL_EXT_SUCCESS #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) OSL_EXT_SUCCESS #define HND_PKTQ_MUTEX_RELEASE(mutex) OSL_EXT_SUCCESS -#endif +#endif /* HND_PKTQ_THREAD_SAFE */ +/* status during txfifo sync */ +#if defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) +#define TXQ_PKT_DEL 0x01 +#define HEAD_PKT_FLUSHED 0xFF +#endif /* defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) */ /* * osl multiple-precedence packet queue * hi_prec is always >= the number of the highest non-empty precedence @@ -61,12 +67,10 @@ return NULL; ASSERT(prec >= 0 && prec < pq->num_prec); - /* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */ - //ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p))); + ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); - PKTSETLINK(p, NULL); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -76,15 +80,48 @@ q->head = p; q->tail = p; - q->len++; + q->n_pkts++; - pq->len++; + pq->n_pkts_tot++; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +/* + * osl simple, non-priority packet queue + */ +void * BCMFASTPATH +spktq_enq(struct spktq *spq, void *p) +{ + struct pktq_prec *q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(!spktq_full(spq)); + + PKTSETLINK(p, NULL); + + q = &spq->q; + + if (q->head) + PKTSETLINK(q->tail, p); + else + q->head = p; + + q->tail = p; + q->n_pkts++; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) return NULL; return p; @@ -100,12 +137,10 @@ return NULL; ASSERT(prec >= 0 && prec < pq->num_prec); - /* queueing chains not allowed and no segmented SKB (Kernel-3.18.y) */ - //ASSERT(!((PKTLINK(p) != NULL) && (PKTLINK(p) != p))); + ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); - PKTSETLINK(p, NULL); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -114,9 +149,9 @@ PKTSETLINK(p, q->head); q->head = p; - q->len++; + q->n_pkts++; - pq->len++; + pq->n_pkts_tot++; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; @@ -128,110 +163,33 @@ return p; } -/* - * Append spktq 'list' to the tail of pktq 'pq' - */ -void BCMFASTPATH -pktq_append(struct pktq *pq, int prec, struct spktq *list) +void * BCMFASTPATH +spktq_enq_head(struct spktq *spq, void *p) { struct pktq_prec *q; - struct pktq_prec *list_q; /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return; + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; - list_q = &list->q[0]; + ASSERT(!spktq_full(spq)); - /* empty list check */ - if (list_q->head == NULL) - goto done; + PKTSETLINK(p, NULL); - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + q = &spq->q; - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + if (q->head == NULL) + q->tail = p; - q = &pq->q[prec]; - - if (q->head) - PKTSETLINK(q->tail, list_q->head); - else - q->head = list_q->head; - - q->tail = list_q->tail; - q->len += list_q->len; - pq->len += list_q->len; - - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; - - list_q->head = NULL; - list_q->tail = NULL; - list_q->len = 0; - list->len = 0; - -done: - /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return; -} - -/* - * Prepend spktq 'list' to the head of pktq 'pq' - */ -void BCMFASTPATH -pktq_prepend(struct pktq *pq, int prec, struct spktq *list) -{ - struct pktq_prec *q; - struct pktq_prec *list_q; + PKTSETLINK(p, q->head); + q->head = p; + q->n_pkts++; /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return; + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; - list_q = &list->q[0]; - - /* empty list check */ - if (list_q->head == NULL) - goto done; - - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ - - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); - - q = &pq->q[prec]; - - /* set the tail packet of list to point at the former pq head */ - PKTSETLINK(list_q->tail, q->head); - /* the new q head is the head of list */ - q->head = list_q->head; - - /* If the q tail was non-null, then it stays as is. - * If the q tail was null, it is now the tail of list - */ - if (q->tail == NULL) { - q->tail = list_q->tail; - } - - q->len += list_q->len; - pq->len += list_q->len; - - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; - - list_q->head = NULL; - list_q->tail = NULL; - list_q->len = 0; - list->len = 0; - -done: - /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return; + return p; } void * BCMFASTPATH @@ -254,9 +212,13 @@ if ((q->head = PKTLINK(p)) == NULL) q->tail = NULL; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); @@ -266,6 +228,360 @@ return NULL; return p; +} + +void * BCMFASTPATH +spktq_deq(struct spktq *spq) +{ + struct pktq_prec *q; + void *p; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + q = &spq->q; + + if ((p = q->head) == NULL) + goto done; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + + PKTSETLINK(p, NULL); + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +pktq_pdeq_tail(struct pktq *pq, int prec) +{ + struct pktq_prec *q; + void *p, *prev; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + goto done; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->n_pkts--; + + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +spktq_deq_tail(struct spktq *spq) +{ + struct pktq_prec *q; + void *p, *prev; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + q = &spq->q; + + if ((p = q->head) == NULL) + goto done; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * +pktq_peek_tail(struct pktq *pq, int *prec_out) +{ + int prec; + void *p = NULL; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + if (pq->n_pkts_tot == 0) + goto done; + + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; + + if (prec_out) + *prec_out = prec; + + p = pq->q[prec].tail; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +/* + * Append spktq 'list' to the tail of pktq 'pq' + */ +void BCMFASTPATH +pktq_append(struct pktq *pq, int prec, struct spktq *list) +{ + struct pktq_prec *q; + struct pktq_prec *list_q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + list_q = &list->q; + + /* empty list check */ + if (list_q->head == NULL) + goto done; + + ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + + ASSERT(!pktq_full(pq)); + ASSERT(!pktqprec_full(pq, prec)); + + q = &pq->q[prec]; + + if (q->head) + PKTSETLINK(q->tail, list_q->head); + else + q->head = list_q->head; + + q->tail = list_q->tail; + q->n_pkts += list_q->n_pkts; + pq->n_pkts_tot += list_q->n_pkts; + + if (pq->hi_prec < prec) + pq->hi_prec = (uint8)prec; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return; +} + +/* + * Append spktq 'list' to the tail of spktq 'spq' + */ +void BCMFASTPATH +spktq_append(struct spktq *spq, struct spktq *list) +{ + struct pktq_prec *q; + struct pktq_prec *list_q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + list_q = &list->q; + + /* empty list check */ + if (list_q->head == NULL) + goto done; + + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + + ASSERT(!spktq_full(spq)); + + q = &spq->q; + + if (q->head) + PKTSETLINK(q->tail, list_q->head); + else + q->head = list_q->head; + + q->tail = list_q->tail; + q->n_pkts += list_q->n_pkts; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; +} + +/* + * Prepend spktq 'list' to the head of pktq 'pq' + */ +void BCMFASTPATH +pktq_prepend(struct pktq *pq, int prec, struct spktq *list) +{ + struct pktq_prec *q; + struct pktq_prec *list_q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + list_q = &list->q; + + /* empty list check */ + if (list_q->head == NULL) + goto done; + + ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + + ASSERT(!pktq_full(pq)); + ASSERT(!pktqprec_full(pq, prec)); + + q = &pq->q[prec]; + + /* set the tail packet of list to point at the former pq head */ + PKTSETLINK(list_q->tail, q->head); + /* the new q head is the head of list */ + q->head = list_q->head; + + /* If the q tail was non-null, then it stays as is. + * If the q tail was null, it is now the tail of list + */ + if (q->tail == NULL) { + q->tail = list_q->tail; + } + + q->n_pkts += list_q->n_pkts; + pq->n_pkts_tot += list_q->n_pkts; + + if (pq->hi_prec < prec) + pq->hi_prec = (uint8)prec; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return; +} + +/* + * Prepend spktq 'list' to the head of spktq 'spq' + */ +void BCMFASTPATH +spktq_prepend(struct spktq *spq, struct spktq *list) +{ + struct pktq_prec *q; + struct pktq_prec *list_q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + list_q = &list->q; + + /* empty list check */ + if (list_q->head == NULL) + goto done; + + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + + ASSERT(!spktq_full(spq)); + + q = &spq->q; + + /* set the tail packet of list to point at the former pq head */ + PKTSETLINK(list_q->tail, q->head); + /* the new q head is the head of list */ + q->head = list_q->head; + + /* If the q tail was non-null, then it stays as is. + * If the q tail was null, it is now the tail of list + */ + if (q->tail == NULL) { + q->tail = list_q->tail; + } + + q->n_pkts += list_q->n_pkts; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; } void * BCMFASTPATH @@ -288,10 +604,13 @@ if ((p = PKTLINK(prev_p)) == NULL) goto done; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(prev_p, PKTLINK(p)); PKTSETLINK(p, NULL); @@ -340,10 +659,13 @@ } } - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); done: @@ -352,84 +674,6 @@ return NULL; return p; -} - -void * BCMFASTPATH -pktq_pdeq_tail(struct pktq *pq, int prec) -{ - struct pktq_prec *q; - void *p, *prev; - - /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return NULL; - - ASSERT(prec >= 0 && prec < pq->num_prec); - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - goto done; - - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; - - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; - - q->tail = prev; - q->len--; - - pq->len--; - -done: - /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return NULL; - - return p; -} - -void -pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) -{ - struct pktq_prec *q; - void *p, *prev = NULL; - - /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return; - - q = &pq->q[prec]; - p = q->head; - while (p) { - if (fn == NULL || (*fn)(p, arg)) { - bool head = (p == q->head); - if (head) - q->head = PKTLINK(p); - else - PKTSETLINK(prev, PKTLINK(p)); - PKTSETLINK(p, NULL); - PKTFREE(osh, p, dir); - q->len--; - pq->len--; - p = (head ? q->head : PKTLINK(prev)); - } else { - prev = p; - p = PKTLINK(p); - } - } - - if (q->head == NULL) { - ASSERT(q->len == 0); - q->tail = NULL; - } - - /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return; } bool BCMFASTPATH @@ -465,8 +709,13 @@ q->tail = p; } - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + PKTSETLINK(pktbuf, NULL); ret = TRUE; @@ -478,25 +727,226 @@ return ret; } +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) +{ + struct pktq_prec wq; + struct pktq_prec *q; + void *p; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + /* move the prec queue aside to a work queue */ + q = &pq->q[prec]; + + wq = *q; + + q->head = NULL; + q->tail = NULL; + q->n_pkts = 0; + +#ifdef WL_TXQ_STALL + q->dequeue_count += wq.n_pkts; +#endif // endif + + pq->n_pkts_tot -= wq.n_pkts; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return; + + /* start with the head of the work queue */ + while ((p = wq.head) != NULL) { + /* unlink the current packet from the list */ + wq.head = PKTLINK(p); + PKTSETLINK(p, NULL); + wq.n_pkts--; + +#ifdef WL_TXQ_STALL + wq.dequeue_count++; +#endif // endif + + /* call the filter function on current packet */ + ASSERT(fltr != NULL); + switch ((*fltr)(fltr_ctx, p)) { + case PKT_FILTER_NOACTION: + /* put this packet back */ + pktq_penq(pq, prec, p); + break; + + case PKT_FILTER_DELETE: + /* delete this packet */ + ASSERT(defer != NULL); + (*defer)(defer_ctx, p); + break; + + case PKT_FILTER_REMOVE: + /* pkt already removed from list */ + break; + + default: + ASSERT(0); + break; + } + } + + ASSERT(wq.n_pkts == 0); +} + +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) +{ + _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx); + + ASSERT(flush != NULL); + (*flush)(flush_ctx); +} + +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) +{ + bool filter = FALSE; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + /* Optimize if pktq n_pkts = 0, just return. + * pktq len of 0 means pktq's prec q's are all empty. + */ + if (pq->n_pkts_tot > 0) { + filter = TRUE; + } + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return; + + if (filter) { + int prec; + + PKTQ_PREC_ITER(pq, prec) { + _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx); + } + + ASSERT(flush != NULL); + (*flush)(flush_ctx); + } +} + +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) +{ + struct pktq_prec wq; + struct pktq_prec *q; + void *p = NULL; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + q = &spq->q; + + /* Optimize if pktq_prec n_pkts = 0, just return. */ + if (q->n_pkts == 0) { + (void)HND_PKTQ_MUTEX_RELEASE(&spq->mutex); + return; + } + + wq = *q; + + q->head = NULL; + q->tail = NULL; + q->n_pkts = 0; + +#ifdef WL_TXQ_STALL + q->dequeue_count += wq.n_pkts; +#endif // endif + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; + + /* start with the head of the work queue */ + + while ((p = wq.head) != NULL) { + /* unlink the current packet from the list */ + wq.head = PKTLINK(p); + PKTSETLINK(p, NULL); + wq.n_pkts--; + +#ifdef WL_TXQ_STALL + wq.dequeue_count++; +#endif // endif + + /* call the filter function on current packet */ + ASSERT(fltr != NULL); + switch ((*fltr)(fltr_ctx, p)) { + case PKT_FILTER_NOACTION: + /* put this packet back */ + spktq_enq(spq, p); + break; + + case PKT_FILTER_DELETE: + /* delete this packet */ + ASSERT(defer != NULL); + (*defer)(defer_ctx, p); + break; + + case PKT_FILTER_REMOVE: + /* pkt already removed from list */ + break; + + default: + ASSERT(0); + break; + } + } + + ASSERT(wq.n_pkts == 0); + + ASSERT(flush != NULL); + (*flush)(flush_ctx); +} + bool -pktq_init(struct pktq *pq, int num_prec, int max_len) +pktq_init(struct pktq *pq, int num_prec, int max_pkts) { int prec; - - if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS) - return FALSE; ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); /* pq is variable size; only zero out what's requested */ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); + if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + pq->num_prec = (uint16)num_prec; - pq->max = (uint16)max_len; + pq->max_pkts = (uint16)max_pkts; for (prec = 0; prec < num_prec; prec++) - pq->q[prec].max = pq->max; + pq->q[prec].max_pkts = pq->max_pkts; + + return TRUE; +} + +bool +spktq_init(struct spktq *spq, int max_pkts) +{ + bzero(spq, sizeof(struct spktq)); + + if (HND_PKTQ_MUTEX_CREATE("spktq", &spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + spq->q.max_pkts = (uint16)max_pkts; return TRUE; } @@ -504,14 +954,25 @@ bool pktq_deinit(struct pktq *pq) { + BCM_REFERENCE(pq); if (HND_PKTQ_MUTEX_DELETE(&pq->mutex) != OSL_EXT_SUCCESS) return FALSE; return TRUE; } +bool +spktq_deinit(struct spktq *spq) +{ + BCM_REFERENCE(spq); + if (HND_PKTQ_MUTEX_DELETE(&spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + return TRUE; +} + void -pktq_set_max_plen(struct pktq *pq, int prec, int max_len) +pktq_set_max_plen(struct pktq *pq, int prec, int max_pkts) { ASSERT(prec >= 0 && prec < pq->num_prec); @@ -520,7 +981,7 @@ return; if (prec < pq->num_prec) - pq->q[prec].max = (uint16)max_len; + pq->q[prec].max_pkts = (uint16)max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -538,7 +999,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -552,9 +1013,13 @@ if ((q->head = PKTLINK(p)) == NULL) q->tail = NULL; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; @@ -580,7 +1045,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; for (prec = 0; prec < pq->hi_prec; prec++) @@ -601,9 +1066,13 @@ q->head = NULL; q->tail = prev; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; @@ -628,7 +1097,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -648,59 +1117,84 @@ } void * -pktq_peek_tail(struct pktq *pq, int *prec_out) +spktq_peek(struct spktq *spq) { - int prec; void *p = NULL; /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (spq->q.n_pkts == 0) goto done; - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; - - if (prec_out) - *prec_out = prec; - - p = pq->q[prec].tail; + p = spq->q.head; done: /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) return NULL; return p; } void -pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) +pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir) { - int prec; + void *p; + + /* no need for a mutex protection! */ + + /* start with the head of the list */ + while ((p = pktq_pdeq(pq, prec)) != NULL) { + + /* delete this packet */ + PKTFREE(osh, p, dir); + } +} + +void +spktq_flush(osl_t *osh, struct spktq *spq, bool dir) +{ + void *p; + + /* no need for a mutex protection! */ + + /* start with the head of the list */ + while ((p = spktq_deq(spq)) != NULL) { + + /* delete this packet */ + PKTFREE(osh, p, dir); + } +} + +void +pktq_flush(osl_t *osh, struct pktq *pq, bool dir) +{ + bool flush = FALSE; /* protect shared resource */ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return; - /* Optimize flush, if pktq len = 0, just return. + /* Optimize flush, if pktq n_pkts_tot = 0, just return. * pktq len of 0 means pktq's prec q's are all empty. */ - if (pq->len == 0) - goto done; + if (pq->n_pkts_tot > 0) { + flush = TRUE; + } - for (prec = 0; prec < pq->num_prec; prec++) - pktq_pflush(osh, pq, prec, dir, fn, arg); - if (fn == NULL) - ASSERT(pq->len == 0); - -done: /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) return; + + if (flush) { + int prec; + + PKTQ_PREC_ITER(pq, prec) { + pktq_pflush(osh, pq, prec, dir); + } + } } /* Return sum of lengths of a specific set of precedences */ @@ -717,7 +1211,7 @@ for (prec = 0; prec <= pq->hi_prec; prec++) if (prec_bmp & (1 << prec)) - len += pq->q[prec].len; + len += pq->q[prec].n_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -738,7 +1232,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -775,7 +1269,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -793,12 +1287,16 @@ if ((q->head = PKTLINK(p)) == NULL) q->tail = NULL; - q->len--; + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; - pq->len--; + pq->n_pkts_tot--; PKTSETLINK(p, NULL); @@ -812,7 +1310,7 @@ #ifdef HND_PKTQ_THREAD_SAFE int -pktq_pavail(struct pktq *pq, int prec) +pktqprec_avail_pkts(struct pktq *pq, int prec) { int ret; @@ -822,7 +1320,7 @@ ASSERT(prec >= 0 && prec < pq->num_prec); - ret = pq->q[prec].max - pq->q[prec].len; + ret = pq->q[prec].max_pkts - pq->q[prec].n_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -832,7 +1330,7 @@ } bool -pktq_pfull(struct pktq *pq, int prec) +pktqprec_full(struct pktq *pq, int prec) { bool ret; @@ -842,7 +1340,7 @@ ASSERT(prec >= 0 && prec < pq->num_prec); - ret = pq->q[prec].len >= pq->q[prec].max; + ret = pq->q[prec].n_pkts >= pq->q[prec].max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -860,10 +1358,28 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return 0; - ret = pq->max - pq->len; + ret = pq->max_pkts - pq->n_pkts_tot; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return 0; + + return ret; +} + +int +spktq_avail(struct spktq *spq) +{ + int ret; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return 0; + + ret = spq->q.max_pkts - spq->q.n_pkts; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) return 0; return ret; @@ -878,7 +1394,7 @@ if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return FALSE; - ret = pq->len >= pq->max; + ret = pq->n_pkts_tot >= pq->max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -886,4 +1402,23 @@ return ret; } + +bool +spktq_full(struct spktq *spq) +{ + bool ret; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return FALSE; + + ret = spq->q.n_pkts >= spq->q.max_pkts; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + return ret; +} + #endif /* HND_PKTQ_THREAD_SAFE */ -- Gitblit v1.6.2