| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424 |
- /*
- * HND generic pktq operation primitives
- *
- * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
- *
- * Copyright (C) 1999-2020, 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
- * you also meet, for each linked independent module, the terms and conditions of
- * 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.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: hnd_pktq.c 698847 2017-05-11 00:10:48Z $
- */
- #include <typedefs.h>
- #include <osl.h>
- #include <osl_ext.h>
- #include <bcmutils.h>
- #include <hnd_pktq.h>
- /* mutex macros for thread safe */
- #ifdef HND_PKTQ_THREAD_SAFE
- #define HND_PKTQ_MUTEX_CREATE(name, mutex) osl_ext_mutex_create(name, mutex)
- #define HND_PKTQ_MUTEX_DELETE(mutex) osl_ext_mutex_delete(mutex)
- #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) osl_ext_mutex_acquire(mutex, msec)
- #define HND_PKTQ_MUTEX_RELEASE(mutex) osl_ext_mutex_release(mutex)
- #else
- #define HND_PKTQ_MUTEX_CREATE(name, mutex) OSL_EXT_SUCCESS
- #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 /* 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
- */
- void * BCMFASTPATH
- pktq_penq(struct pktq *pq, int prec, void *p)
- {
- struct pktq_prec *q;
- /* 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);
- ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
- ASSERT(!pktq_full(pq));
- ASSERT(!pktqprec_full(pq, prec));
- q = &pq->q[prec];
- if (q->head)
- PKTSETLINK(q->tail, p);
- else
- q->head = p;
- q->tail = p;
- q->n_pkts++;
- 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;
- }
- void * BCMFASTPATH
- pktq_penq_head(struct pktq *pq, int prec, void *p)
- {
- struct pktq_prec *q;
- /* 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);
- ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
- ASSERT(!pktq_full(pq));
- ASSERT(!pktqprec_full(pq, prec));
- q = &pq->q[prec];
- if (q->head == NULL)
- q->tail = p;
- PKTSETLINK(p, q->head);
- q->head = p;
- q->n_pkts++;
- 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;
- }
- void * BCMFASTPATH
- spktq_enq_head(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 == NULL)
- q->tail = p;
- PKTSETLINK(p, q->head);
- q->head = p;
- q->n_pkts++;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void * BCMFASTPATH
- pktq_pdeq(struct pktq *pq, int prec)
- {
- struct pktq_prec *q;
- void *p;
- /* 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;
- if ((q->head = PKTLINK(p)) == NULL)
- q->tail = NULL;
- q->n_pkts--;
- pq->n_pkts_tot--;
- #ifdef WL_TXQ_STALL
- q->dequeue_count++;
- #endif // endif
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- 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
- pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
- {
- struct pktq_prec *q;
- void *p = NULL;
- /* 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 (prev_p == NULL)
- goto done;
- if ((p = PKTLINK(prev_p)) == NULL)
- goto done;
- q->n_pkts--;
- pq->n_pkts_tot--;
- #ifdef WL_TXQ_STALL
- q->dequeue_count++;
- #endif // endif
- PKTSETLINK(prev_p, PKTLINK(p));
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void * BCMFASTPATH
- pktq_pdeq_with_fn(struct pktq *pq, int prec, 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 NULL;
- ASSERT(prec >= 0 && prec < pq->num_prec);
- q = &pq->q[prec];
- p = q->head;
- while (p) {
- if (fn == NULL || (*fn)(p, arg)) {
- break;
- } else {
- prev = p;
- p = PKTLINK(p);
- }
- }
- if (p == NULL)
- goto done;
- if (prev == NULL) {
- if ((q->head = PKTLINK(p)) == NULL) {
- q->tail = NULL;
- }
- } else {
- PKTSETLINK(prev, PKTLINK(p));
- if (q->tail == p) {
- q->tail = prev;
- }
- }
- q->n_pkts--;
- pq->n_pkts_tot--;
- #ifdef WL_TXQ_STALL
- q->dequeue_count++;
- #endif // endif
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- bool BCMFASTPATH
- pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
- {
- bool ret = FALSE;
- struct pktq_prec *q;
- void *p = NULL;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return FALSE;
- ASSERT(prec >= 0 && prec < pq->num_prec);
- /* Should this just assert pktbuf? */
- if (!pktbuf)
- goto done;
- q = &pq->q[prec];
- if (q->head == pktbuf) {
- if ((q->head = PKTLINK(pktbuf)) == NULL)
- q->tail = NULL;
- } else {
- for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
- ;
- if (p == NULL)
- goto done;
- PKTSETLINK(p, PKTLINK(pktbuf));
- if (q->tail == pktbuf)
- q->tail = p;
- }
- q->n_pkts--;
- pq->n_pkts_tot--;
- #ifdef WL_TXQ_STALL
- q->dequeue_count++;
- #endif // endif
- PKTSETLINK(pktbuf, NULL);
- ret = TRUE;
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return FALSE;
- 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_pkts)
- {
- int prec;
- 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_pkts = (uint16)max_pkts;
- for (prec = 0; prec < num_prec; prec++)
- 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;
- }
- 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_pkts)
- {
- ASSERT(prec >= 0 && prec < pq->num_prec);
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return;
- if (prec < pq->num_prec)
- pq->q[prec].max_pkts = (uint16)max_pkts;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return;
- }
- void * BCMFASTPATH
- pktq_deq(struct pktq *pq, int *prec_out)
- {
- struct pktq_prec *q;
- void *p = NULL;
- int prec;
- /* 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;
- while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
- pq->hi_prec--;
- q = &pq->q[prec];
- if ((p = q->head) == NULL)
- goto done;
- if ((q->head = PKTLINK(p)) == NULL)
- q->tail = NULL;
- q->n_pkts--;
- pq->n_pkts_tot--;
- #ifdef WL_TXQ_STALL
- q->dequeue_count++;
- #endif // endif
- if (prec_out)
- *prec_out = prec;
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void * BCMFASTPATH
- pktq_deq_tail(struct pktq *pq, int *prec_out)
- {
- struct pktq_prec *q;
- void *p = NULL, *prev;
- int prec;
- /* 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;
- 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
- if (prec_out)
- *prec_out = prec;
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void *
- pktq_peek(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;
- while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
- pq->hi_prec--;
- if (prec_out)
- *prec_out = prec;
- p = pq->q[prec].head;
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void *
- spktq_peek(struct spktq *spq)
- {
- void *p = NULL;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return NULL;
- if (spq->q.n_pkts == 0)
- goto done;
- p = spq->q.head;
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- void
- pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir)
- {
- 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 n_pkts_tot = 0, just return.
- * pktq len of 0 means pktq's prec q's are all empty.
- */
- if (pq->n_pkts_tot > 0) {
- flush = TRUE;
- }
- /* 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 */
- int
- pktq_mlen(struct pktq *pq, uint prec_bmp)
- {
- int prec, len;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return 0;
- len = 0;
- for (prec = 0; prec <= pq->hi_prec; prec++)
- if (prec_bmp & (1 << prec))
- len += pq->q[prec].n_pkts;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return 0;
- return len;
- }
- /* Priority peek from a specific set of precedences */
- void * BCMFASTPATH
- pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
- {
- struct pktq_prec *q;
- void *p = NULL;
- int prec;
- /* 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;
- while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
- pq->hi_prec--;
- while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
- if (prec-- == 0)
- goto done;
- q = &pq->q[prec];
- if ((p = q->head) == NULL)
- goto done;
- if (prec_out)
- *prec_out = prec;
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- /* Priority dequeue from a specific set of precedences */
- void * BCMFASTPATH
- pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
- {
- struct pktq_prec *q;
- void *p = NULL;
- int prec;
- /* 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;
- while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
- pq->hi_prec--;
- while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
- if (prec-- == 0)
- goto done;
- q = &pq->q[prec];
- 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
- if (prec_out)
- *prec_out = prec;
- pq->n_pkts_tot--;
- PKTSETLINK(p, NULL);
- done:
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return NULL;
- return p;
- }
- #ifdef HND_PKTQ_THREAD_SAFE
- int
- pktqprec_avail_pkts(struct pktq *pq, int prec)
- {
- int ret;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return 0;
- ASSERT(prec >= 0 && prec < pq->num_prec);
- ret = pq->q[prec].max_pkts - pq->q[prec].n_pkts;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return 0;
- return ret;
- }
- bool
- pktqprec_full(struct pktq *pq, int prec)
- {
- bool ret;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return FALSE;
- ASSERT(prec >= 0 && prec < pq->num_prec);
- ret = pq->q[prec].n_pkts >= pq->q[prec].max_pkts;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return FALSE;
- return ret;
- }
- int
- pktq_avail(struct pktq *pq)
- {
- int ret;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return 0;
- 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;
- }
- bool
- pktq_full(struct pktq *pq)
- {
- bool ret;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
- return FALSE;
- ret = pq->n_pkts_tot >= pq->max_pkts;
- /* protect shared resource */
- if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
- return FALSE;
- 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 */
|