ixethaccdataplane.c

来自「有关ARM开发板上的IXP400网络驱动程序的源码以。」· C语言 代码 · 共 2,320 行 · 第 1/5 页

C
2,320
字号
IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, 					      IxEthAccPortRxCallback					      rxCallbackFn, 					      UINT32 callbackTag){	    IxEthAccPortId port;    IxEthAccStatus status;    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_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);    }    /* Check the user is not changing the callback type     * when the port is enabled.     */    if (ixEthAccMacState[portId].portDisableState == ACTIVE)    {	for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++)	{	    if ((ixEthAccMacState[port].portDisableState == ACTIVE)		&& (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == TRUE))	    {		/* one of the active ports has a different rx callback type.		 * Changing the callback type when the port is enabled		 * is not safe 		 */		return (IX_ETH_ACC_INVALID_ARG);	    }	}    }    /* update the callback pointer : this is done before      * registering the new qmgr callback     */    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = rxCallbackFn;    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = callbackTag;        if(ixEthAccDataInfo.rxQMCbTypeSet != NORMAL)    {        /* update the qmgr callback for rx queues            if priority scheduling is enabled for Rx, use the priority callback         */        if(ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY)        {            status = ixEthAccQMgrRxCallbacksRegister(                         (IxQMgrCallback) ixEthRxPriorityPoll,                          IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK);         } else {            status = ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback, 0);         }        if(status != IX_ETH_ACC_SUCCESS)        {	    /* unexpected qmgr error */            IX_ETH_ACC_FATAL_LOG("ixEthAccPortRxCallbackRegister: unexpected QMgr error, " \                "could not register Rx single-buffer callback\n", 0, 0, 0, 0, 0, 0);             RX_INC(portId,rxUnexpectedError);            return (status);        }        ixEthAccDataInfo.rxQMCbTypeSet = NORMAL;    }    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = FALSE;    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister(			 IxEthAccPortId portId, 			 IxEthAccPortMultiBufferRxCallback			 rxCallbackFn, 			 UINT32 callbackTag){    IxEthAccPortId port;    IxEthAccStatus status;    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_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);    }    /* Check the user is not changing the callback type     * when the port is enabled.     */    if (ixEthAccMacState[portId].portDisableState == ACTIVE)    {	for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++)	{	    if ((ixEthAccMacState[port].portDisableState == ACTIVE)		&& (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == FALSE))	    {		/* one of the active ports has a different rx callback type.		 * Changing the callback type when the port is enabled		 * is not safe 		 */		return (IX_ETH_ACC_INVALID_ARG);	    }	}    }    /* update the callback pointer : this is done before      * registering the new qmgr callback     */    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = rxCallbackFn;    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = callbackTag;    if(ixEthAccDataInfo.rxQMCbTypeSet != MULTIBUFFER)    {        /* update the qmgr callback for rx queues            if priority scheduling is enabled for Rx, use the priority callback         */        if(ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY)        {            status = ixEthAccQMgrRxCallbacksRegister(                         (IxQMgrCallback)ixEthRxMultiBufferPriorityPoll,                         IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK);        } else {            status = ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback, 0);        }        if(status != IX_ETH_ACC_SUCCESS)        {	    /* unexpected qmgr error */	    RX_INC(portId,rxUnexpectedError);            IX_ETH_ACC_FATAL_LOG("ixEthAccPortMultiBufferRxCallbackRegister: unexpected QMgr error, " \                "could not register Rx multi-buffer callback\n", 0, 0, 0, 0, 0, 0);	    return (IX_ETH_ACC_INVALID_ARG);        }        ixEthAccDataInfo.rxQMCbTypeSet = MULTIBUFFER;    }    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = TRUE;    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortTxFrameSubmit(IxEthAccPortId portId, 					 IX_OSAL_MBUF *buffer, 					 IxEthAccTxPriority priority){	    IX_STATUS	qStatus = IX_SUCCESS;    UINT32      qBuffer;    IxEthAccTxPriority highestPriority;    IxQMgrQStatus txQStatus;#ifndef NDEBUG     if (buffer == NULL)    {	return (IX_ETH_ACC_FAIL);    }    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_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }    if ((UINT32)priority > (UINT32)IX_ETH_ACC_TX_PRIORITY_7)    {	return (IX_ETH_ACC_INVALID_ARG);    }#endif     /*     * Need to Flush the MBUF and its contents (data) as it may be     * read from the NPE. Convert virtual addresses to physical addresses also.     */    qBuffer = ixEthAccMbufTxQPrepare(buffer);    /*     * If no fifo priority set on Xscale ...     */    if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == 	FIFO_NO_PRIORITY)    {	/*	 * Add The Tx Buffer to the H/W Tx Q if possible  	 * (the priority is passed to the NPE, because	 * the NPE is able to reorder the frames 	 * before transmission to the underlying hardware)	 */	qStatus = ixEthAccQmgrTxWrite(portId,				      qBuffer,				      IX_ETH_ACC_TX_DEFAULT_PRIORITY);	if (qStatus == IX_SUCCESS)	{	    TX_STATS_INC(portId,txQOK);	    /*  	     * "best case" scenario : Buffer added to h/w Q.	     */	    return (IX_SUCCESS);	}	else if (qStatus == IX_QMGR_Q_OVERFLOW)	{	    /*	     * We were unable to write the buffer to the 	     * appropriate H/W Q,  Save it in the sw Q.	     * (use the default priority queue regardless of 	     * input parameter)	     */	    priority = IX_ETH_ACC_TX_DEFAULT_PRIORITY;	}	else 	{	    /* unexpected qmgr error */	    TX_INC(portId,txUnexpectedError);	    IX_ETH_ACC_FATAL_LOG(		"ixEthAccPortTxFrameSubmit:Error: qStatus = %u\n", 		(UINT32)qStatus, 0, 0, 0, 0, 0);	    return (IX_ETH_ACC_FAIL);	}    }    else if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline == 	     FIFO_PRIORITY)    {		/*	 * For priority transmission, put the frame directly on the H/W queue	 * if the H/W queue is empty, otherwise, put it in a S/W Q	 */	ixQMgrQStatusGet(IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), &txQStatus);	if((txQStatus & IX_QMGR_Q_STATUS_E_BIT_MASK) != 0)	{	    /*The tx queue is empty, check whether there are buffers on the s/w queues*/	    if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority)	       !=IX_ETH_ACC_FAIL)	    {		/*there are buffers on the s/w queues, submit them*/		ixEthAccTxFromSwQ(portId, highestPriority);		/* the queue was empty, 1 buffer is already supplied		 * but is likely to be immediately transmitted and the 		 * hw queue is likely to be empty again, so submit 		 * more from the sw queues		 */		if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority)		   !=IX_ETH_ACC_FAIL)		{		    ixEthAccTxFromSwQ(portId, highestPriority);		    /*		     * and force the buffer supplied to be placed 		     * on a priority queue		     */		    qStatus = IX_QMGR_Q_OVERFLOW;		}		else		{		    /*there are no buffers in the s/w queues, submit directly*/		    qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority);		}	    }	    else	    {		/*there are no buffers in the s/w queues, submit directly*/		qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority);	    }	}	else	{	    qStatus = IX_QMGR_Q_OVERFLOW;	}    }    else     {	TX_INC(portId,txUnexpectedError);	IX_ETH_ACC_FATAL_LOG(	    "ixEthAccPortTxFrameSubmit:Error: wrong schedule discipline setup\n", 	    0, 0, 0, 0, 0, 0);	return (IX_ETH_ACC_FAIL);    }        if(qStatus == IX_SUCCESS )     {	TX_STATS_INC(portId,txQOK);	return IX_ETH_ACC_SUCCESS;    }    else if(qStatus == IX_QMGR_Q_OVERFLOW)    {	TX_STATS_INC(portId,txQDelayed);	/*	 * We were unable to write the buffer to the 	 * appropriate H/W Q,  Save it in a s/w Q.	 */	IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL(		ixEthAccPortData[portId].		ixEthAccTxData.txQ[priority], 		buffer);	    	qStatus = ixQMgrNotificationEnable(		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),		IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId));        if (qStatus != IX_SUCCESS)	{	    if (qStatus == IX_QMGR_WARNING)	    {		/* notification is enabled for a queue 		 * which is already empty (the condition is already met)		 * and there will be no more queue event to drain the sw queue		 */		TX_STATS_INC(portId,txLateNotificationEnabled);				/* pull a buffer from the sw queue */		if(ixEthAccTxSwQHighestPriorityGet(portId,  &highestPriority)		   !=IX_ETH_ACC_FAIL)		{		    /*there are buffers on the s/w queues, submit from them*/		    ixEthAccTxFromSwQ(portId, highestPriority);		}	    }	    else	    {		TX_INC(portId,txUnexpectedError);		IX_ETH_ACC_FATAL_LOG(		     "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", 		     qStatus, 0, 0, 0, 0, 0);	    }        }    }    else    {	TX_INC(portId,txUnexpectedError);	IX_ETH_ACC_FATAL_LOG(	     "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n", 	     qStatus, 0, 0, 0, 0, 0);	return (IX_ETH_ACC_FAIL);    }    return (IX_ETH_ACC_SUCCESS);}/** * * @brief replenish: convert a chain of mbufs to the format  *        expected by the NPE *  */IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortRxFreeReplenish(IxEthAccPortId portId, 					   IX_OSAL_MBUF *buffer){	    IX_STATUS	qStatus = IX_SUCCESS;    UINT32      qBuffer;        /*      * Check buffer is valid.     */    #ifndef NDEBUG     /* check parameter value */    if (buffer == 0)    {	return (IX_ETH_ACC_FAIL);    }    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);    }    /* check initialisation is done */    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }    /* check boundaries and constraints */    if (IX_OSAL_MBUF_MLEN(buffer) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN)    {	return (IX_ETH_ACC_FAIL);    }#endif     qBuffer = ixEthAccMbufRxQPrepare(buffer);    /*     * Add The Rx Buffer to the H/W Free buffer Q if possible       */    qStatus = ixEthAccQmgrLockRxWrite(portId, qBuffer);    if (qStatus == IX_SUCCESS)    {	RX_STATS_INC(portId,rxFreeRepOK);	/* 	 * Buffer added to h/w Q.	 */	return (IX_SUCCESS);    }    else if (qStatus == IX_QMGR_Q_OVERFLOW)    {	RX_STATS_INC(portId,rxFreeRepDelayed);	/*	 * We were unable to write the buffer to the approprate H/W Q, 	 * Save it in a s/w Q.	 */	IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL(	    ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, 	    buffer);	qStatus = ixQMgrNotificationEnable(	    IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId),	    IX_ETH_ACC_PORT_TO_RX_FREE_Q_SOURCE(portId));                if (qStatus != IX_SUCCESS)	{	    if (qStatus == IX_QMGR_WARNING)	    {		/* notification is enabled for a queue 		 * which is already empty (the condition is already met)		 * and there will be no more queue event to drain the sw queue		 * move an entry from the sw queue to the hw queue */		RX_STATS_INC(portId,rxFreeLateNotificationEnabled);		ixEthAccRxFreeFromSwQ(portId);	    }	    else	    {		RX_INC(portId,rxUnexpectedError);		IX_ETH_ACC_FATAL_LOG(

⌨️ 快捷键说明

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