1 /*********************************
2 * FILE: pktio.c
3 * PURPOSE: pktio library for NETAPI
4 **************************************************************
5 * FILE: pktio.c
6 *
7 * DESCRIPTION: pktio source file for user space transport
8 * library
9 *
10 * REVISION HISTORY: rev 0.0.1
11 *
12 * Copyright (c) Texas Instruments Incorporated 2010-2011
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ********************************/
44 #include <unistd.h>
45 #include "netapi.h"
46 #include "pktio.h"
51 /*This defines the maximum number of packets to receive in one pktio poll */
52 #define PKTIO_MAX_RECV (TUNE_NETAPI_MAX_BURST_RCV)
54 static hplib_spinLock_T netapi_pktio_lock = hplib_spinLock_UNLOCKED_INITIALIZER;
57 /* Utilites*/
58 static PKTIO_HANDLE_T * netapip_pktioGetFreeChannelSlot(NETAPI_T n)
59 {
60 PKTIO_HANDLE_T ** pp = (PKTIO_HANDLE_T **) netapi_get_pktio_list(n);
61 int i;
62 hplib_mSpinLockLock(&netapi_pktio_lock);
63 for(i=0;i<NETAPI_MAX_PKTIO;i++)
64 {
65 if (pp[i]->inuse != PKTIO_INUSE)
66 {
67 pp[i]->inuse = PKTIO_INUSE;
68 hplib_mSpinLockUnlock(&netapi_pktio_lock);
69 return pp[i];
70 }
71 }
72 hplib_mSpinLockUnlock(&netapi_pktio_lock);
73 return NULL;
74 }
77 /*Optimized send functions */
80 /********************************************************************
81 * FUNCTION PURPOSE: Send packet via low level NWAL API's
82 * with updates for L4 checksum,ESP Crypto and outgoing EMAC port
83 * to NetCP command.
84 ********************************************************************
85 * DESCRIPTION: Send packet via low level NWAL API's
86 * with updates for L4 checksum,ESP Crypto and outgoing EMAC port
87 * to NetCP command.
88 ********************************************************************/
89 static int netapip_pktioSendL4CkSumCryptPort(struct PKTIO_HANDLE_tag * pp,
90 Ti_Pkt *pkt,
91 PKTIO_METADATA_T *m,
92 int * err)
93 {
94 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
95 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
96 Cppi_HostDesc* pPloadDesc;
97 uint32_t swInfo0, swInfo1;
99 NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle;
101 if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1))
102 {
103 nwal_mCmdSetL4CkSumCrypPort(pkt,
104 &p->tx_psCmdInfo,
105 pTxPktInfo->l4OffBytes,
106 pTxPktInfo->ploadLen + pTxPktInfo->l4HdrLen,
107 pTxPktInfo->pseudoHdrChecksum,
108 pTxPktInfo->saOffBytes,
109 pTxPktInfo->saPayloadLen,
110 swInfo0,
111 swInfo1,
112 0);
114 pPloadDesc = Pktlib_getDescFromPacket(pkt);
115 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
116 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
117 pPloadDesc,
118 NWAL_DESC_SIZE);
119 }
120 else
121 {
122 *err=NETAPI_ERR_BAD_INPUT;
123 return -1;
124 }
126 return 1;
127 }
129 /********************************************************************
130 * FUNCTION PURPOSE: Send packet via low level NWAL API's
131 * with updates for ESP Crypto and outgoing EMAC port
132 * to NetCP command.
133 ********************************************************************
134 * DESCRIPTION: Send packet via low level NWAL API's
135 * with updates for ESP Crypto and outgoing EMAC port
136 * to NetCP command.
137 ********************************************************************/
138 static int netapip_pktioSendCryptPort(struct PKTIO_HANDLE_tag * pp,
139 Ti_Pkt *pkt,
140 PKTIO_METADATA_T *m,
141 int * err)
142 {
143 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
144 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
145 Cppi_HostDesc* pPloadDesc;
146 uint32_t swInfo0, swInfo1;
148 NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle;
150 if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1))
151 {
152 nwal_mCmdSetCrypPort(pkt,
153 &p->tx_psCmdInfo,
154 pTxPktInfo->saOffBytes,
155 pTxPktInfo->saPayloadLen,
156 swInfo0,
157 swInfo1,
158 0);
160 pPloadDesc = Pktlib_getDescFromPacket(pkt);
161 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
162 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
163 pPloadDesc,
164 NWAL_DESC_SIZE);
165 }
166 else
167 {
168 *err=NETAPI_ERR_BAD_INPUT;
169 return -1;
170 }
172 return 1;
173 }
175 /********************************************************************
176 * FUNCTION PURPOSE: Send packet via low level NWAL API's
177 * with updates for L4 checksum,AH Crypto and outgoing EMAC port
178 * to NetCP command.
179 *******************************************************************
180 * DESCRIPTION: Send packet via low level NWAL API's
181 * with updates for L4 checksum,AH Crypto and outgoing EMAC port
182 * to NetCP command.
183 ********************************************************************/
184 static int netapip_pktioSendL4CkSumAHCryptPort(struct PKTIO_HANDLE_tag * pp,
185 Ti_Pkt *pkt,
186 PKTIO_METADATA_T *m,
187 int * err)
188 {
189 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
190 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
191 Cppi_HostDesc* pPloadDesc;
192 uint32_t swInfo0, swInfo1;
194 NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle;
196 if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1))
197 {
198 nwal_mCmdSetL4CkSumAHCrypPort(pkt,
199 &p->tx_psCmdInfo,
200 pTxPktInfo->l4OffBytes,
201 pTxPktInfo->ploadLen + pTxPktInfo->l4HdrLen,
202 pTxPktInfo->pseudoHdrChecksum,
203 pTxPktInfo->saOffBytes,
204 pTxPktInfo->saPayloadLen,
205 swInfo0,
206 swInfo1,
207 pTxPktInfo->saAhIcvOffBytes,
208 pTxPktInfo->saAhMacSize,
209 pTxPktInfo->enetPort);
211 pPloadDesc = Pktlib_getDescFromPacket(pkt);
212 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
213 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
214 pPloadDesc,
215 NWAL_DESC_SIZE);
216 }
217 else
218 {
219 *err=NETAPI_ERR_BAD_INPUT;
220 return -1;
221 }
223 return 1;
224 }
226 /********************************************************************
227 * FUNCTION PURPOSE: Send packet via low level NWAL API's
228 * with updates for AH Crypto and outgoing EMAC port
229 * to NetCP command.
230 ********************************************************************
231 * DESCRIPTION: Send packet via low level NWAL API's
232 * with updates for AH Crypto and outgoing EMAC port
233 * to NetCP command.
234 ********************************************************************/
235 static int netapip_pktioSendAHCryptPort(struct PKTIO_HANDLE_tag * pp,
236 Ti_Pkt *pkt,
237 PKTIO_METADATA_T *m,
238 int * err)
239 {
240 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
241 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
242 Cppi_HostDesc* pPloadDesc;
243 uint32_t swInfo0, swInfo1;
245 NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle;
247 if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1))
248 {
249 nwal_mCmdSetAHCrypPort(pkt,
250 &p->tx_psCmdInfo,
251 pTxPktInfo->saOffBytes,
252 pTxPktInfo->saPayloadLen,
253 swInfo0,
254 swInfo1,
255 pTxPktInfo->saAhIcvOffBytes,
256 pTxPktInfo->saAhMacSize,
257 pTxPktInfo->enetPort);
259 pPloadDesc = Pktlib_getDescFromPacket(pkt);
260 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
261 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
262 pPloadDesc,
263 NWAL_DESC_SIZE);
264 }
265 else
266 {
267 *err= NETAPI_ERR_BAD_INPUT;
268 return -1;
269 }
270 return 1;
271 }
275 /********************************************************************
276 * FUNCTION PURPOSE: Send packet via low level NWAL API's
277 * with updates for L4 checksum and outgoing EMAC port
278 * to NetCP command.
279 *******************************************************************
280 * DESCRIPTION: Send packet via low level NWAL API's
281 * with updates for L4 checksum and outgoing EMAC port
282 * to NetCP command.
283 ********************************************************************/
284 static int netapip_pktioSendL4CkSumPort(struct PKTIO_HANDLE_tag * pp,
285 Ti_Pkt *pkt,
286 PKTIO_METADATA_T *m,
287 int * err)
288 {
290 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
291 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
292 Cppi_HostDesc* pPloadDesc;
293 nwal_mCmdSetL4CkSumPort(pkt,
294 &p->tx_psCmdInfo,
295 pTxPktInfo->l4OffBytes,
296 pTxPktInfo->l4HdrLen + pTxPktInfo->ploadLen,
297 pTxPktInfo->pseudoHdrChecksum,
298 pTxPktInfo->enetPort);
300 pPloadDesc = Pktlib_getDescFromPacket(pkt);
301 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
302 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
303 pPloadDesc,
304 NWAL_DESC_SIZE);
305 }
308 /********************************************************************
309 * FUNCTION PURPOSE: Send packet via low level NWAL API's
310 * with updates for outgoing EMAC port to NetCP command.
311 ********************************************************************
312 * DESCRIPTION: Send packet via low level NWAL API's
313 * with updates for outgoing EMAC port to NetCP command.
314 ********************************************************************/
315 static int netapip_pktioSendPort(struct PKTIO_HANDLE_tag * pp,
316 Ti_Pkt *pkt,
317 PKTIO_METADATA_T *m,
318 int * err)
319 {
320 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
321 nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta;
322 Cppi_HostDesc* pPloadDesc;
323 nwal_mCmdSetPort(pkt,
324 &p->tx_psCmdInfo,
325 pTxPktInfo->enetPort);
326 pPloadDesc = Pktlib_getDescFromPacket(pkt);
327 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
328 Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue,
329 pPloadDesc,
330 NWAL_DESC_SIZE);
331 return 1;
332 }
334 /********************************************************************
335 * FUNCTION PURPOSE: Send packet via IPC queue
336 ********************************************************************
337 * DESCRIPTION: Send packet via IPC queue
338 ********************************************************************/
339 static int netapip_pktioSendIpc(struct PKTIO_HANDLE_tag * pp,
340 Ti_Pkt *pkt,
341 PKTIO_METADATA_T *m,
342 int * err)
343 {
344 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
345 err=0;
346 Qmss_queuePushDesc (p->q, (void*)pkt);
347 return 1;
348 }
349 /********************************************************************
350 * FUNCTION PURPOSE: Send packet to NETCP via NWAL
351 ********************************************************************
352 * DESCRIPTION: Send packet to NETCP via NWAL
353 ********************************************************************/
354 static int netapip_pktioSendNwal(struct PKTIO_HANDLE_tag * pp,
355 Ti_Pkt *pkt,
356 PKTIO_METADATA_T *m,
357 int * err)
358 {
359 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
360 nwalTxPktInfo_t * pPktInfo=m->u.tx_meta;
361 nwal_RetValue res;
362 *err=0;
363 pPktInfo->pPkt = pkt;
364 res=nwal_send(p->nwalInstanceHandle, m->sa_handle,pPktInfo);
365 if (res != nwal_OK)
366 {
367 *err = NETAPI_ERR_NWAL_TX_ERR -res;
368 return -1;
369 }
370 return 1;
371 }
373 /********************************************************************
374 * FUNCTION PURPOSE: Send packet to SA via NWAL
375 ********************************************************************
376 * DESCRIPTION: Send packet to NETCP via NWAL for side band data mode
377 * channel via NWAL
378 ********************************************************************/
379 static int netapip_pktioSendSb(struct PKTIO_HANDLE_tag * pp,
380 Ti_Pkt *pkt,
381 PKTIO_METADATA_T *m,
382 int * err)
383 {
384 nwal_RetValue nwalRetVal;
385 nwalTxDmPSCmdInfo_t *dmPSCmdInfo;
386 nwalLocCxtInfo_t nwalLocCxt;
387 Cppi_HostDesc* pPloadDesc;
388 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
389 Qmss_QueueHnd rxQ;
390 nwalDmTxPayloadInfo_t *pPktInfoSB = m->u.tx_sb_meta;
392 NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle;
394 dmPSCmdInfo = netapip_netcpCfgGetSaSBInfo(&netapi_get_global()->nwal_context, tunnel_id);
395 if (dmPSCmdInfo)
396 {
397 nwalRetVal = nwal_getDmRxQueue(pktio_mGetNwalInstance(p), &rxQ);
398 if(nwalRetVal == nwal_OK)
399 {
400 dmPSCmdInfo->rxSbSaQ = rxQ;
401 }
402 else
403 {
404 *err=NETAPI_ERR_BAD_INPUT;
405 return -1;
406 }
407 nwal_mCmdDMUpdate(pkt,
408 dmPSCmdInfo,
409 pPktInfoSB->appCtxId,
410 pPktInfoSB->encOffset,
411 pPktInfoSB->encSize,
412 pPktInfoSB->pEncIV,
413 pPktInfoSB->authOffset,
414 pPktInfoSB->authSize,
415 pPktInfoSB->pAuthIV,
416 pPktInfoSB->aadSize,
417 pPktInfoSB->pAad);
418 pPloadDesc = Pktlib_getDescFromPacket(pkt);
419 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
420 Qmss_queuePushDescSizeRaw(dmPSCmdInfo->txQueue,
421 pPloadDesc,
422 NWAL_DESC_SIZE);
423 }
424 else
425 {
426 *err=NETAPI_ERR_BAD_INPUT;
427 return -1;
428 }
429 return 1;
430 }
432 /********************************************************************
433 * FUNCTION PURPOSE: Send packet via infrastructure DMA channel
434 ********************************************************************
435 * DESCRIPTION: Send packet via infrastructure DMA channel
436 ********************************************************************/
437 static int netapip_pktioSendIfdma(struct PKTIO_HANDLE_tag * pp,
438 Ti_Pkt *pkt,
439 PKTIO_METADATA_T *m,
440 int * err)
441 {
442 Cppi_DescTag tag={0};
443 Cppi_HostDesc* pPloadDesc;
444 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
445 *err=0;
446 tag.srcTagLo = m->u.tx_ifdma_dest;
447 Cppi_setTag (Cppi_DescType_HOST, (Cppi_Desc *)pkt, &tag);
448 pPloadDesc = Pktlib_getDescFromPacket(pkt);
449 pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc);
450 Qmss_queuePushDescSizeRaw(p->q,
451 pPloadDesc,
452 NWAL_DESC_SIZE);
453 return 1;
454 }
458 /********************************************************************
459 * FUNCTION PURPOSE: Stub function for send, do nothing.
460 ********************************************************************
461 * DESCRIPTION: Stub function for send, do nothing.
462 ********************************************************************/
463 static int netapip_pktioSendDummy(struct PKTIO_HANDLE_tag * p,
464 Ti_Pkt *pkt,
465 PKTIO_METADATA_T *m,
466 int * err)
467 {
468 *err = NETAPI_ERR_BAD_INPUT;
469 return -1;
470 }
472 /********************************************************************
473 * FUNCTION PURPOSE: Stub function for poll, do nothing.
474 ********************************************************************
475 * DESCRIPTION: Stub function for send, do nothing.
476 ********************************************************************/
477 static int netapip_pktioPollDummy(struct PKTIO_HANDLE_tag * p,
478 PKTIO_POLL_T * p_poll_cfg,
479 int * err)
480 {
481 *err= NETAPI_ERR_BAD_INPUT;
482 return 0;
483 }
485 /********************************************************************
486 * FUNCTION PURPOSE: Poll IPC queue
487 ********************************************************************
488 * DESCRIPTION: Poll IPC queue
489 ********************************************************************/
490 static int netapip_pktioPollIpc(struct PKTIO_HANDLE_tag * pp,
491 PKTIO_POLL_T * p_poll_cfg,
492 int * err)
493 {
494 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
495 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
496 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
497 int r=0;
498 int n;
499 Ti_Pkt * temp;
500 *err=0;
501 n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV;
502 for(r=0;r<n;r++)
503 {
505 temp=(Ti_Pkt*)(Cppi_HostDesc*)QMSS_DESC_PTR(Qmss_queuePop(p->q));
507 if(!temp) break;
508 /* process meta data */
509 pkt_list[r]= temp;
510 meta_s[r].flags1=0x1;
511 }
512 if (r)
513 {
514 p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL);
515 }
516 return r;
517 }
519 /********************************************************************
520 * FUNCTION PURPOSE: Poll nwal data queues for pkts from netcp
521 ********************************************************************
522 * DESCRIPTION: Poll nwal data queues for pkts from netcp
523 ********************************************************************/
524 static int netapip_pktioPollNwal(struct PKTIO_HANDLE_tag * pp,
525 PKTIO_POLL_T * p_poll_cfg,
526 int * err)
527 {
528 int r=0;
529 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
530 *err=0;
531 /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are
532 set. optimizaion maybe? */
533 r=nwal_pollPkt(p->nwalInstanceHandle,
534 p->poll_flags,
535 (uint32_t) p,
536 p->max_n,
537 QMSS_PARAM_NOT_SPECIFIED,
538 (void*) NULL);
539 return r;
540 }
541 /********************************************************************
542 * FUNCTION PURPOSE: Poll nwal sideband queues for pkts from SA
543 ********************************************************************
544 * DESCRIPTION: Poll nwal sideband queues for pkts from SA
545 ********************************************************************/
546 static int netapip_pktioPollSb(struct PKTIO_HANDLE_tag * pp,
547 PKTIO_POLL_T * p_poll_cfg,
548 int * err)
549 {
550 int r=0;
551 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
552 *err=0;
553 r=nwal_pollDm(p->nwalInstanceHandle,
554 nwal_POLL_DM_DEF_SB_SA_Q,
555 (uint32_t) p,
556 p->max_n,
557 QMSS_PARAM_NOT_SPECIFIED,
558 (void *) NULL);
559 return r;
560 }
562 /********************************************************************
563 * FUNCTION PURPOSE: Poll application provided NETCP RX queue
564 ********************************************************************
565 * DESCRIPTION: Poll application provided NETCP RX queue
566 ********************************************************************/
567 static int netapip_pktioPollNwalAdj(struct PKTIO_HANDLE_tag * pp,
568 PKTIO_POLL_T * p_poll_cfg,
569 int * err)
570 {
571 int r=0;
572 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
573 *err=0;
574 /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are
575 set. optimizaion maybe? */
576 r=nwal_pollPkt(p->nwalInstanceHandle,
577 nwal_POLL_APP_MANAGED_PKT_Q,
578 (uint32_t) p,
579 p->max_n,
580 p->q,
581 (void *) NULL);
582 return r;
583 }
585 /*************************************************************************
586 * FUNCTION PURPOSE: Poll application defined sideband queues for packets
587 * from SA
588 ************************************************************************
589 * DESCRIPTION: Poll application defined sideband queues for packets
590 * from SA
591 *************************************************************************/
592 static int netapip_pktioPollSbAdj(struct PKTIO_HANDLE_tag * pp,
593 PKTIO_POLL_T * p_poll_cfg,
594 int * err)
595 {
596 int r=0;
597 PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp;
598 *err=0;
599 r=nwal_pollDm(p->nwalInstanceHandle,
600 nwal_POLL_DM_APP_MANAGED_Q,
601 (uint32_t) p,
602 p->max_n,
603 p->q,
604 (void *) NULL);
605 return r;
606 }
608 /*-----------------------MAIN API----------------------*/
609 /********************************************************************
610 * FUNCTION PURPOSE: API creates a NETAPI PKTIO channel
611 ********************************************************************
612 * DESCRIPTION: API creates a NETAPI PKTIO channel
613 ********************************************************************/
614 PKTIO_HANDLE_T * netapi_pktioCreate(NETAPI_T n,
615 char * name,
616 PKTIO_CB cb,
617 PKTIO_CFG_T * p_cfg,
618 int * err)
619 {
620 int r = 0;
621 PKTIO_HANDLE_T *p;
622 uint8_t isAllocated;
624 *err=0;
625 int q= QMSS_PARAM_NOT_SPECIFIED;
626 int qtype=Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
628 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
629 if ((p_cfg->flags2 & PKTIO_PKT) &&(p_cfg->flags1& PKTIO_TX)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;};
630 if ((p_cfg->flags2 & PKTIO_SB) &&(p_cfg->flags1& PKTIO_TX)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;};
632 /* get a free channel handle */
633 p=netapip_pktioGetFreeChannelSlot(n);
635 if (!p) {*err = NETAPI_ERR_NOMEM; return (p); }
637 p->back = n;
638 p->cb = cb;
639 p->max_n = p_cfg->max_n;
640 p->_poll=netapip_pktioPollDummy;
641 p->_send=netapip_pktioSendDummy;
642 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
645 /* special case for infrastructure dma channels */
646 if (p_cfg->flags2 & PKTIO_IFDMA)
647 {
648 if (p_cfg->qnum!=PKTIO_Q_ANY)
649 {
650 q= p_cfg->qnum;
651 }
652 qtype=Qmss_QueueType_INFRASTRUCTURE_QUEUE;
653 }
656 /* create a general queue */
657 p->q = Qmss_queueOpen(qtype,
658 q,
659 &isAllocated);
660 if (p->q == (Qmss_QueueHnd) NULL)
661 {
662 netapi_Log("netapi_pktioCreate: queueOpen failed\n");
663 p->inuse=0;
664 *err= NETAPI_ERR_QLLD; ///queue lld error
665 return NULL;
666 }
667 p->qInfo = Qmss_getQueueNumber(p->q);
668 if (p_cfg->flags2 & PKTIO_PKT)
669 {
670 p->use_nwal = PKTIO_4_ADJ_NWAL;
671 p->_poll=netapip_pktioPollNwalAdj;
672 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
673 }
674 else if (p_cfg->flags2 & PKTIO_SB)
675 {
676 p->use_nwal = PKTIO_4_ADJ_SB;
677 p->_poll=netapip_pktioPollSbAdj;
678 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
679 }
680 else if (p_cfg->flags2 & PKTIO_IFDMA)
681 {
682 p->use_nwal = 0;
683 p->_send = netapip_pktioSendIfdma;
684 p->cfg.flags1=PKTIO_TX;
685 r= netapip_pktioCreateIFDMA(p); //we create the IF DMA channel here
686 if (r<0)
687 {
688 //trouble -> couldn't set up DMA
689 //close queue and return failure
690 if (p->q)
691 {
692 Qmss_queueClose(p->q);
693 }
694 p->inuse=0;
695 *err= NETAPI_ERR_QLLD; ///queue lld error TODO: fix error code
696 return NULL;
697 }
698 }
699 else
700 {
701 p->use_nwal=0;
702 if (p_cfg->flags1& PKTIO_TX) p->_send=netapip_pktioSendIpc;
703 if (p_cfg->flags1& PKTIO_RX) p->_poll=netapip_pktioPollIpc;
704 }
706 /* save name */
707 strncpy(p->name,name,
708 strlen(name)<PKTIO_MAX_NAME ?
709 strlen(name):PKTIO_MAX_NAME);
711 /* add name, qnum to global name list */
712 if ((strcmp(name,NETCP_RX)) &&
713 (strcmp(name,NETCP_TX)) &&
714 (strcmp(name,NETCP_SB_RX)) &&
715 (strcmp(name,NETCP_SB_TX)) &&
716 (p_cfg->flags1 & PKTIO_GLOBAL))
717 {
718 //todo: make sure this succeeds..
719 hplib_mSpinLockLock(&netapi_pktio_lock);
720 r=netapip_addGlobalPktio(n, name, &p->qInfo);
721 hplib_mSpinLockUnlock(&netapi_pktio_lock);
722 }
724 ((NETAPI_HANDLE_T *)n )->n_pktios+=1;
725 return p;
726 }
728 /********************************************************************
729 * FUNCTION PURPOSE: API opens an existing NETAPI PKTIO channel
730 ********************************************************************
731 * DESCRIPTION: API opens an existing NETAPI PKTIO channel
732 ********************************************************************/
733 PKTIO_HANDLE_T * netapi_pktioOpen(NETAPI_T n,
734 char *name,
735 PKTIO_CB cb,
736 PKTIO_CFG_T * p_cfg,
737 int * err)
738 {
739 int r=0;
740 PKTIO_HANDLE_T *p, *p2;
741 uint8_t isAllocated;
742 *err=0;
743 Qmss_Queue *p_qnum;
744 int qtype=Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
747 if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;}
749 /* get a free channel handle */
751 p=netapip_pktioGetFreeChannelSlot(n);
753 if (!p) {*err = NETAPI_ERR_NOMEM; return (p); }
754 ((NETAPI_HANDLE_T *)n)->n_pktios+=1;
756 p->inuse= PKTIO_INUSE;
757 p->back = n;
758 p->cb = cb;
759 p->max_n = p_cfg->max_n;
760 p->_poll=netapip_pktioPollDummy;
761 p->_send=netapip_pktioSendDummy;
762 memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T));
764 /* special handling of NETCP_RX, NETCP_TX */
765 if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) )
766 {
767 /* these have already been opened internally, so don't search in global list */
768 p->use_nwal = PKTIO_DEF_NWAL;
769 p->q = 0;
770 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
771 if (!strcmp(name,NETCP_RX))
772 {
773 p->_poll=netapip_pktioPollNwal;
774 p->poll_flags= nwal_POLL_DEFAULT_GLOB_PKT_Q|
775 nwal_POLL_DEFAULT_PER_PROC_PKT_Q;
776 }
777 if (!strcmp(name,NETCP_TX))
778 {
779 p->_send=netapip_pktioSendNwal;
780 }
781 }
782 else if( (!strcmp(name, NETCP_SB_RX)) || (!strcmp(name,NETCP_SB_TX)) )
783 {
784 /* these have already been opened internally, so don't search in global list */
785 p->use_nwal = PKTIO_DEF_SB;
786 p->q = 0;
787 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
788 if (!strcmp(name,NETCP_SB_RX)) p->_poll=netapip_pktioPollSb;
789 if (!strcmp(name,NETCP_SB_TX)) p->_send=netapip_pktioSendSb;
790 }
791 else
792 {
793 hplib_mSpinLockLock(&netapi_pktio_lock);
794 /* Find queue in global list
795 Note names like "QUEUE:%d" or IFDMA:%d cause general purpose or
796 IFDMA queues of that number to be opened */
797 if (p_cfg->flags2 & PKTIO_IFDMA)
798 {
799 qtype= Qmss_QueueType_INFRASTRUCTURE_QUEUE;
800 }
802 hplib_mSpinLockUnlock(&netapi_pktio_lock);
803 p_qnum = netapip_findGlobalPktio(n, name);
805 if (!p_qnum )
806 {
807 netapi_Log("netapi_pktioOpen: can't find %s\n",name);
808 p->inuse=0;
809 *err= NETAPI_ERR_NOTFOUND; ///queue lld error
810 return NULL;
811 }
813 /* open a general queue (for now). use qnum that was just found */
814 p->q = Qmss_queueOpen(qtype,
815 p_qnum->qNum , &isAllocated);
816 if (p->q == (Qmss_QueueHnd) NULL)
817 {
818 netapi_Log("netapi_pktioCreate: queueOpen failed\n");
819 p->inuse=0;
820 *err= NETAPI_ERR_QLLD; ///queue lld error
821 return NULL;
822 }
823 p->qInfo = Qmss_getQueueNumber(p->q);
824 netapi_Log("netapi_pktioOpen: queueMgr %d, queueNum; %d\n", p->qInfo.qMgr, p->qInfo.qNum);
825 if (p_cfg->flags2 & PKTIO_PKT)
826 {
827 p->use_nwal = PKTIO_4_ADJ_NWAL; //additonal RX q for nwal
828 p->_poll = netapip_pktioPollNwalAdj;
829 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
830 netapi_Log("netapi_pktioOpen: nwalInstanceHandle 0x%x\n", p->nwalInstanceHandle);
831 }
832 else if (p_cfg->flags2 & PKTIO_SB)
833 {
834 p->use_nwal = PKTIO_4_ADJ_SB; //additional RX q for sideband with NWAL
835 p->_poll = netapip_pktioPollSbAdj;
836 p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n);
837 }
838 else if (p_cfg->flags2 & PKTIO_IFDMA)
839 {
840 p->_send= netapip_pktioSendIfdma;
841 p->use_nwal = 0;
842 }
843 else
844 {
845 p->use_nwal=0; //not handled by nwal
846 if (p_cfg->flags1& PKTIO_TX) p->_send=netapip_pktioSendIpc;
847 if (p_cfg->flags1& PKTIO_RX) p->_poll=netapip_pktioPollIpc;
848 }
849 }
851 /* save name */
852 strncpy(p->name,name,
853 strlen(name)<PKTIO_MAX_NAME ?
854 strlen(name):PKTIO_MAX_NAME);
856 netapi_Log("netapi_pktioOpen: returning with sucess for name %s\n", p->name);
857 return p;
858 }
860 /********************************************************************
861 * FUNCTION PURPOSE: API controls an existing NETAPI PKTIO channel
862 ********************************************************************
863 * DESCRIPTION: API controls an existing NETAPI PKTIO channel
864 ********************************************************************/
865 void netapi_pktioControl(PKTIO_HANDLE_T * p,
866 PKTIO_CB cb,
867 PKTIO_CFG_T * p_cfg,
868 PKTIO_CONTROL_T * p_control,
869 int *err)
870 {
871 nwal_RetValue nwalRetVal;
872 if (!p)
873 {
874 *err= NETAPI_ERR_BAD_INPUT;
875 return;
876 }
877 if (cb)
878 {
879 p->cb = cb;
880 }
881 if (p_control)
882 {
883 /* todo: check for validity, eg don't allow clear of NETCP TX queues */
884 /* todo: implement divert */
885 switch(p_control->op)
886 {
887 //clear the queue
888 case(PKTIO_SET_POLL_FLAGS):
889 p->poll_flags=p_control->poll_flags;
890 break;
891 case(PKTIO_CLEAR):
892 netapip_zapQ(p->q);
893 break;
894 case (PKTIO_UPDATE_FAST_PATH):
895 if (p_cfg)
896 {
897 nwalRetVal = nwal_initPSCmdInfo(p->nwalInstanceHandle,
898 p_cfg->fast_path_cfg.txPktInfo,
899 &p->tx_psCmdInfo);
900 if (nwalRetVal == nwal_OK)
901 {
902 switch (p_cfg->fast_path_cfg.fp_send_option)
903 {
904 case (PKTIO_FP_ESP_L4CKSUM_PORT):
905 p->_send = netapip_pktioSendL4CkSumCryptPort;
906 break;
907 case (PKTIO_FP_AH_L4CKSUM_PORT):
908 p->_send = netapip_pktioSendL4CkSumAHCryptPort;
909 break;
910 case (PKTIO_FP_ESP_PORT):
911 p->_send = netapip_pktioSendCryptPort;
912 break;
913 case (PKTIO_FP_AH_PORT):
914 p->_send = netapip_pktioSendAHCryptPort;
915 break;
916 case (PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT):
917 p->_send = netapip_pktioSendPort;
918 break;
919 case (PKTIO_FP_L4CKSUM_PORT):
920 p->_send = netapip_pktioSendL4CkSumPort;
921 break;
922 default:
923 break;
924 }
925 }
926 else
927 {
928 *err = NETAPI_ERR_BAD_INPUT;
929 }
930 }
931 else
932 {
933 *err = NETAPI_ERR_BAD_INPUT;
934 }
935 break;
936 case (PKTIO_UPDATE_MAX_PKTS_PER_POLL):
937 if (p_cfg)
938 {
939 p->max_n = p_cfg->max_n;
940 }
941 else
942 {
943 *err = NETAPI_ERR_BAD_INPUT;
944 }
945 break;
946 case(PKTIO_DIVERT):
947 default:
948 netapi_Log("netapi_pktioControl: pktio_control op %d not implemented\n",p_control->op);
949 *err= NETAPI_ERR_NOT_IMPLEMENTED;
950 break;
951 }
952 }
954 *err = NETAPI_ERR_OK;
955 return;
956 }
957 /********************************************************************
958 * FUNCTION PURPOSE: API closes a NETAPI PKTIO channel
959 ********************************************************************
960 * DESCRIPTION: API closes a NETAPI PKTIO channel
961 ********************************************************************/
962 void netapi_pktioClose(PKTIO_HANDLE_T * p,
963 int * err)
964 {
965 if(!p)
966 {
967 *err=1;
968 return;
969 }
970 *err=0;
971 if (p->q)
972 {
973 Qmss_queueClose(p->q);
974 }
975 p->q=-1;
976 p->inuse=0;
977 ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
978 return;
979 }
981 /********************************************************************
982 * FUNCTION PURPOSE: API deletes a NETAPI PKTIO channel
983 ********************************************************************
984 * DESCRIPTION: API deletes a NETAPI PKTIO channel
985 ********************************************************************/
986 void netapi_pktioDelete(PKTIO_HANDLE_T * p,
987 int * err)
988 {
989 if(!p)
990 {
991 *err=1;
992 return;
993 }
994 *err=0;
995 if (p->cfg.flags2 & PKTIO_IFDMA)
996 {
997 netapip_pktioDeleteIFDMA(p);
998 }
1000 /* remove from name list */
1001 hplib_mSpinLockLock(&netapi_pktio_lock);
1002 netapi_del_global_pktio((NETAPI_HANDLE_T *)p->back, p->name);
1003 hplib_mSpinLockUnlock(&netapi_pktio_lock);
1004 if((p->use_nwal != PKTIO_DEF_NWAL) && (p->use_nwal != PKTIO_DEF_SB))
1005 {
1006 netapip_zapQ(p->q); //since we are deleting, zap the queue
1007 Qmss_queueClose(p->q);
1008 }
1009 p->q=-1;
1010 p->inuse=0;
1011 ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1;
1012 return ;
1013 }
1015 /********************************************************************
1016 * FUNCTION PURPOSE: API sends multiple packets to a NETAPI PKTIO channel
1017 ********************************************************************
1018 * DESCRIPTION: API sends multiple packets to a NETAPI PKTIO channel
1019 ********************************************************************/
1020 int netapi_pktioSendMulti(PKTIO_HANDLE_T * p,
1021 Ti_Pkt * pkt[],
1022 PKTIO_METADATA_T * m[],
1023 int np,
1024 int* err)
1025 {
1026 int r=0;
1027 for(r=0;r<np;r++)
1028 {
1029 p->_send((struct PKTIO_HANDLE_tag *)p, (Ti_Pkt *)pkt, (PKTIO_METADATA_T *)m, err);
1030 }
1031 return r;
1032 }
1034 /********************************************************************
1035 * FUNCTION PURPOSE: API polls all NETAPI PKTIO channels associated with NETAPI_T
1036 * instance for received packets
1037 ********************************************************************
1038 * DESCRIPTION: API polls all NETAPI PKTIO channels associated with NETAPI_T
1039 * instance for received packets
1040 ********************************************************************/
1041 int netapi_pktioPollAll(NETAPI_T handle,
1042 PKTIO_POLL_T * p_poll_cfg,
1043 int *err)
1044 {
1045 int i=0;
1046 int r=0;
1047 int err2;
1048 int cnt=0;
1049 PKTIO_HANDLE_T **pp =( PKTIO_HANDLE_T **) netapi_get_pktio_list(handle);
1051 *err=0;
1052 for(i=0;i<NETAPI_MAX_PKTIO && cnt < ((NETAPI_HANDLE_T *)handle)->n_pktios;i++)
1053 {
1054 if (pp[i]->inuse != PKTIO_INUSE) continue;
1055 if(!(pp[i]->cfg.flags1&PKTIO_RX)) continue;
1056 r+=pktio_poll(pp[i], p_poll_cfg, &err2); cnt+=1;
1057 if (err2) { *err = err2; break;}
1058 }
1059 return r;
1061 }
1063 /********************************************************************
1064 * FUNCTION PURPOSE: Internal function to delete a PKTIO infrastructure DMA channel
1065 ********************************************************************
1066 * DESCRIPTION: Internal function to delete a PKTIO infrastructure DMA channel
1067 ********************************************************************/
1068 int netapip_pktioDeleteIFDMA(PKTIO_HANDLE_T *p)
1069 {
1070 Cppi_channelDisable (p->txChHnd);
1071 Cppi_channelDisable (p->rxChHnd);
1072 Cppi_channelClose(p->txChHnd);
1073 Cppi_channelClose(p->rxChHnd);
1074 Cppi_close(p->cppiHnd);
1075 return 1;
1076 }
1078 /********************************************************************
1079 * FUNCTION PURPOSE: Internal function to create a PKTIO infrastructure DMA channel
1080 ********************************************************************
1081 * DESCRIPTION: Internal function to create a PKTIO infrastructure DMA channel
1082 * for infrastructure DMQ queue
1083 ********************************************************************/
1084 int netapip_pktioCreateIFDMA(PKTIO_HANDLE_T * p )
1085 {
1086 int dmaChan = p->qInfo.qNum - QMSS_INFRASTRUCTURE_QUEUE_BASE;
1087 unsigned char isAllocated;
1088 Cppi_TxChInitCfg txChCfg;
1089 Cppi_RxChInitCfg rxChCfg;
1090 Cppi_CpDmaInitCfg cpdmaCfg;
1092 /* Set up QMSS CPDMA configuration */
1093 memset ((void *) &cpdmaCfg, 0, sizeof (Cppi_CpDmaInitCfg));
1094 cpdmaCfg.dmaNum = Cppi_CpDma_QMSS_CPDMA;
1096 /* Open QMSS CPDMA */
1097 p->cppiHnd = (Cppi_Handle) Cppi_open (&cpdmaCfg);
1098 if (p->cppiHnd == NULL)
1099 {
1100 return -1;
1101 }
1103 /* Set up Tx Channel parameters */
1104 memset ((void *) &txChCfg, 0, sizeof (Cppi_TxChInitCfg));
1105 txChCfg.channelNum = dmaChan;
1106 txChCfg.priority = 0;
1107 txChCfg.filterEPIB = 0;
1108 txChCfg.filterPS = 0;
1109 txChCfg.aifMonoMode = 0;
1110 txChCfg.txEnable = Cppi_ChState_CHANNEL_DISABLE;
1112 /* Open Tx Channel */
1113 p->txChHnd = (Cppi_ChHnd) Cppi_txChannelOpen (p->cppiHnd, &txChCfg, &isAllocated);
1114 if (p->txChHnd == NULL)
1115 {
1116 Cppi_close(p->cppiHnd);
1117 return -1;
1118 }
1120 /* Set up Rx Channel parameters */
1121 memset ((void *) &rxChCfg, 0, sizeof (Cppi_RxChInitCfg));
1122 rxChCfg.channelNum = dmaChan;
1123 rxChCfg.rxEnable = Cppi_ChState_CHANNEL_DISABLE;
1125 /* Open Rx Channel */
1126 p->rxChHnd = (Cppi_ChHnd) Cppi_rxChannelOpen (p->cppiHnd, &rxChCfg, &isAllocated);
1127 if (p->rxChHnd == NULL)
1128 {
1129 Cppi_channelClose(p->txChHnd);
1130 Cppi_close(p->cppiHnd);
1131 return -1;
1132 }
1133 if (Cppi_channelEnable (p->txChHnd) != CPPI_SOK)
1134 {
1135 Cppi_channelClose(p->txChHnd);
1136 Cppi_channelClose(p->rxChHnd);
1137 Cppi_close(p->cppiHnd);
1138 return -1;
1139 }
1141 /* Enable receive channel */
1142 if (Cppi_channelEnable (p->rxChHnd) != CPPI_SOK)
1143 {
1144 Cppi_channelDisable (p->txChHnd);
1145 Cppi_channelClose(p->txChHnd);
1146 Cppi_channelClose(p->rxChHnd);
1147 Cppi_close(p->cppiHnd);
1148 return -1;
1149 }
1150 return 1;
1151 }
1153 /**********************************************************************
1154 * FUNCTION PURPOSE: Internal Callback that gets registered with NWAL for packet reception
1155 **********************************************************************
1156 * DESCRIPTION: Callback that gets registered with NWAL for packet reception
1157 * appCookie is the pktio handle
1158 **********************************************************************/
1159 void netapip_pktioNWALRxPktCallback(uint32_t appCookie,
1160 uint16_t numPkts,
1161 nwalRxPktInfo_t* pPktInfo,
1162 uint64_t timestamp,
1163 nwal_Bool_t* pFreePkt)
1164 {
1165 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;
1166 int r=0;
1167 int n;
1168 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
1169 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
1171 for(r=0;r<numPkts;r++)
1172 {
1173 pkt_list[r] = pPktInfo[r].pPkt;
1174 meta_s[r].flags1 = PKTIO_META_RX;
1175 meta_s[r].u.rx_meta = &pPktInfo[r];
1176 }
1177 if (r)
1178 {
1179 p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, timestamp);
1180 }
1181 }
1184 /**********************************************************************
1185 * FUNCTION PURPOSE: Internal Callback that gets registered with NWAL for crypto reception
1186 **********************************************************************
1187 * DESCRIPTION: Callback that gets registered with NWAL for crypto reception,
1188 * appCookie is the pktio handle
1189 **********************************************************************/
1190 void netapip_pktioNWALSBPktCallback(uint32_t appCookie,
1191 uint16_t numPkts,
1192 nwalDmRxPayloadInfo_t* pDmRxPktInfo,
1193 nwal_Bool_t* pFreePkt)
1194 {
1195 PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie;
1196 int r=0;
1197 int n;
1198 Ti_Pkt * pkt_list[PKTIO_MAX_RECV];
1199 PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV];
1200 for(r=0;r<numPkts;r++)
1201 {
1202 pkt_list[r] = pDmRxPktInfo[r].pPkt;
1203 meta_s[r].flags1 = PKTIO_META_SB_RX;
1204 meta_s[r].u.rx_sb_meta = &pDmRxPktInfo[r];
1205 }
1206 if (r)
1207 {
1208 p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL);
1209 }
1210 }