dhd_flowring.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * @file Header file describing the flow rings DHD interfaces.
  3. *
  4. * Flow rings are transmit traffic (=propagating towards antenna) related entities.
  5. *
  6. * Provides type definitions and function prototypes used to create, delete and manage flow rings at
  7. * high level.
  8. *
  9. * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
  10. *
  11. * Copyright (C) 1999-2020, Broadcom Corporation
  12. *
  13. * Unless you and Broadcom execute a separate written software license
  14. * agreement governing use of this software, this software is licensed to you
  15. * under the terms of the GNU General Public License version 2 (the "GPL"),
  16. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  17. * following added to such license:
  18. *
  19. * As a special exception, the copyright holders of this software give you
  20. * permission to link this software with independent modules, and to copy and
  21. * distribute the resulting executable under terms of your choice, provided that
  22. * you also meet, for each linked independent module, the terms and conditions of
  23. * the license of that module. An independent module is a module which is not
  24. * derived from this software. The special exception does not apply to any
  25. * modifications of the software.
  26. *
  27. * Notwithstanding the above, under no circumstances may you combine this
  28. * software in any way with any other Broadcom software provided under a license
  29. * other than the GPL, without Broadcom's express prior written consent.
  30. *
  31. *
  32. * <<Broadcom-WL-IPTag/Open:>>
  33. *
  34. * $Id: dhd_flowring.h 697690 2017-05-04 14:16:18Z $
  35. */
  36. /****************
  37. * Common types *
  38. */
  39. #ifndef _dhd_flowrings_h_
  40. #define _dhd_flowrings_h_
  41. /* Max pkts held in a flow ring's backup queue */
  42. #define FLOW_RING_QUEUE_THRESHOLD (2048)
  43. /* Number of H2D common rings */
  44. #define FLOW_RING_COMMON BCMPCIE_H2D_COMMON_MSGRINGS
  45. #define FLOWID_INVALID (ID16_INVALID)
  46. #define FLOWID_RESERVED (FLOW_RING_COMMON)
  47. #define FLOW_RING_STATUS_OPEN 0
  48. #define FLOW_RING_STATUS_CREATE_PENDING 1
  49. #define FLOW_RING_STATUS_CLOSED 2
  50. #define FLOW_RING_STATUS_DELETE_PENDING 3
  51. #define FLOW_RING_STATUS_FLUSH_PENDING 4
  52. #ifdef IDLE_TX_FLOW_MGMT
  53. #define FLOW_RING_STATUS_SUSPENDED 5
  54. #define FLOW_RING_STATUS_RESUME_PENDING 6
  55. #endif /* IDLE_TX_FLOW_MGMT */
  56. #define FLOW_RING_STATUS_STA_FREEING 7
  57. #define DHD_FLOWRING_RX_BUFPOST_PKTSZ 2048
  58. #define DHD_FLOWRING_RX_BUFPOST_PKTSZ_MAX 4096
  59. #define DHD_FLOW_PRIO_AC_MAP 0
  60. #define DHD_FLOW_PRIO_TID_MAP 1
  61. /* Flow ring prority map for lossless roaming */
  62. #define DHD_FLOW_PRIO_LLR_MAP 2
  63. /* Hashing a MacAddress for lkup into a per interface flow hash table */
  64. #define DHD_FLOWRING_HASH_SIZE 256
  65. #define DHD_FLOWRING_HASHINDEX(ea, prio) \
  66. ((((uint8 *)(ea))[3] ^ ((uint8 *)(ea))[4] ^ ((uint8 *)(ea))[5] ^ ((uint8)(prio))) \
  67. % DHD_FLOWRING_HASH_SIZE)
  68. #define DHD_IF_ROLE(pub, idx) (((if_flow_lkup_t *)(pub)->if_flow_lkup)[idx].role)
  69. #define DHD_IF_ROLE_AP(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_AP)
  70. #define DHD_IF_ROLE_STA(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_STA)
  71. #define DHD_IF_ROLE_P2PGC(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_CLIENT)
  72. #define DHD_IF_ROLE_P2PGO(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_GO)
  73. #define DHD_IF_ROLE_WDS(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_WDS)
  74. #define DHD_IF_ROLE_IBSS(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_IBSS)
  75. #ifdef WL_NAN
  76. #define DHD_IF_ROLE_NAN(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_NAN)
  77. #else
  78. #define DHD_IF_ROLE_NAN(pub, idx) (FALSE)
  79. #endif /* WL_NAN */
  80. #define DHD_IF_ROLE_AWDL(pub, idx) (FALSE)
  81. #define DHD_IF_ROLE_GENERIC_STA(pub, idx) \
  82. (DHD_IF_ROLE_STA(pub, idx) || DHD_IF_ROLE_P2PGC(pub, idx) || DHD_IF_ROLE_WDS(pub, idx))
  83. #define DHD_IF_ROLE_MULTI_CLIENT(pub, idx) \
  84. (DHD_IF_ROLE_AP(pub, idx) || DHD_IF_ROLE_P2PGO(pub, idx) || DHD_IF_ROLE_AWDL(pub, idx) ||\
  85. DHD_IF_ROLE_NAN(pub, idx))
  86. #define DHD_FLOW_RING(dhdp, flowid) \
  87. (flow_ring_node_t *)&(((flow_ring_node_t *)((dhdp)->flow_ring_table))[flowid])
  88. struct flow_queue;
  89. /* Flow Ring Queue Enqueue overflow callback */
  90. typedef int (*flow_queue_cb_t)(struct flow_queue * queue, void * pkt);
  91. /**
  92. * Each flow ring has an associated (tx flow controlled) queue. 802.3 packets are transferred
  93. * between queue and ring. A packet from the host stack is first added to the queue, and in a later
  94. * stage transferred to the flow ring. Packets in the queue are dhd owned, whereas packets in the
  95. * flow ring are device owned.
  96. */
  97. typedef struct flow_queue {
  98. dll_t list; /* manage a flowring queue in a double linked list */
  99. void * head; /* first packet in the queue */
  100. void * tail; /* last packet in the queue */
  101. uint16 len; /* number of packets in the queue */
  102. uint16 max; /* maximum or min budget (used in cumm) */
  103. uint32 threshold; /* parent's cummulative length threshold */
  104. void * clen_ptr; /* parent's cummulative length counter */
  105. uint32 failures; /* enqueue failures due to queue overflow */
  106. flow_queue_cb_t cb; /* callback invoked on threshold crossing */
  107. uint32 l2threshold; /* grandparent's (level 2) cummulative length threshold */
  108. void * l2clen_ptr; /* grandparent's (level 2) cummulative length counter */
  109. } flow_queue_t;
  110. #define DHD_FLOW_QUEUE_LEN(queue) ((int)(queue)->len)
  111. #define DHD_FLOW_QUEUE_MAX(queue) ((int)(queue)->max)
  112. #define DHD_FLOW_QUEUE_THRESHOLD(queue) ((int)(queue)->threshold)
  113. #define DHD_FLOW_QUEUE_L2THRESHOLD(queue) ((int)(queue)->l2threshold)
  114. #define DHD_FLOW_QUEUE_EMPTY(queue) ((queue)->len == 0)
  115. #define DHD_FLOW_QUEUE_FAILURES(queue) ((queue)->failures)
  116. #define DHD_FLOW_QUEUE_AVAIL(queue) ((int)((queue)->max - (queue)->len))
  117. #define DHD_FLOW_QUEUE_FULL(queue) ((queue)->len >= (queue)->max)
  118. #define DHD_FLOW_QUEUE_OVFL(queue, budget) \
  119. (((queue)->len) > budget)
  120. #define DHD_FLOW_QUEUE_SET_MAX(queue, budget) \
  121. ((queue)->max) = ((budget) - 1)
  122. /* Queue's cummulative threshold. */
  123. #define DHD_FLOW_QUEUE_SET_THRESHOLD(queue, cumm_threshold) \
  124. ((queue)->threshold) = ((cumm_threshold) - 1)
  125. /* Queue's cummulative length object accessor. */
  126. #define DHD_FLOW_QUEUE_CLEN_PTR(queue) ((queue)->clen_ptr)
  127. /* Set a queue's cumm_len point to a parent's cumm_ctr_t cummulative length */
  128. #define DHD_FLOW_QUEUE_SET_CLEN(queue, parent_clen_ptr) \
  129. ((queue)->clen_ptr) = (void *)(parent_clen_ptr)
  130. /* Queue's level 2 cummulative threshold. */
  131. #define DHD_FLOW_QUEUE_SET_L2THRESHOLD(queue, l2cumm_threshold) \
  132. ((queue)->l2threshold) = ((l2cumm_threshold) - 1)
  133. /* Queue's level 2 cummulative length object accessor. */
  134. #define DHD_FLOW_QUEUE_L2CLEN_PTR(queue) ((queue)->l2clen_ptr)
  135. /* Set a queue's level 2 cumm_len point to a grandparent's cumm_ctr_t cummulative length */
  136. #define DHD_FLOW_QUEUE_SET_L2CLEN(queue, grandparent_clen_ptr) \
  137. ((queue)->l2clen_ptr) = (void *)(grandparent_clen_ptr)
  138. #define DHD_FLOWRING_TXSTATUS_CNT_UPDATE(bus, flowid, txstatus)
  139. /* Pkttag not compatible with PROP_TXSTATUS or WLFC */
  140. typedef struct dhd_pkttag_fr {
  141. uint16 flowid;
  142. uint16 ifid;
  143. #ifdef DHD_LB_TXC
  144. int dataoff;
  145. dmaaddr_t physaddr;
  146. uint32 pa_len;
  147. #endif /* DHD_LB_TXC */
  148. } dhd_pkttag_fr_t;
  149. #define DHD_PKTTAG_SET_IFID(tag, idx) ((tag)->ifid = (uint16)(idx))
  150. #define DHD_PKTTAG_SET_PA(tag, pa) ((tag)->physaddr = (pa))
  151. #define DHD_PKTTAG_SET_PA_LEN(tag, palen) ((tag)->pa_len = (palen))
  152. #define DHD_PKTTAG_IFID(tag) ((tag)->ifid)
  153. #define DHD_PKTTAG_PA(tag) ((tag)->physaddr)
  154. #define DHD_PKTTAG_PA_LEN(tag) ((tag)->pa_len)
  155. /** each flow ring is dedicated to a tid/sa/da combination */
  156. typedef struct flow_info {
  157. uint8 tid;
  158. uint8 ifindex;
  159. uchar sa[ETHER_ADDR_LEN];
  160. uchar da[ETHER_ADDR_LEN];
  161. #ifdef TX_STATUS_LATENCY_STATS
  162. /* total number of tx_status received on this flowid */
  163. uint64 num_tx_status;
  164. /* cumulative tx_status latency for this flowid */
  165. uint64 cum_tx_status_latency;
  166. /* num tx packets sent on this flowring */
  167. uint64 num_tx_pkts;
  168. #endif /* TX_STATUS_LATENCY_STATS */
  169. } flow_info_t;
  170. /** a flow ring is used for outbound (towards antenna) 802.3 packets */
  171. typedef struct flow_ring_node {
  172. dll_t list; /* manage a constructed flowring in a dll, must be at first place */
  173. flow_queue_t queue; /* queues packets before they enter the flow ring, flow control */
  174. bool active;
  175. uint8 status;
  176. /*
  177. * flowid: unique ID of a flow ring, which can either be unicast or broadcast/multicast. For
  178. * unicast flow rings, the flow id accelerates ARM 802.3->802.11 header translation.
  179. */
  180. uint16 flowid;
  181. flow_info_t flow_info;
  182. void *prot_info;
  183. void *lock; /* lock for flowring access protection */
  184. #ifdef IDLE_TX_FLOW_MGMT
  185. uint64 last_active_ts; /* contains last active timestamp */
  186. #endif /* IDLE_TX_FLOW_MGMT */
  187. #ifdef DHD_HP2P
  188. bool hp2p_ring;
  189. #endif /* DHD_HP2P */
  190. } flow_ring_node_t;
  191. typedef flow_ring_node_t flow_ring_table_t;
  192. typedef struct flow_hash_info {
  193. uint16 flowid;
  194. flow_info_t flow_info;
  195. struct flow_hash_info *next;
  196. } flow_hash_info_t;
  197. typedef struct if_flow_lkup {
  198. bool status;
  199. uint8 role; /* Interface role: STA/AP */
  200. flow_hash_info_t *fl_hash[DHD_FLOWRING_HASH_SIZE]; /* Lkup Hash table */
  201. } if_flow_lkup_t;
  202. static INLINE flow_ring_node_t *
  203. dhd_constlist_to_flowring(dll_t *item)
  204. {
  205. return ((flow_ring_node_t *)item);
  206. }
  207. /* Exported API */
  208. /* Flow ring's queue management functions */
  209. extern flow_ring_node_t * dhd_flow_ring_node(dhd_pub_t *dhdp, uint16 flowid);
  210. extern flow_queue_t * dhd_flow_queue(dhd_pub_t *dhdp, uint16 flowid);
  211. extern void dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max);
  212. extern void dhd_flow_queue_reinit(dhd_pub_t *dhdp, flow_queue_t *queue, int max);
  213. extern void dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb);
  214. extern int dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
  215. extern void * dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue);
  216. extern void dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
  217. extern void dhd_flow_ring_config_thresholds(dhd_pub_t *dhdp, uint16 flowid,
  218. int queue_budget, int cumm_threshold, void *cumm_ctr,
  219. int l2cumm_threshold, void *l2cumm_ctr);
  220. extern int dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings);
  221. extern void dhd_flow_rings_deinit(dhd_pub_t *dhdp);
  222. extern int dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio,
  223. void *pktbuf);
  224. extern int dhd_flowid_debug_create(dhd_pub_t *dhdp, uint8 ifindex,
  225. uint8 prio, char *sa, char *da, uint16 *flowid);
  226. extern int dhd_flowid_find_by_ifidx(dhd_pub_t *dhdp, uint8 ifidex, uint16 flowid);
  227. extern void dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid);
  228. extern void dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex);
  229. extern void dhd_flow_rings_flush(dhd_pub_t *dhdp, uint8 ifindex);
  230. extern void dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex,
  231. char *addr);
  232. /* Handle Interface ADD, DEL operations */
  233. extern void dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex,
  234. uint8 op, uint8 role);
  235. /* Handle a STA interface link status update */
  236. extern int dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex,
  237. uint8 status);
  238. extern int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set);
  239. extern int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map);
  240. extern uint8 dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex);
  241. #endif /* _dhd_flowrings_h_ */