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