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