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