Beispiel #1
0
/*****************************************************************
 *
 *  Interface query functions
 *
 */
IxEthAccStatus
ixEthAccMdioShow (void)
{
    UINT32 regval;

    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
    {
	return (IX_ETH_ACC_FAIL);
    }

    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
    ixEthAccMdioCmdRead(&regval);
    ixOsalMutexUnlock(&miiAccessLock);
    
    printf("MDIO command register\n");
    printf("    Go bit      : 0x%x\n", (regval & BIT(31)) >> 31);
    printf("    MDIO Write  : 0x%x\n", (regval & BIT(26)) >> 26);
    printf("    PHY address : 0x%x\n", (regval >> 21) & 0x1f);
    printf("    Reg address : 0x%x\n", (regval >> 16) & 0x1f);
	
    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
    ixEthAccMdioStatusRead(&regval);
    ixOsalMutexUnlock(&miiAccessLock);

    printf("MDIO status register\n");
    printf("    Read OK     : 0x%x\n", (regval & BIT(31)) >> 31);
    printf("    Read Data   : 0x%x\n", (regval >> 16) & 0xff);

    return IX_ETH_ACC_SUCCESS;   
}
Beispiel #2
0
/*********************************************************************
 * ixEthAccMiiWriteRtn - write a 16 bit value to a PHY
 */
IxEthAccStatus
ixEthAccMiiWriteRtn (UINT8 phyAddr, 
		     UINT8 phyReg, 
		     UINT16 value)
{
    UINT32 mdioCommand;
    UINT32 regval;
    UINT16 readVal;
    UINT32 miiTimeout;

    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
    {
	return (IX_ETH_ACC_FAIL);
    }

    if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) 
	|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
    {
	return (IX_ETH_ACC_FAIL);
    }
   
    /* ensure that a PHY is present at this address */
    if(ixEthAccMiiReadRtn(phyAddr,
                          IX_ETH_ACC_MII_CTRL_REG,
                          &readVal) != IX_ETH_ACC_SUCCESS)
    {
        return (IX_ETH_ACC_FAIL);
    }

    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
    mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL
	| phyAddr << IX_ETH_ACC_MII_ADDR_SHL ;
    mdioCommand |= IX_ETH_ACC_MII_GO | IX_ETH_ACC_MII_WRITE | value;

    ixEthAccMdioCmdWrite(mdioCommand);
    
    miiTimeout = ixEthAccMiiRetryCount;

    while(miiTimeout)
    {
	
	ixEthAccMdioCmdRead(&regval);

	/*The "GO" bit is reset to 0 when the write completes*/
	if((regval & IX_ETH_ACC_MII_GO) == 0x0)
	{	    	    
	    break;
	}
	/* Sleep for a while */
	ixOsalSleep(ixEthAccMiiAccessTimeout);
        miiTimeout--;
    }
    
    ixOsalMutexUnlock(&miiAccessLock);
    if(miiTimeout == 0)
    {
	return IX_ETH_ACC_FAIL;
    }
    return IX_ETH_ACC_SUCCESS;
}
PRIVATE void 
ixEthAccCodeletDispatcherPoll (void* arg, void** ptrRetObj)
{
    if (ixOsalMutexLock (&ixEthAccCodeletDispatcherPollRunning,
			 IX_OSAL_WAIT_FOREVER) != IX_SUCCESS)
    {
        printf("Dispatcher: Error starting QMgr Dispatcher thread! Failed to lock mutex.\n");
        return;
    }

    ixEthAccCodeletDispatcherPollStopTrigger = FALSE;

    while (1)
    {
        if (ixEthAccCodeletDispatcherPollStopTrigger)
        {
            break;  /* Exit the loop */
        }

	ixOsalYield();

	(*ixEthAccCodeletDispatcherFunc) (IX_QMGR_QUELOW_GROUP);
    }

    ixOsalMutexUnlock (&ixEthAccCodeletDispatcherPollRunning); 

    /* Exit the thread */
}
IX_STATUS 
ixEthAccCodeletDispatcherStop(BOOL useInterrupt)
{
    if(useInterrupt) /* Interrupt mode */
    {
	/* 
	 * Unhook the QM QLOW dispatcher to the interrupt controller. 
	 */
	if (ixOsalIrqUnbind(IX_ETH_CODELET_QMGR_IRQ) != IX_SUCCESS)
	{
	    printf("Dispatcher: Failed to unbind to QM1 interrupt\n");
	    return (IX_FAIL);
	}
    }
    else
    {
	if (!ixEthAccCodeletDispatcherPollStopTrigger)
	{
	    ixEthAccCodeletDispatcherPollStopTrigger = TRUE;
	    if (ixOsalMutexLock (&ixEthAccCodeletDispatcherPollRunning,
				 IX_OSAL_WAIT_FOREVER) != IX_SUCCESS)
	    {
		printf("Dispatcher: Error stopping QMgr Dispatcher thread!\n");
		return (IX_FAIL);
	    }
	    ixOsalMutexUnlock (&ixEthAccCodeletDispatcherPollRunning);
	    
	    ixOsalMutexDestroy(&ixEthAccCodeletDispatcherPollRunning);
	}
    }

    ixEthAccCodeletDispatcherInitialized = FALSE;

    return (IX_SUCCESS);
}
/*
 * Function definition: ixEthAccCodeletDBMaintenanceStop()
 *
 * Stop the EDB Maintenance task
 */
