1 /* 2 * Copyright (c) 2013-2014, 2016-2017, 2019-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #ifndef HTC_PACKET_H_ 21 #define HTC_PACKET_H_ 22 23 #include <osdep.h> 24 #include "dl_list.h" 25 26 /* ------ Endpoint IDS ------ */ 27 typedef enum { 28 ENDPOINT_UNUSED = -1, 29 ENDPOINT_0 = 0, 30 ENDPOINT_1 = 1, 31 ENDPOINT_2 = 2, 32 ENDPOINT_3, 33 ENDPOINT_4, 34 ENDPOINT_5, 35 ENDPOINT_6, 36 ENDPOINT_7, 37 ENDPOINT_8, 38 ENDPOINT_MAX, 39 } HTC_ENDPOINT_ID; 40 41 struct _HTC_PACKET; 42 43 typedef void (*HTC_PACKET_COMPLETION)(void *, struct _HTC_PACKET *); 44 45 typedef uint16_t HTC_TX_TAG; 46 47 /** 48 * struct htc_tx_packet_info - HTC TX packet information 49 * @Tag: tag used to selective flush packets 50 * @CreditsUsed: number of credits used for this TX packet (HTC internal) 51 * @SendFlags: send flags (HTC internal) 52 * @SeqNo: internal seq no for debugging (HTC internal) 53 * @Flags: Internal use 54 */ 55 struct htc_tx_packet_info { 56 HTC_TX_TAG Tag; 57 int CreditsUsed; 58 uint8_t SendFlags; 59 int SeqNo; 60 uint32_t Flags; 61 }; 62 63 /* 64 * HTC_TX_PACKET_TAG_XXX - #defines for tagging packets for special handling 65 * HTC_TX_PACKET_TAG_ALL: zero is reserved and used to flush ALL packets 66 * HTC_TX_PACKET_TAG_INTERNAL: internal tags start here 67 * HTC_TX_PACKET_TAG_USER_DEFINED: user-defined tags start here 68 * HTC_TX_PACKET_TAG_BUNDLED: indicate this is a bundled tx packet 69 * HTC_TX_PACKET_TAG_AUTO_PM: indicate a power management wmi command 70 */ 71 #define HTC_TX_PACKET_TAG_ALL 0 72 #define HTC_TX_PACKET_TAG_INTERNAL 1 73 #define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) 74 #define HTC_TX_PACKET_TAG_BUNDLED (HTC_TX_PACKET_TAG_USER_DEFINED + 1) 75 #define HTC_TX_PACKET_TAG_AUTO_PM (HTC_TX_PACKET_TAG_USER_DEFINED + 2) 76 77 /* Tag packet for runtime put after sending */ 78 #define HTC_TX_PACKET_TAG_RUNTIME_PUT (HTC_TX_PACKET_TAG_USER_DEFINED + 3) 79 80 /*Tag packet for runtime put in response or cleanup */ 81 #define HTC_TX_PACKET_TAG_RTPM_PUT_RC (HTC_TX_PACKET_TAG_USER_DEFINED + 4) 82 83 #define HTC_TX_PACKET_SYSTEM_SUSPEND (HTC_TX_PACKET_TAG_USER_DEFINED + 5) 84 #define HTC_TX_PACKET_SYSTEM_RESUME (HTC_TX_PACKET_TAG_USER_DEFINED + 6) 85 86 #define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0) 87 #define HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA (1 << 1) 88 89 /** 90 * struct htc_rx_packet_info - HTC RX Packet information 91 * @ExpectedHdr: HTC Internal use 92 * @HTCRxFlags: HTC Internal use 93 * @IndicationFlags: indication flags set on each RX packet indication 94 */ 95 struct htc_rx_packet_info { 96 uint32_t ExpectedHdr; 97 uint32_t HTCRxFlags; 98 uint32_t IndicationFlags; 99 }; 100 101 /* more packets on this endpoint are being fetched */ 102 #define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) 103 #define HTC_PACKET_MAGIC_COOKIE 0xdeadbeef 104 105 /* wrapper around endpoint-specific packets */ 106 /** 107 * struct _HTC_PACKET - HTC Packet data structure 108 * @ListLink: double link 109 * @pPktContext: caller's per packet specific context 110 * @pBufferStart: The true buffer start, the caller can store the real buffer 111 * start here. In receive callbacks, the HTC layer sets pBuffer 112 * to the start of the payload past the header. This field allows 113 * the caller to reset pBuffer when it recycles receive packets 114 * back to HTC 115 * @pBuffer: payload start (RX/TX) 116 * @BufferLength: length of buffer 117 * @ActualLength: actual length of payload 118 * @Endpoint: endpoint that this packet was sent/recv'd from 119 * @Status: completion status 120 * @PktInfo: Packet specific info 121 * @netbufOrigHeadRoom: Original head room of skb 122 * @Completion: completion 123 * @pContext: HTC private completion context 124 * @pNetBufContext: optimization for network-oriented data, the HTC packet can 125 * pass the network buffer corresponding to the HTC packet 126 * lower layers may optimized the transfer knowing this is a 127 * network buffer 128 * @magic_cookie: HTC Magic cookie 129 */ 130 typedef struct _HTC_PACKET { 131 DL_LIST ListLink; 132 void *pPktContext; 133 uint8_t *pBufferStart; 134 /* 135 * Pointer to the start of the buffer. In the transmit 136 * direction this points to the start of the payload. In the 137 * receive direction, however, the buffer when queued up 138 * points to the start of the HTC header but when returned 139 * to the caller points to the start of the payload 140 */ 141 uint8_t *pBuffer; 142 uint32_t BufferLength; 143 uint32_t ActualLength; 144 HTC_ENDPOINT_ID Endpoint; 145 QDF_STATUS Status; 146 union { 147 struct htc_tx_packet_info AsTx; 148 struct htc_rx_packet_info AsRx; 149 } PktInfo; 150 /* the following fields are for internal HTC use */ 151 uint32_t netbufOrigHeadRoom; 152 HTC_PACKET_COMPLETION Completion; 153 void *pContext; 154 void *pNetBufContext; 155 uint32_t magic_cookie; 156 } HTC_PACKET; 157 158 #define COMPLETE_HTC_PACKET(p, status) \ 159 { \ 160 (p)->Status = (status); \ 161 (p)->Completion((p)->pContext, (p)); \ 162 } 163 164 #define INIT_HTC_PACKET_INFO(p, b, len) \ 165 { \ 166 (p)->pBufferStart = (b); \ 167 (p)->BufferLength = (len); \ 168 } 169 170 /* macro to set an initial RX packet for refilling HTC */ 171 #define SET_HTC_PACKET_INFO_RX_REFILL(p, c, b, len, ep) \ 172 do { \ 173 (p)->pPktContext = (c); \ 174 (p)->pBuffer = (b); \ 175 (p)->pBufferStart = (b); \ 176 (p)->BufferLength = (len); \ 177 (p)->Endpoint = (ep); \ 178 } while (0) 179 180 /* fast macro to recycle an RX packet that will be re-queued to HTC */ 181 #define HTC_PACKET_RESET_RX(p) \ 182 { (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; } 183 184 /* macro to set packet parameters for TX */ 185 #define SET_HTC_PACKET_INFO_TX(p, c, b, len, ep, tag) \ 186 do { \ 187 (p)->pPktContext = (c); \ 188 (p)->pBuffer = (b); \ 189 (p)->ActualLength = (len); \ 190 (p)->Endpoint = (ep); \ 191 (p)->PktInfo.AsTx.Tag = (tag); \ 192 (p)->PktInfo.AsTx.Flags = 0; \ 193 (p)->PktInfo.AsTx.SendFlags = 0; \ 194 } while (0) 195 196 #define SET_HTC_PACKET_NET_BUF_CONTEXT(p, nb) \ 197 { \ 198 (p)->pNetBufContext = (nb); \ 199 } 200 201 #define GET_HTC_PACKET_NET_BUF_CONTEXT(p) (p)->pNetBufContext 202 203 /* HTC Packet Queueing Macros */ 204 typedef struct _HTC_PACKET_QUEUE { 205 DL_LIST QueueHead; 206 int Depth; 207 } HTC_PACKET_QUEUE; 208 209 /* initialize queue */ 210 #define INIT_HTC_PACKET_QUEUE(pQ) \ 211 { \ 212 DL_LIST_INIT(&(pQ)->QueueHead); \ 213 (pQ)->Depth = 0; \ 214 } 215 216 /* enqueue HTC packet to the tail of the queue */ 217 #define HTC_PACKET_ENQUEUE(pQ, p) \ 218 { dl_list_insert_tail(&(pQ)->QueueHead, &(p)->ListLink); \ 219 (pQ)->Depth++; \ 220 } 221 222 /* enqueue HTC packet to the tail of the queue */ 223 #define HTC_PACKET_ENQUEUE_TO_HEAD(pQ, p) \ 224 { dl_list_insert_head(&(pQ)->QueueHead, &(p)->ListLink); \ 225 (pQ)->Depth++; \ 226 } 227 /* test if a queue is empty */ 228 #define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0) 229 /* get packet at head without removing it */ htc_get_pkt_at_head(HTC_PACKET_QUEUE * queue)230 static inline HTC_PACKET *htc_get_pkt_at_head(HTC_PACKET_QUEUE *queue) 231 { 232 if (queue->Depth == 0) 233 return NULL; 234 235 return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD( 236 &queue->QueueHead)), 237 HTC_PACKET, ListLink); 238 } 239 240 /* remove a packet from a queue, where-ever it is in the queue */ 241 #define HTC_PACKET_REMOVE(pQ, p) \ 242 { \ 243 dl_list_remove(&(p)->ListLink); \ 244 (pQ)->Depth--; \ 245 } 246 247 /* dequeue an HTC packet from the head of the queue */ htc_packet_dequeue(HTC_PACKET_QUEUE * queue)248 static inline HTC_PACKET *htc_packet_dequeue(HTC_PACKET_QUEUE *queue) 249 { 250 DL_LIST *pItem = dl_list_remove_item_from_head(&queue->QueueHead); 251 252 if (pItem) { 253 queue->Depth--; 254 return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink); 255 } 256 return NULL; 257 } 258 259 /* dequeue an HTC packet from the tail of the queue */ htc_packet_dequeue_tail(HTC_PACKET_QUEUE * queue)260 static inline HTC_PACKET *htc_packet_dequeue_tail(HTC_PACKET_QUEUE *queue) 261 { 262 DL_LIST *pItem = dl_list_remove_item_from_tail(&queue->QueueHead); 263 264 if (pItem) { 265 queue->Depth--; 266 return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink); 267 } 268 return NULL; 269 } 270 271 #define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth 272 273 #define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint 274 #define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag 275 276 /* transfer the packets from one queue to the tail of another queue */ 277 #define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest, pQSrc) \ 278 { \ 279 dl_list_transfer_items_to_tail(&(pQDest)->QueueHead, \ 280 &(pQSrc)->QueueHead); \ 281 (pQDest)->Depth += (pQSrc)->Depth; \ 282 (pQSrc)->Depth = 0; \ 283 } 284 285 /* 286 * Transfer the packets from one queue to the head of another queue. 287 * This xfer_to_head(q1,q2) is basically equivalent to xfer_to_tail(q2,q1), 288 * but it updates the queue descriptor object for the initial queue to refer 289 * to the concatenated queue. 290 */ 291 #define HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(pQDest, pQSrc) \ 292 { \ 293 dl_list_transfer_items_to_head(&(pQDest)->QueueHead, \ 294 &(pQSrc)->QueueHead); \ 295 (pQDest)->Depth += (pQSrc)->Depth; \ 296 (pQSrc)->Depth = 0; \ 297 } 298 299 /* fast version to init and add a single packet to a queue */ 300 #define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ, pP) \ 301 { \ 302 DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead, &(pP)->ListLink) \ 303 (pQ)->Depth = 1; \ 304 } 305 306 #define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \ 307 ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead, \ 308 (pPTemp), HTC_PACKET, ListLink) 309 310 #define HTC_PACKET_QUEUE_ITERATE_IS_VALID(pQ) ITERATE_IS_VALID(&(pQ)->QueueHead) 311 #define HTC_PACKET_QUEUE_ITERATE_RESET(pQ) ITERATE_RESET(&(pQ)->QueueHead) 312 313 #define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END 314 315 /** 316 * htc_packet_set_magic_cookie() - set magic cookie in htc packet 317 * @htc_pkt: pointer to htc packet 318 * @value: value to set in magic cookie 319 * 320 * This API sets the magic cookie passed in htc packet. 321 * 322 * Return : None 323 */ htc_packet_set_magic_cookie(HTC_PACKET * htc_pkt,uint32_t value)324 static inline void htc_packet_set_magic_cookie(HTC_PACKET *htc_pkt, 325 uint32_t value) 326 { 327 htc_pkt->magic_cookie = value; 328 } 329 330 /** 331 * htc_packet_get_magic_cookie() - get magic cookie in htc packet 332 * @htc_pkt: pointer to htc packet 333 * 334 * This API returns the magic cookie in htc packet. 335 * 336 * Return : magic cookie 337 */ htc_packet_get_magic_cookie(HTC_PACKET * htc_pkt)338 static inline uint32_t htc_packet_get_magic_cookie(HTC_PACKET *htc_pkt) 339 { 340 return htc_pkt->magic_cookie; 341 } 342 343 #endif /*HTC_PACKET_H_ */ 344