blob: 0135682841468fcb4c91e88a529358642fd7da0e [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05302 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Kiet Lam1ed83fc2014-02-19 01:15:45 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
Jeff Johnson295189b2012-06-20 16:38:30 -070027
28/**=========================================================================
29
30 \file vos_packet.c
31
32 \brief virtual Operating System Services (vOSS) network Packet APIs
33
34 Network Protocol packet/buffer support interfaces
35
Kiet Lamaa8e15a2014-02-11 23:30:06 -080036
Jeff Johnson295189b2012-06-20 16:38:30 -070037 ========================================================================*/
38
39/* $Header$ */
40
41/*--------------------------------------------------------------------------
42 Include Files
43 ------------------------------------------------------------------------*/
44#include <vos_packet.h>
45#include <i_vos_packet.h>
46#include <vos_timer.h>
47#include <vos_trace.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070048#include <wlan_hdd_main.h>
Sameer Thalappild0158402013-05-03 13:19:03 -070049#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070050
51/*--------------------------------------------------------------------------
52 Preprocessor definitions and constants
53 ------------------------------------------------------------------------*/
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -080054/* Protocol specific packet tracking feature */
55#define VOS_PKT_PROT_ETH_TYPE_OFFSET 12
56#define VOS_PKT_PROT_IP_OFFSET 14
57#define VOS_PKT_PROT_IP_HEADER_SIZE 20
58#define VOS_PKT_PROT_DHCP_SRV_PORT 67
59#define VOS_PKT_PROT_DHCP_CLI_PORT 68
60#define VOS_PKT_PROT_EAPOL_ETH_TYPE 0x888E
Mihir Shete39f7c752015-06-11 15:40:09 +053061#define VOS_PKT_PROT_ARP_ETH_TYPE 0x0806
Bhargav Shah7dbfb6f2016-02-12 20:49:58 +053062#define VOS_PKT_GET_HEAD(skb) (skb->head)
63#define VOS_PKT_GET_END(skb) (skb->end)
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65/*--------------------------------------------------------------------------
66 Type declarations
67 ------------------------------------------------------------------------*/
68
69/*---------------------------------------------------------------------------
70 Data definitions
71 ------------------------------------------------------------------------*/
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -070072static vos_pkt_context_t *gpVosPacketContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070073
74/*-------------------------------------------------------------------------
75 Function declarations and documentation
76 ------------------------------------------------------------------------*/
77
78static VOS_STATUS vos_pkti_packet_init( struct vos_pkt_t *pPkt,
79 VOS_PKT_TYPE pktType )
80{
81 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
82
83 // fixed fields
84 pPkt->packetType = pktType;
85 pPkt->magic = VPKT_MAGIC_NUMBER;
86
87 // some packet types need an attached skb
88 switch (pktType)
89 {
90 case VOS_PKT_TYPE_RX_RAW:
91 case VOS_PKT_TYPE_TX_802_11_MGMT:
92 // these need an attached skb.
93 // we preallocate a fixed-size skb and reserve the entire buffer
94 // as headroom since that is what other components expect
Kumar Pavan32af4e32012-12-27 17:30:09 -080095 pPkt->pSkb = alloc_skb(VPKT_SIZE_BUFFER , in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -070096 if (likely(pPkt->pSkb))
97 {
98 skb_reserve(pPkt->pSkb, VPKT_SIZE_BUFFER);
99 }
100 else
101 {
102 vosStatus = VOS_STATUS_E_NOMEM;
103 }
104
Jeff Johnson295189b2012-06-20 16:38:30 -0700105 /* Init PAL Packet */
106 WPAL_PACKET_SET_BD_POINTER(&(pPkt->palPacket), NULL);
107 WPAL_PACKET_SET_BD_PHYS(&(pPkt->palPacket), NULL);
108 WPAL_PACKET_SET_BD_LENGTH(&(pPkt->palPacket), 0);
109 WPAL_PACKET_SET_OS_STRUCT_POINTER(&(pPkt->palPacket), NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110
111 break;
112 default:
113 // no attached skb needed
114 break;
115 }
116
117 return vosStatus;
118}
119
120
121
122static VOS_STATUS vos_pkti_list_destroy( struct list_head *pList )
123{
124 struct vos_pkt_t *pVosPacket;
125
126 if (unlikely(NULL == pList))
127 {
128 // something is fishy -- don't even bother trying
129 // clean up this list since it is apparently hosed
130 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
131 "VPKT [%d]: NULL pList", __LINE__);
132 VOS_ASSERT(0);
133 return VOS_STATUS_E_INVAL;
134 }
135
136 list_for_each_entry(pVosPacket, pList, node)
137 {
138
139 // is this really an initialized vos packet?
140 if (unlikely(VPKT_MAGIC_NUMBER != pVosPacket->magic))
141 {
142 // no, so don't try any deinitialization on it, and
143 // since we can't trust the linkages, stop trying
144 // to destroy the list
145 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
146 "VPKT [%d]: Invalid magic", __LINE__);
147 VOS_ASSERT(0);
148 break;
149 }
150
151 // does this vos packet have an skb attached?
152 if (pVosPacket->pSkb)
153 {
154 // yes, so give it back to the kernel
155 kfree_skb(pVosPacket->pSkb);
156 pVosPacket->pSkb = NULL;
157 }
158
159 // the vos packet itself is a static portion of the vos packet context
160 // so there is no deallocation we have to do with it. just clear the
161 // magic so we no longer think it is valid
162 pVosPacket->magic = 0;
163
164 }
165
166 // all nodes of the list have been processed so reinitialize the list
167 INIT_LIST_HEAD(pList);
168
169 return VOS_STATUS_SUCCESS;
170}
171
172
173static void vos_pkti_replenish_raw_pool(void)
174{
175 struct sk_buff * pSkb;
176 struct vos_pkt_t *pVosPacket;
177 v_BOOL_t didOne = VOS_FALSE;
178 vos_pkt_get_packet_callback callback;
Jeff Johnson295189b2012-06-20 16:38:30 -0700179
180 // if there are no packets in the replenish pool then we can't do anything
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530181 mutex_lock(&gpVosPacketContext->rxReplenishListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700182 if (likely(0 == gpVosPacketContext->rxReplenishListCount))
183 {
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530184 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700185 return;
186 }
187
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -0700188 // we only replenish if the Rx Raw pool is empty or the Replenish pool
189 // reaches a high water mark
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530190 mutex_lock(&gpVosPacketContext->rxRawFreeListLock);
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -0700191
Sameer Thalappild0158402013-05-03 13:19:03 -0700192 if ((gpVosPacketContext->rxReplenishListCount <
193 gpVosPacketContext->numOfRxRawPackets/4) &&
194 (!list_empty(&gpVosPacketContext->rxRawFreeList)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700195 {
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530196 mutex_unlock(&gpVosPacketContext->rxRawFreeListLock);
197 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -0700198 return;
Jeff Johnson295189b2012-06-20 16:38:30 -0700199 }
200
Jeff Johnson295189b2012-06-20 16:38:30 -0700201 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
202 "VPKT [%d]: Packet replenish activated", __LINE__);
203
204 // try to replenish all of the packets in the replenish pool
205 while (gpVosPacketContext->rxReplenishListCount)
206 {
207 // we preallocate a fixed-size skb and reserve the entire buffer
208 // as headroom since that is what other components expect
209 pSkb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
210 if (unlikely(NULL == pSkb))
211 {
Mihir Shete058fcff2014-06-26 18:54:06 +0530212 gpVosPacketContext->rxReplenishFailCount++;
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 break;
214 }
215 skb_reserve(pSkb, VPKT_SIZE_BUFFER);
216
217 // remove a vos packet from the replenish pool
218 pVosPacket = list_first_entry(&gpVosPacketContext->rxReplenishList,
219 struct vos_pkt_t, node);
220 list_del(&pVosPacket->node);
221 gpVosPacketContext->rxReplenishListCount--;
222
223 // attach the skb to the vos packet
224 pVosPacket->pSkb = pSkb;
225
226 // add it to the Rx Raw Free Pool
227 list_add_tail(&pVosPacket->node, &gpVosPacketContext->rxRawFreeList);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800228 gpVosPacketContext->rxRawFreeListCount++;
Jeff Johnson295189b2012-06-20 16:38:30 -0700229
230 didOne = VOS_TRUE;
231
232 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -0700233 "VPKT [%d]: [%pK] Packet replenished",
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 __LINE__, pVosPacket);
235
236 }
237
238 // if we replenished anything and if there is a callback waiting
239 // then invoke the callback
240 if ((VOS_TRUE == didOne) &&
241 (gpVosPacketContext->rxRawLowResourceInfo.callback))
242 {
243 // remove the first record from the free pool
244 pVosPacket = list_first_entry(&gpVosPacketContext->rxRawFreeList,
245 struct vos_pkt_t, node);
246 list_del(&pVosPacket->node);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800247 gpVosPacketContext->rxRawFreeListCount--;
Jeff Johnson295189b2012-06-20 16:38:30 -0700248
249 // clear out the User Data pointers in the voss packet..
250 memset(&pVosPacket->pvUserData, 0, sizeof(pVosPacket->pvUserData));
251
252 // initialize the 'chain' pointer to NULL.
253 pVosPacket->pNext = NULL;
254
255 // timestamp the vos packet.
256 pVosPacket->timestamp = vos_timer_get_system_ticks();
257
258 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -0700259 "VPKT [%d]: [%pK] Packet replenish callback",
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 __LINE__, pVosPacket);
261
262 callback = gpVosPacketContext->rxRawLowResourceInfo.callback;
263 gpVosPacketContext->rxRawLowResourceInfo.callback = NULL;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530264 mutex_unlock(&gpVosPacketContext->rxRawFreeListLock);
265 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 callback(pVosPacket, gpVosPacketContext->rxRawLowResourceInfo.userData);
267 }
268 else
269 {
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530270 mutex_unlock(&gpVosPacketContext->rxRawFreeListLock);
271 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 }
273}
274
275
276#if defined( WLAN_DEBUG )
277static char *vos_pkti_packet_type_str(VOS_PKT_TYPE pktType)
278{
279 switch (pktType)
280 {
281 case VOS_PKT_TYPE_TX_802_11_MGMT:
282 return "TX_802_11_MGMT";
283 break;
284
285 case VOS_PKT_TYPE_TX_802_11_DATA:
286 return "TX_802_11_DATA";
287 break;
288
289 case VOS_PKT_TYPE_TX_802_3_DATA:
290 return "TX_802_3_DATA";
291 break;
292
293 case VOS_PKT_TYPE_RX_RAW:
294 return "RX_RAW";
295 break;
296
297 default:
298 return "UNKNOWN";
299 break;
300 }
301}
302#endif // defined( WLAN_DEBUG )
303
304/*---------------------------------------------------------------------------
305
306 \brief vos_packet_open() - initialize the vOSS Packet module
307
308 The \a vos_packet_open() function initializes the vOSS Packet
309 module.
310
311 \param pVosContext - pointer to the global vOSS Context
312
313 \param pVosPacketContext - pointer to a previously allocated
314 buffer big enough to hold the vos Packet context.
315
316 \param vosPacketContextSize - the size allocated for the vos
317 packet context.
318
319 \return VOS_STATUS_SUCCESS - vos Packet module was successfully
320 initialized and is ready to be used.
321
322 VOS_STATUS_E_RESOURCES - System resources (other than memory)
323 are unavailable to initilize the vos Packet module
324
325 VOS_STATUS_E_NOMEM - insufficient memory exists to initialize
326 the vos packet module
327
328 VOS_STATUS_E_INVAL - Invalid parameter passed to the vos open
329 function
330
331 VOS_STATUS_E_FAILURE - Failure to initialize the vos packet
332 module
333
334 \sa vos_packet_close()
335
336 -------------------------------------------------------------------------*/
337VOS_STATUS vos_packet_open( v_VOID_t *pVosContext,
338 vos_pkt_context_t *pVosPacketContext,
339 v_SIZE_t vosPacketContextSize )
340{
341 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
342 unsigned int freePacketIndex;
343 unsigned int idx;
344 struct vos_pkt_t *pPkt;
345 struct list_head *pFreeList;
346
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700347 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "Enter:%s",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700348
349 do
350 {
351
352 if (NULL == pVosContext)
353 {
354 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
355 "VPKT [%d]: NULL pVosContext", __LINE__);
356 vosStatus = VOS_STATUS_E_INVAL;
357 break;
358 }
359
360 if (NULL == pVosPacketContext)
361 {
362 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
363 "VPKT [%d]: NULL pVosPacketContext", __LINE__);
364 vosStatus = VOS_STATUS_E_INVAL;
365 break;
366 }
367
368 if (sizeof(vos_pkt_context_t) != vosPacketContextSize)
369 {
370 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson69546fd2013-11-22 18:53:57 -0800371 "VPKT [%d]: invalid vosPacketContextSize, %zu vs %d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700372 __LINE__, sizeof(vos_pkt_context_t), vosPacketContextSize);
373 vosStatus = VOS_STATUS_E_INVAL;
374 break;
375 }
376
377 // clear the vos packet context. in the process this will
378 // initialize the low resource info blocks
379 memset(pVosPacketContext, 0, vosPacketContextSize);
380
381 // save a global pointer to the vos packet context.
382 gpVosPacketContext = pVosPacketContext;
383
384 // save the vos Context pointer in the vos Packet Context.
385 pVosPacketContext->vosContext = pVosContext;
386
387 // initialize the rx Replenish pool (initially empty)
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530388 mutex_init(&gpVosPacketContext->rxReplenishListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 INIT_LIST_HEAD(&pVosPacketContext->rxReplenishList);
390 pVosPacketContext->rxReplenishListCount = 0;
391
392 // index into the packet context's vosPktBuffer[] array
393 freePacketIndex = 0;
394
395 // initialize the rxRaw free list pool
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530396 mutex_init(&gpVosPacketContext->rxRawFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700397 pFreeList = &pVosPacketContext->rxRawFreeList;
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800398 pVosPacketContext->rxRawFreeListCount = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700399 INIT_LIST_HEAD(pFreeList);
400
Sameer Thalappild0158402013-05-03 13:19:03 -0700401 pVosPacketContext->numOfRxRawPackets = vos_pkt_get_num_of_rx_raw_pkts();
402
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 // fill the rxRaw free list
Sameer Thalappild0158402013-05-03 13:19:03 -0700404 for (idx = 0; idx < pVosPacketContext->numOfRxRawPackets; idx++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700405 {
406 pPkt = &pVosPacketContext->vosPktBuffers[freePacketIndex++];
407 vosStatus = vos_pkti_packet_init(pPkt, VOS_PKT_TYPE_RX_RAW);
408
Jeff Johnson295189b2012-06-20 16:38:30 -0700409 WPAL_PACKET_SET_METAINFO_POINTER(&(pPkt->palPacket),
410 (void*)&pVosPacketContext->rxMetaInfo[idx]);
411 WPAL_PACKET_SET_TYPE(&(pPkt->palPacket),
412 eWLAN_PAL_PKT_TYPE_RX_RAW);
Jeff Johnson295189b2012-06-20 16:38:30 -0700413
414 if (VOS_STATUS_SUCCESS != vosStatus)
415 {
416 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
417 "VPKT [%d]: Packet init failure", __LINE__);
418 break;
419 }
420 list_add_tail(&pPkt->node, pFreeList);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800421 pVosPacketContext->rxRawFreeListCount++;
Jeff Johnson295189b2012-06-20 16:38:30 -0700422 }
423
424 // exit if any problems so far
425 if (VOS_STATUS_SUCCESS != vosStatus)
426 {
427 break;
428 }
429
430 // initialize the txData free list pool
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530431 mutex_init(&gpVosPacketContext->txDataFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700432 pFreeList = &pVosPacketContext->txDataFreeList;
433 INIT_LIST_HEAD(pFreeList);
434
435 // fill the txData free list
436 for (idx = 0; idx < VPKT_NUM_TX_DATA_PACKETS; idx++)
437 {
438 pPkt = &pVosPacketContext->vosPktBuffers[freePacketIndex++];
439 vosStatus = vos_pkti_packet_init(pPkt, VOS_PKT_TYPE_TX_802_3_DATA);
Jeff Johnson295189b2012-06-20 16:38:30 -0700440 WPAL_PACKET_SET_METAINFO_POINTER(&(pPkt->palPacket),
441 (void*)&pVosPacketContext->txDataMetaInfo[idx]);
442 WPAL_PACKET_SET_TYPE(&(pPkt->palPacket),
443 eWLAN_PAL_PKT_TYPE_TX_802_3_DATA);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444 if (VOS_STATUS_SUCCESS != vosStatus)
445 {
446 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
447 "VPKT [%d]: Packet init failure", __LINE__);
448 break;
449 }
450 list_add_tail(&pPkt->node, pFreeList);
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 pVosPacketContext->uctxDataFreeListCount++;
Jeff Johnson295189b2012-06-20 16:38:30 -0700452 }
453
454 // exit if any problems so far
455 if (VOS_STATUS_SUCCESS != vosStatus)
456 {
457 break;
458 }
459
460 // initialize the txMgmt free list pool
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530461 mutex_init(&gpVosPacketContext->txMgmtFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 pFreeList = &pVosPacketContext->txMgmtFreeList;
463 INIT_LIST_HEAD(pFreeList);
464
Jeff Johnson295189b2012-06-20 16:38:30 -0700465 // fill the txMgmt free list
466 for (idx = 0; idx < VPKT_NUM_TX_MGMT_PACKETS; idx++)
467 {
468 pPkt = &pVosPacketContext->vosPktBuffers[freePacketIndex++];
469
470 vosStatus = vos_pkti_packet_init(pPkt, VOS_PKT_TYPE_TX_802_11_MGMT);
471
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 WPAL_PACKET_SET_METAINFO_POINTER(&(pPkt->palPacket),
473 (void*)&pVosPacketContext->txMgmtMetaInfo[idx]);
474 WPAL_PACKET_SET_TYPE(&(pPkt->palPacket),
475 eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT);
Jeff Johnson295189b2012-06-20 16:38:30 -0700476
477 if (VOS_STATUS_SUCCESS != vosStatus)
478 {
479 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
480 "VPKT [%d]: Packet init failure", __LINE__);
481 break;
482 }
483 list_add_tail(&pPkt->node, pFreeList);
484 }
485
486 // exit if any problems so far
487 if (VOS_STATUS_SUCCESS != vosStatus)
488 {
489 break;
490 }
491
492 } while (0);
493
494 return vosStatus;
495}
496
497
498
499/*---------------------------------------------------------------------------
500
501 \brief vos_packet_close() - Close the vOSS Packet module
502
503 The \a vos_packet_close() function closes the vOSS Packet module
504 Upon successful close all resources allocated from the OS will be
505 relinquished.
506
507 \param pVosContext - pointer to the global vOSS Context
508
509 \return VOS_STATUS_SUCCESS - Packet module was successfully closed.
510
511 VOS_STATUS_E_INVAL - Invalid parameter passed to the packet
512 close function
513
514 VOS_STATUS_E_FAILURE - Failure to close the vos Packet module
515
516 \sa vos_packet_open()
517
518 ---------------------------------------------------------------------------*/
519VOS_STATUS vos_packet_close( v_PVOID_t pVosContext )
520{
521
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700522 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "Enter:%s",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700523
524 if (unlikely(NULL == pVosContext))
525 {
526 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
527 "VPKT [%d]: NULL pVosContext", __LINE__);
528 return VOS_STATUS_E_INVAL;
529 }
530
531 if (unlikely(gpVosPacketContext->vosContext != pVosContext))
532 {
533 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
534 "VPKT [%d]: invalid pVosContext", __LINE__);
535 return VOS_STATUS_E_INVAL;
536 }
537
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530538
539 mutex_lock(&gpVosPacketContext->txMgmtFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700540 (void) vos_pkti_list_destroy(&gpVosPacketContext->txMgmtFreeList);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530541 mutex_unlock(&gpVosPacketContext->txMgmtFreeListLock);
542
543 mutex_lock(&gpVosPacketContext->txDataFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700544 (void) vos_pkti_list_destroy(&gpVosPacketContext->txDataFreeList);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530545 gpVosPacketContext->uctxDataFreeListCount = 0;
546 mutex_unlock(&gpVosPacketContext->txDataFreeListLock);
547
548 mutex_lock(&gpVosPacketContext->rxRawFreeListLock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700549 (void) vos_pkti_list_destroy(&gpVosPacketContext->rxRawFreeList);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800550 gpVosPacketContext->rxRawFreeListCount = 0;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530551 mutex_unlock(&gpVosPacketContext->rxRawFreeListLock);
552
553 mutex_lock(&gpVosPacketContext->rxReplenishListLock);
554 (void) vos_pkti_list_destroy(&gpVosPacketContext->rxReplenishList);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800555 gpVosPacketContext->rxReplenishListCount = 0;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530556 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800557
Jeff Johnson295189b2012-06-20 16:38:30 -0700558
Jeff Johnson295189b2012-06-20 16:38:30 -0700559
560 return VOS_STATUS_SUCCESS;
561}
562
563
564/**--------------------------------------------------------------------------
565
566 \brief vos_pkt_get_packet() - Get a voss Packet
567
568 Gets a voss Packet from an internally managed packet pool.
569
570 \param ppPacket - pointer to location where the voss Packet pointer is
571 returned. If multiple packets are requested, they
572 will be chained onto this first packet.
573
574 \param pktType - the packet type to be retreived. Valid packet types are:
575 <ul>
576 <li> VOS_PKT_TYPE_TX_802_11_MGMT - voss packet is for Transmitting
577 802.11 Management frames.
578
579 <li> VOS_PKT_TYPE_RX_RAW - voss Packet contains a buffer for Receiving
580 raw frames of unknown type.
581 </ul>
582
583 \param dataSize - the Data size needed in the voss Packet.
584
585 \param numPackets - the number of packets requested.
586
587 \param zeroBuffer - parameter that tells the API to zero the data buffer
588 in this voss Packet.
589 <ul>
590 <li> VOS_TRUE - the API will zero out the entire data buffer.
591
592 <li> VOS_FALSE - the API will not zero out the data buffer.
593 </ul>
594
595 \note If enough room for headers to transmit or receive the packet is not
596 available, this API will fail.
597
598 \param callback - This callback function, if provided, is invoked in the
599 case when resources are not available at the time of the call to
600 get packets. This callback function is invoked when packets are
601 available.
602
603 \param userData - This user data is passed back to the caller in the
604 callback function, if the callback is invoked.
605
606 \return VOS_STATUS_SUCCESS - the API was able to get a vos_packet for the
607 requested type. *ppPacket contains a pointer to the packet.
608
609 VOS_STATUS_E_INVAL - pktType is not a valid packet type. This
610 API only supports getting vos packets for 802_11_MGMT and
611 RX_RAW packet types. This status is also returned if the
612 numPackets or dataSize are invalid.
613
614 VOS_STATUS_E_RESOURCES - unable to get resources needed to get
615 a vos packet. If a callback function is specified and this
616 status is returned from the API, the callback will be called
617 when resources are available to fulfill the original request.
618
619 Note that the low resources condition is indicated to the caller
620 by returning VOS_STATUS_E_RESOURCES. This status is the only
621 non-success status that indicates to the caller that the callback
622 will be called when resources are available. All other status
623 indicate failures that are not recoverable and the 'callback'
624 will not be called.
625
626 VOS_STATUS_E_FAILURE - The API returns this status when unable
627 to get a packet from the packet pool because the pool
628 is depleted and the caller did not specify a low resource callback.
629
630 VOS_STATUS_E_ALREADY - This status is returned when the VOS
631 packet pool is in a 'low resource' condition and cannot
632 accomodate any more calls to retrieve packets from that
633 pool. Note this is a FAILURE and the 'low resource' callback
634 will *not* be called.
635
636 VOS_STATUS_E_FAULT - ppPacket does not specify a valid pointer.
637
638 \sa
639
640 ------------------------------------------------------------------------*/
641VOS_STATUS vos_pkt_get_packet( vos_pkt_t **ppPacket,
642 VOS_PKT_TYPE pktType,
643 v_SIZE_t dataSize,
644 v_SIZE_t numPackets,
645 v_BOOL_t zeroBuffer,
646 vos_pkt_get_packet_callback callback,
647 v_VOID_t *userData )
648{
649 struct list_head *pPktFreeList;
650 vos_pkt_low_resource_info *pLowResourceInfo;
651 struct vos_pkt_t *pVosPacket;
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800652 v_SIZE_t *pCount = NULL;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530653 struct mutex *mlock;
654
Jeff Johnson295189b2012-06-20 16:38:30 -0700655 // Validate the return parameter pointer
656 if (unlikely(NULL == ppPacket))
657 {
658 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
659 "VPKT [%d]: NULL ppPacket", __LINE__);
660 return VOS_STATUS_E_INVAL;
661 }
662
663 // we only support getting 1 packet at this time (as do WM & AMSS)
664 if (unlikely(1 != numPackets))
665 {
666 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
667 "VPKT [%d]: invalid numPackets, %d", __LINE__, numPackets);
668 return VOS_STATUS_E_INVAL;
669 }
670
671 // Validate the dataSize is within range
672 if (unlikely((0 == dataSize) || (dataSize > VPKT_SIZE_BUFFER)))
673 {
674 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
675 "VPKT [%d]: invalid dataSize, %d", __LINE__, dataSize);
676 return VOS_STATUS_E_INVAL;
677 }
678
679 // determine which packet pool and low resource block we should use.
680 // this API is only valid for TX MGMT and RX RAW packets
681 // (TX DATA will use vos_pkt_wrap_data_packet())
682 switch (pktType)
683 {
684
685 case VOS_PKT_TYPE_RX_RAW:
686 pPktFreeList = &gpVosPacketContext->rxRawFreeList;
687 pLowResourceInfo = &gpVosPacketContext->rxRawLowResourceInfo;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530688 mlock = &gpVosPacketContext->rxRawFreeListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -0700689
690 // see if we need to replenish the Rx Raw pool
691 vos_pkti_replenish_raw_pool();
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800692 pCount = &gpVosPacketContext->rxRawFreeListCount;
Jeff Johnson295189b2012-06-20 16:38:30 -0700693
694 break;
695
696 case VOS_PKT_TYPE_TX_802_11_MGMT:
697 pPktFreeList = &gpVosPacketContext->txMgmtFreeList;
698 pLowResourceInfo = &gpVosPacketContext->txMgmtLowResourceInfo;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530699 mlock = &gpVosPacketContext->txMgmtFreeListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -0700700 break;
701
702 default:
703 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
704 "VPKT [%d]: invalid packet type %d[%s]",
705 __LINE__, pktType, vos_pkti_packet_type_str(pktType));
706 return VOS_STATUS_E_INVAL;
707 }
708
709 // is there already a low resource callback registered for this pool?
710 // we only support one callback per pool, so if one is already registered
711 // then we know we are already in a low-resource condition
712 if (unlikely(pLowResourceInfo->callback))
713 {
Madan Mohan Koyyalamudi16ea9c42013-09-20 00:43:35 +0530714 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700715 "VPKT [%d]: Low resource handler already registered",
716 __LINE__);
717 return VOS_STATUS_E_ALREADY;
718 }
719
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530720 mutex_lock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 // are there vos packets on the associated free pool?
722 if (unlikely(list_empty(pPktFreeList)))
723 {
724 // allocation failed
725 // did the caller specify a callback?
726 if (unlikely(NULL == callback))
727 {
728 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
729 "VPKT [%d]: Low resource condition and no callback provided",
730 __LINE__);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530731 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700732
733 return VOS_STATUS_E_FAILURE;
734 }
735
736 // save the low resource information so that we can invoke the
737 // callback when a packet becomes available
738 pLowResourceInfo->callback = callback;
739 pLowResourceInfo->userData = userData;
740 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
741 "VPKT [%d]: Low resource condition for packet type %d[%s]",
742 __LINE__, pktType, vos_pkti_packet_type_str(pktType));
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530743 mutex_unlock(mlock);
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -0700744
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 return VOS_STATUS_E_RESOURCES;
746 }
747
748 // remove the first record from the free pool
749 pVosPacket = list_first_entry(pPktFreeList, struct vos_pkt_t, node);
750 list_del(&pVosPacket->node);
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -0800751 if (NULL != pCount)
752 {
753 (*pCount)--;
754 }
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530755 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700756
757 // clear out the User Data pointers in the voss packet..
758 memset(&pVosPacket->pvUserData, 0, sizeof(pVosPacket->pvUserData));
759
760 // initialize the 'chain' pointer to NULL.
761 pVosPacket->pNext = NULL;
762
763 // set the packet type.
764 pVosPacket->packetType = pktType;
765
766 // timestamp the vos packet.
767 pVosPacket->timestamp = vos_timer_get_system_ticks();
768
769 // zero the data buffer if the user asked for it to be cleared.
770 if (unlikely(zeroBuffer))
771 {
772 memset(pVosPacket->pSkb->head,
773 0,
774 skb_end_pointer(pVosPacket->pSkb) - pVosPacket->pSkb->head);
775 }
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -0700776
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -0700778 "VPKT [%d]: [%pK] Packet allocated, type %d[%s]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700779 __LINE__, pVosPacket, pktType, vos_pkti_packet_type_str(pktType));
780
781 *ppPacket = pVosPacket;
782 return VOS_STATUS_SUCCESS;
783}
784
785
786/**--------------------------------------------------------------------------
787
788 \brief vos_pkt_wrap_data_packets() - Wrap an OS provided data packet in a
789 vos packet.
790
791 Takes as input an OS provided data packet and 'wraps' that packet in a
792 vos_packet, returning the vos_packet to the caller.
793
794 This function is intended to be called from the HDD to wrap Tx data packets
795 from the OS into vos_packets before sending them to TL for transmission.
796
797 \param ppPacket - pointer to location where the voss Packet pointer is
798 returned. If multiple packets are requested, they
799 will be chained onto this first packet.
800
801 \param pktType - the packet type to be retreived. Valid packet types are:
802 <ul>
803 <li> VOS_PKT_TYPE_802_3_DATA - voss packet is for Transmitting 802.3
804 data frames.
805
806 <li> VOS_PKT_TYPE_802_11_DATA - voss Packet is for Transmitting 802.11
807 data frames.
808 </ul>
809
810 \param pOSPacket - a pointer to the Transmit packet provided by the OS. This
811 OS provided packet will be wrapped into a vos_packet_t. Note this
812 OS packet pointer can be NULL. The OS packet pointer can be inserted
813 into a VOS packet of type VOS_PKT_TYPE_802_3_DATA or
814 VOS_PKT_TYPE_802_11_DATA through vos_pkt_set_os_packet().
815
816 \note If enough room for headers to transmit or receive the packet is not
817 available, this API will fail.
818
819 \param callback - This callback function, if provided, is invoked in the
820 case where packets are not available at the time of the call to
821 return the packets to the caller (a 'low resource' condition).
822
823 When packets become available, the callback callback function is
824 invoked to return a VOS packet to the caller. Note that the
825 OS Packet is *not* inserted into the VOS packet when it is returned
826 to the low resource callback. It is up to the caller to insert
827 the OS packet into the VOS packet by calling vos_pkt_set_os_packet()
828
829 \param userData - This user data is passed back to the caller in the
830 callback function, if the callback is invoked.
831
832 \return VOS_STATUS_SUCCESS - the API was able to get a vos_packet for the
833 requested type. *ppPacket contains a pointer to the packet.
834
835 VOS_STATUS_E_INVAL - pktType is not a valid packet type. This
836 API only supports getting vos packets for 802_11_MGMT and
837 RX_RAW packet types.
838
839 VOS_STATUS_E_RESOURCES - unable to get resources needed to get
840 a vos packet. If a callback function is specified and this
841 status is returned from the API, the callback will be called
842 when resources are available to fulfill the original request.
843
844 Note that the low resources condition is indicated to the caller
845 by returning VOS_STATUS_E_RESOURCES. This status is the only
846 non-success status that indicates to the caller that the callback
847 will be called when resources are available. All other status
848 indicate failures that are not recoverable and the 'callback'
849 will not be called.
850
851 VOS_STATUS_E_FAILURE - The API returns this status when unable
852 to get a packet from the packet pool because the pool
853 is depleted and the caller did not specify a low resource callback.
854
855 VOS_STATUS_E_ALREADY - This status is returned when the VOS
856 packet pool is in a 'low resource' condition and cannot
857 accomodate any more calls to retrieve packets from that
858 pool. Note this is a FAILURE and the 'low resource' callback
859 will *not* be called.
860
861 VOS_STATUS_E_FAULT - ppPacket or pOSPacket do not specify valid
862 pointers.
863
864 \sa vos_pkt_set_os_packet()
865
866 ------------------------------------------------------------------------*/
867VOS_STATUS vos_pkt_wrap_data_packet( vos_pkt_t **ppPacket,
868 VOS_PKT_TYPE pktType,
869 v_VOID_t *pOSPacket,
870 vos_pkt_get_packet_callback callback,
871 v_VOID_t *userData )
872{
873 struct list_head *pPktFreeList;
874 vos_pkt_low_resource_info *pLowResourceInfo;
875 struct vos_pkt_t *pVosPacket;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530876 struct mutex *mlock;
Jeff Johnson295189b2012-06-20 16:38:30 -0700877
878 // Validate the return parameter pointer
879 if (unlikely(NULL == ppPacket))
880 {
881 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
882 "VPKT [%d]: NULL ppPacket", __LINE__);
883 return VOS_STATUS_E_INVAL;
884 }
885
886 // Validate the packet type. Only Tx Data packets can have an OS
887 // packet attached to them (Tx Mgmt and Rx Raw have OS packets
888 // pre-attached to them)
889 if (unlikely(VOS_PKT_TYPE_TX_802_3_DATA != pktType))
890 {
891 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +0530892 "VPKT [%d]: invalid pktType %d", __LINE__, pktType);
Jeff Johnson295189b2012-06-20 16:38:30 -0700893 return VOS_STATUS_E_INVAL;
894 }
895
896 // determine which packet pool and low resource block we should use.
897 pPktFreeList = &gpVosPacketContext->txDataFreeList;
898 pLowResourceInfo = &gpVosPacketContext->txDataLowResourceInfo;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530899 mlock = &gpVosPacketContext->txDataFreeListLock;
900
901 mutex_lock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700902
903 // is there already a low resource callback registered for this pool?
904 // we only support one callback per pool, so if one is already registered
905 // then we know we are already in a low-resource condition
906 if (unlikely(pLowResourceInfo->callback))
907 {
Madan Mohan Koyyalamudi16ea9c42013-09-20 00:43:35 +0530908 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 "VPKT [%d]: Low resource handler already registered",
910 __LINE__);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530911 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700912 return VOS_STATUS_E_ALREADY;
913 }
914
915 // are there vos packets on the associated free pool?
916 if (unlikely(list_empty(pPktFreeList)))
917 {
918 // allocation failed
919 // did the caller specify a callback?
920 if (unlikely(NULL == callback))
921 {
922 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
923 "VPKT [%d]: Low resource condition and no callback provided",
924 __LINE__);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530925 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700926 return VOS_STATUS_E_FAILURE;
927 }
928
929 // save the low resource information so that we can invoke the
930 // callback when a packet becomes available
931 pLowResourceInfo->callback = callback;
932 pLowResourceInfo->userData = userData;
933 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
934 "VPKT [%d]: Low resource condition for pool %s",
935 __LINE__, vos_pkti_packet_type_str(pktType));
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530936 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 return VOS_STATUS_E_RESOURCES;
938 }
939
940 // remove the first record from the free pool
941 pVosPacket = list_first_entry(pPktFreeList, struct vos_pkt_t, node);
942 list_del(&pVosPacket->node);
Jeff Johnson295189b2012-06-20 16:38:30 -0700943 gpVosPacketContext->uctxDataFreeListCount --;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +0530944 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700945
946 // clear out the User Data pointers in the voss packet..
947 memset(&pVosPacket->pvUserData, 0, sizeof(pVosPacket->pvUserData));
948
949 // initialize the 'chain' pointer to NULL.
950 pVosPacket->pNext = NULL;
951
952 // set the packet type.
953 pVosPacket->packetType = pktType;
954
955 // set the skb pointer
956 pVosPacket->pSkb = (struct sk_buff *) pOSPacket;
957
958 // timestamp the vos packet.
959 pVosPacket->timestamp = vos_timer_get_system_ticks();
960
961 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -0700962 "VPKT [%d]: [%pK] Packet allocated, type %s",
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 __LINE__, pVosPacket, vos_pkti_packet_type_str(pktType));
964
965 *ppPacket = pVosPacket;
966 return VOS_STATUS_SUCCESS;
967}
968
969
970
971/*---------------------------------------------------------------------------
972
973 \brief vos_pkt_set_os_packet() - set the OS packet in a VOS data packet
974
975 This API inserts an OS packet into a previously retreived VOS packet.
976 This API only applies to VOS packets of type VOS_PKT_TYPE_802_3_DATA or
977 VOS_PKT_TYPE_802_11_DATA.
978
979 There are cases where a user will need to get a VOS data packet without
980 having the OS packet to insert/wrap into the data packet. This could happen
981 if the user calls vos_pkt_wrap_data_packet() without the OS packet.
982
983 Also, when the user hit a 'low resource' situation for data packets, the
984 low resource callback is going to return a VOS packet without an OS packet
985 attached to it. The caller who gets the packet through the low resource
986 callback uses this API to insert an OS packet into the VOS packet that
987 was returned through the low resource callback.
988
989 \param pPacket - the voss Packet to insert the OS packet into.
990
991 \param pOSPacket - a pointer to the Transmit packet provided by the OS. This
992 OS provided packet will be wrapped into a vos_packet_t. Note this
993 OS packet pointer can be NULL. The OS packet pointer can be inserted
994 into a VOS packet of type VOS_PKT_TYPE_802_3_DATA or
995 VOS_PKT_TYPE_802_11_DATA through vos_pkt_set_os_packet().
996
997 Caller beware. If there is a valid OS packet wrapped into this
998 VOS packet already, this API will blindly overwrite the OS packet
999 with the new one specified on this API call. If you need to determine
1000 or retreive the current OS packet from a VOS packet, call
1001 vos_pkt_get_os_packet() first.
1002
1003 \return VOS_STATUS_SUCCESS - the API was able to insert the OS packet into
1004 the vos_packet.
1005
1006 VOS_STATUS_E_INVAL - pktType is not a valid packet type. This
1007 API only supports getting vos packets of type
1008 VOS_PKT_TYPE_802_3_DATA or VOS_PKT_TYPE_802_11_DATA.
1009
1010 VOS_STATUS_E_FAULT - pPacket does not specify a valid pointer.
1011
1012 \sa vos_pkt_get_os_packet()
1013
1014 ---------------------------------------------------------------------------*/
1015VOS_STATUS vos_pkt_set_os_packet( vos_pkt_t *pPacket,
1016 v_VOID_t *pOSPacket )
1017{
1018 // Validate the input parameter pointers
1019 if (unlikely((NULL == pPacket)||(NULL == pOSPacket)))
1020 {
1021 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1022 "VPKT [%d]: NULL pointer", __LINE__);
1023 return VOS_STATUS_E_INVAL;
1024 }
1025
1026 // Validate that this really an initialized vos packet
1027 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1028 {
1029 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1030 "VPKT [%d]: Invalid magic", __LINE__);
1031 return VOS_STATUS_E_INVAL;
1032 }
1033
1034 // Validate the packet type. Only Tx Data packets can have an OS
1035 // packet attached to them (Tx Mgmt and Rx Raw have OS packets
1036 // pre-attached to them)
1037 if (unlikely(VOS_PKT_TYPE_TX_802_3_DATA != pPacket->packetType))
1038 {
1039 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1040 "VPKT [%d]: invalid packet type %d[%s]",
1041 __LINE__, pPacket->packetType,
1042 vos_pkti_packet_type_str(pPacket->packetType));
1043 return VOS_STATUS_E_INVAL;
1044 }
1045
1046 // Is there already a packet attached? If so, just warn and continue
1047 if (unlikely(pPacket->pSkb))
1048 {
1049 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
1050 "VPKT [%d]: Packet previously attached", __LINE__);
1051 }
1052
1053 // attach
1054 pPacket->pSkb = (struct sk_buff *) pOSPacket;
1055
1056 return VOS_STATUS_SUCCESS;
1057}
1058
1059
1060/*---------------------------------------------------------------------------
1061
1062 \brief vos_pkt_get_os_packet() - get the OS packet in a VOS data packet
1063
1064 This API returns the OS packet that is inserted in a VOS packet.
1065 This API only applies to VOS packets of type VOS_PKT_TYPE_802_3_DATA or
1066 VOS_PKT_TYPE_802_11_DATA.
1067
1068 \param pPacket - the voss Packet to return the OS packet from.
1069
1070 \param ppOSPacket - a pointer to the location where the OS packet pointer
1071 retreived from the VOS packet will be returned. Note this OS packet
1072 pointer can be NULL, meaning there is no OS packet attached to this
1073 VOS data packet.
1074
1075 \param clearOSPacket - a boolean value that tells the API to clear out the
1076 OS packet pointer from the VOS packet. Setting this to 'true' will
1077 essentially remove the OS packet from the VOS packet. 'false' means
1078 the OS packet remains chained to the VOS packet. In either case,
1079 the OS packet pointer is returned to the caller.
1080
1081 \return VOS_STATUS_SUCCESS - the API was able to retreive the OS packet
1082 pointer from the VOS packet and return it to the caller in
1083 *ppOsPacket
1084
1085 VOS_STATUS_E_INVAL - pktType is not a valid packet type. This
1086 API only supports getting vos packets of type
1087 VOS_PKT_TYPE_802_3_DATA or VOS_PKT_TYPE_802_11_DATA.
1088
1089 VOS_STATUS_E_FAULT - pPacket or ppOsPacket does not specify a valid
1090 pointers.
1091
1092 \sa vos_pkt_set_os_packet(), vos_pkt_wrap_data_packet(),
1093 vos_pkt_return_packet()
1094
1095 ---------------------------------------------------------------------------*/
1096VOS_STATUS vos_pkt_get_os_packet( vos_pkt_t *pPacket,
1097 v_VOID_t **ppOSPacket,
1098 v_BOOL_t clearOSPacket )
1099{
1100 // Validate the input and output parameter pointers
1101 if (unlikely((NULL == pPacket)||(NULL == ppOSPacket)))
1102 {
1103 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1104 "VPKT [%d]: NULL pointer", __LINE__);
1105 return VOS_STATUS_E_INVAL;
1106 }
1107
1108 // Validate that this really an initialized vos packet
1109 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1110 {
1111 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1112 "VPKT [%d]: Invalid magic", __LINE__);
1113 return VOS_STATUS_E_INVAL;
1114 }
1115
1116 // get OS packet pointer
1117 *ppOSPacket = (v_VOID_t *) pPacket->pSkb;
1118
1119 // clear it?
1120 if (clearOSPacket)
1121 {
1122 pPacket->pSkb = NULL;
1123 }
1124
1125 return VOS_STATUS_SUCCESS;
1126}
1127
1128/**--------------------------------------------------------------------------
1129
1130 \brief vos_pkt_get_user_data_ptr() - return a pointer to user data area
1131 of a voss Packet
1132
1133 This API returns a pointer to a specified user Data area in the voss
1134 Packet. User data areas are uniqua areas of the voss Packet that can
1135 be used by specific components to store private data. These areas are
1136 identified by a user "ID" and should only be accessed by the component
1137 specified.
1138
1139 \param pPacket - the voss Packet to retreive the user data pointer from.
1140
1141 \param userID - the identifier for the user data area in the voss Packet
1142 to get.
1143
1144 User IDs and user data areas in the voss Packet are
1145 available for:
1146 - Transport Layer (TL)
1147 - Bus Abstraction Layer (BAL)
1148 - SDIO Services Component (SSC)
1149 - Host Device Driver (HDD)
1150
1151 \param ppUserData - pointer to location to return the pointer to the user
1152 data.
1153
1154 \return - Nothing.
1155
1156 \sa
1157
1158 ---------------------------------------------------------------------------*/
1159v_VOID_t vos_pkt_get_user_data_ptr( vos_pkt_t *pPacket,
1160 VOS_PKT_USER_DATA_ID userID,
1161 v_VOID_t **ppUserData )
1162{
1163 // Validate the input and output parameter pointers
1164 if (unlikely(NULL == pPacket))
1165 {
1166 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1167 "VPKT [%d]: NULL pointer", __LINE__);
1168 if (ppUserData != NULL)
1169 {
1170 *ppUserData = NULL;
1171 }
1172 return;
1173 }
1174
1175 // Validate that this really an initialized vos packet
1176 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1177 {
1178 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1179 "VPKT [%d]: Invalid magic", __LINE__);
1180 *ppUserData = NULL;
1181 return;
1182 }
1183
1184 // Validate userID
1185 if (unlikely(userID >= VOS_PKT_USER_DATA_ID_MAX))
1186 {
1187 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1188 "VPKT [%d]: Invalid user ID [%d]", __LINE__, userID);
1189 *ppUserData = NULL;
1190 return;
1191 }
1192
1193 // retreive the user data pointer from the vos Packet and
1194 // return it to the caller.
1195 *ppUserData = pPacket->pvUserData[userID];
1196
1197 return;
1198}
1199
1200
1201/**--------------------------------------------------------------------------
1202
1203 \brief vos_pkt_set_user_data_ptr() - set the user data pointer of a voss
1204 Packet
1205
1206 This API sets a pointer in the specified user Data area in the voss
1207 Packet. User data areas are uniqua areas of the voss Packet that can
1208 be used by specific components to store private data. These areas are
1209 identified by a user "ID" and should only be accessed by the component
1210 specified.
1211
1212 Note: The size of the user data areas in the voss Packet are fixed. The
1213 size of a single pointer is available in each user area.
1214
1215 \param pPacket - the voss Packet to set the user pointer.
1216
1217 \param userID - the identifier for the user data area in the voss Packet
1218 to set.
1219
1220 User IDs and user data areas in the voss Packet are
1221 available for:
1222 - Transport Layer (TL)
1223 - Bus Abstraction Layer (BAL)
1224 - SDIO Services Component (SSC)
1225 - Host Device Driver (HDD)
1226
1227 \param pUserData - pointer value to set in the user data area of the voss
1228 packet..
1229
1230 \return - Nothing.
1231
1232 \sa
1233
1234 ---------------------------------------------------------------------------*/
1235v_VOID_t vos_pkt_set_user_data_ptr( vos_pkt_t *pPacket,
1236 VOS_PKT_USER_DATA_ID userID,
1237 v_VOID_t *pUserData )
1238{
1239 // Validate the input parameter pointer
1240 if (unlikely(NULL == pPacket))
1241 {
1242 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1243 "VPKT [%d]: NULL pointer", __LINE__);
1244 return;
1245 }
1246
1247 // Validate that this is really an initialized vos packet
1248 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1249 {
1250 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1251 "VPKT [%d]: Invalid magic", __LINE__);
1252 return;
1253 }
1254
1255 // Validate userID
1256 if (unlikely(userID >= VOS_PKT_USER_DATA_ID_MAX))
1257 {
1258 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1259 "VPKT [%d]: Invalid user ID [%d]", __LINE__, userID);
1260 return;
1261 }
1262
1263 // retreive the user data pointer from the vos Packet and
1264 // return it to the caller.
1265 pPacket->pvUserData[userID] = pUserData;
1266
1267 return;
1268}
1269
1270/**--------------------------------------------------------------------------
1271
1272 \brief vos_pkt_return_packet() - Return a voss Packet (chain) to vOSS
1273
1274 This API returns a voss Packet to the internally managed packet pool.
1275
1276 Note: If there are multiple packets chained to this packet, the entire
1277 packet chain is returned to vOSS. The caller must unchain the
1278 packets through vos_pkt_get_next_packet() and return them individually
1279 if all packets in the packet chain are not to be returned.
1280
1281 \param pPacket - the voss Packet(s) to return. Note all packets chained
1282 to this packet are returned to vOSS.
1283
1284 \return
1285
1286 \sa
1287
1288 ---------------------------------------------------------------------------*/
1289VOS_STATUS vos_pkt_return_packet( vos_pkt_t *pPacket )
1290{
1291 vos_pkt_t *pNext;
1292 struct list_head *pPktFreeList;
1293 vos_pkt_low_resource_info *pLowResourceInfo;
1294 vos_pkt_get_packet_callback callback;
1295 v_SIZE_t *pCount;
Jeff Johnson295189b2012-06-20 16:38:30 -07001296 VOS_PKT_TYPE packetType = VOS_PKT_TYPE_TX_802_3_DATA;
Mihir Sheteaf278b32014-05-08 13:02:05 +05301297 v_BOOL_t lowResource;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301298 struct mutex * mlock;
Jeff Johnson295189b2012-06-20 16:38:30 -07001299
1300 // Validate the input parameter pointer
1301 if (unlikely(NULL == pPacket))
1302 {
1303 return VOS_STATUS_E_INVAL;
1304 }
1305
1306 // iterate though all packets in the chain
1307 while (pPacket)
1308 {
1309 // unlink this packet from the chain
1310 pNext = pPacket->pNext;
1311 pPacket->pNext = NULL;
1312
Mihir Sheteaf278b32014-05-08 13:02:05 +05301313 lowResource = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001314 // Validate that this really an initialized vos packet
1315 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1318 "VPKT [%d]: Invalid magic", __LINE__);
1319 return VOS_STATUS_E_INVAL;
1320 }
Madan Mohan Koyyalamudi700913e2012-09-24 13:50:50 -07001321
Jeff Johnson295189b2012-06-20 16:38:30 -07001322 //If an skb is attached then reset the pointers
1323 if (pPacket->pSkb)
1324 {
1325 pPacket->pSkb->len = 0;
1326 pPacket->pSkb->data = pPacket->pSkb->head;
1327 skb_reset_tail_pointer(pPacket->pSkb);
1328 skb_reserve(pPacket->pSkb, VPKT_SIZE_BUFFER);
1329 }
1330
1331 pCount = NULL;
1332 // determine which packet pool and low resource block we should use.
1333 switch (pPacket->packetType)
1334 {
1335 case VOS_PKT_TYPE_RX_RAW:
1336 // if this packet still has an skb attached, we can put it
1337 // back in the free pool, otherwise we need to put it in the
1338 // replenish pool
1339 if (pPacket->pSkb)
1340 {
1341 pPktFreeList = &gpVosPacketContext->rxRawFreeList;
1342 pLowResourceInfo = &gpVosPacketContext->rxRawLowResourceInfo;
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -08001343 pCount = &gpVosPacketContext->rxRawFreeListCount;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301344 mlock = &gpVosPacketContext->rxRawFreeListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -07001345 }
1346 else
1347 {
1348 pPktFreeList = &gpVosPacketContext->rxReplenishList;
1349 pLowResourceInfo = NULL;
1350 pCount = &gpVosPacketContext->rxReplenishListCount;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301351 mlock = &gpVosPacketContext->rxReplenishListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -07001352 }
1353 packetType = VOS_PKT_TYPE_RX_RAW;
1354 break;
1355
1356 case VOS_PKT_TYPE_TX_802_11_MGMT:
1357
1358 pPktFreeList = &gpVosPacketContext->txMgmtFreeList;
1359 pLowResourceInfo = &gpVosPacketContext->txMgmtLowResourceInfo;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301360 mlock = &gpVosPacketContext->txMgmtFreeListLock;
1361
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 break;
1363
1364 case VOS_PKT_TYPE_TX_802_3_DATA:
1365 pPktFreeList = &gpVosPacketContext->txDataFreeList;
1366 pLowResourceInfo = &gpVosPacketContext->txDataLowResourceInfo;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301367 mlock = &gpVosPacketContext->txDataFreeListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -07001368 gpVosPacketContext->uctxDataFreeListCount ++;
Jeff Johnson295189b2012-06-20 16:38:30 -07001369 break;
1370
1371 default:
1372 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1373 "VPKT [%d]: invalid packet type %d[%s]",
1374 __LINE__, pPacket->packetType,
1375 vos_pkti_packet_type_str(pPacket->packetType));
1376
1377 return VOS_STATUS_E_INVAL;
1378 }
1379
1380
1381 // is there a low resource condition pending for this packet type?
1382 if (pLowResourceInfo && pLowResourceInfo->callback)
1383 {
Madan Mohan Koyyalamudi87209592012-11-19 20:30:29 -08001384 // pLowResourceInfo->callback is modified from threads (different CPU's).
1385 // So a mutex is enough to protect is against a race condition.
1386 // mutex is SMP safe
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301387 mutex_lock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 callback = pLowResourceInfo->callback;
1389 pLowResourceInfo->callback = NULL;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301390 mutex_unlock(mlock);
Madan Mohan Koyyalamudi87209592012-11-19 20:30:29 -08001391
1392 // only one context can get a valid callback
1393 if(callback)
1394 {
1395 // [DEBUG]
Jeff Johnson1b067b52017-09-19 08:33:10 -07001396 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"VPKT [%d]: recycle %pK", __LINE__, pPacket);
Madan Mohan Koyyalamudi87209592012-11-19 20:30:29 -08001397
1398 // yes, so rather than placing the packet back in the free pool
1399 // we will invoke the low resource callback
1400 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -07001401 "VPKT [%d]: [%pK] Packet recycled, type %d[%s]",
Madan Mohan Koyyalamudi87209592012-11-19 20:30:29 -08001402 __LINE__, pPacket, pPacket->packetType,
1403 vos_pkti_packet_type_str(pPacket->packetType));
1404
1405 // clear out the User Data pointers in the voss packet..
1406 memset(&pPacket->pvUserData, 0, sizeof(pPacket->pvUserData));
1407
1408 // initialize the 'chain' pointer to NULL.
1409 pPacket->pNext = NULL;
1410
1411 // timestamp the vos packet.
1412 pPacket->timestamp = vos_timer_get_system_ticks();
1413
1414 callback(pPacket, pLowResourceInfo->userData);
1415
1416 // We did process low resource condition
1417 lowResource = VOS_TRUE;
1418 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001419 }
Madan Mohan Koyyalamudi87209592012-11-19 20:30:29 -08001420
1421
1422 if(!lowResource)
Jeff Johnson295189b2012-06-20 16:38:30 -07001423 {
1424 // this packet does not satisfy a low resource condition
1425 // so put it back in the appropriate free pool
1426 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1b067b52017-09-19 08:33:10 -07001427 "VPKT [%d]: [%pK] Packet returned, type %d[%s]",
Jeff Johnson295189b2012-06-20 16:38:30 -07001428 __LINE__, pPacket, pPacket->packetType,
1429 vos_pkti_packet_type_str(pPacket->packetType));
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301430 mutex_lock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001431 list_add_tail(&pPacket->node, pPktFreeList);
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301432
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 if (pCount)
1434 {
1435 (*pCount)++;
1436 }
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05301437 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001438 }
1439
1440 // move to next packet in the chain
1441 pPacket = pNext;
1442
1443 } // while (pPacket)
1444
1445 // see if we need to replenish the Rx Raw pool
1446 if (VOS_PKT_TYPE_RX_RAW == packetType)
1447 {
1448 vos_pkti_replenish_raw_pool();
1449 }
1450 return VOS_STATUS_SUCCESS;
1451}
1452
1453/**--------------------------------------------------------------------------
1454
1455 \brief vos_pkt_chain_packet() - chain a voss Packet to another packet
1456
1457 This API chains a voss Packet to another voss Packet, creating a packet
1458 chain. Packets can be chained before or after the current packet in the
1459 packet chain.
1460
1461 \param pPacket - pointer to a voss packet to chain to
1462
1463 \param pChainPacket - pointer to packet to chain
1464
1465 \param chainAfter - boolean to specify to chain packet after or before
1466 the input packet
1467 <ul>
1468 <li> true - chain packet AFTER pPacket (chain behind)
1469 <li> false - chain packet BEFORE pPacket (chain in front)
1470 </ul>
1471
1472 \return
1473
1474 \sa
1475
1476 ---------------------------------------------------------------------------*/
1477VOS_STATUS vos_pkt_chain_packet( vos_pkt_t *pPacket,
1478 vos_pkt_t *pChainPacket,
1479 v_BOOL_t chainAfter )
1480{
1481 // Validate the parameter pointers
1482 if (unlikely((NULL == pPacket) || (NULL == pChainPacket)))
1483 {
1484 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1485 "VPKT [%d]: NULL pointer", __LINE__);
1486 return VOS_STATUS_E_INVAL;
1487 }
1488
1489 // Validate that these are really initialized vos packets
1490 if (unlikely((VPKT_MAGIC_NUMBER != pPacket->magic) ||
1491 (VPKT_MAGIC_NUMBER != pChainPacket->magic)))
1492 {
1493 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1494 "VPKT [%d]: Invalid magic", __LINE__);
1495 return VOS_STATUS_E_INVAL;
1496 }
1497
1498 // swap pointers if we chain before
1499 if (unlikely(VOS_FALSE == chainAfter))
1500 {
1501 vos_pkt_t *pTmp = pPacket;
1502 pPacket = pChainPacket;
1503 pChainPacket = pTmp;
1504 }
1505
1506 // find the end of the chain
1507 while (pPacket->pNext)
1508 {
1509 pPacket = pPacket->pNext;
1510 }
1511
1512 // attach
1513 pPacket->pNext = pChainPacket;
1514
1515 return VOS_STATUS_SUCCESS;
1516}
1517
1518
1519/**--------------------------------------------------------------------------
1520
1521 \brief vos_pkt_walk_packet_chain() - Walk packet chain and (possibly)
1522 unchain packets
1523
1524 This API will walk the voss Packet and unchain the packet from the chain,
1525 if specified. The 'next' packet in the packet chain is returned as the
1526 packet chain is traversed.
1527
1528 \param pPacket - input vos_packet walk
1529
1530 \param ppChainedPacket - pointer to location to return the 'next' voss
1531 packet pointer in the packet chain.
1532 NULL means there is was not packet chained
1533 to this packet.
1534
1535 \param unchainPacket - Flag that specifies if the caller wants the packet
1536 to be removed from the packet chain. This is
1537 provided to allow the caller to walk the packet chain
1538 with or without breaking the chain.
1539
1540 <ul>
1541 <li> true - when set 'true' the API will return
1542 the 'next' packet pointer in the voss Packte chain and
1543 *WILL* unchain the input packet from the packet chain.
1544
1545 <li> NOT false - when set 'false' the API will return
1546 the 'next' packet pointer in the voss Packet chain but
1547 *WILL NOT* unchain the packet chain. This option gives
1548 the caller the ability to walk the packet chain without
1549 modifying it in the process.
1550 </ul>
1551
1552 \note Having the packets chained has an implicaiton on how the return
1553 packet API (vos_pkt_return_packet() ) operates.
1554
1555 \return
1556
1557 \sa
1558
1559 ---------------------------------------------------------------------------*/
1560VOS_STATUS vos_pkt_walk_packet_chain( vos_pkt_t *pPacket,
1561 vos_pkt_t **ppChainedPacket,
1562 v_BOOL_t unchainPacket )
1563{
1564 // Validate the parameter pointers
1565 if (unlikely((NULL == pPacket) || (NULL == ppChainedPacket)))
1566 {
1567 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1568 "VPKT [%d]: NULL pointer", __LINE__);
1569 return VOS_STATUS_E_INVAL;
1570 }
1571
1572 // Validate that this is really an initialized vos packet
1573 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1574 {
1575 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1576 "VPKT [%d]: Invalid magic", __LINE__);
1577 return VOS_STATUS_E_INVAL;
1578 }
1579
1580 // get next packet
1581 *ppChainedPacket = pPacket->pNext;
1582
1583 // if asked to unchain, then unchain it
1584 if (VOS_FALSE != unchainPacket)
1585 {
1586 pPacket->pNext = NULL;
1587 }
1588
1589 // if end of the chain, indicate empty to the caller
1590 if (*ppChainedPacket)
1591 {
1592 return VOS_STATUS_SUCCESS;
1593 }
1594 else
1595 {
1596 return VOS_STATUS_E_EMPTY;
1597 }
1598}
1599
1600/**--------------------------------------------------------------------------
1601
1602 \brief vos_pkt_get_data_vector() - Get data vectors from a voss Packet
1603
1604 This API gets the complete set of Vectors (pointer / length pairs) that
1605 describe all of the data that makes up the voss Packet.
1606
1607 \param pPacket - pointer to the vOSS Packet to get the pointer/length
1608 vector from
1609
1610 \param pVector - pointer to the vector array where the vectors are returned.
1611
1612 \param pNumVectors - Number of vector's in the vector array (at pVector).
1613 On successful return, *pNumVectors is updated with the
1614 number of pointer/length vectors at pVector populated
1615 with valid vectors.
1616
1617 Call with NULL pVector or 0 vectorSize, will return the size of vector
1618 needed (in *pNumVectors)
1619
1620 Caller allocates and frees the vector memory.
1621
1622 \return
1623
1624 \sa
1625
1626 ---------------------------------------------------------------------------*/
1627VOS_STATUS vos_pkt_get_data_vector( vos_pkt_t *pPacket,
1628 vos_pkt_data_vector_t *pVector,
1629 v_SIZE_t *pNumVectors )
1630{
1631 // not supported
1632
1633 VOS_ASSERT(0);
1634 return VOS_STATUS_E_FAILURE;
1635}
1636
1637
1638/**--------------------------------------------------------------------------
1639
1640 \brief vos_pkt_extract_data() - Extract data from the voss Packet.
1641
1642 This API extracts data from a voss Packet, copying the data into the
1643 supplied output buffer. Note the data is copied from the vos packet
1644 but the data remains in the vos packet and the size is unaffected.
1645
1646 \param pPacket - the voss Packet to get the data from.
1647
1648 \param pktOffset - the offset from the start of the voss Packet to get the
1649 data. (i.e. 0 would be the beginning of the voss Packet).
1650
1651 \param pOutputBuffer - Pointer to the location where the voss Packet data
1652 will be copied.
1653
1654 \param pOutputBufferSize - on input, contains the amount of data to extract
1655 into the output buffer. Upon return, contains the amount of data
1656 extracted into the output buffer.
1657
1658 Note: an input of 0 in *pOutputBufferSize, means to copy *all*
1659 data in the voss Packet into the output buffer. The caller is
1660 responsible for assuring the output buffer size is big enough
1661 since the size of the buffer is not being passed in!
1662
1663 \return
1664
1665 \sa
1666
1667 ---------------------------------------------------------------------------*/
1668VOS_STATUS vos_pkt_extract_data( vos_pkt_t *pPacket,
1669 v_SIZE_t pktOffset,
1670 v_VOID_t *pOutputBuffer,
1671 v_SIZE_t *pOutputBufferSize )
1672{
1673 v_SIZE_t len;
1674 struct sk_buff *skb;
1675
1676 // Validate the parameter pointers
1677 if (unlikely((NULL == pPacket) ||
1678 (NULL == pOutputBuffer) ||
1679 (NULL == pOutputBufferSize)))
1680 {
1681 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1682 "VPKT [%d]: NULL pointer", __LINE__);
1683 return VOS_STATUS_E_INVAL;
1684 }
1685
1686 // Validate that this is really an initialized vos packet
1687 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1688 {
1689 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1690 "VPKT [%d]: Invalid magic", __LINE__);
1691 return VOS_STATUS_E_INVAL;
1692 }
1693
1694 // get pointer to the skb
1695 skb = pPacket->pSkb;
1696
1697 // Validate the skb
1698 if (unlikely(NULL == skb))
1699 {
1700 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1701 "VPKT [%d]: NULL skb", __LINE__);
1702 return VOS_STATUS_E_INVAL;
1703 }
1704
1705 // get number of bytes requested
1706 len = *pOutputBufferSize;
1707
1708 // if 0 is input in the *pOutputBufferSize, then the user wants us to
1709 // extract *all* the data in the buffer. Otherwise, the user has
1710 // specified the output buffer size in *pOutputBufferSize. In the
1711 // case where the output buffer size is specified, let's validate that
1712 // it is big enough.
1713 //
1714 // \note: i'm not crazy about this. we should enforce the output
1715 // buffer size on input so this API is not going to cause crashes
1716 // because buffers are too small and the caller inputs 0 == don't care
1717 // to check the size... !!
1718 if (0 == len)
1719 {
1720 len = skb->len - pktOffset;
1721
1722 // return # of bytes copied
1723 *pOutputBufferSize = len;
1724 }
1725 else
1726 {
1727 // make sure we aren't extracting past the end of the packet
1728 if (len > (skb->len - pktOffset))
1729 {
1730 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1731 "VPKT [%d]: Request overrun, "
1732 "req offset %d, req size %d, packet size %d",
1733 __LINE__, pktOffset, len, skb->len);
1734 return VOS_STATUS_E_INVAL;
1735 }
1736 }
1737
1738 // copy the data
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05301739 vos_mem_copy(pOutputBuffer, &skb->data[pktOffset], len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001740
1741 return VOS_STATUS_SUCCESS;
1742}
1743
1744/**--------------------------------------------------------------------------
1745
1746 \brief vos_pkt_extract_data_chain() - Extract data from a voss Packet chain.
1747
1748 This API extracts *all* the data from a voss Packet chain, copying the
1749 data into the supplied output buffer. Note the data is copied from
1750 the vos packet chain but the data remains in the vos packet and the
1751 size of the vos packets are unaffected.
1752
1753 \param pPacket - the first voss Packet in the voss packet chain to
1754 extract data.
1755
1756 \param pOutputBuffer - Pointer to the location where the voss Packet data
1757 will be copied.
1758
1759 \param pOutputBufferSize - on input, contains the maximum amount of data
1760 that can be extracted into the output buffer. Upon return, contains
1761 the amount of data extracted from the packet chain.
1762
1763 \return VOS_STATUS_SUCCESS - the data from the entire packet chain is
1764 extracted and found at *pOutputBuffer. *pOutputBufferSize bytes
1765 were extracted.
1766
1767 VOS_STATUS_E_FAULT - pPacket, pOutputBuffer, or pOutputBufferSize
1768 is not a valid pointer.
1769
1770 VOS_STATUS_E_NOMEM - there is not enough room to extract the data
1771 from the entire packet chain. *pOutputBufferSize has been updated
1772 with the size needed to extract the entier packet chain.
1773
1774 \sa vos_pkt_extract_data()
1775
1776 ---------------------------------------------------------------------------*/
1777VOS_STATUS vos_pkt_extract_data_chain( vos_pkt_t *pPacket,
1778 v_VOID_t *pOutputBuffer,
1779 v_SIZE_t *pOutputBufferSize )
1780{
1781 VOS_STATUS vosStatus;
1782 v_SIZE_t len;
1783 struct sk_buff *skb;
1784
1785 // Validate the parameter pointers
1786 if (unlikely((NULL == pPacket) ||
1787 (NULL == pOutputBuffer) ||
1788 (NULL == pOutputBufferSize)))
1789 {
1790 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1791 "VPKT [%d]: NULL pointer", __LINE__);
1792 return VOS_STATUS_E_INVAL;
1793 }
1794
1795 // Validate that this is really an initialized vos packet
1796 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1797 {
1798 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1799 "VPKT [%d]: Invalid magic", __LINE__);
1800 return VOS_STATUS_E_INVAL;
1801 }
1802
1803 // get the length of the entire packet chain.
1804 vosStatus = vos_pkt_get_packet_chain_length(pPacket, &len);
1805 if (unlikely(VOS_STATUS_SUCCESS != vosStatus))
1806 {
1807 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1808 "VPKT [%d]: Unable to get packet chain length", __LINE__);
1809 return VOS_STATUS_E_FAILURE;
1810 }
1811
1812 // if the output buffer size is too small, return NOMEM and update
1813 // the actual size needed in *pOutputBufferSize
1814 if (len > *pOutputBufferSize)
1815 {
1816 *pOutputBufferSize = len;
1817 return VOS_STATUS_E_NOMEM;
1818 }
1819
1820 // walk through each packet in the chain, copying the data
1821 while (pPacket)
1822 {
1823 // get pointer to the skb
1824 skb = pPacket->pSkb;
1825
1826 // Validate the skb
1827 if (unlikely(NULL == skb))
1828 {
1829 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1830 "VPKT [%d]: NULL skb", __LINE__);
1831 return VOS_STATUS_E_INVAL;
1832 }
1833
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05301834 vos_mem_copy(pOutputBuffer, skb->data, skb->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 pOutputBuffer += skb->len;
1836
1837 pPacket = pPacket->pNext;
1838 }
1839
1840 return VOS_STATUS_SUCCESS;
1841}
1842
1843/**--------------------------------------------------------------------------
1844
1845 \brief vos_pkt_peek_data() - peek into voss Packet at given offset
1846
1847 This API provides a pointer to a specified offset into a voss Packet,
1848 allowing the caller to peek at a given number of bytes in the voss Packet.
1849 Upon successful return, the caller can access "numBytes" of data at
1850 "pPacketData".
1851
1852 This API will fail if the data length requested to peek at is not in
1853 contiguous memory in the voss Packet. In this case, the caller should
1854 use vos_pkt_extract_data() to have the data copied into a caller supplied
1855 buffer.
1856
1857 \param pPacket - the vOSS Packet to peek into
1858
1859 \param pktOffset - the offset into the voss Packet data to peek into.
1860
1861 \param ppPacketData - pointer to the location where the pointer to the
1862 packet data at pktOffset will be returned.
1863
1864 \param numBytes - the number of bytes the caller wishes to peek at.
1865
1866 \return
1867
1868 \sa
1869
1870 ---------------------------------------------------------------------------*/
1871VOS_STATUS vos_pkt_peek_data( vos_pkt_t *pPacket,
1872 v_SIZE_t pktOffset,
1873 v_VOID_t **ppPacketData,
1874 v_SIZE_t numBytes )
1875{
1876 struct sk_buff *skb;
1877
1878 // Validate the parameter pointers
1879 if (unlikely((NULL == pPacket) ||
1880 (NULL == ppPacketData)))
1881 {
1882 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1883 "VPKT [%d]: NULL pointer", __LINE__);
1884 return VOS_STATUS_E_INVAL;
1885 }
1886
1887 // Validate that this is really an initialized vos packet
1888 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1889 {
1890 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1891 "VPKT [%d]: Invalid magic", __LINE__);
1892 return VOS_STATUS_E_INVAL;
1893 }
1894
1895 // Validate numBytes
1896 if (unlikely(0 == numBytes))
1897 {
1898 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1899 "VPKT [%d]: Invalid numBytes", __LINE__);
1900 return VOS_STATUS_E_INVAL;
1901 }
1902
1903 // get pointer to the skb
1904 skb = pPacket->pSkb;
1905
1906 // Validate the skb
1907 if (unlikely(NULL == skb))
1908 {
1909 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1910 "VPKT [%d]: NULL skb", __LINE__);
1911 return VOS_STATUS_E_INVAL;
1912 }
1913
1914 // check for overflow
1915 if (unlikely((pktOffset + numBytes) > skb->len))
1916 {
1917 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1918 "VPKT [%d]: Packet overflow, offset %d size %d len %d",
1919 __LINE__, pktOffset, numBytes, skb->len);
1920 return VOS_STATUS_E_INVAL;
1921 }
1922
1923 // return pointer to the requested data
1924 *ppPacketData = &skb->data[pktOffset];
1925 return VOS_STATUS_SUCCESS;
1926}
1927
1928
1929/**--------------------------------------------------------------------------
1930
1931 \brief vos_pkt_get_packet_type() - Get packet type for a voss Packet
1932
1933 This API returns the packet Type for a voss Packet.
1934
1935 \param pPacket - the voss Packet to get the packet type from.
1936
1937 \param pPacketType - location to return the packet type for the voss Packet
1938
1939 \return
1940
1941 \sa
1942
1943 ---------------------------------------------------------------------------*/
1944VOS_STATUS vos_pkt_get_packet_type( vos_pkt_t *pPacket,
1945 VOS_PKT_TYPE *pPacketType )
1946{
1947 // Validate the parameter pointers
1948 if (unlikely((NULL == pPacket) ||
1949 (NULL == pPacketType)))
1950 {
1951 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1952 "VPKT [%d]: NULL pointer", __LINE__);
1953 return VOS_STATUS_E_INVAL;
1954 }
1955
1956 // Validate that this is really an initialized vos packet
1957 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
1958 {
1959 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1960 "VPKT [%d]: Invalid magic", __LINE__);
1961 return VOS_STATUS_E_INVAL;
1962 }
1963
1964 // return the requested information
1965 *pPacketType = pPacket->packetType;
1966 return VOS_STATUS_SUCCESS;
1967}
1968
1969
1970
1971/**--------------------------------------------------------------------------
1972
1973 \brief vos_pkt_get_packet_length() - Get packet length for a voss Packet
1974
1975 This API returns the total length of the data in a voss Packet.
1976
1977 \param pPacket - the voss Packet to get the packet length from.
1978
1979 \param pPacketSize - location to return the total size of the data contained
1980 in the voss Packet.
1981 \return
1982
1983 \sa
1984
1985 ---------------------------------------------------------------------------*/
1986VOS_STATUS vos_pkt_get_packet_length( vos_pkt_t *pPacket,
1987 v_U16_t *pPacketSize )
1988{
1989 // Validate the parameter pointers
1990 if (unlikely((NULL == pPacket) ||
1991 (NULL == pPacketSize)))
1992 {
1993 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1994 "VPKT [%d]: NULL pointer", __LINE__);
1995 return VOS_STATUS_E_INVAL;
1996 }
1997
1998 // Validate that this is really an initialized vos packet
1999 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2000 {
2001 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2002 "VPKT [%d]: Invalid magic", __LINE__);
2003 return VOS_STATUS_E_INVAL;
2004 }
2005
2006 // Validate the skb
2007 if (unlikely(NULL == pPacket->pSkb))
2008 {
2009 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2010 "VPKT [%d]: NULL skb", __LINE__);
2011 return VOS_STATUS_E_INVAL;
2012 }
2013
2014 // return the requested information
2015 *pPacketSize = pPacket->pSkb->len;
2016 return VOS_STATUS_SUCCESS;
2017}
2018
2019
2020/**--------------------------------------------------------------------------
2021
2022 \brief vos_pkt_get_packet_chain_length() - Get length of a vos packet chain
2023
2024 This API returns the total length of the data in a voss Packet chain.
2025
2026 \param pPacket - the voss Packet at the start of the packet chain. This API
2027 will calculate the length of data in the packet chain stating with
2028 this packet.
2029
2030 \param pPacketSize - location to return the total size of the data contained
2031 in the voss Packet.
2032 \return
2033
2034 \sa
2035
2036 ---------------------------------------------------------------------------*/
2037VOS_STATUS vos_pkt_get_packet_chain_length( vos_pkt_t *pPacketChain,
2038 v_SIZE_t *pPacketChainSize )
2039{
2040 v_SIZE_t chainSize = 0;
2041
2042 // Validate the parameter pointers
2043 if (unlikely((NULL == pPacketChain) ||
2044 (NULL == pPacketChainSize)))
2045 {
2046 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2047 "VPKT [%d]: NULL pointer", __LINE__);
2048 return VOS_STATUS_E_INVAL;
2049 }
2050
2051 // walk through each packet in the chain, adding its length
2052 while (pPacketChain)
2053 {
2054
2055 // Validate that this is really an initialized vos packet
2056 if (unlikely(VPKT_MAGIC_NUMBER != pPacketChain->magic))
2057 {
2058 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2059 "VPKT [%d]: Invalid magic", __LINE__);
2060 return VOS_STATUS_E_INVAL;
2061 }
2062
2063 // Validate the skb
2064 if (unlikely(NULL == pPacketChain->pSkb))
2065 {
2066 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2067 "VPKT [%d]: NULL skb", __LINE__);
2068 return VOS_STATUS_E_INVAL;
2069 }
2070
2071 chainSize += pPacketChain->pSkb->len;
2072 pPacketChain = pPacketChain->pNext;
2073 }
2074
2075 // return result
2076 *pPacketChainSize = chainSize;
2077 return VOS_STATUS_SUCCESS;
2078}
2079
2080
2081/**--------------------------------------------------------------------------
2082
2083 \brief vos_pkt_push_head() - push data on the front a of a voss Packet
2084
2085 This API will push data onto the front of a voss Packet. The data will be
2086 appended in front of any data already contained in the voss Packet.
2087
2088 \param pPacket - the voss Packet to modify.
2089
2090 \param pData - pointer to the data to push onto the head of the voss Packet.
2091
2092 \param dataSize - the size of the data to put onto the head of the voss
2093 Packet.
2094
2095 \return
2096
2097 \sa
2098
2099 ---------------------------------------------------------------------------*/
2100VOS_STATUS vos_pkt_push_head( vos_pkt_t *pPacket,
2101 v_VOID_t *pData,
2102 v_SIZE_t dataSize )
2103{
2104 struct sk_buff *skb;
2105
2106 // Validate the parameter pointers
2107 if (unlikely((NULL == pPacket) || (NULL == pData)))
2108 {
2109 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2110 "VPKT [%d]: NULL pointer", __LINE__);
2111 return VOS_STATUS_E_INVAL;
2112 }
2113
2114 // Validate that this is really an initialized vos packet
2115 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2116 {
2117 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2118 "VPKT [%d]: Invalid magic", __LINE__);
2119 return VOS_STATUS_E_INVAL;
2120 }
2121
2122 // get pointer to the skb
2123 skb = pPacket->pSkb;
2124
2125 // Validate the skb
2126 if (unlikely(NULL == skb))
2127 {
2128 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2129 "VPKT [%d]: NULL skb", __LINE__);
2130 return VOS_STATUS_E_INVAL;
2131 }
2132
2133 // Make sure there is headroom. As a performance optimization we
2134 // can omit this check later since skb_push() will also perform the
2135 // check (except skb_push() will panic the kernel)
2136 if (unlikely(skb_headroom(skb) < dataSize))
2137 {
2138 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2139 "VPKT [%d]: Insufficient headroom, "
Jeff Johnson1b067b52017-09-19 08:33:10 -07002140 "head[%pK], data[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002141 __LINE__, skb->head, skb->data, dataSize);
2142 return VOS_STATUS_E_INVAL;
2143 }
2144
2145 // actually push the data
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05302146 vos_mem_copy(skb_push(skb, dataSize), pData, dataSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07002147
2148 return VOS_STATUS_SUCCESS;
2149}
2150
2151/**--------------------------------------------------------------------------
2152
2153 \brief vos_pkt_reserve_head() - Reserve space at the front of a voss Packet
2154
2155 This API will reserve space at the front of a voss Packet. The caller can
2156 then copy data into this reserved space using memcpy() like functions. This
2157 allows the caller to reserve space and build headers directly in this
2158 reserved space in the voss Packet.
2159
2160 Upon successful return, the length of the voss Packet is increased by
2161 dataSize.
2162
2163 < put a before / after picture here>
2164
2165 \param pPacket - the voss Packet to modify.
2166
2167 \param ppData - pointer to the location where the pointer to the reserved
2168 space is returned. Upon successful return, the caller has
2169 write / read access to the data space at *ppData for length
2170 dataSize to build headers, etc.
2171
2172 \param dataSize - the size of the data to reserve at the head of the voss
2173 Packet. Upon successful return, the length of the voss
2174 Packet is increased by dataSize.
2175
2176 \return
2177
2178 \sa
2179
2180 ---------------------------------------------------------------------------*/
2181VOS_STATUS vos_pkt_reserve_head( vos_pkt_t *pPacket,
2182 v_VOID_t **ppData,
2183 v_SIZE_t dataSize )
2184{
2185 struct sk_buff *skb;
2186 struct sk_buff *newskb;
2187
2188 // Validate the parameter pointers
2189 if (unlikely((NULL == pPacket) || (NULL == ppData)))
2190 {
2191 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2192 "VPKT [%d]: NULL pointer", __LINE__);
2193 return VOS_STATUS_E_INVAL;
2194 }
2195
2196 // Validate that this is really an initialized vos packet
2197 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2198 {
2199 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2200 "VPKT [%d]: Invalid magic", __LINE__);
2201 return VOS_STATUS_E_INVAL;
2202 }
2203
2204 // get pointer to the skb
2205 skb = pPacket->pSkb;
2206
2207 // Validate the skb
2208 if (unlikely(NULL == skb))
2209 {
2210 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2211 "VPKT [%d]: NULL skb", __LINE__);
2212 return VOS_STATUS_E_INVAL;
2213 }
2214
2215 // Make sure there is headroom. As a performance optimization we
2216 // can omit this check later since skb_push() will also perform the
2217 // check (except skb_push() will panic the kernel)
2218 if (unlikely(skb_headroom(skb) < dataSize))
2219 {
2220 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
2221 "VPKT [%d]: Insufficient headroom, "
Jeff Johnson1b067b52017-09-19 08:33:10 -07002222 "head[%pK], data[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002223 __LINE__, skb->head, skb->data, dataSize);
2224
2225 if ((newskb = skb_realloc_headroom(skb, dataSize)) == NULL) {
2226 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2227 "VPKT [%d]: Failed to realloc headroom", __LINE__);
2228 return VOS_STATUS_E_INVAL;
2229 }
2230
2231 kfree_skb(skb);
2232 skb = newskb;
2233
2234 // set the skb pointer
2235 pPacket->pSkb = newskb;
2236 }
2237
2238 // actually allocate the headroom
2239 *ppData = skb_push(skb, dataSize);
2240 // Zero out so we dont take the fastpath on Android.
2241 memset( (void *)*ppData, 0, dataSize );
2242
2243 return VOS_STATUS_SUCCESS;
2244}
2245
2246
2247/**--------------------------------------------------------------------------
2248
2249 \brief vos_pkt_reserve_head_fast() - Reserve space at the front of a voss Packet
2250
2251 This API will reserve space at the front of a voss Packet. The caller can
2252 then copy data into this reserved space using memcpy() like functions. This
2253 allows the caller to reserve space and build headers directly in this
2254 reserved space in the voss Packet.
2255
2256 Upon successful return, the length of the voss Packet is increased by
2257 dataSize.
2258
2259 Same as above APi but no memset to 0 at the end.
2260
2261 < put a before / after picture here>
2262
2263 \param pPacket - the voss Packet to modify.
2264
2265 \param ppData - pointer to the location where the pointer to the reserved
2266 space is returned. Upon successful return, the caller has
2267 write / read access to the data space at *ppData for length
2268 dataSize to build headers, etc.
2269
2270 \param dataSize - the size of the data to reserve at the head of the voss
2271 Packet. Upon successful return, the length of the voss
2272 Packet is increased by dataSize.
2273
2274 \return
2275
2276 \sa
2277
2278 ---------------------------------------------------------------------------*/
2279VOS_STATUS vos_pkt_reserve_head_fast( vos_pkt_t *pPacket,
2280 v_VOID_t **ppData,
2281 v_SIZE_t dataSize )
2282{
2283 struct sk_buff *skb;
2284 struct sk_buff *newskb;
2285
2286 // get pointer to the skb
2287 skb = pPacket->pSkb;
2288
2289 // Validate the skb
2290 if (unlikely(NULL == skb))
2291 {
2292 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2293 "VPKT [%d]: NULL skb", __LINE__);
2294 return VOS_STATUS_E_INVAL;
2295 }
2296
2297 // Make sure there is headroom. As a performance optimization we
2298 // can omit this check later since skb_push() will also perform the
2299 // check (except skb_push() will panic the kernel)
2300 if (unlikely(skb_headroom(skb) < dataSize))
2301 {
2302 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
2303 "VPKT [%d]: Insufficient headroom, "
Jeff Johnson1b067b52017-09-19 08:33:10 -07002304 "head[%pK], data[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002305 __LINE__, skb->head, skb->data, dataSize);
2306
2307 if ((newskb = skb_realloc_headroom(skb, dataSize)) == NULL) {
2308 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2309 "VPKT [%d]: Failed to realloc headroom", __LINE__);
2310 return VOS_STATUS_E_INVAL;
2311 }
2312
2313 kfree_skb(skb);
2314 skb = newskb;
2315
2316 // set the skb pointer
2317 pPacket->pSkb = newskb;
2318 }
2319
2320 // actually allocate the headroom
2321 *ppData = skb_push(skb, dataSize);
2322 // Zero out so we dont take the fastpath on Android.
2323 //memset( (void *)*ppData, 0, dataSize );
2324
2325 return VOS_STATUS_SUCCESS;
2326}
2327
2328/**--------------------------------------------------------------------------
2329
2330 \brief vos_pkt_pop_head() - Remove data from the front of the voss Packet
2331
2332 This API removes data from the front of a voss Packet. The data is
2333 copied into the output buffer described by pData and pDataSize
2334
2335 \param pPacket - the voss Packet to operate on.
2336
2337 \param pData - pointer to the data buffer where the data removed from the
2338 voss Packet is placed.
2339
2340 \param dataSize - The amount of space to remove from the head of the voss
2341 Packet. The output buffer (at *pData) must contain at
2342 least this amount of space.
2343
2344 \return
2345
2346 \sa
2347
2348 ---------------------------------------------------------------------------*/
2349VOS_STATUS vos_pkt_pop_head( vos_pkt_t *pPacket,
2350 v_VOID_t *pData,
2351 v_SIZE_t dataSize )
2352{
2353 struct sk_buff *skb;
2354
2355 // Validate the parameter pointers
2356 if (unlikely((NULL == pPacket) || (NULL == pData)))
2357 {
2358 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2359 "VPKT [%d]: NULL pointer", __LINE__);
2360 return VOS_STATUS_E_INVAL;
2361 }
2362
2363 // Validate that this is really an initialized vos packet
2364 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2365 {
2366 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2367 "VPKT [%d]: Invalid magic", __LINE__);
2368 return VOS_STATUS_E_INVAL;
2369 }
2370
2371 // get pointer to the skb
2372 skb = pPacket->pSkb;
2373
2374 // Validate the skb
2375 if (unlikely(NULL == skb))
2376 {
2377 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2378 "VPKT [%d]: NULL skb", __LINE__);
2379 return VOS_STATUS_E_INVAL;
2380 }
2381
2382 // Make sure there is enough data to pop
2383 if (unlikely(skb->len < dataSize))
2384 {
Kaushik, Sushante386ee12014-05-01 15:50:52 +05302385 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -07002386 "VPKT [%d]: pop exceeds packet size, len[%d], req[%d]",
2387 __LINE__, skb->len, dataSize);
2388 return VOS_STATUS_E_INVAL;
2389 }
2390
2391 // copy the data
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05302392 vos_mem_copy(pData, skb->data, dataSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07002393 skb_pull(skb, dataSize);
2394
2395 return VOS_STATUS_SUCCESS;
2396}
2397
2398
2399/**--------------------------------------------------------------------------
2400
2401 \brief vos_pkt_trim_head() - Skip over bytes at the front of a voss Packet
2402
2403 This API moves the pointers at the head of a voss Packet to essentially
2404 skip over data at the front of a voss Packet. Upon successful return, the
2405 length of the voss Packet is reduced by dataSize and the starting pointer
2406 to the voss Packet is adjusted to eliminate the data from the start of the
2407 voss Packet.
2408
2409 This API has the opposite effect of \a vos_pkt_reserve_head().
2410
2411 \param pPacket - the voss Packet to operate on.
2412
2413 \param dataSize - The amount of space to skip at the start of the voss
2414 Packet.
2415
2416 Note that upon return, the data skipped over is
2417 inaccessible to the caller. If the caller needs access
2418 to the head data, use vos_pkt_pop_head() or
2419 vos_pkt_extract_data() to get a copy of the data.
2420
2421 \return
2422
2423 \sa
2424
2425 ---------------------------------------------------------------------------*/
2426VOS_STATUS vos_pkt_trim_head( vos_pkt_t *pPacket,
2427 v_SIZE_t dataSize )
2428{
2429 struct sk_buff *skb;
2430
2431 // Validate the parameter pointers
2432 if (unlikely(NULL == pPacket))
2433 {
2434 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2435 "VPKT [%d]: NULL pointer", __LINE__);
2436 return VOS_STATUS_E_INVAL;
2437 }
2438
2439 // Validate that this is really an initialized vos packet
2440 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2441 {
2442 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2443 "VPKT [%d]: Invalid magic", __LINE__);
2444 return VOS_STATUS_E_INVAL;
2445 }
2446
2447 // get pointer to the skb
2448 skb = pPacket->pSkb;
2449
2450 // Validate the skb
2451 if (unlikely(NULL == skb))
2452 {
2453 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2454 "VPKT [%d]: NULL skb", __LINE__);
2455 return VOS_STATUS_E_INVAL;
2456 }
2457
2458 // Make sure there is enough data to trim
2459 if (unlikely(skb->len < dataSize))
2460 {
2461 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2462 "VPKT [%d]: trim exceeds packet size, len[%d], req[%d]",
2463 __LINE__, skb->len, dataSize);
2464 return VOS_STATUS_E_INVAL;
2465 }
2466
2467 // adjust the skb
2468 skb_pull(skb, dataSize);
2469
2470 return VOS_STATUS_SUCCESS;
2471}
2472
2473/**--------------------------------------------------------------------------
2474
2475 \brief vos_pkt_push_tail() - push data on the end a of a voss Packet
2476
2477 This API will push data onto the end of a voss Packet. The data will be
2478 appended to the end of any data already contained in the voss Packet.
2479
2480 \param pPacket - the voss Packet to modify.
2481
2482 \param pData - pointer to the data to push onto the tail of the voss Packet.
2483
2484 \param dataSize - the size of the data to put onto the tail of the voss Packet.
2485
2486 \return
2487
2488 \sa
2489
2490 ---------------------------------------------------------------------------*/
2491VOS_STATUS vos_pkt_push_tail( vos_pkt_t *pPacket,
2492 v_VOID_t *pData,
2493 v_SIZE_t dataSize )
2494{
2495 struct sk_buff *skb;
2496
2497 // Validate the parameter pointers
2498 if (unlikely((NULL == pPacket) || (NULL == pData)))
2499 {
2500 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2501 "VPKT [%d]: NULL pointer", __LINE__);
2502 return VOS_STATUS_E_INVAL;
2503 }
2504
2505 // Validate that this is really an initialized vos packet
2506 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2507 {
2508 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2509 "VPKT [%d]: Invalid magic", __LINE__);
2510 return VOS_STATUS_E_INVAL;
2511 }
2512
2513 // get pointer to the skb
2514 skb = pPacket->pSkb;
2515
2516 // Validate the skb
2517 if (unlikely(NULL == skb))
2518 {
2519 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2520 "VPKT [%d]: NULL skb", __LINE__);
2521 return VOS_STATUS_E_INVAL;
2522 }
2523
2524 // Make sure there is tailroom. As a performance optimization we
2525 // can omit this check later since skb_put() will also perform the
2526 // check (except skb_put() will panic the kernel)
2527 if (unlikely(skb_tailroom(skb) < dataSize))
2528 {
2529 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2530 "VPKT [%d]: Insufficient tailroom, "
Jeff Johnson1b067b52017-09-19 08:33:10 -07002531 "tail[%pK], end[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002532 __LINE__, skb_tail_pointer(skb),
2533 skb_end_pointer(skb), dataSize);
2534 return VOS_STATUS_E_INVAL;
2535 }
2536
2537 // actually push the data
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05302538 vos_mem_copy(skb_put(skb, dataSize), pData, dataSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07002539
2540 return VOS_STATUS_SUCCESS;
2541}
2542
2543
2544/**--------------------------------------------------------------------------
2545
2546 \brief vos_pkt_reserve_tail() - Reserve space at the end of a voss Packet
2547
2548 This API will reserve space at the end of a voss Packet. The caller can
2549 then copy data into this reserved space using memcpy() like functions. This
2550 allows the caller to reserve space and build headers directly in this
2551 reserved space in the voss Packet.
2552
2553 Upon successful return, the length of the voss Packet is increased by
2554 dataSize.
2555
2556 \param pPacket - the voss Packet to modify.
2557
2558 \param ppData - pointer to the location where the pointer to the reserved
2559 space is returned. Upon successful return, the caller has
2560 write / read access to the data space at *ppData for length
2561 dataSize to build headers, etc.
2562
2563 \param dataSize - the size of the data to reserve at the head of the voss
2564 Packet. Upon successful return, the length of the voss
2565 Packet is increased by dataSize.
2566
2567 \return
2568
2569 \sa
2570
2571 ---------------------------------------------------------------------------*/
2572VOS_STATUS vos_pkt_reserve_tail( vos_pkt_t *pPacket,
2573 v_VOID_t **ppData,
2574 v_SIZE_t dataSize )
2575{
2576 struct sk_buff *skb;
2577
2578 // Validate the parameter pointers
2579 if (unlikely((NULL == pPacket) || (NULL == ppData)))
2580 {
2581 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2582 "VPKT [%d]: NULL pointer", __LINE__);
2583 return VOS_STATUS_E_INVAL;
2584 }
2585
2586 // Validate that this is really an initialized vos packet
2587 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2588 {
2589 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2590 "VPKT [%d]: Invalid magic", __LINE__);
2591 return VOS_STATUS_E_INVAL;
2592 }
2593
2594 // get pointer to the skb
2595 skb = pPacket->pSkb;
2596
2597 // Validate the skb
2598 if (unlikely(NULL == skb))
2599 {
2600 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2601 "VPKT [%d]: NULL skb", __LINE__);
2602 return VOS_STATUS_E_INVAL;
2603 }
2604
2605 // Make sure there is tailroom. As a performance optimization we
2606 // can omit this check later since skb_put() will also perform the
2607 // check (except skb_put() will panic the kernel)
2608 if (unlikely(skb_tailroom(skb) < dataSize))
2609 {
2610 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2611 "VPKT [%d]: Insufficient tailroom, "
Jeff Johnson1b067b52017-09-19 08:33:10 -07002612 "tail[%pK], end[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002613 __LINE__, skb_tail_pointer(skb),
2614 skb_end_pointer(skb), dataSize);
2615 return VOS_STATUS_E_INVAL;
2616 }
2617
2618 // actually allocate the space
2619 *ppData = skb_put(skb, dataSize);
2620
2621 return VOS_STATUS_SUCCESS;
2622}
2623
2624
2625
2626/**--------------------------------------------------------------------------
2627
2628 \brief vos_pkt_pop_tail() - Remove data from the end of the voss Packet
2629
2630 This API removes data from the end of a voss Packet. The data is
2631 copied into the output buffer described by pData and pDataSize
2632
2633 \param pPacket - the voss Packet to operate on.
2634
2635 \param pData - pointer to the data buffer where the data removed from the
2636 voss Packet is placed.
2637
2638 \param dataSize - The amount of space to remove from the end of the voss
2639 Packet. The output buffer (at *pData) must contain at
2640 least this amount of space.
2641
2642 \return
2643
2644 \sa
2645
2646 ---------------------------------------------------------------------------*/
2647VOS_STATUS vos_pkt_pop_tail( vos_pkt_t *pPacket,
2648 v_VOID_t *pData,
2649 v_SIZE_t dataSize )
2650{
2651 struct sk_buff *skb;
2652
2653 // Validate the parameter pointers
2654 if (unlikely((NULL == pPacket) || (NULL == pData)))
2655 {
2656 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2657 "VPKT [%d]: NULL pointer", __LINE__);
2658 return VOS_STATUS_E_INVAL;
2659 }
2660
2661 // Validate that this is really an initialized vos packet
2662 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2663 {
2664 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2665 "VPKT [%d]: Invalid magic", __LINE__);
2666 return VOS_STATUS_E_INVAL;
2667 }
2668
2669 // get pointer to the skb
2670 skb = pPacket->pSkb;
2671
2672 // Validate the skb
2673 if (unlikely(NULL == skb))
2674 {
2675 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2676 "VPKT [%d]: NULL skb", __LINE__);
2677 return VOS_STATUS_E_INVAL;
2678 }
2679
2680 // Make sure there is enough data to pop
2681 if (unlikely(skb->len < dataSize))
2682 {
Kaushik, Sushante386ee12014-05-01 15:50:52 +05302683 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -07002684 "VPKT [%d]: pop exceeds packet size, len[%d], req[%d]",
2685 __LINE__, skb->len, dataSize);
2686 return VOS_STATUS_E_INVAL;
2687 }
2688
2689 // adjust pointers (there isn't a native Linux API for this)
2690 skb->tail -= dataSize;
2691 skb->len -= dataSize;
2692
2693 // actually push the data
Rajesh Babu Prathipatiddbe2892014-07-01 18:57:16 +05302694 vos_mem_copy(pData, skb_tail_pointer(skb), dataSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07002695
2696 return VOS_STATUS_SUCCESS;
2697}
2698
2699/**--------------------------------------------------------------------------
2700
2701 \brief vos_pkt_trim_tail() - Skip over bytes at the end of a voss Packet
2702
2703 This API moves the pointers at the head of a voss Packet to essentially
2704 skip over data at the end of a voss Packet. Upon successful return, the
2705 length of the voss Packet is reduced by dataSize and voss Packet is
2706 adjusted to eliminate the data from the end of the voss Packet.
2707
2708 This API has the opposite effect of \a vos_pkt_reserve_tail().
2709
2710 \param pPacket - the voss Packet to operate on.
2711
2712 \param dataSize - The amount of space to remove at the end of the voss
2713 Packet.
2714
2715 Note that upon return, the data skipped over is
2716 inaccessible to the caller. If the caller needs access
2717 to the tail data, use vos_pkt_pop_tail() or
2718 vos_pkt_extract_data() to get a copy of the data.
2719
2720 \return
2721
2722 \sa
2723
2724 ---------------------------------------------------------------------------*/
2725VOS_STATUS vos_pkt_trim_tail( vos_pkt_t *pPacket,
2726 v_SIZE_t dataSize )
2727{
2728 struct sk_buff *skb;
2729
2730 // Validate the parameter pointers
2731 if (unlikely(NULL == pPacket))
2732 {
2733 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2734 "VPKT [%d]: NULL pointer", __LINE__);
2735 return VOS_STATUS_E_INVAL;
2736 }
2737
2738 // Validate that this is really an initialized vos packet
2739 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2740 {
2741 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2742 "VPKT [%d]: Invalid magic", __LINE__);
2743 return VOS_STATUS_E_INVAL;
2744 }
2745
2746 // get pointer to the skb
2747 skb = pPacket->pSkb;
2748
2749 // Validate the skb
2750 if (unlikely(NULL == skb))
2751 {
2752 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2753 "VPKT [%d]: NULL skb", __LINE__);
2754 return VOS_STATUS_E_INVAL;
2755 }
2756
2757 // Make sure there is enough data to pop
2758 if (unlikely(skb->len < dataSize))
2759 {
Kaushik, Sushante386ee12014-05-01 15:50:52 +05302760 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Jeff Johnson295189b2012-06-20 16:38:30 -07002761 "VPKT [%d]: pop exceeds packet size, len[%d], req[%d]",
2762 __LINE__, skb->len, dataSize);
2763 return VOS_STATUS_E_INVAL;
2764 }
2765
2766 // adjust pointers (there isn't a native Linux API for this)
2767 skb->tail -= dataSize;
2768 skb->len -= dataSize;
2769
2770 return VOS_STATUS_SUCCESS;
2771}
2772
2773
2774/**--------------------------------------------------------------------------
2775
2776 \brief vos_pkt_get_timestamp() - Retrive the timestamp attribute from the
2777 specified VOSS packet
2778
2779 \param pPacket - the voss Packet to operate on.
2780
2781 \param pTstamp - the timestamp will be returned here.
2782
2783 \return VOS_STATUS_E_FAULT - invalid parameter(s) specified
2784
2785 VOS_STATUS_SUCCESS - timestamp retrived successfully
2786
2787 \sa
2788
2789 ---------------------------------------------------------------------------*/
2790VOS_STATUS vos_pkt_get_timestamp( vos_pkt_t *pPacket,
2791 v_TIME_t* pTstamp )
2792{
2793 // Validate the parameter pointers
2794 if (unlikely((NULL == pPacket) ||
2795 (NULL == pTstamp)))
2796 {
2797 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2798 "VPKT [%d]: NULL pointer", __LINE__);
2799 return VOS_STATUS_E_INVAL;
2800 }
2801
2802 // Validate that this is really an initialized vos packet
2803 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2804 {
2805 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2806 "VPKT [%d]: Invalid magic", __LINE__);
2807 return VOS_STATUS_E_INVAL;
2808 }
2809
2810 // return the requested information
2811 *pTstamp = pPacket->timestamp;
2812 return VOS_STATUS_SUCCESS;
2813}
2814
2815
2816/**--------------------------------------------------------------------------
2817
2818 \brief vos_pkt_flatten_rx_pkt() - Transform a platform based RX VOSS
2819 packet into a flat buffer based VOSS packet if needed. This is needed in
2820 cases where for reasons of efficiency we want the RX packets to be very
2821 platform specific (for e.g. DSM based on AMSS, etc). However platform
2822 independent code may rely on making calls on the VOSS packet which can only
2823 be supported by the flat buffer based implementation of a RX packet. This API
2824 will allocate a new VOSS packet with flat buffer, extract the data from the
2825 input VOSS packet and then release the input VOSS packet. The new VOSS packet
2826 will be returned from this call.
2827
2828 \param ppPacket - the voss Packet to operate on. On input contains
2829 the platform based packet. On output contains the flat
2830 buffer based packet. Any applicable resources
2831 are freed as part of this call.
2832
2833 \return VOS_STATUS_E_FAULT - invalid parameter specified
2834
2835 VOS_STATUS_E_INVAL - packet type not RX_RAW
2836
2837 VOS_STATUS_SUCCESS - transform successful
2838
2839 other VOSS status - other errors encountered
2840
2841 \sa
2842
2843 ----------------------------------------------------------------------------*/
2844VOS_STATUS vos_pkt_flatten_rx_pkt( vos_pkt_t **ppPacket )
2845{
2846 // Linux/Android skbs are already flat, no work required
2847 return VOS_STATUS_SUCCESS;
2848}
2849
2850/**--------------------------------------------------------------------------
2851
2852 \brief vos_pkt_set_rx_length() - Set the length of a received packet
2853
2854 This API set the length of the data inside the packet after a DMA has occurred
2855 on rx, it will also set the tail pointer to the end of the data.
2856
2857 \param pPacket - the voss Packet to operate on.
2858
2859 \param pktLen - The size of the data placed in the Rx packet during DMA.
2860
2861
2862 \return
2863
2864 \sa
2865
2866 ---------------------------------------------------------------------------*/
2867VOS_STATUS vos_pkt_set_rx_length( vos_pkt_t *pPacket,
2868 v_SIZE_t pktLen )
2869{
2870 struct sk_buff *skb;
2871
2872 // Validate the parameter pointers
2873 if (unlikely(NULL == pPacket))
2874 {
2875 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2876 "VPKT [%d]: NULL pointer", __LINE__);
2877 return VOS_STATUS_E_INVAL;
2878 }
2879
2880 // Validate that this is really an initialized vos packet
2881 if (unlikely(VPKT_MAGIC_NUMBER != pPacket->magic))
2882 {
2883 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2884 "VPKT [%d]: Invalid magic", __LINE__);
2885 return VOS_STATUS_E_INVAL;
2886 }
2887
2888 // get pointer to the skb
2889 skb = pPacket->pSkb;
2890
2891 // Validate the skb
2892 if (unlikely(NULL == skb))
2893 {
2894 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2895 "VPKT [%d]: NULL skb", __LINE__);
2896 return VOS_STATUS_E_INVAL;
2897 }
2898
2899 // adjust pointers (there isn't a native Linux API for this)
2900 // ?? - is this sufficient?
2901 skb_set_tail_pointer(skb, pktLen);
2902 skb->len = pktLen;
2903
2904 return VOS_STATUS_SUCCESS;
2905
2906}
2907/**--------------------------------------------------------------------------
2908
2909 \brief vos_pkt_get_available_buffer_pool() - Get avaliable VOS packet size
2910 VOSS Packet pool is limitted resource
2911 VOSS Client need to know how many packet pool is still avaliable to control
2912 the flow
2913
2914 \param pktType - Packet type want to know free buffer count
2915 VOS_PKT_TYPE_TX_802_11_MGMT, management free buffer count,
2916 VOS_PKT_TYPE_TX_802_11_DATA
2917 VOS_PKT_TYPE_TX_802_3_DATA, TX free buffer count
2918 VOS_PKT_TYPE_RX_RAW, RX free buffer count
2919
2920 vosFreeBuffer - free frame buffer size
2921
2922 \return VOS_STATUS_E_INVAL - invalid input parameter
2923
2924 VOS_STATUS_SUCCESS - Get size success
2925
2926 \sa
2927
2928 ----------------------------------------------------------------------------*/
2929VOS_STATUS vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE pktType,
2930 v_SIZE_t *vosFreeBuffer)
2931{
2932 struct list_head *pList;
2933 struct list_head *pNode;
2934 v_SIZE_t count;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05302935 struct mutex *mlock;
2936
Jeff Johnson295189b2012-06-20 16:38:30 -07002937 if (NULL == vosFreeBuffer)
2938 {
2939 return VOS_STATUS_E_INVAL;
2940 }
2941
2942 switch (pktType)
2943 {
2944 case VOS_PKT_TYPE_TX_802_11_MGMT:
2945 pList = &gpVosPacketContext->txMgmtFreeList;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05302946 mlock = &gpVosPacketContext->txMgmtFreeListLock;
Jeff Johnson295189b2012-06-20 16:38:30 -07002947 break;
2948
2949 case VOS_PKT_TYPE_TX_802_11_DATA:
2950 case VOS_PKT_TYPE_TX_802_3_DATA:
Jeff Johnson295189b2012-06-20 16:38:30 -07002951 if (VOS_STA_SAP_MODE == hdd_get_conparam())
2952 {
2953 *vosFreeBuffer = gpVosPacketContext->uctxDataFreeListCount;
2954 return VOS_STATUS_SUCCESS;
2955 }
2956 else
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05302957 {
2958 pList = &gpVosPacketContext->txDataFreeList;
2959 mlock = &gpVosPacketContext->txDataFreeListLock;
2960 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002961 break;
2962
2963 case VOS_PKT_TYPE_RX_RAW:
2964 // if the caller is curious how many raw packets are available
2965 // then he probably wants as many packets to be available as
2966 // possible so replenish the raw pool
2967 vos_pkti_replenish_raw_pool();
Mahesh Kumar Kalikot Veetil78b1f372013-02-21 17:32:37 -08002968 // Return the pre-calculated count 'rxRawFreeListCount'
2969 *vosFreeBuffer = gpVosPacketContext->rxRawFreeListCount;
2970 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002971 break;
2972
2973 default:
2974 return (VOS_STATUS_E_INVAL);
2975 }
2976
2977 count = 0;
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05302978 mutex_lock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -07002979 list_for_each(pNode, pList)
2980 {
2981 count++;
2982 }
Madan Mohan Koyyalamudi1c2d1232013-10-07 23:30:54 +05302983 mutex_unlock(mlock);
Jeff Johnson295189b2012-06-20 16:38:30 -07002984 *vosFreeBuffer = count;
2985 return VOS_STATUS_SUCCESS;
2986}
2987
Sameer Thalappild0158402013-05-03 13:19:03 -07002988/**
2989 @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of RX packets
2990 that should be allocated.
2991
2992 This function is called by VOS packet module to know how many RX raw
2993 packets it should allocate/reserve. This value can be configured thru
2994 Kernel device tree to save memory usage.
2995
2996 @param
2997 NONE
2998 @return
2999 v_SIZE_t the number of packets to allocate
3000
3001*/
3002v_SIZE_t vos_pkt_get_num_of_rx_raw_pkts(void)
3003{
3004#ifdef HAVE_WCNSS_RX_BUFF_COUNT
3005 v_SIZE_t buffCount;
3006
3007 buffCount = wcnss_get_wlan_rx_buff_count();
3008 return (buffCount > VPKT_NUM_RX_RAW_PACKETS ?
3009 VPKT_NUM_RX_RAW_PACKETS : buffCount);
3010#else
3011 return VPKT_NUM_RX_RAW_PACKETS;
3012#endif
3013}
Jeff Johnson295189b2012-06-20 16:38:30 -07003014
Mihir Sheted183cef2014-09-26 19:17:56 +05303015/**
3016 @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of times
3017 skb allocation failed while replenishing packets
3018
3019
3020 @param
3021 NONE
3022 @return
3023 v_SIZE_t the number of times packet allocation failed
3024
3025*/
3026v_SIZE_t vos_pkt_get_num_of_rx_pkt_alloc_failures(void)
3027{
3028 v_SIZE_t failCount;
3029
3030 mutex_lock(&gpVosPacketContext->rxReplenishListLock);
3031 mutex_lock(&gpVosPacketContext->rxRawFreeListLock);
3032
3033 failCount = gpVosPacketContext->rxReplenishFailCount;
3034
3035 mutex_unlock(&gpVosPacketContext->rxReplenishListLock);
3036 mutex_unlock(&gpVosPacketContext->rxRawFreeListLock);
3037
3038 return failCount;
3039}
3040
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08003041v_U8_t vos_pkt_get_proto_type
3042(
3043 void *pskb,
3044 v_U8_t tracking_map
3045)
3046{
3047 v_U8_t pkt_proto_type = 0;
3048 v_U16_t ether_type;
3049 v_U16_t SPort;
3050 v_U16_t DPort;
3051 struct sk_buff *skb = NULL;
3052
3053
3054 if (NULL == pskb)
3055 {
3056 return pkt_proto_type;
3057 }
3058 else
3059 {
3060 skb = (struct sk_buff *)pskb;
3061 }
3062
3063 /* EAPOL Tracking enabled */
3064 if (VOS_PKT_PROTO_TYPE_EAPOL & tracking_map)
3065 {
3066 ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET));
3067 if (VOS_PKT_PROT_EAPOL_ETH_TYPE == VOS_SWAP_U16(ether_type))
3068 {
3069 pkt_proto_type |= VOS_PKT_PROTO_TYPE_EAPOL;
3070 }
3071 }
3072
Mihir Shete39f7c752015-06-11 15:40:09 +05303073 /* ARP Tracking Enabled */
3074 if (VOS_PKT_PROTO_TYPE_ARP & tracking_map)
3075 {
3076 ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET));
3077 if (VOS_PKT_PROT_ARP_ETH_TYPE == VOS_SWAP_U16(ether_type))
3078 {
3079 pkt_proto_type |= VOS_PKT_PROTO_TYPE_ARP;
3080 }
3081 }
3082
Tushnim Bhattacharyyaa3ba5a52014-01-30 11:37:33 -08003083 /* DHCP Tracking enabled */
3084 if (VOS_PKT_PROTO_TYPE_DHCP & tracking_map)
3085 {
3086 SPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_IP_OFFSET +
3087 VOS_PKT_PROT_IP_HEADER_SIZE));
3088 DPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_IP_OFFSET +
3089 VOS_PKT_PROT_IP_HEADER_SIZE + sizeof(v_U16_t)));
3090 if (((VOS_PKT_PROT_DHCP_SRV_PORT == VOS_SWAP_U16(SPort)) &&
3091 (VOS_PKT_PROT_DHCP_CLI_PORT == VOS_SWAP_U16(DPort))) ||
3092 ((VOS_PKT_PROT_DHCP_CLI_PORT == VOS_SWAP_U16(SPort)) &&
3093 (VOS_PKT_PROT_DHCP_SRV_PORT == VOS_SWAP_U16(DPort))))
3094 {
3095 pkt_proto_type |= VOS_PKT_PROTO_TYPE_DHCP;
3096 }
3097 }
3098
3099 /* Protocol type map */
3100 return pkt_proto_type;
3101}
Bhargav Shah7dbfb6f2016-02-12 20:49:58 +05303102
Asodi T,Venkateswara Reddy9826c872017-01-18 19:08:25 +05303103bool vos_is_arp_pkt(void *pskb, bool is_translated)
3104{
3105 v_U16_t ether_type;
3106 struct sk_buff *skb = NULL;
3107#define HEADER_OFFSET_802_11 20
3108
3109 if (NULL == pskb)
3110 {
3111 return FALSE;
3112 }
3113
3114 skb = (struct sk_buff *)pskb;
3115
3116 if (is_translated)
3117 ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET + HEADER_OFFSET_802_11));
3118 else
3119 ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET));
3120
3121 if (VOS_PKT_PROT_ARP_ETH_TYPE == VOS_SWAP_U16(ether_type))
3122 {
3123 return TRUE;
3124 }
3125 else
3126 {
3127 return FALSE;
3128 }
3129#undef HEADER_OFFSET_802_11
3130}
3131
Bhargav Shah7dbfb6f2016-02-12 20:49:58 +05303132v_PVOID_t vos_get_pkt_head(vos_pkt_t *pPacket)
3133{
3134 struct sk_buff *skb;
3135
3136 // Validate the parameter pointers
3137 if (unlikely(NULL == pPacket))
3138 {
3139 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3140 "VPKT [%d]: NULL pointer", __LINE__);
3141 return NULL;
3142 }
3143
3144 if ( VOS_STATUS_SUCCESS !=
3145 vos_pkt_get_os_packet(pPacket, (void**)&skb, VOS_FALSE ))
3146 {
3147 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3148 "OS-PKT [%d]: OS PKT pointer is NULL", __LINE__);
3149 return NULL;
3150 }
3151
3152 return VOS_PKT_GET_HEAD(skb);
3153}
3154
3155v_PVOID_t vos_get_pkt_end(vos_pkt_t *pPacket)
3156{
3157 struct sk_buff *skb;
3158
3159 // Validate the parameter pointers
3160 if (unlikely(NULL == pPacket))
3161 {
3162 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3163 "VPKT [%d]: NULL pointer", __LINE__);
3164 return NULL;
3165 }
3166
3167 if ( VOS_STATUS_SUCCESS !=
3168 vos_pkt_get_os_packet(pPacket, (void**)&skb, VOS_FALSE ))
3169 {
3170 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3171 "OS-PKT [%d]: OS PKT pointer is NULL", __LINE__);
3172 return NULL;
3173 }
3174
3175 /* find end point if skb->end is an offset */
3176#ifdef NET_SKBUFF_DATA_USES_OFFSET
3177 return VOS_PKT_GET_HEAD(skb) + VOS_PKT_GET_END(skb);
3178#else
3179 return VOS_PKT_GET_END(skb);
3180#endif
3181}
3182
3183v_VOID_t vos_recover_tail(vos_pkt_t *pPacket)
3184{
3185 struct skb_shared_info *shinfo;
3186 struct sk_buff *skb;
3187
3188 // Validate the parameter pointers
3189 if (unlikely(NULL == pPacket))
3190 {
3191 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3192 "VPKT [%d]: NULL pointer", __LINE__);
3193 return;
3194 }
3195
3196 if ( VOS_STATUS_SUCCESS !=
3197 vos_pkt_get_os_packet(pPacket, (void**)&skb, VOS_FALSE ))
3198 {
3199 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3200 "OS-PKT [%d]: OS PKT pointer is NULL", __LINE__);
3201 return;
3202 }
3203
3204 shinfo = skb_shinfo(skb);
3205 memset(shinfo, 0, sizeof(struct skb_shared_info));
3206 atomic_set(&shinfo->dataref, 1);
3207 kmemcheck_annotate_variable(shinfo->destructor_arg);
3208
3209 return;
3210}
3211
Jeff Johnson295189b2012-06-20 16:38:30 -07003212#ifdef VOS_PACKET_UNIT_TEST
3213#include "vos_packet_test.c"
3214#endif