IX_STATUS 
ixEthAccCodeletDBMaintenanceStop(void)
{
    if (!(ixEthAccCodeletDBMaintenanceTaskStopTrigger))
    {
	ixEthAccCodeletDBMaintenanceTaskStopTrigger = TRUE;
	if (ixOsalMutexLock (&ixEthAccCodeletDBMaintenanceTaskRunning, IX_OSAL_WAIT_FOREVER)
	    != IX_SUCCESS)
	{
	    printf("DBLearning: Error stopping Database Maintenance thread!\n");
	    return (IX_FAIL);
	}
	ixOsalMutexUnlock (&ixEthAccCodeletDBMaintenanceTaskRunning);
	
	ixOsalMutexDestroy(&ixEthAccCodeletDBMaintenanceTaskRunning);
    }

    ixEthAccCodeletDBMaintenanceInitialized = FALSE; 

    return (IX_SUCCESS);
}
PRIVATE void ixEthAccCodeletDBMaintenanceTask (void* arg, void** ptrRetObj)
{
    UINT32 count;

    ixEthAccCodeletDBMaintenanceTaskStopTrigger = FALSE;

    if (ixOsalMutexLock (&ixEthAccCodeletDBMaintenanceTaskRunning, IX_OSAL_WAIT_FOREVER) 
	!= IX_SUCCESS)
    {
        printf("DbLearning: Error starting Database Maintenance thread! Failed to lock mutex.\n");
        return;
    }

    while (1)
    {
	/* 
	 * The Database maintenance function must be called at a period 
	 * of approximately IX_ETH_DB_MAINTENANCE_TIME seconds 
	 * regardless of whether learning is enabled or not.
 	 */
        for (count = 0; count < IX_ETH_DB_MAINTENANCE_TIME; count++)
        { 
	    ixOsalSleep(1000); /* 1000 milliseconds */
	    if (ixEthAccCodeletDBMaintenanceTaskStopTrigger)
	    {
		break;  /* Exit the delay loop */
	    }
        }
	if (ixEthAccCodeletDBMaintenanceTaskStopTrigger)
	{
	    break;  /* Exit the thread loop */
	}

	ixEthDBDatabaseMaintenance();
    }

    ixOsalMutexUnlock (&ixEthAccCodeletDBMaintenanceTaskRunning);
}
Beispiel #7
0
/**
 * @brief initializes the event queue and the event processor
 *
 * This function is called by the component initialization
 * function, ixEthDBInit().
 *
 * @warning do not call directly
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or IX_ETH_DB_FAIL otherwise
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBStartLearningFunction(void)
{
    IxOsalThread eventProcessorThread;
    IxOsalThreadAttr threadAttr;

    threadAttr.name      = "EthDB event thread";
    threadAttr.stackSize = 32 * 1024; /* 32kbytes */
    threadAttr.priority  = 128;

    /* reset event queue */
    ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);

    RESET_QUEUE(&eventQueue);

    ixOsalMutexUnlock(&eventQueueLock);

    /* init event queue semaphore */
    if (ixOsalSemaphoreInit(&eventQueueSemaphore, 0) != IX_SUCCESS)
    {
        return IX_ETH_DB_FAIL;
    }

    ixEthDBLearningShutdown = FALSE;

    /* create processor loop thread */
    if (ixOsalThreadCreate(&eventProcessorThread, &threadAttr, ixEthDBEventProcessorLoop, NULL) != IX_SUCCESS)
    {
        return IX_ETH_DB_FAIL;
    }

    /* start event processor */
    ixOsalThreadStart(&eventProcessorThread);

    return IX_ETH_DB_SUCCESS;
}
Beispiel #8
0
/**
 * @brief Locks learning tree updates and port disable
 *
 *
 * This function locks portUpdateLock single mutex. It is primarily used
 * to avoid executing 'port disable' during ELT maintenance.
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBUpdateLock(void)
{
    ixOsalMutexLock(&portUpdateLock, IX_OSAL_WAIT_FOREVER);
}
Beispiel #9
0
/**
 * @brief Ethernet event processor loop
 *
 * Extracts at most EVENT_PROCESSING_LIMIT batches of events and
 * sends them for processing to @ref ixEthDBProcessEvent().
 * Triggers port updates which normally follow learning events.
 *
 * @warning do not call directly, executes in separate thread
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBEventProcessorLoop(void *unused1)
{
    IxEthDBPortMap triggerPorts;
    IxEthDBPortId portIndex;

    ixEthDBEventProcessorRunning = TRUE;

    IX_ETH_DB_EVENTS_TRACE("DB: (Events) Event processor loop was started\n");

    while (!ixEthDBLearningShutdown)
    {
        BOOL keepProcessing    = TRUE;
        UINT32 processedEvents = 0;

        if (ixEthDBEventProcessorPausing == TRUE)
	{
          /* 100 ms*/
          ixOsalSleep(100);
          continue;
        } 

        IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Waiting for new learning event...\n");

        ixOsalSemaphoreWait(&eventQueueSemaphore, IX_OSAL_WAIT_FOREVER);

        IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Received new event\n");

        if (!ixEthDBLearningShutdown)
        {
            /* port update handling */
            SET_EMPTY_DEPENDENCY_MAP(triggerPorts);

            while (keepProcessing)
            {
                PortEvent local_event;
                UINT32 intLockKey;

                /* lock queue */
                ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);

                /* lock NPE interrupts */
                intLockKey = ixOsalIrqLock();

                /* extract event */
                local_event = *(QUEUE_TAIL(&eventQueue));

                SHIFT_UPDATE_QUEUE(&eventQueue);

                ixOsalIrqUnlock(intLockKey);

                ixOsalMutexUnlock(&eventQueueLock);

                IX_ETH_DB_EVENTS_TRACE("DB: (Events) Processing event with ID 0x%X\n", local_event.eventType);

                ixEthDBProcessEvent(&local_event, triggerPorts);

                processedEvents++;

                if (processedEvents > EVENT_PROCESSING_LIMIT /* maximum burst reached? */
                    || ixOsalSemaphoreTryWait(&eventQueueSemaphore) != IX_SUCCESS) /* or empty queue? */
                {
                    keepProcessing = FALSE;
                }
            }

            /* Added a pause check here to prevent NPE message
             * from being sent from ixEthDBUpdatePortLearningTrees() 
             */ 
	    while (ixEthDBEventProcessorPausing == TRUE)
	      {
		/* 100 ms*/
		ixOsalSleep(100);		
	      } 
	    
            ixEthDBUpdatePortLearningTrees(triggerPorts);
        }
    }

    /* turn off automatic updates */
    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
    {
        ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE;
    }

    ixEthDBEventProcessorRunning = FALSE;
}
Beispiel #10
0
/* 
 * Attempt to get mutex, return immediately,
 * no error info because users expect some failures
 * when using this API.
 */
