/********************************* * FILE: pktio.c * PURPOSE: pktio library for NETAPI ************************************************************** * FILE: pktio.c * * DESCRIPTION: pktio source file for user space transport * library * * REVISION HISTORY: rev 0.0.1 * * Copyright (c) Texas Instruments Incorporated 2010-2011 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************/ #include #include "netapi.h" #include "pktio.h" /*This defines the maximum number of packets to receive in one pktio poll */ #define PKTIO_MAX_RECV (TUNE_NETAPI_MAX_BURST_RCV) extern NETAPI_SHM_T* pnetapiShm; /* Utilites*/ static PKTIO_HANDLE_T * netapip_pktioGetFreeChannelSlot(NETAPI_T n) { PKTIO_HANDLE_T ** pp = (PKTIO_HANDLE_T **) netapi_get_pktio_list(n); int i; hplib_mSpinLockLock(&pnetapiShm->netapi_pktio_lock); for(i=0;iinuse != PKTIO_INUSE) { pp[i]->inuse = PKTIO_INUSE; hplib_mSpinLockUnlock(&pnetapiShm->netapi_pktio_lock); return pp[i]; } } hplib_mSpinLockUnlock(&pnetapiShm->netapi_pktio_lock); return NULL; } /*Optimized send functions */ /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for L4 checksum,ESP Crypto and outgoing EMAC port * to NetCP command. ******************************************************************** * DESCRIPTION: Send packet via low level NWAL API's * with updates for L4 checksum,ESP Crypto and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendL4CkSumCryptPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; uint32_t swInfo0, swInfo1; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1)) { nwal_mCmdSetL4CkSumCrypPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->l4OffBytes, pTxPktInfo->ploadLen + pTxPktInfo->l4HdrLen, pTxPktInfo->pseudoHdrChecksum, pTxPktInfo->saOffBytes, pTxPktInfo->saPayloadLen, swInfo0, swInfo1, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for ESP Crypto and outgoing EMAC port * to NetCP command. ******************************************************************** * DESCRIPTION: Send packet via low level NWAL API's * with updates for ESP Crypto and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendCryptPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; uint32_t swInfo0, swInfo1; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1)) { nwal_mCmdSetCrypPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->saOffBytes, pTxPktInfo->saPayloadLen, swInfo0, swInfo1, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for L3 checksum, ESP Crypto and outgoing EMAC port * to NetCP command. ******************************************************************** * DESCRIPTION: Send packet via low level NWAL API's * with updates for L3 checksum, ESP Crypto and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendL3CkSumCryptPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; uint32_t swInfo0, swInfo1; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1)) { nwal_mCmdSetL3CkSumCrypPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->saOffBytes, pTxPktInfo->saPayloadLen, swInfo0, swInfo1, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for L4 checksum,AH Crypto and outgoing EMAC port * to NetCP command. ******************************************************************* * DESCRIPTION: Send packet via low level NWAL API's * with updates for L4 checksum,AH Crypto and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendL4CkSumAHCryptPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; uint32_t swInfo0, swInfo1; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1)) { nwal_mCmdSetL4CkSumAHCrypPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->l4OffBytes, pTxPktInfo->ploadLen + pTxPktInfo->l4HdrLen, pTxPktInfo->pseudoHdrChecksum, pTxPktInfo->saOffBytes, pTxPktInfo->saPayloadLen, swInfo0, swInfo1, pTxPktInfo->saAhIcvOffBytes, pTxPktInfo->saAhMacSize, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for AH Crypto and outgoing EMAC port * to NetCP command. ******************************************************************** * DESCRIPTION: Send packet via low level NWAL API's * with updates for AH Crypto and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendAHCryptPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; uint32_t swInfo0, swInfo1; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; if (netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, tunnel_id, &swInfo0, &swInfo1)) { nwal_mCmdSetAHCrypPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->saOffBytes, pTxPktInfo->saPayloadLen, swInfo0, swInfo1, pTxPktInfo->saAhIcvOffBytes, pTxPktInfo->saAhMacSize, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err= NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for L4 checksum and outgoing EMAC port * to NetCP command. ******************************************************************* * DESCRIPTION: Send packet via low level NWAL API's * with updates for L4 checksum and outgoing EMAC port * to NetCP command. ********************************************************************/ static int netapip_pktioSendL4CkSumPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; nwal_mCmdSetL4CkSumPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->l4OffBytes, pTxPktInfo->l4HdrLen + pTxPktInfo->ploadLen, pTxPktInfo->pseudoHdrChecksum, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); } /******************************************************************** * FUNCTION PURPOSE: Send packet via low level NWAL API's * with updates for outgoing EMAC port to NetCP command. ******************************************************************** * DESCRIPTION: Send packet via low level NWAL API's * with updates for outgoing EMAC port to NetCP command. ********************************************************************/ static int netapip_pktioSendPort(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t *pTxPktInfo = m->u.tx_meta; Cppi_HostDesc* pPloadDesc; nwal_mCmdSetPort(pkt, &p->tx_psCmdInfo, pTxPktInfo->enetPort); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->tx_psCmdInfo.txQueue, pPloadDesc, NWAL_DESC_SIZE); return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via IPC queue ******************************************************************** * DESCRIPTION: Send packet via IPC queue ********************************************************************/ static int netapip_pktioSendIpc(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; err=0; Qmss_queuePushDesc (p->q, (void*)pkt); return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet to NETCP via NWAL ******************************************************************** * DESCRIPTION: Send packet to NETCP via NWAL ********************************************************************/ static int netapip_pktioSendNwal(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalTxPktInfo_t * pPktInfo=m->u.tx_meta; nwal_RetValue res; *err=0; pPktInfo->pPkt = pkt; res=nwal_send(p->nwalInstanceHandle, m->sa_handle,pPktInfo); if (res != nwal_OK) { *err = NETAPI_ERR_NWAL_TX_ERR -res; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet to SA via NWAL ******************************************************************** * DESCRIPTION: Send packet to NETCP via NWAL for side band data mode * channel via NWAL ********************************************************************/ static int netapip_pktioSendSb(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { nwal_RetValue nwalRetVal; nwalTxDmPSCmdInfo_t *dmPSCmdInfo; nwalLocCxtInfo_t nwalLocCxt; Cppi_HostDesc* pPloadDesc; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; nwalLocCxtInfo_t info; nwalDmTxPayloadInfo_t *pPktInfoSB = m->u.tx_sb_meta; NETCP_CFG_SA_T tunnel_id = (NETCP_CFG_SA_T) m->sa_handle; dmPSCmdInfo = netapip_netcpCfgGetSaSBInfo(&netapi_get_global()->nwal_context, tunnel_id); if (dmPSCmdInfo) { nwalRetVal = nwal_getLocCxtInfo(pktio_mGetNwalInstance(p),&info); if(nwalRetVal == nwal_OK) { dmPSCmdInfo->rxSbSaQ = info.rxSbSaQ; } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } nwal_mCmdDMUpdate(pkt, dmPSCmdInfo, pPktInfoSB->appCtxId, pPktInfoSB->encOffset, pPktInfoSB->encSize, pPktInfoSB->pEncIV, pPktInfoSB->authOffset, pPktInfoSB->authSize, pPktInfoSB->pAuthIV, pPktInfoSB->aadSize, pPktInfoSB->pAad); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(dmPSCmdInfo->txQueue, pPloadDesc, NWAL_DESC_SIZE); } else { *err=NETAPI_ERR_BAD_INPUT; return -1; } return 1; } /******************************************************************** * FUNCTION PURPOSE: Send packet via infrastructure DMA channel ******************************************************************** * DESCRIPTION: Send packet via infrastructure DMA channel ********************************************************************/ static int netapip_pktioSendIfdma(struct PKTIO_HANDLE_tag * pp, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { Cppi_DescTag tag={0}; Cppi_HostDesc* pPloadDesc; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; *err=0; tag.srcTagLo = m->u.tx_ifdma_dest; Cppi_setTag (Cppi_DescType_HOST, (Cppi_Desc *)pkt, &tag); pPloadDesc = Pktlib_getDescFromPacket(pkt); pPloadDesc = Qmss_osalConvertDescVirtToPhy(pPloadDesc); Qmss_queuePushDescSizeRaw(p->q, pPloadDesc, NWAL_DESC_SIZE); return 1; } /******************************************************************** * FUNCTION PURPOSE: Stub function for send, do nothing. ******************************************************************** * DESCRIPTION: Stub function for send, do nothing. ********************************************************************/ static int netapip_pktioSendDummy(struct PKTIO_HANDLE_tag * p, Ti_Pkt *pkt, PKTIO_METADATA_T *m, int * err) { *err = NETAPI_ERR_BAD_INPUT; return -1; } /******************************************************************** * FUNCTION PURPOSE: Stub function for poll, do nothing. ******************************************************************** * DESCRIPTION: Stub function for send, do nothing. ********************************************************************/ static int netapip_pktioPollDummy(struct PKTIO_HANDLE_tag * p, PKTIO_POLL_T * p_poll_cfg, int * err) { *err= NETAPI_ERR_BAD_INPUT; return 0; } /******************************************************************** * FUNCTION PURPOSE: Poll IPC queue ******************************************************************** * DESCRIPTION: Poll IPC queue ********************************************************************/ static int netapip_pktioPollIpc(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg, int * err) { Ti_Pkt * pkt_list[PKTIO_MAX_RECV]; PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV]; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; int r=0; int n; Ti_Pkt * temp; *err=0; n= (p->max_n< PKTIO_MAX_RECV) ? p->max_n : PKTIO_MAX_RECV; for(r=0;rq)); if(!temp) break; /* process meta data */ pkt_list[r]= temp; meta_s[r].flags1=0x1; } if (r) { p->cb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL); } return r; } /******************************************************************** * FUNCTION PURPOSE: Poll nwal data queues for pkts from netcp ******************************************************************** * DESCRIPTION: Poll nwal data queues for pkts from netcp ********************************************************************/ static int netapip_pktioPollNwal(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; *err=0; /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are set. optimizaion maybe? */ r=nwal_pollPkt(p->nwalInstanceHandle, p->poll_flags, (uint32_t) p, p->max_n, QMSS_PARAM_NOT_SPECIFIED, (void*) NULL); return r; } /******************************************************************** * FUNCTION PURPOSE: Poll nwal sideband queues for pkts from SA ******************************************************************** * DESCRIPTION: Poll nwal sideband queues for pkts from SA ********************************************************************/ static int netapip_pktioPollSb(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; *err=0; r=nwal_pollDm(p->nwalInstanceHandle, nwal_POLL_DM_DEF_SB_SA_Q, (uint32_t) p, p->max_n, QMSS_PARAM_NOT_SPECIFIED, (void *) NULL); return r; } /******************************************************************** * FUNCTION PURPOSE: Poll application provided NETCP RX queue ******************************************************************** * DESCRIPTION: Poll application provided NETCP RX queue ********************************************************************/ static int netapip_pktioPollNwalAdj(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; *err=0; /* Poll for common L2/L3 packets and L4 class pkts (todo-> only do L4 if classifiers are set. optimizaion maybe? */ r=nwal_pollPkt(p->nwalInstanceHandle, nwal_POLL_APP_MANAGED_PKT_Q, (uint32_t) p, p->max_n, p->q, (void *) NULL); return r; } /************************************************************************* * FUNCTION PURPOSE: Poll application defined sideband queues for packets * from SA ************************************************************************ * DESCRIPTION: Poll application defined sideband queues for packets * from SA *************************************************************************/ static int netapip_pktioPollSbAdj(struct PKTIO_HANDLE_tag * pp, PKTIO_POLL_T * p_poll_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p=(PKTIO_HANDLE_T*) pp; *err=0; r=nwal_pollDm(p->nwalInstanceHandle, nwal_POLL_DM_APP_MANAGED_Q, (uint32_t) p, p->max_n, p->q, (void *) NULL); return r; } /*-----------------------MAIN API----------------------*/ /******************************************************************** * FUNCTION PURPOSE: API creates a NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API creates a NETAPI PKTIO channel ********************************************************************/ PKTIO_HANDLE_T * netapi_pktioCreate(NETAPI_T n, char * name, PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err) { int r = 0; PKTIO_HANDLE_T *p; uint8_t isAllocated; *err=0; int q= QMSS_PARAM_NOT_SPECIFIED; int qtype=Qmss_QueueType_GENERAL_PURPOSE_QUEUE; if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;} if ((p_cfg->flags2 & PKTIO_PKT) &&(p_cfg->flags1& PKTIO_TX)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;}; if ((p_cfg->flags2 & PKTIO_SB) &&(p_cfg->flags1& PKTIO_TX)) { *err=NETAPI_ERR_BAD_INPUT; return NULL;}; /* get a free channel handle */ p=netapip_pktioGetFreeChannelSlot(n); if (!p) {*err = NETAPI_ERR_NOMEM; return (p); } p->back = n; p->cb = cb; p->max_n = p_cfg->max_n; p->_poll=netapip_pktioPollDummy; p->_send=netapip_pktioSendDummy; memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T)); if (p_cfg->qnum!=PKTIO_Q_ANY) { q= p_cfg->qnum; } /* special case for infrastructure dma channels */ if (p_cfg->flags2 & PKTIO_IFDMA) { qtype=Qmss_QueueType_INFRASTRUCTURE_QUEUE; } /* create a general queue */ p->q = Qmss_queueOpen(qtype, q, &isAllocated); if (p->q == (Qmss_QueueHnd) NULL) { netapi_Log("netapi_pktioCreate: queueOpen failed\n"); p->inuse=0; *err= NETAPI_ERR_QLLD; ///queue lld error return NULL; } p->qInfo = Qmss_getQueueNumber(p->q); if (p_cfg->flags2 & PKTIO_PKT) { p->use_nwal = PKTIO_4_ADJ_NWAL; p->_poll=netapip_pktioPollNwalAdj; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); } else if (p_cfg->flags2 & PKTIO_SB) { p->use_nwal = PKTIO_4_ADJ_SB; p->_poll=netapip_pktioPollSbAdj; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); } else if (p_cfg->flags2 & PKTIO_IFDMA) { p->use_nwal = 0; p->_send = netapip_pktioSendIfdma; p->cfg.flags1=PKTIO_TX; r= netapip_pktioCreateIFDMA(p); //we create the IF DMA channel here if (r<0) { //trouble -> couldn't set up DMA //close queue and return failure if (p->q) { Qmss_queueClose(p->q); } p->inuse=0; *err= NETAPI_ERR_QLLD; ///queue lld error TODO: fix error code return NULL; } } else { p->use_nwal=0; if (p_cfg->flags1& PKTIO_TX) p->_send=netapip_pktioSendIpc; if (p_cfg->flags1& PKTIO_RX) p->_poll=netapip_pktioPollIpc; } /* save name */ strncpy(p->name,name, strlen(name)flags1 & PKTIO_GLOBAL)) { //todo: make sure this succeeds.. hplib_mSpinLockLock(&pnetapiShm->netapi_pktio_lock); r=netapip_addGlobalPktio(n, name, &p->qInfo); hplib_mSpinLockUnlock(&pnetapiShm->netapi_pktio_lock); } ((NETAPI_HANDLE_T *)n )->n_pktios+=1; return p; } /******************************************************************** * FUNCTION PURPOSE: API opens an existing NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API opens an existing NETAPI PKTIO channel ********************************************************************/ PKTIO_HANDLE_T * netapi_pktioOpen(NETAPI_T n, char *name, PKTIO_CB cb, PKTIO_CFG_T * p_cfg, int * err) { int r=0; PKTIO_HANDLE_T *p, *p2; uint8_t isAllocated; *err=0; Qmss_Queue *p_qnum; int qtype=Qmss_QueueType_GENERAL_PURPOSE_QUEUE; if ((!p_cfg)||(!name)) {*err=NETAPI_ERR_BAD_INPUT; return NULL;} /* get a free channel handle */ p=netapip_pktioGetFreeChannelSlot(n); if (!p) {*err = NETAPI_ERR_NOMEM; return (p); } ((NETAPI_HANDLE_T *)n)->n_pktios+=1; p->inuse= PKTIO_INUSE; p->back = n; p->cb = cb; p->max_n = p_cfg->max_n; p->_poll=netapip_pktioPollDummy; p->_send=netapip_pktioSendDummy; memcpy((char *)&p->cfg, (char*) p_cfg, sizeof(PKTIO_CFG_T)); /* special handling of NETCP_RX, NETCP_TX */ if( (!strcmp(name, NETCP_RX)) || (!strcmp(name,NETCP_TX)) ) { /* these have already been opened internally, so don't search in global list */ p->use_nwal = PKTIO_DEF_NWAL; p->q = 0; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); if (!strcmp(name,NETCP_RX)) { p->_poll=netapip_pktioPollNwal; p->poll_flags= nwal_POLL_DEFAULT_GLOB_PKT_Q| nwal_POLL_DEFAULT_PER_PROC_PKT_Q; } if (!strcmp(name,NETCP_TX)) { p->_send=netapip_pktioSendNwal; } } else if( (!strcmp(name, NETCP_SB_RX)) || (!strcmp(name,NETCP_SB_TX)) ) { /* these have already been opened internally, so don't search in global list */ p->use_nwal = PKTIO_DEF_SB; p->q = 0; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); if (!strcmp(name,NETCP_SB_RX)) p->_poll=netapip_pktioPollSb; if (!strcmp(name,NETCP_SB_TX)) p->_send=netapip_pktioSendSb; } else { hplib_mSpinLockLock(&pnetapiShm->netapi_pktio_lock); /* Find queue in global list Note names like "QUEUE:%d" or IFDMA:%d cause general purpose or IFDMA queues of that number to be opened */ if (p_cfg->flags2 & PKTIO_IFDMA) { qtype= Qmss_QueueType_INFRASTRUCTURE_QUEUE; } hplib_mSpinLockUnlock(&pnetapiShm->netapi_pktio_lock); p_qnum = netapip_findGlobalPktio(n, name); if (!p_qnum ) { netapi_Log("netapi_pktioOpen: can't find %s\n",name); p->inuse=0; *err= NETAPI_ERR_NOTFOUND; ///queue lld error return NULL; } /* open a general queue (for now). use qnum that was just found */ p->q = Qmss_queueOpen(qtype, p_qnum->qNum , &isAllocated); if (p->q == (Qmss_QueueHnd) NULL) { netapi_Log("netapi_pktioCreate: queueOpen failed\n"); p->inuse=0; *err= NETAPI_ERR_QLLD; ///queue lld error return NULL; } p->qInfo = Qmss_getQueueNumber(p->q); netapi_Log("netapi_pktioOpen: queueMgr %d, queueNum; %d\n", p->qInfo.qMgr, p->qInfo.qNum); if (p_cfg->flags2 & PKTIO_PKT) { p->use_nwal = PKTIO_4_ADJ_NWAL; //additonal RX q for nwal p->_poll = netapip_pktioPollNwalAdj; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); netapi_Log("netapi_pktioOpen: nwalInstanceHandle 0x%x\n", p->nwalInstanceHandle); } else if (p_cfg->flags2 & PKTIO_SB) { p->use_nwal = PKTIO_4_ADJ_SB; //additional RX q for sideband with NWAL p->_poll = netapip_pktioPollSbAdj; p->nwalInstanceHandle = netapip_returnNwalInstanceHandle(n); } else if (p_cfg->flags2 & PKTIO_IFDMA) { p->_send= netapip_pktioSendIfdma; p->use_nwal = 0; } else { p->use_nwal=0; //not handled by nwal if (p_cfg->flags1& PKTIO_TX) p->_send=netapip_pktioSendIpc; if (p_cfg->flags1& PKTIO_RX) p->_poll=netapip_pktioPollIpc; } } /* save name */ strncpy(p->name,name, strlen(name)name); return p; } /******************************************************************** * FUNCTION PURPOSE: API controls an existing NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API controls an existing NETAPI PKTIO channel ********************************************************************/ void netapi_pktioControl(PKTIO_HANDLE_T * p, PKTIO_CB cb, PKTIO_CFG_T * p_cfg, PKTIO_CONTROL_T * p_control, int *err) { nwal_RetValue nwalRetVal; if (!p) { *err= NETAPI_ERR_BAD_INPUT; return; } if (cb) { p->cb = cb; } if (p_control) { /* todo: check for validity, eg don't allow clear of NETCP TX queues */ /* todo: implement divert */ switch(p_control->op) { //clear the queue case(PKTIO_SET_POLL_FLAGS): p->poll_flags=p_control->poll_flags; break; case(PKTIO_CLEAR): netapip_zapQ(p->q); break; case (PKTIO_UPDATE_FAST_PATH): if (p_cfg) { nwalRetVal = nwal_initPSCmdInfo(p->nwalInstanceHandle, p_cfg->fast_path_cfg.txPktInfo, &p->tx_psCmdInfo); if (nwalRetVal == nwal_OK) { switch (p_cfg->fast_path_cfg.fp_send_option) { case (PKTIO_FP_ESP_L4CKSUM_PORT): p->_send = netapip_pktioSendL4CkSumCryptPort; break; case (PKTIO_FP_AH_L4CKSUM_PORT): p->_send = netapip_pktioSendL4CkSumAHCryptPort; break; case (PKTIO_FP_ESP_PORT): p->_send = netapip_pktioSendCryptPort; break; case (PKTIO_FP_ESP_L3CKSUM_PORT): p->_send = netapip_pktioSendL3CkSumCryptPort; break; case (PKTIO_FP_AH_PORT): p->_send = netapip_pktioSendAHCryptPort; break; case (PKTIO_FP_NO_CRYPTO_NO_CKSUM_PORT): p->_send = netapip_pktioSendPort; break; case (PKTIO_FP_L4CKSUM_PORT): p->_send = netapip_pktioSendL4CkSumPort; break; default: break; } } else { *err = NETAPI_ERR_BAD_INPUT; } } else { *err = NETAPI_ERR_BAD_INPUT; } break; case (PKTIO_UPDATE_MAX_PKTS_PER_POLL): if (p_cfg) { p->max_n = p_cfg->max_n; } else { *err = NETAPI_ERR_BAD_INPUT; } break; case(PKTIO_DIVERT): default: netapi_Log("netapi_pktioControl: pktio_control op %d not implemented\n",p_control->op); *err= NETAPI_ERR_NOT_IMPLEMENTED; break; } } *err = NETAPI_ERR_OK; return; } /******************************************************************** * FUNCTION PURPOSE: API closes a NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API closes a NETAPI PKTIO channel ********************************************************************/ void netapi_pktioClose(PKTIO_HANDLE_T * p, int * err) { if(!p) { *err=1; return; } *err=0; if (p->q) { Qmss_queueClose(p->q); } p->q=-1; p->inuse=0; ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1; return; } /******************************************************************** * FUNCTION PURPOSE: API deletes a NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API deletes a NETAPI PKTIO channel ********************************************************************/ void netapi_pktioDelete(PKTIO_HANDLE_T * p, int * err) { if(!p) { *err=1; return; } *err=0; if (p->cfg.flags2 & PKTIO_IFDMA) { netapip_pktioDeleteIFDMA(p); } /* remove from name list */ hplib_mSpinLockLock(&pnetapiShm->netapi_pktio_lock); netapi_del_global_pktio((NETAPI_HANDLE_T *)p->back, p->name); hplib_mSpinLockUnlock(&pnetapiShm->netapi_pktio_lock); if((p->use_nwal != PKTIO_DEF_NWAL) && (p->use_nwal != PKTIO_DEF_SB)) { netapip_zapQ(p->q); //since we are deleting, zap the queue Qmss_queueClose(p->q); } p->q=-1; p->inuse=0; ((NETAPI_HANDLE_T *)p->back)->n_pktios-=1; return ; } /******************************************************************** * FUNCTION PURPOSE: API sends multiple packets to a NETAPI PKTIO channel ******************************************************************** * DESCRIPTION: API sends multiple packets to a NETAPI PKTIO channel ********************************************************************/ int netapi_pktioSendMulti(PKTIO_HANDLE_T * p, Ti_Pkt * pkt[], PKTIO_METADATA_T * m[], int np, int* err) { int r=0; for(r=0;r_send((struct PKTIO_HANDLE_tag *)p, (Ti_Pkt *)pkt, (PKTIO_METADATA_T *)m, err); } return r; } /******************************************************************** * FUNCTION PURPOSE: API polls all NETAPI PKTIO channels associated with NETAPI_T * instance for received packets ******************************************************************** * DESCRIPTION: API polls all NETAPI PKTIO channels associated with NETAPI_T * instance for received packets ********************************************************************/ int netapi_pktioPollAll(NETAPI_T handle, PKTIO_POLL_T * p_poll_cfg, int *err) { int i=0; int r=0; int err2; int cnt=0; PKTIO_HANDLE_T **pp =( PKTIO_HANDLE_T **) netapi_get_pktio_list(handle); *err=0; for(i=0;in_pktios;i++) { if (pp[i]->inuse != PKTIO_INUSE) continue; if(!(pp[i]->cfg.flags1&PKTIO_RX)) continue; r+=netapi_pktioPoll(pp[i], p_poll_cfg, &err2); cnt+=1; if (err2) { *err = err2; break;} } return r; } /******************************************************************** * FUNCTION PURPOSE: Internal function to delete a PKTIO infrastructure DMA channel ******************************************************************** * DESCRIPTION: Internal function to delete a PKTIO infrastructure DMA channel ********************************************************************/ int netapip_pktioDeleteIFDMA(PKTIO_HANDLE_T *p) { Cppi_channelDisable (p->txChHnd); Cppi_channelDisable (p->rxChHnd); Cppi_channelClose(p->txChHnd); Cppi_channelClose(p->rxChHnd); Cppi_close(p->cppiHnd); return 1; } /******************************************************************** * FUNCTION PURPOSE: Internal function to create a PKTIO infrastructure DMA channel ******************************************************************** * DESCRIPTION: Internal function to create a PKTIO infrastructure DMA channel * for infrastructure DMQ queue ********************************************************************/ int netapip_pktioCreateIFDMA(PKTIO_HANDLE_T * p ) { int dmaChan = p->qInfo.qNum - QMSS_INFRASTRUCTURE_QUEUE_BASE; unsigned char isAllocated; Cppi_TxChInitCfg txChCfg; Cppi_RxChInitCfg rxChCfg; Cppi_CpDmaInitCfg cpdmaCfg; /* Set up QMSS CPDMA configuration */ memset ((void *) &cpdmaCfg, 0, sizeof (Cppi_CpDmaInitCfg)); cpdmaCfg.dmaNum = Cppi_CpDma_QMSS_CPDMA; /* Open QMSS CPDMA */ p->cppiHnd = (Cppi_Handle) Cppi_open (&cpdmaCfg); if (p->cppiHnd == NULL) { return -1; } /* Set up Tx Channel parameters */ memset ((void *) &txChCfg, 0, sizeof (Cppi_TxChInitCfg)); txChCfg.channelNum = dmaChan; txChCfg.priority = 0; txChCfg.filterEPIB = 0; txChCfg.filterPS = 0; txChCfg.aifMonoMode = 0; txChCfg.txEnable = Cppi_ChState_CHANNEL_DISABLE; /* Open Tx Channel */ p->txChHnd = (Cppi_ChHnd) Cppi_txChannelOpen (p->cppiHnd, &txChCfg, &isAllocated); if (p->txChHnd == NULL) { Cppi_close(p->cppiHnd); return -1; } /* Set up Rx Channel parameters */ memset ((void *) &rxChCfg, 0, sizeof (Cppi_RxChInitCfg)); rxChCfg.channelNum = dmaChan; rxChCfg.rxEnable = Cppi_ChState_CHANNEL_DISABLE; /* Open Rx Channel */ p->rxChHnd = (Cppi_ChHnd) Cppi_rxChannelOpen (p->cppiHnd, &rxChCfg, &isAllocated); if (p->rxChHnd == NULL) { Cppi_channelClose(p->txChHnd); Cppi_close(p->cppiHnd); return -1; } if (Cppi_channelEnable (p->txChHnd) != CPPI_SOK) { Cppi_channelClose(p->txChHnd); Cppi_channelClose(p->rxChHnd); Cppi_close(p->cppiHnd); return -1; } /* Enable receive channel */ if (Cppi_channelEnable (p->rxChHnd) != CPPI_SOK) { Cppi_channelDisable (p->txChHnd); Cppi_channelClose(p->txChHnd); Cppi_channelClose(p->rxChHnd); Cppi_close(p->cppiHnd); return -1; } return 1; } /********************************************************************** * FUNCTION PURPOSE: Internal Callback that gets registered with NWAL for packet reception ********************************************************************** * DESCRIPTION: Callback that gets registered with NWAL for packet reception * appCookie is the pktio handle **********************************************************************/ void netapip_pktioNWALRxPktCallback(uint32_t appCookie, uint16_t numPkts, nwalRxPktInfo_t* pPktInfo, uint64_t timestamp, nwal_Bool_t* pFreePkt) { PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie; int r=0; int n; Ti_Pkt * pkt_list[PKTIO_MAX_RECV]; PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV]; for(r=0;rcb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, timestamp); } } /********************************************************************** * FUNCTION PURPOSE: Internal Callback that gets registered with NWAL for crypto reception ********************************************************************** * DESCRIPTION: Callback that gets registered with NWAL for crypto reception, * appCookie is the pktio handle **********************************************************************/ void netapip_pktioNWALSBPktCallback(uint32_t appCookie, uint16_t numPkts, nwalDmRxPayloadInfo_t* pDmRxPktInfo, nwal_Bool_t* pFreePkt) { PKTIO_HANDLE_T * p = (PKTIO_HANDLE_T *) appCookie; int r=0; int n; Ti_Pkt * pkt_list[PKTIO_MAX_RECV]; PKTIO_METADATA_T meta_s[PKTIO_MAX_RECV]; for(r=0;rcb((struct PKTIO_HANDLE_tag *)p, pkt_list, &meta_s[0], r, 0LL); } }