hnd_pktq.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. /*
  2. * HND generic pktq operation primitives
  3. *
  4. * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
  5. *
  6. * Copyright (C) 1999-2020, Broadcom Corporation
  7. *
  8. * Unless you and Broadcom execute a separate written software license
  9. * agreement governing use of this software, this software is licensed to you
  10. * under the terms of the GNU General Public License version 2 (the "GPL"),
  11. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  12. * following added to such license:
  13. *
  14. * As a special exception, the copyright holders of this software give you
  15. * permission to link this software with independent modules, and to copy and
  16. * distribute the resulting executable under terms of your choice, provided that
  17. * you also meet, for each linked independent module, the terms and conditions of
  18. * the license of that module. An independent module is a module which is not
  19. * derived from this software. The special exception does not apply to any
  20. * modifications of the software.
  21. *
  22. * Notwithstanding the above, under no circumstances may you combine this
  23. * software in any way with any other Broadcom software provided under a license
  24. * other than the GPL, without Broadcom's express prior written consent.
  25. *
  26. *
  27. * <<Broadcom-WL-IPTag/Open:>>
  28. *
  29. * $Id: hnd_pktq.c 698847 2017-05-11 00:10:48Z $
  30. */
  31. #include <typedefs.h>
  32. #include <osl.h>
  33. #include <osl_ext.h>
  34. #include <bcmutils.h>
  35. #include <hnd_pktq.h>
  36. /* mutex macros for thread safe */
  37. #ifdef HND_PKTQ_THREAD_SAFE
  38. #define HND_PKTQ_MUTEX_CREATE(name, mutex) osl_ext_mutex_create(name, mutex)
  39. #define HND_PKTQ_MUTEX_DELETE(mutex) osl_ext_mutex_delete(mutex)
  40. #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) osl_ext_mutex_acquire(mutex, msec)
  41. #define HND_PKTQ_MUTEX_RELEASE(mutex) osl_ext_mutex_release(mutex)
  42. #else
  43. #define HND_PKTQ_MUTEX_CREATE(name, mutex) OSL_EXT_SUCCESS
  44. #define HND_PKTQ_MUTEX_DELETE(mutex) OSL_EXT_SUCCESS
  45. #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) OSL_EXT_SUCCESS
  46. #define HND_PKTQ_MUTEX_RELEASE(mutex) OSL_EXT_SUCCESS
  47. #endif /* HND_PKTQ_THREAD_SAFE */
  48. /* status during txfifo sync */
  49. #if defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS)
  50. #define TXQ_PKT_DEL 0x01
  51. #define HEAD_PKT_FLUSHED 0xFF
  52. #endif /* defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) */
  53. /*
  54. * osl multiple-precedence packet queue
  55. * hi_prec is always >= the number of the highest non-empty precedence
  56. */
  57. void * BCMFASTPATH
  58. pktq_penq(struct pktq *pq, int prec, void *p)
  59. {
  60. struct pktq_prec *q;
  61. /* protect shared resource */
  62. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  63. return NULL;
  64. ASSERT(prec >= 0 && prec < pq->num_prec);
  65. ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
  66. ASSERT(!pktq_full(pq));
  67. ASSERT(!pktqprec_full(pq, prec));
  68. q = &pq->q[prec];
  69. if (q->head)
  70. PKTSETLINK(q->tail, p);
  71. else
  72. q->head = p;
  73. q->tail = p;
  74. q->n_pkts++;
  75. pq->n_pkts_tot++;
  76. if (pq->hi_prec < prec)
  77. pq->hi_prec = (uint8)prec;
  78. /* protect shared resource */
  79. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  80. return NULL;
  81. return p;
  82. }
  83. /*
  84. * osl simple, non-priority packet queue
  85. */
  86. void * BCMFASTPATH
  87. spktq_enq(struct spktq *spq, void *p)
  88. {
  89. struct pktq_prec *q;
  90. /* protect shared resource */
  91. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  92. return NULL;
  93. ASSERT(!spktq_full(spq));
  94. PKTSETLINK(p, NULL);
  95. q = &spq->q;
  96. if (q->head)
  97. PKTSETLINK(q->tail, p);
  98. else
  99. q->head = p;
  100. q->tail = p;
  101. q->n_pkts++;
  102. /* protect shared resource */
  103. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  104. return NULL;
  105. return p;
  106. }
  107. void * BCMFASTPATH
  108. pktq_penq_head(struct pktq *pq, int prec, void *p)
  109. {
  110. struct pktq_prec *q;
  111. /* protect shared resource */
  112. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  113. return NULL;
  114. ASSERT(prec >= 0 && prec < pq->num_prec);
  115. ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
  116. ASSERT(!pktq_full(pq));
  117. ASSERT(!pktqprec_full(pq, prec));
  118. q = &pq->q[prec];
  119. if (q->head == NULL)
  120. q->tail = p;
  121. PKTSETLINK(p, q->head);
  122. q->head = p;
  123. q->n_pkts++;
  124. pq->n_pkts_tot++;
  125. if (pq->hi_prec < prec)
  126. pq->hi_prec = (uint8)prec;
  127. /* protect shared resource */
  128. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  129. return NULL;
  130. return p;
  131. }
  132. void * BCMFASTPATH
  133. spktq_enq_head(struct spktq *spq, void *p)
  134. {
  135. struct pktq_prec *q;
  136. /* protect shared resource */
  137. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  138. return NULL;
  139. ASSERT(!spktq_full(spq));
  140. PKTSETLINK(p, NULL);
  141. q = &spq->q;
  142. if (q->head == NULL)
  143. q->tail = p;
  144. PKTSETLINK(p, q->head);
  145. q->head = p;
  146. q->n_pkts++;
  147. /* protect shared resource */
  148. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  149. return NULL;
  150. return p;
  151. }
  152. void * BCMFASTPATH
  153. pktq_pdeq(struct pktq *pq, int prec)
  154. {
  155. struct pktq_prec *q;
  156. void *p;
  157. /* protect shared resource */
  158. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  159. return NULL;
  160. ASSERT(prec >= 0 && prec < pq->num_prec);
  161. q = &pq->q[prec];
  162. if ((p = q->head) == NULL)
  163. goto done;
  164. if ((q->head = PKTLINK(p)) == NULL)
  165. q->tail = NULL;
  166. q->n_pkts--;
  167. pq->n_pkts_tot--;
  168. #ifdef WL_TXQ_STALL
  169. q->dequeue_count++;
  170. #endif // endif
  171. PKTSETLINK(p, NULL);
  172. done:
  173. /* protect shared resource */
  174. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  175. return NULL;
  176. return p;
  177. }
  178. void * BCMFASTPATH
  179. spktq_deq(struct spktq *spq)
  180. {
  181. struct pktq_prec *q;
  182. void *p;
  183. /* protect shared resource */
  184. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  185. return NULL;
  186. q = &spq->q;
  187. if ((p = q->head) == NULL)
  188. goto done;
  189. if ((q->head = PKTLINK(p)) == NULL)
  190. q->tail = NULL;
  191. q->n_pkts--;
  192. #ifdef WL_TXQ_STALL
  193. q->dequeue_count++;
  194. #endif // endif
  195. PKTSETLINK(p, NULL);
  196. done:
  197. /* protect shared resource */
  198. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  199. return NULL;
  200. return p;
  201. }
  202. void * BCMFASTPATH
  203. pktq_pdeq_tail(struct pktq *pq, int prec)
  204. {
  205. struct pktq_prec *q;
  206. void *p, *prev;
  207. /* protect shared resource */
  208. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  209. return NULL;
  210. ASSERT(prec >= 0 && prec < pq->num_prec);
  211. q = &pq->q[prec];
  212. if ((p = q->head) == NULL)
  213. goto done;
  214. for (prev = NULL; p != q->tail; p = PKTLINK(p))
  215. prev = p;
  216. if (prev)
  217. PKTSETLINK(prev, NULL);
  218. else
  219. q->head = NULL;
  220. q->tail = prev;
  221. q->n_pkts--;
  222. pq->n_pkts_tot--;
  223. #ifdef WL_TXQ_STALL
  224. q->dequeue_count++;
  225. #endif // endif
  226. done:
  227. /* protect shared resource */
  228. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  229. return NULL;
  230. return p;
  231. }
  232. void * BCMFASTPATH
  233. spktq_deq_tail(struct spktq *spq)
  234. {
  235. struct pktq_prec *q;
  236. void *p, *prev;
  237. /* protect shared resource */
  238. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  239. return NULL;
  240. q = &spq->q;
  241. if ((p = q->head) == NULL)
  242. goto done;
  243. for (prev = NULL; p != q->tail; p = PKTLINK(p))
  244. prev = p;
  245. if (prev)
  246. PKTSETLINK(prev, NULL);
  247. else
  248. q->head = NULL;
  249. q->tail = prev;
  250. q->n_pkts--;
  251. #ifdef WL_TXQ_STALL
  252. q->dequeue_count++;
  253. #endif // endif
  254. done:
  255. /* protect shared resource */
  256. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  257. return NULL;
  258. return p;
  259. }
  260. void *
  261. pktq_peek_tail(struct pktq *pq, int *prec_out)
  262. {
  263. int prec;
  264. void *p = NULL;
  265. /* protect shared resource */
  266. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  267. return NULL;
  268. if (pq->n_pkts_tot == 0)
  269. goto done;
  270. for (prec = 0; prec < pq->hi_prec; prec++)
  271. if (pq->q[prec].head)
  272. break;
  273. if (prec_out)
  274. *prec_out = prec;
  275. p = pq->q[prec].tail;
  276. done:
  277. /* protect shared resource */
  278. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  279. return NULL;
  280. return p;
  281. }
  282. /*
  283. * Append spktq 'list' to the tail of pktq 'pq'
  284. */
  285. void BCMFASTPATH
  286. pktq_append(struct pktq *pq, int prec, struct spktq *list)
  287. {
  288. struct pktq_prec *q;
  289. struct pktq_prec *list_q;
  290. /* protect shared resource */
  291. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  292. return;
  293. list_q = &list->q;
  294. /* empty list check */
  295. if (list_q->head == NULL)
  296. goto done;
  297. ASSERT(prec >= 0 && prec < pq->num_prec);
  298. ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
  299. ASSERT(!pktq_full(pq));
  300. ASSERT(!pktqprec_full(pq, prec));
  301. q = &pq->q[prec];
  302. if (q->head)
  303. PKTSETLINK(q->tail, list_q->head);
  304. else
  305. q->head = list_q->head;
  306. q->tail = list_q->tail;
  307. q->n_pkts += list_q->n_pkts;
  308. pq->n_pkts_tot += list_q->n_pkts;
  309. if (pq->hi_prec < prec)
  310. pq->hi_prec = (uint8)prec;
  311. #ifdef WL_TXQ_STALL
  312. list_q->dequeue_count += list_q->n_pkts;
  313. #endif // endif
  314. list_q->head = NULL;
  315. list_q->tail = NULL;
  316. list_q->n_pkts = 0;
  317. done:
  318. /* protect shared resource */
  319. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  320. return;
  321. }
  322. /*
  323. * Append spktq 'list' to the tail of spktq 'spq'
  324. */
  325. void BCMFASTPATH
  326. spktq_append(struct spktq *spq, struct spktq *list)
  327. {
  328. struct pktq_prec *q;
  329. struct pktq_prec *list_q;
  330. /* protect shared resource */
  331. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  332. return;
  333. list_q = &list->q;
  334. /* empty list check */
  335. if (list_q->head == NULL)
  336. goto done;
  337. ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
  338. ASSERT(!spktq_full(spq));
  339. q = &spq->q;
  340. if (q->head)
  341. PKTSETLINK(q->tail, list_q->head);
  342. else
  343. q->head = list_q->head;
  344. q->tail = list_q->tail;
  345. q->n_pkts += list_q->n_pkts;
  346. #ifdef WL_TXQ_STALL
  347. list_q->dequeue_count += list_q->n_pkts;
  348. #endif // endif
  349. list_q->head = NULL;
  350. list_q->tail = NULL;
  351. list_q->n_pkts = 0;
  352. done:
  353. /* protect shared resource */
  354. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  355. return;
  356. }
  357. /*
  358. * Prepend spktq 'list' to the head of pktq 'pq'
  359. */
  360. void BCMFASTPATH
  361. pktq_prepend(struct pktq *pq, int prec, struct spktq *list)
  362. {
  363. struct pktq_prec *q;
  364. struct pktq_prec *list_q;
  365. /* protect shared resource */
  366. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  367. return;
  368. list_q = &list->q;
  369. /* empty list check */
  370. if (list_q->head == NULL)
  371. goto done;
  372. ASSERT(prec >= 0 && prec < pq->num_prec);
  373. ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
  374. ASSERT(!pktq_full(pq));
  375. ASSERT(!pktqprec_full(pq, prec));
  376. q = &pq->q[prec];
  377. /* set the tail packet of list to point at the former pq head */
  378. PKTSETLINK(list_q->tail, q->head);
  379. /* the new q head is the head of list */
  380. q->head = list_q->head;
  381. /* If the q tail was non-null, then it stays as is.
  382. * If the q tail was null, it is now the tail of list
  383. */
  384. if (q->tail == NULL) {
  385. q->tail = list_q->tail;
  386. }
  387. q->n_pkts += list_q->n_pkts;
  388. pq->n_pkts_tot += list_q->n_pkts;
  389. if (pq->hi_prec < prec)
  390. pq->hi_prec = (uint8)prec;
  391. #ifdef WL_TXQ_STALL
  392. list_q->dequeue_count += list_q->n_pkts;
  393. #endif // endif
  394. list_q->head = NULL;
  395. list_q->tail = NULL;
  396. list_q->n_pkts = 0;
  397. done:
  398. /* protect shared resource */
  399. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  400. return;
  401. }
  402. /*
  403. * Prepend spktq 'list' to the head of spktq 'spq'
  404. */
  405. void BCMFASTPATH
  406. spktq_prepend(struct spktq *spq, struct spktq *list)
  407. {
  408. struct pktq_prec *q;
  409. struct pktq_prec *list_q;
  410. /* protect shared resource */
  411. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  412. return;
  413. list_q = &list->q;
  414. /* empty list check */
  415. if (list_q->head == NULL)
  416. goto done;
  417. ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
  418. ASSERT(!spktq_full(spq));
  419. q = &spq->q;
  420. /* set the tail packet of list to point at the former pq head */
  421. PKTSETLINK(list_q->tail, q->head);
  422. /* the new q head is the head of list */
  423. q->head = list_q->head;
  424. /* If the q tail was non-null, then it stays as is.
  425. * If the q tail was null, it is now the tail of list
  426. */
  427. if (q->tail == NULL) {
  428. q->tail = list_q->tail;
  429. }
  430. q->n_pkts += list_q->n_pkts;
  431. #ifdef WL_TXQ_STALL
  432. list_q->dequeue_count += list_q->n_pkts;
  433. #endif // endif
  434. list_q->head = NULL;
  435. list_q->tail = NULL;
  436. list_q->n_pkts = 0;
  437. done:
  438. /* protect shared resource */
  439. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  440. return;
  441. }
  442. void * BCMFASTPATH
  443. pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
  444. {
  445. struct pktq_prec *q;
  446. void *p = NULL;
  447. /* protect shared resource */
  448. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  449. return NULL;
  450. ASSERT(prec >= 0 && prec < pq->num_prec);
  451. q = &pq->q[prec];
  452. if (prev_p == NULL)
  453. goto done;
  454. if ((p = PKTLINK(prev_p)) == NULL)
  455. goto done;
  456. q->n_pkts--;
  457. pq->n_pkts_tot--;
  458. #ifdef WL_TXQ_STALL
  459. q->dequeue_count++;
  460. #endif // endif
  461. PKTSETLINK(prev_p, PKTLINK(p));
  462. PKTSETLINK(p, NULL);
  463. done:
  464. /* protect shared resource */
  465. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  466. return NULL;
  467. return p;
  468. }
  469. void * BCMFASTPATH
  470. pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
  471. {
  472. struct pktq_prec *q;
  473. void *p, *prev = NULL;
  474. /* protect shared resource */
  475. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  476. return NULL;
  477. ASSERT(prec >= 0 && prec < pq->num_prec);
  478. q = &pq->q[prec];
  479. p = q->head;
  480. while (p) {
  481. if (fn == NULL || (*fn)(p, arg)) {
  482. break;
  483. } else {
  484. prev = p;
  485. p = PKTLINK(p);
  486. }
  487. }
  488. if (p == NULL)
  489. goto done;
  490. if (prev == NULL) {
  491. if ((q->head = PKTLINK(p)) == NULL) {
  492. q->tail = NULL;
  493. }
  494. } else {
  495. PKTSETLINK(prev, PKTLINK(p));
  496. if (q->tail == p) {
  497. q->tail = prev;
  498. }
  499. }
  500. q->n_pkts--;
  501. pq->n_pkts_tot--;
  502. #ifdef WL_TXQ_STALL
  503. q->dequeue_count++;
  504. #endif // endif
  505. PKTSETLINK(p, NULL);
  506. done:
  507. /* protect shared resource */
  508. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  509. return NULL;
  510. return p;
  511. }
  512. bool BCMFASTPATH
  513. pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
  514. {
  515. bool ret = FALSE;
  516. struct pktq_prec *q;
  517. void *p = NULL;
  518. /* protect shared resource */
  519. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  520. return FALSE;
  521. ASSERT(prec >= 0 && prec < pq->num_prec);
  522. /* Should this just assert pktbuf? */
  523. if (!pktbuf)
  524. goto done;
  525. q = &pq->q[prec];
  526. if (q->head == pktbuf) {
  527. if ((q->head = PKTLINK(pktbuf)) == NULL)
  528. q->tail = NULL;
  529. } else {
  530. for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
  531. ;
  532. if (p == NULL)
  533. goto done;
  534. PKTSETLINK(p, PKTLINK(pktbuf));
  535. if (q->tail == pktbuf)
  536. q->tail = p;
  537. }
  538. q->n_pkts--;
  539. pq->n_pkts_tot--;
  540. #ifdef WL_TXQ_STALL
  541. q->dequeue_count++;
  542. #endif // endif
  543. PKTSETLINK(pktbuf, NULL);
  544. ret = TRUE;
  545. done:
  546. /* protect shared resource */
  547. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  548. return FALSE;
  549. return ret;
  550. }
  551. static void
  552. _pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void* fltr_ctx,
  553. defer_free_pkt_fn_t defer, void *defer_ctx)
  554. {
  555. struct pktq_prec wq;
  556. struct pktq_prec *q;
  557. void *p;
  558. /* protect shared resource */
  559. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  560. return;
  561. /* move the prec queue aside to a work queue */
  562. q = &pq->q[prec];
  563. wq = *q;
  564. q->head = NULL;
  565. q->tail = NULL;
  566. q->n_pkts = 0;
  567. #ifdef WL_TXQ_STALL
  568. q->dequeue_count += wq.n_pkts;
  569. #endif // endif
  570. pq->n_pkts_tot -= wq.n_pkts;
  571. /* protect shared resource */
  572. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  573. return;
  574. /* start with the head of the work queue */
  575. while ((p = wq.head) != NULL) {
  576. /* unlink the current packet from the list */
  577. wq.head = PKTLINK(p);
  578. PKTSETLINK(p, NULL);
  579. wq.n_pkts--;
  580. #ifdef WL_TXQ_STALL
  581. wq.dequeue_count++;
  582. #endif // endif
  583. /* call the filter function on current packet */
  584. ASSERT(fltr != NULL);
  585. switch ((*fltr)(fltr_ctx, p)) {
  586. case PKT_FILTER_NOACTION:
  587. /* put this packet back */
  588. pktq_penq(pq, prec, p);
  589. break;
  590. case PKT_FILTER_DELETE:
  591. /* delete this packet */
  592. ASSERT(defer != NULL);
  593. (*defer)(defer_ctx, p);
  594. break;
  595. case PKT_FILTER_REMOVE:
  596. /* pkt already removed from list */
  597. break;
  598. default:
  599. ASSERT(0);
  600. break;
  601. }
  602. }
  603. ASSERT(wq.n_pkts == 0);
  604. }
  605. void
  606. pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void* fltr_ctx,
  607. defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx)
  608. {
  609. _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx);
  610. ASSERT(flush != NULL);
  611. (*flush)(flush_ctx);
  612. }
  613. void
  614. pktq_filter(struct pktq *pq, pktq_filter_t fltr, void* fltr_ctx,
  615. defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx)
  616. {
  617. bool filter = FALSE;
  618. /* protect shared resource */
  619. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  620. return;
  621. /* Optimize if pktq n_pkts = 0, just return.
  622. * pktq len of 0 means pktq's prec q's are all empty.
  623. */
  624. if (pq->n_pkts_tot > 0) {
  625. filter = TRUE;
  626. }
  627. /* protect shared resource */
  628. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  629. return;
  630. if (filter) {
  631. int prec;
  632. PKTQ_PREC_ITER(pq, prec) {
  633. _pktq_pfilter(pq, prec, fltr, fltr_ctx, defer, defer_ctx);
  634. }
  635. ASSERT(flush != NULL);
  636. (*flush)(flush_ctx);
  637. }
  638. }
  639. void
  640. spktq_filter(struct spktq *spq, pktq_filter_t fltr, void* fltr_ctx,
  641. defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx)
  642. {
  643. struct pktq_prec wq;
  644. struct pktq_prec *q;
  645. void *p = NULL;
  646. /* protect shared resource */
  647. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  648. return;
  649. q = &spq->q;
  650. /* Optimize if pktq_prec n_pkts = 0, just return. */
  651. if (q->n_pkts == 0) {
  652. (void)HND_PKTQ_MUTEX_RELEASE(&spq->mutex);
  653. return;
  654. }
  655. wq = *q;
  656. q->head = NULL;
  657. q->tail = NULL;
  658. q->n_pkts = 0;
  659. #ifdef WL_TXQ_STALL
  660. q->dequeue_count += wq.n_pkts;
  661. #endif // endif
  662. /* protect shared resource */
  663. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  664. return;
  665. /* start with the head of the work queue */
  666. while ((p = wq.head) != NULL) {
  667. /* unlink the current packet from the list */
  668. wq.head = PKTLINK(p);
  669. PKTSETLINK(p, NULL);
  670. wq.n_pkts--;
  671. #ifdef WL_TXQ_STALL
  672. wq.dequeue_count++;
  673. #endif // endif
  674. /* call the filter function on current packet */
  675. ASSERT(fltr != NULL);
  676. switch ((*fltr)(fltr_ctx, p)) {
  677. case PKT_FILTER_NOACTION:
  678. /* put this packet back */
  679. spktq_enq(spq, p);
  680. break;
  681. case PKT_FILTER_DELETE:
  682. /* delete this packet */
  683. ASSERT(defer != NULL);
  684. (*defer)(defer_ctx, p);
  685. break;
  686. case PKT_FILTER_REMOVE:
  687. /* pkt already removed from list */
  688. break;
  689. default:
  690. ASSERT(0);
  691. break;
  692. }
  693. }
  694. ASSERT(wq.n_pkts == 0);
  695. ASSERT(flush != NULL);
  696. (*flush)(flush_ctx);
  697. }
  698. bool
  699. pktq_init(struct pktq *pq, int num_prec, int max_pkts)
  700. {
  701. int prec;
  702. ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
  703. /* pq is variable size; only zero out what's requested */
  704. bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
  705. if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS)
  706. return FALSE;
  707. pq->num_prec = (uint16)num_prec;
  708. pq->max_pkts = (uint16)max_pkts;
  709. for (prec = 0; prec < num_prec; prec++)
  710. pq->q[prec].max_pkts = pq->max_pkts;
  711. return TRUE;
  712. }
  713. bool
  714. spktq_init(struct spktq *spq, int max_pkts)
  715. {
  716. bzero(spq, sizeof(struct spktq));
  717. if (HND_PKTQ_MUTEX_CREATE("spktq", &spq->mutex) != OSL_EXT_SUCCESS)
  718. return FALSE;
  719. spq->q.max_pkts = (uint16)max_pkts;
  720. return TRUE;
  721. }
  722. bool
  723. pktq_deinit(struct pktq *pq)
  724. {
  725. BCM_REFERENCE(pq);
  726. if (HND_PKTQ_MUTEX_DELETE(&pq->mutex) != OSL_EXT_SUCCESS)
  727. return FALSE;
  728. return TRUE;
  729. }
  730. bool
  731. spktq_deinit(struct spktq *spq)
  732. {
  733. BCM_REFERENCE(spq);
  734. if (HND_PKTQ_MUTEX_DELETE(&spq->mutex) != OSL_EXT_SUCCESS)
  735. return FALSE;
  736. return TRUE;
  737. }
  738. void
  739. pktq_set_max_plen(struct pktq *pq, int prec, int max_pkts)
  740. {
  741. ASSERT(prec >= 0 && prec < pq->num_prec);
  742. /* protect shared resource */
  743. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  744. return;
  745. if (prec < pq->num_prec)
  746. pq->q[prec].max_pkts = (uint16)max_pkts;
  747. /* protect shared resource */
  748. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  749. return;
  750. }
  751. void * BCMFASTPATH
  752. pktq_deq(struct pktq *pq, int *prec_out)
  753. {
  754. struct pktq_prec *q;
  755. void *p = NULL;
  756. int prec;
  757. /* protect shared resource */
  758. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  759. return NULL;
  760. if (pq->n_pkts_tot == 0)
  761. goto done;
  762. while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
  763. pq->hi_prec--;
  764. q = &pq->q[prec];
  765. if ((p = q->head) == NULL)
  766. goto done;
  767. if ((q->head = PKTLINK(p)) == NULL)
  768. q->tail = NULL;
  769. q->n_pkts--;
  770. pq->n_pkts_tot--;
  771. #ifdef WL_TXQ_STALL
  772. q->dequeue_count++;
  773. #endif // endif
  774. if (prec_out)
  775. *prec_out = prec;
  776. PKTSETLINK(p, NULL);
  777. done:
  778. /* protect shared resource */
  779. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  780. return NULL;
  781. return p;
  782. }
  783. void * BCMFASTPATH
  784. pktq_deq_tail(struct pktq *pq, int *prec_out)
  785. {
  786. struct pktq_prec *q;
  787. void *p = NULL, *prev;
  788. int prec;
  789. /* protect shared resource */
  790. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  791. return NULL;
  792. if (pq->n_pkts_tot == 0)
  793. goto done;
  794. for (prec = 0; prec < pq->hi_prec; prec++)
  795. if (pq->q[prec].head)
  796. break;
  797. q = &pq->q[prec];
  798. if ((p = q->head) == NULL)
  799. goto done;
  800. for (prev = NULL; p != q->tail; p = PKTLINK(p))
  801. prev = p;
  802. if (prev)
  803. PKTSETLINK(prev, NULL);
  804. else
  805. q->head = NULL;
  806. q->tail = prev;
  807. q->n_pkts--;
  808. pq->n_pkts_tot--;
  809. #ifdef WL_TXQ_STALL
  810. q->dequeue_count++;
  811. #endif // endif
  812. if (prec_out)
  813. *prec_out = prec;
  814. PKTSETLINK(p, NULL);
  815. done:
  816. /* protect shared resource */
  817. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  818. return NULL;
  819. return p;
  820. }
  821. void *
  822. pktq_peek(struct pktq *pq, int *prec_out)
  823. {
  824. int prec;
  825. void *p = NULL;
  826. /* protect shared resource */
  827. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  828. return NULL;
  829. if (pq->n_pkts_tot == 0)
  830. goto done;
  831. while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
  832. pq->hi_prec--;
  833. if (prec_out)
  834. *prec_out = prec;
  835. p = pq->q[prec].head;
  836. done:
  837. /* protect shared resource */
  838. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  839. return NULL;
  840. return p;
  841. }
  842. void *
  843. spktq_peek(struct spktq *spq)
  844. {
  845. void *p = NULL;
  846. /* protect shared resource */
  847. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  848. return NULL;
  849. if (spq->q.n_pkts == 0)
  850. goto done;
  851. p = spq->q.head;
  852. done:
  853. /* protect shared resource */
  854. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  855. return NULL;
  856. return p;
  857. }
  858. void
  859. pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir)
  860. {
  861. void *p;
  862. /* no need for a mutex protection! */
  863. /* start with the head of the list */
  864. while ((p = pktq_pdeq(pq, prec)) != NULL) {
  865. /* delete this packet */
  866. PKTFREE(osh, p, dir);
  867. }
  868. }
  869. void
  870. spktq_flush(osl_t *osh, struct spktq *spq, bool dir)
  871. {
  872. void *p;
  873. /* no need for a mutex protection! */
  874. /* start with the head of the list */
  875. while ((p = spktq_deq(spq)) != NULL) {
  876. /* delete this packet */
  877. PKTFREE(osh, p, dir);
  878. }
  879. }
  880. void
  881. pktq_flush(osl_t *osh, struct pktq *pq, bool dir)
  882. {
  883. bool flush = FALSE;
  884. /* protect shared resource */
  885. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  886. return;
  887. /* Optimize flush, if pktq n_pkts_tot = 0, just return.
  888. * pktq len of 0 means pktq's prec q's are all empty.
  889. */
  890. if (pq->n_pkts_tot > 0) {
  891. flush = TRUE;
  892. }
  893. /* protect shared resource */
  894. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  895. return;
  896. if (flush) {
  897. int prec;
  898. PKTQ_PREC_ITER(pq, prec) {
  899. pktq_pflush(osh, pq, prec, dir);
  900. }
  901. }
  902. }
  903. /* Return sum of lengths of a specific set of precedences */
  904. int
  905. pktq_mlen(struct pktq *pq, uint prec_bmp)
  906. {
  907. int prec, len;
  908. /* protect shared resource */
  909. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  910. return 0;
  911. len = 0;
  912. for (prec = 0; prec <= pq->hi_prec; prec++)
  913. if (prec_bmp & (1 << prec))
  914. len += pq->q[prec].n_pkts;
  915. /* protect shared resource */
  916. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  917. return 0;
  918. return len;
  919. }
  920. /* Priority peek from a specific set of precedences */
  921. void * BCMFASTPATH
  922. pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
  923. {
  924. struct pktq_prec *q;
  925. void *p = NULL;
  926. int prec;
  927. /* protect shared resource */
  928. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  929. return NULL;
  930. if (pq->n_pkts_tot == 0)
  931. goto done;
  932. while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
  933. pq->hi_prec--;
  934. while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
  935. if (prec-- == 0)
  936. goto done;
  937. q = &pq->q[prec];
  938. if ((p = q->head) == NULL)
  939. goto done;
  940. if (prec_out)
  941. *prec_out = prec;
  942. done:
  943. /* protect shared resource */
  944. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  945. return NULL;
  946. return p;
  947. }
  948. /* Priority dequeue from a specific set of precedences */
  949. void * BCMFASTPATH
  950. pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
  951. {
  952. struct pktq_prec *q;
  953. void *p = NULL;
  954. int prec;
  955. /* protect shared resource */
  956. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  957. return NULL;
  958. if (pq->n_pkts_tot == 0)
  959. goto done;
  960. while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
  961. pq->hi_prec--;
  962. while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
  963. if (prec-- == 0)
  964. goto done;
  965. q = &pq->q[prec];
  966. if ((p = q->head) == NULL)
  967. goto done;
  968. if ((q->head = PKTLINK(p)) == NULL)
  969. q->tail = NULL;
  970. q->n_pkts--;
  971. #ifdef WL_TXQ_STALL
  972. q->dequeue_count++;
  973. #endif // endif
  974. if (prec_out)
  975. *prec_out = prec;
  976. pq->n_pkts_tot--;
  977. PKTSETLINK(p, NULL);
  978. done:
  979. /* protect shared resource */
  980. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  981. return NULL;
  982. return p;
  983. }
  984. #ifdef HND_PKTQ_THREAD_SAFE
  985. int
  986. pktqprec_avail_pkts(struct pktq *pq, int prec)
  987. {
  988. int ret;
  989. /* protect shared resource */
  990. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  991. return 0;
  992. ASSERT(prec >= 0 && prec < pq->num_prec);
  993. ret = pq->q[prec].max_pkts - pq->q[prec].n_pkts;
  994. /* protect shared resource */
  995. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  996. return 0;
  997. return ret;
  998. }
  999. bool
  1000. pktqprec_full(struct pktq *pq, int prec)
  1001. {
  1002. bool ret;
  1003. /* protect shared resource */
  1004. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  1005. return FALSE;
  1006. ASSERT(prec >= 0 && prec < pq->num_prec);
  1007. ret = pq->q[prec].n_pkts >= pq->q[prec].max_pkts;
  1008. /* protect shared resource */
  1009. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  1010. return FALSE;
  1011. return ret;
  1012. }
  1013. int
  1014. pktq_avail(struct pktq *pq)
  1015. {
  1016. int ret;
  1017. /* protect shared resource */
  1018. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  1019. return 0;
  1020. ret = pq->max_pkts - pq->n_pkts_tot;
  1021. /* protect shared resource */
  1022. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  1023. return 0;
  1024. return ret;
  1025. }
  1026. int
  1027. spktq_avail(struct spktq *spq)
  1028. {
  1029. int ret;
  1030. /* protect shared resource */
  1031. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  1032. return 0;
  1033. ret = spq->q.max_pkts - spq->q.n_pkts;
  1034. /* protect shared resource */
  1035. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  1036. return 0;
  1037. return ret;
  1038. }
  1039. bool
  1040. pktq_full(struct pktq *pq)
  1041. {
  1042. bool ret;
  1043. /* protect shared resource */
  1044. if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  1045. return FALSE;
  1046. ret = pq->n_pkts_tot >= pq->max_pkts;
  1047. /* protect shared resource */
  1048. if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS)
  1049. return FALSE;
  1050. return ret;
  1051. }
  1052. bool
  1053. spktq_full(struct spktq *spq)
  1054. {
  1055. bool ret;
  1056. /* protect shared resource */
  1057. if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS)
  1058. return FALSE;
  1059. ret = spq->q.n_pkts >= spq->q.max_pkts;
  1060. /* protect shared resource */
  1061. if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS)
  1062. return FALSE;
  1063. return ret;
  1064. }
  1065. #endif /* HND_PKTQ_THREAD_SAFE */