PUBLIC IX_STATUS
ixOsalMutexTryLock (IxOsalMutex * mutex)
{
    return ixOsalMutexLock(mutex, IX_OSAL_WAIT_NONE);
}
Beispiel #11
0
IX_STATUS
ixQMgrQConfig (char *qName,
	      IxQMgrQId qId,
	      IxQMgrQSizeInWords qSizeInWords,
	      IxQMgrQEntrySizeInWords qEntrySizeInWords)
{
    UINT32 aqmLocalBaseAddress;

    if (!cfgInitialized)
    {
        return IX_FAIL;
    }
    
    if (!IX_QMGR_QID_IS_VALID(qId))
    {
	return IX_QMGR_INVALID_Q_ID;
    }
    
    else if (NULL == qName)
    {
	return IX_QMGR_PARAMETER_ERROR;
    }
    
    else if (strlen (qName) > IX_QMGR_MAX_QNAME_LEN)
    {
	return IX_QMGR_PARAMETER_ERROR;
    }

    else if (!qSizeInWordsIsOk (qSizeInWords))
    {
	return IX_QMGR_INVALID_QSIZE;
    }

    else if (!qEntrySizeInWordsIsOk (qEntrySizeInWords))
    {
	return IX_QMGR_INVALID_Q_ENTRY_SIZE;
    }
    
    else if (cfgQueueInfo[qId].isConfigured)
    {
	return IX_QMGR_Q_ALREADY_CONFIGURED;
    }
   
    ixOsalMutexLock(&ixQMgrQCfgMutex, IX_OSAL_WAIT_FOREVER);

    /* Write the config register */
    ixQMgrAqmIfQueCfgWrite (qId,
			   qSizeInWords,
			   qEntrySizeInWords,
			   freeSramAddress);


    strcpy (cfgQueueInfo[qId].qName, qName);
    cfgQueueInfo[qId].qSizeInWords = qSizeInWords;
    cfgQueueInfo[qId].qEntrySizeInWords = qEntrySizeInWords;

    /* store pre-computed information in the same cache line
     * to facilitate inlining of QRead and QWrite functions 
     * in IxQMgr.h
     */
    ixQMgrQInlinedReadWriteInfo[qId].qReadCount = 0;
    ixQMgrQInlinedReadWriteInfo[qId].qWriteCount = 0;
    ixQMgrQInlinedReadWriteInfo[qId].qEntrySizeInWords = qEntrySizeInWords;
    ixQMgrQInlinedReadWriteInfo[qId].qSizeInEntries = 
		(UINT32)qSizeInWords / (UINT32)qEntrySizeInWords;

    /* Calculate the new freeSramAddress from the size of the queue
     * currently being configured.
     */
    freeSramAddress += (qSizeInWords * IX_QMGR_NUM_BYTES_PER_WORD);

    /* Get the virtual SRAM address */
    ixQMgrAqmIfBaseAddressGet (&aqmLocalBaseAddress);

    IX_OSAL_ASSERT((freeSramAddress - (aqmLocalBaseAddress + (IX_QMGR_QUEBUFFER_SPACE_OFFSET))) <=
	      IX_QMGR_QUE_BUFFER_SPACE_SIZE);

    /* The queue is now configured */
    cfgQueueInfo[qId].isConfigured = TRUE;

    ixOsalMutexUnlock(&ixQMgrQCfgMutex);

#ifndef NDEBUG
    /* Update statistics */
    stats.qStats[qId].isConfigured = TRUE;
    stats.qStats[qId].qName = cfgQueueInfo[qId].qName;
#endif
    return IX_SUCCESS;
}
/**
 * @brief scans the capabilities of the loaded NPE images
 *
 * This function MUST be called by the ixEthDBInit() function.
 * No EthDB features (including learning and filtering) are enabled
 * before this function is called.
 *
 * @return none
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBFeatureCapabilityScan(void)
{
    IxNpeDlImageId imageId, npeAImageId;
    IxEthDBPortId portIndex;
    PortInfo *portInfo;
    IxEthDBPriorityTable defaultPriorityTable;
    IX_STATUS result;
    UINT32 queueIndex;
    UINT32 queueStructureIndex;
    UINT32 trafficClassDefinitionIndex;

    /* read version of NPE A - required to set the AQM queues for B and C */
    npeAImageId.functionalityId = 0;
    ixNpeDlLoadedImageGet(IX_NPEDL_NPEID_NPEA, &npeAImageId);

    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
    {
        IxNpeMhMessage msg;

        portInfo = &ixEthDBPortInfo[portIndex];

        /* check and bypass if NPE B or C is fused out */
        if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue;

        /* all ports are capable of LEARNING by default */
        portInfo->featureCapability |= IX_ETH_DB_LEARNING;
        portInfo->featureStatus     |= IX_ETH_DB_LEARNING;

        if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
        {

            if (ixNpeDlLoadedImageGet(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), &imageId) != IX_SUCCESS)
            {
                WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex);
            }
            else
            {
                /* initialize and empty NPE response mutex */
                ixOsalMutexInit(&portInfo->npeAckLock);
                ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER);

                /* check NPE response to GetStatus */
                msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24;
                msg.data[1] = 0;
                IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), msg, result);
                if (result != IX_SUCCESS)
                {
                    WARNING_LOG("DB: (FeatureScan) warning, could not send message to the NPE\n");
                    continue;
                }


                if (imageId.functionalityId == 0x00
                    || imageId.functionalityId == 0x03
                    || imageId.functionalityId == 0x04
                    || imageId.functionalityId == 0x80)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                }
                else if (imageId.functionalityId == 0x01
                         || imageId.functionalityId == 0x81)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (imageId.functionalityId == 0x02
                         || imageId.functionalityId == 0x82)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }

                /* reset AQM queues */
                memset(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments));

                /* ensure there's at least one traffic class record in the definition table, otherwise we have no default case, hence no queues */
                IX_ENSURE(sizeof (ixEthDBTrafficClassDefinitions) != 0, "DB: no traffic class definitions found, check IxEthDBQoS.h");

                /* find the traffic class definition index compatible with the current NPE A functionality ID */
                for (trafficClassDefinitionIndex = 0 ;
                    trafficClassDefinitionIndex < sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]);
                    trafficClassDefinitionIndex++)
                {
                    if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAImageId.functionalityId)
                    {
                        /* found it */
                        break;
                    }
                }

                /* select the default case if we went over the array boundary */
                if (trafficClassDefinitionIndex == sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]))
                {
                    trafficClassDefinitionIndex = 0; /* the first record is the default case */
                }

                /* select queue assignment structure based on the traffic class configuration index */
                queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX];

                /* only traffic class 0 is active at initialization time */
                portInfo->ixEthDBTrafficClassCount = 1;

                /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */
                portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus |= IX_ETH_DB_FIREWALL;
                portInfo->enabled        = TRUE;

