| /* |
| * HND generic pktq operation primitives |
| * |
| * Copyright 1999-2016, Broadcom Corporation |
| * All rights reserved, |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * This software is provided by the copyright holder "as is" and any express or |
| * implied warranties, including, but not limited to, the implied warranties of |
| * merchantability and fitness for a particular purpose are disclaimed. In no event |
| * shall copyright holder be liable for any direct, indirect, incidental, special, |
| * exemplary, or consequential damages (including, but not limited to, procurement |
| * of substitute goods or services; loss of use, data, or profits; or business |
| * interruption) however caused and on any theory of liability, whether in |
| * contract, strict liability, or tort (including negligence or otherwise) arising |
| * in any way out of the use of this software, even if advised of the possibility |
| * of such damage |
| * |
| * |
| * <<Broadcom-WL-IPTag/Open:>> |
| * |
| * $Id: hnd_pktq.h 591283 2015-10-07 11:52:00Z $ |
| */ |
| |
| #ifndef _hnd_pktq_h_ |
| #define _hnd_pktq_h_ |
| |
| #include <osl_ext.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* mutex macros for thread safe */ |
| #ifdef HND_PKTQ_THREAD_SAFE |
| #define HND_PKTQ_MUTEX_DECL(mutex) OSL_EXT_MUTEX_DECL(mutex) |
| #else |
| #define HND_PKTQ_MUTEX_DECL(mutex) |
| #endif |
| |
| /* osl multi-precedence packet queue */ |
| #define PKTQ_LEN_MAX 0xFFFF /* Max uint16 65535 packets */ |
| #ifndef PKTQ_LEN_DEFAULT |
| #define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ |
| #endif |
| #ifndef PKTQ_MAX_PREC |
| #define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ |
| #endif |
| |
| typedef struct pktq_prec { |
| void *head; /**< first packet to dequeue */ |
| void *tail; /**< last packet to dequeue */ |
| uint16 len; /**< number of queued packets */ |
| uint16 max; /**< maximum number of queued packets */ |
| } pktq_prec_t; |
| |
| #ifdef PKTQ_LOG |
| typedef struct { |
| uint32 requested; /**< packets requested to be stored */ |
| uint32 stored; /**< packets stored */ |
| uint32 saved; /**< packets saved, |
| because a lowest priority queue has given away one packet |
| */ |
| uint32 selfsaved; /**< packets saved, |
| because an older packet from the same queue has been dropped |
| */ |
| uint32 full_dropped; /**< packets dropped, |
| because pktq is full with higher precedence packets |
| */ |
| uint32 dropped; /**< packets dropped because pktq per that precedence is full */ |
| uint32 sacrificed; /**< packets dropped, |
| in order to save one from a queue of a highest priority |
| */ |
| uint32 busy; /**< packets droped because of hardware/transmission error */ |
| uint32 retry; /**< packets re-sent because they were not received */ |
| uint32 ps_retry; /**< packets retried again prior to moving power save mode */ |
| uint32 suppress; /**< packets which were suppressed and not transmitted */ |
| uint32 retry_drop; /**< packets finally dropped after retry limit */ |
| uint32 max_avail; /**< the high-water mark of the queue capacity for packets - |
| goes to zero as queue fills |
| */ |
| uint32 max_used; /**< the high-water mark of the queue utilisation for packets - |
| increases with use ('inverse' of max_avail) |
| */ |
| uint32 queue_capacity; /**< the maximum capacity of the queue */ |
| uint32 rtsfail; /**< count of rts attempts that failed to receive cts */ |
| uint32 acked; /**< count of packets sent (acked) successfully */ |
| uint32 txrate_succ; /**< running total of phy rate of packets sent successfully */ |
| uint32 txrate_main; /**< running totoal of primary phy rate of all packets */ |
| uint32 throughput; /**< actual data transferred successfully */ |
| uint32 airtime; /**< cumulative total medium access delay in useconds */ |
| uint32 _logtime; /**< timestamp of last counter clear */ |
| } pktq_counters_t; |
| |
| typedef struct { |
| uint32 _prec_log; |
| pktq_counters_t* _prec_cnt[PKTQ_MAX_PREC]; /**< Counters per queue */ |
| } pktq_log_t; |
| #endif /* PKTQ_LOG */ |
| |
| |
| #define PKTQ_COMMON \ |
| uint16 num_prec; /**< number of precedences in use */ \ |
| uint16 hi_prec; /**< rapid dequeue hint (>= highest non-empty prec) */ \ |
| uint16 max; /**< total max packets */ \ |
| uint16 len; /**< total number of packets */ |
| |
| /* multi-priority pkt queue */ |
| struct pktq { |
| PKTQ_COMMON |
| /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ |
| struct pktq_prec q[PKTQ_MAX_PREC]; |
| HND_PKTQ_MUTEX_DECL(mutex) |
| #ifdef PKTQ_LOG |
| pktq_log_t* pktqlog; |
| #endif |
| }; |
| |
| /* simple, non-priority pkt queue */ |
| struct spktq { |
| PKTQ_COMMON |
| /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ |
| struct pktq_prec q[1]; |
| HND_PKTQ_MUTEX_DECL(mutex) |
| }; |
| |
| #define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) |
| |
| /* fn(pkt, arg). return true if pkt belongs to if */ |
| typedef bool (*ifpkt_cb_t)(void*, int); |
| |
| /* operations on a specific precedence in packet queue */ |
| |
| #define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) |
| #define pktq_pmax(pq, prec) ((pq)->q[prec].max) |
| #define pktq_plen(pq, prec) ((pq)->q[prec].len) |
| #define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) |
| #define pktq_ppeek(pq, prec) ((pq)->q[prec].head) |
| #define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) |
| #ifdef HND_PKTQ_THREAD_SAFE |
| extern int pktq_pavail(struct pktq *pq, int prec); |
| extern bool pktq_pfull(struct pktq *pq, int prec); |
| #else |
| #define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) |
| #define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) |
| #endif /* HND_PKTQ_THREAD_SAFE */ |
| |
| extern void pktq_append(struct pktq *pq, int prec, struct spktq *list); |
| extern void pktq_prepend(struct pktq *pq, int prec, struct spktq *list); |
| |
| extern void *pktq_penq(struct pktq *pq, int prec, void *p); |
| extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); |
| extern void *pktq_pdeq(struct pktq *pq, int prec); |
| extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); |
| extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg); |
| extern void *pktq_pdeq_tail(struct pktq *pq, int prec); |
| /* Empty the queue at particular precedence level */ |
| extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, |
| ifpkt_cb_t fn, int arg); |
| /* Remove a specified packet from its queue */ |
| extern bool pktq_pdel(struct pktq *pq, void *p, int prec); |
| |
| /* operations on a set of precedences in packet queue */ |
| |
| extern int pktq_mlen(struct pktq *pq, uint prec_bmp); |
| extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); |
| extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); |
| |
| /* operations on packet queue as a whole */ |
| |
| #define pktq_len(pq) ((int)(pq)->len) |
| #define pktq_max(pq) ((int)(pq)->max) |
| #define pktq_empty(pq) ((pq)->len == 0) |
| #ifdef HND_PKTQ_THREAD_SAFE |
| extern int pktq_avail(struct pktq *pq); |
| extern bool pktq_full(struct pktq *pq); |
| #else |
| #define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) |
| #define pktq_full(pq) ((pq)->len >= (pq)->max) |
| #endif /* HND_PKTQ_THREAD_SAFE */ |
| |
| /* operations for single precedence queues */ |
| #define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) |
| #define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) |
| #define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) |
| #define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) |
| #define pktqflush(osh, pq) pktq_flush(osh, ((struct pktq *)(void *)pq), TRUE, NULL, 0) |
| #define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) |
| #define pktqdeinit(pq) pktq_deinit((struct pktq *)(void *)pq) |
| #define pktqavail(pq) pktq_avail((struct pktq *)(void *)pq) |
| #define pktqfull(pq) pktq_full((struct pktq *)(void *)pq) |
| |
| extern bool pktq_init(struct pktq *pq, int num_prec, int max_len); |
| extern bool pktq_deinit(struct pktq *pq); |
| |
| extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); |
| |
| /* prec_out may be NULL if caller is not interested in return value */ |
| extern void *pktq_deq(struct pktq *pq, int *prec_out); |
| extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); |
| extern void *pktq_peek(struct pktq *pq, int *prec_out); |
| extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); |
| extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _hnd_pktq_h_ */ |