2 * HND generic pktq operation primitives
4 * $Copyright Open Broadcom Corporation$
15 * osl multiple-precedence packet queue
16 * hi_prec is always >= the number of the highest non-empty precedence
19 pktq_penq(struct pktq *pq, int prec, void *p)
23 ASSERT(prec >= 0 && prec < pq->num_prec);
24 ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
26 ASSERT(!pktq_full(pq));
27 ASSERT(!pktq_pfull(pq, prec));
32 PKTSETLINK(q->tail, p);
41 if (pq->hi_prec < prec)
42 pq->hi_prec = (uint8)prec;
48 pktq_penq_head(struct pktq *pq, int prec, void *p)
52 ASSERT(prec >= 0 && prec < pq->num_prec);
53 ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
55 ASSERT(!pktq_full(pq));
56 ASSERT(!pktq_pfull(pq, prec));
63 PKTSETLINK(p, q->head);
69 if (pq->hi_prec < prec)
70 pq->hi_prec = (uint8)prec;
76 * Append spktq 'list' to the tail of pktq 'pq'
79 pktq_append(struct pktq *pq, int prec, struct spktq *list)
82 struct pktq_prec *list_q;
86 /* empty list check */
87 if (list_q->head == NULL)
90 ASSERT(prec >= 0 && prec < pq->num_prec);
91 ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
93 ASSERT(!pktq_full(pq));
94 ASSERT(!pktq_pfull(pq, prec));
99 PKTSETLINK(q->tail, list_q->head);
101 q->head = list_q->head;
103 q->tail = list_q->tail;
104 q->len += list_q->len;
105 pq->len += list_q->len;
107 if (pq->hi_prec < prec)
108 pq->hi_prec = (uint8)prec;
117 * Prepend spktq 'list' to the head of pktq 'pq'
120 pktq_prepend(struct pktq *pq, int prec, struct spktq *list)
123 struct pktq_prec *list_q;
125 list_q = &list->q[0];
127 /* empty list check */
128 if (list_q->head == NULL)
131 ASSERT(prec >= 0 && prec < pq->num_prec);
132 ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
134 ASSERT(!pktq_full(pq));
135 ASSERT(!pktq_pfull(pq, prec));
139 /* set the tail packet of list to point at the former pq head */
140 PKTSETLINK(list_q->tail, q->head);
141 /* the new q head is the head of list */
142 q->head = list_q->head;
144 /* If the q tail was non-null, then it stays as is.
145 * If the q tail was null, it is now the tail of list
147 if (q->tail == NULL) {
148 q->tail = list_q->tail;
151 q->len += list_q->len;
152 pq->len += list_q->len;
154 if (pq->hi_prec < prec)
155 pq->hi_prec = (uint8)prec;
164 pktq_pdeq(struct pktq *pq, int prec)
169 ASSERT(prec >= 0 && prec < pq->num_prec);
173 if ((p = q->head) == NULL)
176 if ((q->head = PKTLINK(p)) == NULL)
189 pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
194 ASSERT(prec >= 0 && prec < pq->num_prec);
201 if ((p = PKTLINK(prev_p)) == NULL)
208 PKTSETLINK(prev_p, PKTLINK(p));
215 pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
218 void *p, *prev = NULL;
220 ASSERT(prec >= 0 && prec < pq->num_prec);
226 if (fn == NULL || (*fn)(p, arg)) {
237 if ((q->head = PKTLINK(p)) == NULL) {
241 PKTSETLINK(prev, PKTLINK(p));
257 pktq_pdeq_tail(struct pktq *pq, int prec)
262 ASSERT(prec >= 0 && prec < pq->num_prec);
266 if ((p = q->head) == NULL)
269 for (prev = NULL; p != q->tail; p = PKTLINK(p))
273 PKTSETLINK(prev, NULL);
286 pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg)
289 void *p, *prev = NULL;
294 if (fn == NULL || (*fn)(p, arg)) {
295 bool head = (p == q->head);
297 q->head = PKTLINK(p);
299 PKTSETLINK(prev, PKTLINK(p));
301 PKTFREE(osh, p, dir);
304 p = (head ? q->head : PKTLINK(prev));
311 if (q->head == NULL) {
318 pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
323 ASSERT(prec >= 0 && prec < pq->num_prec);
325 /* Should this just assert pktbuf? */
331 if (q->head == pktbuf) {
332 if ((q->head = PKTLINK(pktbuf)) == NULL)
335 for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
340 PKTSETLINK(p, PKTLINK(pktbuf));
341 if (q->tail == pktbuf)
347 PKTSETLINK(pktbuf, NULL);
352 pktq_init(struct pktq *pq, int num_prec, int max_len)
356 ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
358 /* pq is variable size; only zero out what's requested */
359 bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
361 pq->num_prec = (uint16)num_prec;
363 pq->max = (uint16)max_len;
365 for (prec = 0; prec < num_prec; prec++)
366 pq->q[prec].max = pq->max;
370 pktq_set_max_plen(struct pktq *pq, int prec, int max_len)
372 ASSERT(prec >= 0 && prec < pq->num_prec);
374 if (prec < pq->num_prec)
375 pq->q[prec].max = (uint16)max_len;
379 pktq_deq(struct pktq *pq, int *prec_out)
388 while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
393 if ((p = q->head) == NULL)
396 if ((q->head = PKTLINK(p)) == NULL)
412 pktq_deq_tail(struct pktq *pq, int *prec_out)
421 for (prec = 0; prec < pq->hi_prec; prec++)
422 if (pq->q[prec].head)
427 if ((p = q->head) == NULL)
430 for (prev = NULL; p != q->tail; p = PKTLINK(p))
434 PKTSETLINK(prev, NULL);
452 pktq_peek(struct pktq *pq, int *prec_out)
459 while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
465 return (pq->q[prec].head);
469 pktq_peek_tail(struct pktq *pq, int *prec_out)
476 for (prec = 0; prec < pq->hi_prec; prec++)
477 if (pq->q[prec].head)
483 return (pq->q[prec].tail);
487 pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg)
491 /* Optimize flush, if pktq len = 0, just return.
492 * pktq len of 0 means pktq's prec q's are all empty.
498 for (prec = 0; prec < pq->num_prec; prec++)
499 pktq_pflush(osh, pq, prec, dir, fn, arg);
501 ASSERT(pq->len == 0);
504 /* Return sum of lengths of a specific set of precedences */
506 pktq_mlen(struct pktq *pq, uint prec_bmp)
512 for (prec = 0; prec <= pq->hi_prec; prec++)
513 if (prec_bmp & (1 << prec))
514 len += pq->q[prec].len;
519 /* Priority peek from a specific set of precedences */
521 pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
531 while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
534 while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
540 if ((p = q->head) == NULL)
548 /* Priority dequeue from a specific set of precedences */
550 pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
559 while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
562 while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
568 if ((p = q->head) == NULL)
571 if ((q->head = PKTLINK(p)) == NULL)