#define CONFIG_WITH_VLAN  /* test-only: VLAN support not included to save space!!! */
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
                /* set VLAN initial configuration (permissive) */
                if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */
                {
                    /* QoS capable */
                    portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX];

                    /* set AQM queues */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex];
                    }

                    /* set default PVID (0) and default traffic class 0 */
                    ixEthDBPortVlanTagSet(portIndex, 0);

                    /* enable reception of all frames */
                    ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES);

                    /* clear full VLAN membership */
                    ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);

                    /* clear TTI table - no VLAN tagged frames will be transmitted */
                    ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE);

                    /* set membership on 0, otherwise no Tx or Rx is working */
                    ixEthDBPortVlanMembershipAdd(portIndex, 0);
                }
                else /* QoS not available in this image */
#endif /* test-only */
                {
                    /* initialize traffic class availability (only class 0 is available) */
                    portInfo->ixEthDBTrafficClassAvailable = 1;

                    /* point all AQM queues to traffic class 0 */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] =
                            ixEthDBQueueAssignments[queueStructureIndex][0];
                    }
                }

#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
                /* download priority mapping table and Rx queue configuration */
                memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
                ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable);
#endif

                /* by default we turn off invalid source MAC address filtering */
                ixEthDBFirewallInvalidAddressFilterEnable(portIndex, FALSE);

                /* disable port, VLAN, Firewall feature bits */
                portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL;
                portInfo->enabled        = FALSE;

                /* enable filtering by default if present */
                if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)
                {
                    portInfo->featureStatus |= IX_ETH_DB_FILTERING;
                }
            }
        }
    }
}
Beispiel #13
0
/**
 * @brief scans the capabilities of the loaded NPE images
 *
 * This function MUST be called by the ixEthDBInit() function.
 * No EthDB features (including learning and filtering) are enabled
 * before this function is called.
 *
 * @return none
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBFeatureCapabilityScan(void)
{
    UINT8 functionalityId, npeAFunctionalityId;
    IxEthDBPortId portIndex;
    PortInfo *portInfo;
    IxEthDBPriorityTable defaultPriorityTable;
    IX_STATUS result;
    UINT32 queueIndex;
    UINT32 queueStructureIndex;
    UINT32 trafficClassDefinitionIndex, totalTrafficClass;

    totalTrafficClass = sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]);

    /* ensure there's at least 2 traffic class records in the definition table, otherwise we have no default cases, hence no queues */
    IX_ENSURE(totalTrafficClass >= 2, 
	"DB: no traffic class definitions found, check IxEthDBQoS.h");

    /* read version of NPE A - required to set the AQM queues for B and C */
    npeAFunctionalityId = 0;

    if(IX_FAIL == ixNpeDlLoadedImageFunctionalityGet(IX_NPEDL_NPEID_NPEA, &npeAFunctionalityId))
    {
        /* IX_FAIL is returned when there is no image loaded in NPEA.  Then we can use all 8 queues */
        trafficClassDefinitionIndex = 1; /* the second record is the default if no image loaded */
    } 
    else 
    {
        /* find the traffic class definition index compatible with the current NPE A functionality ID */
        for (trafficClassDefinitionIndex = 0 ; 
             trafficClassDefinitionIndex < totalTrafficClass ;
             trafficClassDefinitionIndex++)
        {
            if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAFunctionalityId)
            {
                /* found it */
                break;
            }
        }

        /* select the default case if we went over the array boundary */
        if (trafficClassDefinitionIndex == totalTrafficClass)
        {
            trafficClassDefinitionIndex = 0; /* the first record is the default case */
        }
    }

    /* To decide port definition for NPE A - IX_ETH_NPE or IX_ETH_GENERIC 
       IX_ETH_NPE will be set for NPE A when the functionality id is ranged from 0x80 to 0x8F
       and ethernet + hss co-exists images range from 0x90 to 0x9F. For the rest of functionality 
       Ids, the port type will be set to IX_ETH_GENERIC. */
    if ((npeAFunctionalityId & 0xF0) != 0x80 && (npeAFunctionalityId & 0xF0) != 0x90)
    {
        /* NPEA is not Ethernet capable. Override default port definition */
	ixEthDBPortDefinitions[IX_NPEA_PORT].type = IX_ETH_GENERIC;
    }

    /* select queue assignment structure based on the traffic class configuration index */
    queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX];

    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
    {
        IxNpeMhMessage msg;

        portInfo = &ixEthDBPortInfo[portIndex];

        /* check and bypass if NPE A, B or C is fused out */
        if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue;
        
        /* all ports are capable of LEARNING by default */
        portInfo->featureCapability = IX_ETH_DB_LEARNING;
        portInfo->featureStatus     = IX_ETH_DB_LEARNING;

        if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
        {

            if (IX_SUCCESS != ixNpeDlLoadedImageFunctionalityGet(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), &functionalityId))
            {
                WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex);
            }
            else
            {
                /* initialize and empty NPE response mutex */
                ixOsalMutexInit(&portInfo->npeAckLock);
		ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER);
                /* check NPE response to GetStatus */
                msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24;
                msg.data[1] = 0;
                IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), msg, result);
                if (result != IX_SUCCESS)
                {
                    WARNING_LOG("DB: (FeatureScan) warning, %d port could not send message to the NPE\n", portIndex);
                    continue;
                }

                if (functionalityId == 0x00
                    || functionalityId == 0x03
                    || functionalityId == 0x04
                    || functionalityId == 0x80)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                }
                else if (functionalityId == 0x01
                         || functionalityId == 0x81
                         || functionalityId == 0x0B
                         || functionalityId == 0x8B
                         || functionalityId == 0x90)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x02
                         || functionalityId == 0x82
                         || functionalityId == 0x0D
                         || functionalityId == 0x8D
                         || functionalityId == 0x91)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x0C
			 || functionalityId == 0x8C)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }

                /* check if image supports mask based firewall */
                if (functionalityId == 0x0B
                    || functionalityId == 0x8B
                    || functionalityId == 0x0D
                    || functionalityId == 0x8D
                    || functionalityId == 0x90
                    || functionalityId == 0x91)
                {
                    /* this feature is always on and is based on the NPE */
                    portInfo->featureStatus |= IX_ETH_DB_ADDRESS_MASKING;
                    portInfo->featureCapability |= IX_ETH_DB_ADDRESS_MASKING;
                }

                /* reset AQM queues */
                ixOsalMemSet(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments));

                /* only traffic class 0 is active at initialization time */
                portInfo->ixEthDBTrafficClassCount = 1;

                /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */
                portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus |= IX_ETH_DB_FIREWALL;
                portInfo->enabled        = TRUE;

                /* set VLAN initial configuration (permissive) */
                if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */
                {
                    /* QoS capable */
                    portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX];

                    /* set AQM queues */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex];
                    }

                    /* set default PVID (0) and default traffic class 0 */
                    ixEthDBPortVlanTagSet(portIndex, 0);

                    /* enable reception of all frames */
                    ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES);

                    /* clear full VLAN membership */
                    ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);

                    /* clear TTI table - no VLAN tagged frames will be transmitted */
                    ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE);

                    /* set membership on 0, otherwise no Tx or Rx is working */
                    ixEthDBPortVlanMembershipAdd(portIndex, 0);
                }
                else /* QoS not available in this image */
                {
                    /* initialize traffic class availability (only class 0 is available) */
                    portInfo->ixEthDBTrafficClassAvailable = 1;

                    /* point all AQM queues to traffic class 0 */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = 
                            ixEthDBQueueAssignments[queueStructureIndex][0];
                    }
                }

                /* download priority mapping table and Rx queue configuration */
                ixOsalMemSet (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
                ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable);

                /* by default we turn on invalid source MAC address filtering */
                ixEthDBFirewallInvalidAddressFilterEnable(portIndex, TRUE);

                /* Notify VLAN tagging is disabled */
		if (ixEthDBIngressVlanTaggingEnabledSet(portIndex, IX_ETH_DB_DISABLE_VLAN)
		    != IX_SUCCESS)
		{
		  WARNING_LOG("DB: (FeatureScan) warning, %d port could not disable VLAN \n", portIndex);
		  continue;		  
		}

                /* disable port, VLAN, Firewall feature bits */
                portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL;
                portInfo->enabled        = FALSE;

                /* enable filtering by default if present */
                if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)
                {
                    portInfo->featureStatus |= IX_ETH_DB_FILTERING;
                }
            }
        } 
    }
}
Beispiel #14
0
/*********************************************************************
 * ixEthAccMiiReadRtn - read a 16 bit value from a PHY
 */
IxEthAccStatus      
ixEthAccMiiReadRtn (UINT8 phyAddr, 
		    UINT8 phyReg, 
		    UINT16 *value)
{
    UINT32 mdioCommand;
    UINT32 regval;
    UINT32 miiTimeout;

    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
    {
	return (IX_ETH_ACC_FAIL);
    }

    if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) 
	|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
    {
	return (IX_ETH_ACC_FAIL);
    }

    if (value == NULL)
    {
	return (IX_ETH_ACC_FAIL);
    }

    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
    mdioCommand = phyReg <<  IX_ETH_ACC_MII_REG_SHL 
	| phyAddr << IX_ETH_ACC_MII_ADDR_SHL;
    mdioCommand |= IX_ETH_ACC_MII_GO;

    ixEthAccMdioCmdWrite(mdioCommand);
    
    miiTimeout = ixEthAccMiiRetryCount;

    while(miiTimeout)
    {
	
	ixEthAccMdioCmdRead(&regval);
     
	if((regval & IX_ETH_ACC_MII_GO) == 0x0)
	{	    
	    break;
	}
	/* Sleep for a while */
	ixOsalSleep(ixEthAccMiiAccessTimeout);
	miiTimeout--;
    }
    

    
    if(miiTimeout == 0)
    {	
	ixOsalMutexUnlock(&miiAccessLock);
	*value = 0xffff;
	return IX_ETH_ACC_FAIL;
    }
    
    
    ixEthAccMdioStatusRead(&regval);
    if(regval & IX_ETH_ACC_MII_READ_FAIL)
    {
	ixOsalMutexUnlock(&miiAccessLock);
	*value = 0xffff;
	return IX_ETH_ACC_FAIL;
    }

    *value = regval & 0xffff;
    ixOsalMutexUnlock(&miiAccessLock);
    return IX_ETH_ACC_SUCCESS;
    
}
Beispiel #15
0
IX_STATUS ixEthAccCodeletUninit(void)
{  
    IxEthAccPortId portId;
    IxEthAccStatus status;

    if(!ixEthAccCodeletInitialised) 
    {
	/* already uninitialized */
	return(IX_SUCCESS);
    }

    if (!ixEthAccCodeletStatsPollTaskStop)
    {
	ixEthAccCodeletStatsPollTaskStop = TRUE;
	if (ixOsalMutexLock (&ixEthAccCodeletStatsPollTaskRunning, 
			     IX_OSAL_WAIT_FOREVER)
	    != IX_SUCCESS)
	{
	    printf("CodeletMain: Error stopping Statistics Polling thread!\n");
	    return (IX_FAIL);
	}
	ixOsalMutexUnlock (&ixEthAccCodeletStatsPollTaskRunning);
    }

    for (portId = IX_ETH_PORT_1; portId < IX_ETHACC_CODELET_MAX_PORT; portId++)
    {
	status = ixEthAccPortDisable (portId);
	if (IX_ETH_ACC_SUCCESS != status)
	{
	    printf("CodeletMain: Failed to disable port %d, error code %d\n", portId, status); 
	    return (IX_FAIL);
	} 
    }

    if (ixEthAccCodeletDBMaintenanceStop() != IX_SUCCESS)
    {
	printf("CodeletMain: Error stopping DB Maintenance task!\n");
	return (IX_FAIL);
    }

    if (ixEthAccUninit() != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to uninitialize Ethernet Access Layer!\n");
	return (IX_FAIL);
    }

#ifdef __ixp46X
    if (ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEA) != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to stop and reset NPE A!\n");
	return (IX_FAIL);
    }
#endif

    if (ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEB) != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to stop and reset NPE B!\n");
	return (IX_FAIL);
    }

    if (ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEC) != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to stop and reset NPE C!\n");
	return (IX_FAIL);
    }

    if (ixNpeDlUnload() != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to unload NPE Downloader!\n");
	return (IX_FAIL);
    }

    if (ixNpeMhUnload() != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to unload NPE Message Handler!\n");
	return (IX_FAIL);
    }

    if (ixEthAccCodeletDispatcherStop(IX_ETH_CODELET_QMGR_DISPATCH_MODE)
	!= IX_SUCCESS)
    {
	printf("CodeletMain: Error stopping QMgr Dispatcher loop!\n");
	return (IX_FAIL);
    }

    if (ixQMgrUnload() != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to unload QMgr!\n");
	return (IX_FAIL);
    }

    if (ixEthAccCodeletMemPoolFree() != IX_SUCCESS)
    {
	printf("CodeletMain: Failed to free memory pool!\n");
	return (IX_FAIL);
    }

    ixEthAccCodeletInitialised = FALSE;

    return (IX_SUCCESS);
}
Beispiel #16
0
/**
 * @fn void ixEthAccCodeletStatsPollTask
 *
 * This task polls the Codelet Stats and displays the rate of Rx and 
 * Tx packets per second.
 * 
 */
PRIVATE void ixEthAccCodeletStatsPollTask(void* arg, void** ptrRetObj)
{
    int portNo = 0;
    static char stillRunning[] = "|/-\\";
    static int  stillRunningIndex = 0;
    static char displayString[20 + (21 * IX_ETHACC_CODELET_MAX_PORT)];
    static char *stringPtr;
    static UINT32 busTimestampEnd = 0;
    static UINT32 busTimestampStart = 0;
    static UINT32 pTimeCycles = 0;
    static UINT64 rxCount = 0;
    static UINT64 txCount = 0;
    static UINT64 pTimeUsecs = 0;

    ixEthAccCodeletStatsPollTaskStop = FALSE;

    if (ixOsalMutexLock (&ixEthAccCodeletStatsPollTaskRunning,
			 IX_OSAL_WAIT_FOREVER) != IX_SUCCESS)
    {
        printf("CodeletMain: Error starting Stats thread! Failed to lock mutex.\n");
        return;
    }

    while (1)
    {
	while (ixEthAccCodeletTrafficPollEnabled == FALSE)
	{
	    /* Sleep 1 sec */
	    ixOsalSleep(1000);
	    if (ixEthAccCodeletStatsPollTaskStop)
	    {
		break;  /* Exit the thread */
	    }
	}

	if (ixEthAccCodeletStatsPollTaskStop)
	{
	    break;  /* Exit the thread */
	}
	printf("\n");
#ifdef __wince
	printf("\r");
#endif
	for(portNo=0; portNo<IX_ETHACC_CODELET_MAX_PORT; portNo++)
	{
	    printf("Port%d Rates:        |",portNo);
	}
	printf("\n");
#ifdef __wince
	printf("\r");
#endif
	for(portNo=0; portNo<IX_ETHACC_CODELET_MAX_PORT; portNo++)
	{
	    printf("=====================");
	}
	printf("=\n");
#ifdef __wince
	printf("\r");
#endif

	/* reset the stats */
	for(portNo=0; portNo<IX_ETHACC_CODELET_MAX_PORT; portNo++)
	{
	    ixEthAccCodeletStats[portNo].rxCount=0;
	    ixEthAccCodeletStats[portNo].txCount=0;
	}

	while (ixEthAccCodeletTrafficPollEnabled)
	{
	    busTimestampStart = ixOsalTimestampGet();
	    /* Sleep approximatively 1 sec */
	    ixOsalSleep(1000);
       
	    /* check if the task should stop */ 
	    if (ixEthAccCodeletStatsPollTaskStop)
	    {
	        break;  /* Exit the thread */
	    }

	    if  (ixEthAccCodeletTrafficPollEnabled)
	    {
		/* \r : reset print curser to beginning of line */
		stringPtr = displayString;
		*stringPtr++ = '\r';

		for(portNo=0; portNo<IX_ETHACC_CODELET_MAX_PORT; portNo++)
		{
		    /* get a snapshot */
		    busTimestampEnd = ixOsalTimestampGet();
		    rxCount = ixEthAccCodeletStats[portNo].rxCount;
		    txCount = ixEthAccCodeletStats[portNo].txCount;
		    /* Got stats, now clear counters */
		    ixEthAccCodeletStats[portNo].rxCount=0;
		    ixEthAccCodeletStats[portNo].txCount=0;

		    /* get the measurement interval using a unsigned
		     * subtraction in order to handle wrap-around. The time unit 
		     * is in APB bus cycles.
		     */
		    pTimeCycles = busTimestampEnd - busTimestampStart;
		    /* convert the time in APB bus cycles to microseconds
		     *
		     * multiplications are done before divisions and
		     * will not overflow the UINT64.
		     */
		    pTimeUsecs = (UINT64)pTimeCycles;

		
		    pTimeUsecs = IX_ETHACC_CODELET_MULDIV(pTimeUsecs,
			     IX_ETHACC_CODELET_PCLOCK_DIVIDER, 
			     IX_ETHACC_CODELET_XCLOCK_FREQ);
		    if (!pTimeUsecs) 
		    {
			/* time may be 0 as the result of the previous operation
			 * In this case (very unlikely to occur), 
			 * just skip the remaining of this loop.
			 * The display will not be updated before the next
			 * loop.
			 */
			continue;
		    }

		    /* convert from the packet count to a rate in pkts per second 
		     *
		     * rate = pkts * usecsPerSec / timeUsec
		     *
		     * multiplications are done before divisions and
		     * will not overflow the UINT64.
		     */
		    rxCount = IX_ETHACC_CODELET_MULDIV(rxCount, 
			        IX_ETHACC_CODELET_USEC_PER_SEC, pTimeUsecs);
		    txCount = IX_ETHACC_CODELET_MULDIV(txCount, 
			        IX_ETHACC_CODELET_USEC_PER_SEC, pTimeUsecs);

		    /* print stats */
		    stringPtr += sprintf(stringPtr, "Rx:%6u Tx:%6u |", 
					 (unsigned)rxCount, 
					 (unsigned)txCount);
		}
		*stringPtr++ = stillRunning[stillRunningIndex++ & 3];
		*stringPtr = 0;
		printf("%s", displayString);
	    }
	}
	printf("\n");
#ifdef __wince
	printf("\r");
#endif
    }

    ixOsalMutexUnlock (&ixEthAccCodeletStatsPollTaskRunning);
}