⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixethaccdataplane.c

📁 AMCC POWERPC 44X系列的U-BOOT文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Convert the mbuf header after NPE transmission * Since there is nothing changed by the NPE, there is no need * to process anything but the update of internal stats * when they are enabled*/PRIVATE voidixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf){#ifndef NDEBUG    /* test for unchained mbufs */    if (IX_ETHACC_NE_NEXT(mbuf) == 0)    {	/* unchained mbufs : update the stats */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxDoneMBufs);    }    else    {	/* chained mbufs : walk the chain and update the stats */	IX_OSAL_MBUF *ptr = mbuf;	do	{	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxDoneMBufs);	    ptr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);	}	while (ptr != NULL);    }#endif}/* Convert the mbuf header after NPE reception */PRIVATE voidixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf){    UINT32 len;    /* endianess swap for tci and flags       note: this is done only once, even for chained buffers */    IX_ETHACC_NE_FLAGS(mbuf)   = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf));    IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf));    /* test for unchained mbufs */    if (IX_ETHACC_NE_NEXT(mbuf) == 0)    {	/* unchained mbufs */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxMBufs);	/* get the frame length. it is the same than the buffer length */	len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));	len &= IX_ETHNPE_ACC_PKTLENGTH_MASK;	IX_OSAL_MBUF_PKT_LEN(mbuf) = IX_OSAL_MBUF_MLEN(mbuf) = len;        /* clears the next packet field */	IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) = NULL;    }    else    {	IX_OSAL_MBUF *ptr = mbuf;	IX_OSAL_MBUF *nextPtr;	UINT32 frmLen;	/* convert the frame length */	frmLen = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));	IX_OSAL_MBUF_PKT_LEN(mbuf) = (frmLen & IX_ETHNPE_ACC_PKTLENGTH_MASK);        /* chained mbufs */	do	{	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxMBufs);	    /* convert the length */	    len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(ptr));	    IX_OSAL_MBUF_MLEN(ptr) = (len >> IX_ETHNPE_ACC_LENGTH_OFFSET);            /* get the next pointer */ 	    PTR_NPE2VIRT(IX_OSAL_MBUF *,IX_ETHACC_NE_NEXT(ptr), nextPtr);	    if (nextPtr != NULL)	    {		nextPtr = (IX_OSAL_MBUF *)((UINT8 *)nextPtr - offsetof(IX_OSAL_MBUF,ix_ne));	    }	    /* set the next pointer */	    IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr) = nextPtr;	    /* move to the next buffer */	    ptr = nextPtr;	}	while (ptr != NULL);    }}/* write to qmgr if possible and report an overflow if not possible * Use a fast lock to protect the queue write. * This way, the tx feature is reentrant. */PRIVATE IX_STATUSixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer){    IX_STATUS qStatus;    if (ixOsalFastMutexTryLock(&txWriteMutex[portId]) == IX_SUCCESS)    {	qStatus = ixQMgrQWrite(	       IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),	       &qBuffer);#ifndef NDEBUG	if (qStatus != IX_SUCCESS)	{	    TX_STATS_INC(portId, txOverflow);	}#endif	ixOsalFastMutexUnlock(&txWriteMutex[portId]);    }    else    {	TX_STATS_INC(portId, txLock);	qStatus = IX_QMGR_Q_OVERFLOW;    }    return qStatus;}/* write to qmgr if possible and report an overflow if not possible * Use a fast lock to protect the queue write. * This way, the Rx feature is reentrant. */PRIVATE IX_STATUSixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer){    IX_STATUS qStatus;    if (ixOsalFastMutexTryLock(&rxWriteMutex[portId]) == IX_SUCCESS)    {	qStatus = ixQMgrQWrite(	       IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId),	       &qBuffer);#ifndef NDEBUG	if (qStatus != IX_SUCCESS)	{	    RX_STATS_INC(portId, rxFreeOverflow);	}#endif	ixOsalFastMutexUnlock(&rxWriteMutex[portId]);    }    else    {	RX_STATS_INC(portId, rxFreeLock);	qStatus = IX_QMGR_Q_OVERFLOW;    }    return qStatus;}/* * Set the priority and write to a qmgr queue. */PRIVATE IX_STATUSixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority){    /* fill the priority field */    qBuffer |= (priority << IX_ETHNPE_QM_Q_FIELD_PRIOR_R);    return ixEthAccQmgrLockTxWrite(portId, qBuffer);}/** * * @brief This function will discover the highest priority S/W Tx Q that *        has entries in it * * @param portId - (in) the id of the port whose S/W Tx queues are to be searched *        priorityPtr - (out) the priority of the highest priority occupied q will be written *                      here * * @return IX_ETH_ACC_SUCCESS if an occupied Q is found *         IX_ETH_ACC_FAIL if no Q has entries * * @internal */PRIVATE IxEthAccStatusixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId,				IxEthAccTxPriority *priorityPtr){    if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline	== FIFO_NO_PRIORITY)    {	if(IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].	       ixEthAccTxData.txQ[IX_ETH_ACC_TX_DEFAULT_PRIORITY]))	{	    return IX_ETH_ACC_FAIL;	}	else	{	    *priorityPtr = IX_ETH_ACC_TX_DEFAULT_PRIORITY;	    TX_STATS_INC(portId,txPriority[*priorityPtr]);	    return IX_ETH_ACC_SUCCESS;	}    }    else    {	IxEthAccTxPriority highestPriority = IX_ETH_ACC_TX_PRIORITY_7;	while(1)	{	    if(!IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].	       ixEthAccTxData.txQ[highestPriority]))	    {		*priorityPtr = highestPriority;		TX_STATS_INC(portId,txPriority[highestPriority]);		return IX_ETH_ACC_SUCCESS;	    }	    if (highestPriority == IX_ETH_ACC_TX_PRIORITY_0)	    {		return IX_ETH_ACC_FAIL;	    }	    highestPriority--;	}    }}/** * * @brief This function will take a buffer from a TX S/W Q and attempt *        to add it to the relevant TX H/W Q * * @param portId - the port whose TX queue is to be written to *        priority - identifies the queue from which the entry is to be read * * @internal */PRIVATE IxEthAccStatusixEthAccTxFromSwQ(IxEthAccPortId portId,		  IxEthAccTxPriority priority){    IX_OSAL_MBUF        *mbuf;    IX_STATUS	   qStatus;    IX_OSAL_ENSURE((UINT32)priority <= (UINT32)7, "Invalid priority");    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(	ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],	mbuf);    if (mbuf != NULL)    {	/*	 * Add the Tx buffer to the H/W Tx Q	 * We do not need to flush here as it is already done	 * in TxFrameSubmit().	 */	qStatus = ixEthAccQmgrTxWrite(	      portId,	      IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)IX_ETHACC_NE_SHARED(mbuf)),	      priority);	if (qStatus == IX_SUCCESS)	{	    TX_STATS_INC(portId,txFromSwQOK);	    return IX_SUCCESS;	}	else if (qStatus == IX_QMGR_Q_OVERFLOW)	{	    /*	     * H/W Q overflow, need to save the buffer	     * back on the s/w Q.	     * we must put it back on the head of the q to avoid	     * reordering packet tx	     */	    TX_STATS_INC(portId,txFromSwQDelayed);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],		mbuf);	    /*enable Q notification*/	    qStatus = ixQMgrNotificationEnable(		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),		IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId));            if (qStatus != IX_SUCCESS && qStatus != IX_QMGR_WARNING)            {		TX_INC(portId,txUnexpectedError);		IX_ETH_ACC_FATAL_LOG(	            "ixEthAccTxFromSwQ:Unexpected Error: %u\n",	            qStatus, 0, 0, 0, 0, 0);            }	}	else	{	    TX_INC(portId,txUnexpectedError);	    /* recovery attempt */	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],		mbuf);	    IX_ETH_ACC_FATAL_LOG(		"ixEthAccTxFromSwQ:Error: unexpected QM status 0x%08X\n",		qStatus, 0, 0, 0, 0, 0);	}    }    else    {	/* sw queue is empty */    }    return IX_ETH_ACC_FAIL;}/** * * @brief This function will take a buffer from a RXfree S/W Q and attempt *        to add it to the relevant RxFree H/W Q * * @param portId - the port whose RXFree queue is to be written to * * @internal */PRIVATE IxEthAccStatusixEthAccRxFreeFromSwQ(IxEthAccPortId portId){    IX_OSAL_MBUF        *mbuf;    IX_STATUS	   qStatus = IX_SUCCESS;    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(	  ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,	  mbuf);    if (mbuf != NULL)    {	/*	 * Add The Rx Buffer to the H/W Free buffer Q if possible	 */	qStatus = ixEthAccQmgrLockRxWrite(portId,		  IX_OSAL_MMU_VIRT_TO_PHYS(			 (UINT32)IX_ETHACC_NE_SHARED(mbuf)));	if (qStatus == IX_SUCCESS)	{	    RX_STATS_INC(portId,rxFreeRepFromSwQOK);	    /*	     * Buffer added to h/w Q.	     */	    return IX_SUCCESS;	}	else if (qStatus == IX_QMGR_Q_OVERFLOW)	{	    /*	     * H/W Q overflow, need to save the buffer back on the s/w Q.	     */	    RX_STATS_INC(portId,rxFreeRepFromSwQDelayed);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		   ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,		   mbuf);	}	else	{	    /* unexpected qmgr error */	    RX_INC(portId,rxUnexpectedError);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		    ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,		    mbuf);	    IX_ETH_ACC_FATAL_LOG("IxEthAccRxFreeFromSwQ:Error: unexpected QM status 0x%08X\n",				 qStatus, 0, 0, 0, 0, 0);	}    }    else    {	/* sw queue is empty */    }    return IX_ETH_ACC_FAIL;}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccInitDataPlane(){    UINT32 portId;    /*     * Initialize the service and register callback to other services.     */    IX_ETH_ACC_MEMSET(&ixEthAccDataStats,		      0,		      sizeof(ixEthAccDataStats));    for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)    {	ixOsalFastMutexInit(&txWriteMutex[portId]);	ixOsalFastMutexInit(&rxWriteMutex[portId]);	IX_ETH_ACC_MEMSET(&ixEthAccPortData[portId],			  0,			  sizeof(ixEthAccPortData[portId]));	ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = FIFO_NO_PRIORITY;    }    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId,						  IxEthAccPortTxDoneCallback						  txCallbackFn,						  UINT32 callbackTag){    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())    {	return (IX_ETH_ACC_FAIL);    }    if (!IX_ETH_ACC_IS_PORT_VALID(portId))    {	return (IX_ETH_ACC_INVALID_PORT);    }/* HACK: removing this code to enable NPE-A preliminary testing *    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) *    { *        IX_ETH_ACC_WARNING_LOG("ixEthAccPortTxDoneCallbackRegister: Unavailable Eth %d: Cannot register TxDone Callback.\n",(INT32)portId,0,0,0,0,0); *        return IX_ETH_ACC_SUCCESS ; *    } */    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }    if (txCallbackFn == 0)	/* Check for null function pointer here. */    {	return (IX_ETH_ACC_INVALID_ARG);    }    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = txCallbackFn;    ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = callbackTag;    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId,					      IxEthAccPortRxCallback					      rxCallbackFn,					      UINT32 callbackTag){    IxEthAccPortId port;    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())    {	return (IX_ETH_ACC_FAIL);    }    if (!IX_ETH_ACC_IS_PORT_VALID(portId))    {	return (IX_ETH_ACC_INVALID_PORT);    }    if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))    {        IX_ETH_ACC_WARNING_LOG("ixEthAccPortRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0);        return IX_ETH_ACC_SUCCESS ;    }    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }    /* Check for null function pointer here. */    if (rxCallbackFn == NULL)    {	return (IX_ETH_ACC_INVALID_ARG);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -