PRIVATE IX_STATUS ixAtmmTxDoneInit (void) { IxOsalThreadAttr ixAtmmTxDoneThreadAttr; IX_STATUS retval = IX_SUCCESS; IX_STATUS retStatus; unsigned qSize; char *threadName = "Atmm Tx Done Thread"; /* Initialization done in first call to Init, * subsequent calls do nothing */ if (!ixAtmmTxDoneInitDone) { /* * Get depth of TxDone Q */ retval = ixAtmdAccTxDoneQueueSizeQuery (&qSize); if (retval == IX_SUCCESS) { /* * Hook Tx Done notification to done handler, * threshold is set to half of q size */ retval = ixAtmdAccTxDoneDispatcherRegister ( qSize/2, ixAtmmTxDoneHandle); } if (retval == IX_SUCCESS) { /* * Setup timer to handle disconnect scenario * during idle traffic */ ixAtmmTxDoneThreadAttr.name = threadName; ixAtmmTxDoneThreadAttr.stackSize = 0; ixAtmmTxDoneThreadAttr.priority = IX_ATMM_THREAD_PRI_HIGH; if ((retStatus = ixOsalThreadCreate( &ixAtmmTaskIds.txDoneId, &ixAtmmTxDoneThreadAttr, (IxOsalVoidFnVoidPtr) ixAtmmTxDoneLoop, NULL)) == IX_SUCCESS ) { /* start the thread */ ixAtmmTxDoneInitDone = TRUE; retStatus |= ixOsalThreadStart(&ixAtmmTaskIds.txDoneId); } if (IX_SUCCESS != retStatus) { ixAtmmTxDoneInitDone = FALSE; retval = IX_FAIL; } } } return retval; }
static int __init ethAccCodelet_init_module(void) { printk ("Load Codelet: EthAcc.\n"); if ((operationType < IX_ETHACC_CODELET_RX_SINK) || (operationType > IX_ETHACC_CODELET_BRIDGE_WIFI)) { printk("\nUsage :"); printk("\n # insmod codelets_ethAcc.o operationType=<x> inPort=<y> outPort=<z>"); printk("\n"); printk("\n Where x : %d = Rx Sink", IX_ETHACC_CODELET_RX_SINK); printk("\n %d = Sw Loopback", IX_ETHACC_CODELET_SW_LOOPBACK); printk("\n %d = Tx Gen/Rx Sink Loopback", IX_ETHACC_CODELET_TXGEN_RXSINK); printk("\n %d = PHY Loopback", IX_ETHACC_CODELET_PHY_LOOPBACK); printk("\n %d = Bridge", IX_ETHACC_CODELET_BRIDGE); printk("\n %d = Bridge + QoS", IX_ETHACC_CODELET_BRIDGE_QOS); printk("\n %d = Bridge + Firewall", IX_ETHACC_CODELET_BRIDGE_FIREWALL); printk("\n %d = Eth DB Learning", IX_ETHACC_CODELET_ETH_LEARNING); printk("\n %d = Bridge + WiFi header conversion", IX_ETHACC_CODELET_BRIDGE_WIFI); printk("\n"); return -EINVAL; } ixOsalThreadCreate(&tid, NULL, operation_func, NULL); ixOsalThreadStart(&tid); return 0; }
PRIVATE IX_STATUS timerInit (void) { IxOsalThread taskId; IX_STATUS ixStatus; IxOsalThreadAttr timerThreadAttr; ixStatus = ixOsalSemaphoreInit (&ixOsalCriticalSectSem, IX_OSAL_TIMER_SEM_AVAILABLE); if (ixStatus != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Error creating critical section semaphore\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixStatus = ixOsalSemaphoreInit (&ixOsalTimerRecalcSem, IX_OSAL_TIMER_SEM_AVAILABLE); if (ixStatus != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Error creating timer recalc semaphore\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } timerThreadAttr.stackSize = 10 * 1024; timerThreadAttr.priority = 90; timerThreadAttr.name = ixOsalTimerThreadName; ixStatus = ixOsalThreadCreate (&taskId, &timerThreadAttr, (IxOsalVoidFnVoidPtr) timerLoop, NULL); if (ixStatus != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "timerInit: fail to create timer thread. \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixStatus = ixOsalThreadStart (&taskId); if (ixStatus != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Error creating timerLoop task\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } return IX_SUCCESS; }
/* * Function definition : ixDmaAccCodeletDispatcherStart() * See header file for documentation. */ PRIVATE IX_STATUS ixDmaAccCodeletDispatcherStart(BOOL useInterrupt) { IxOsalThreadAttr threadAttr; char *pThreadName = "Dispatcher"; ixQMgrDispatcherLoopGet(&ixDmaAccCodeletDispatcherFunc); if(useInterrupt) /* Interrupt mode */ { /* * Hook the QM QLOW dispatcher to the interrupt controller. * IX_QMGR_QUELOW_GROUP refers to Queues 0-31 * Dma NPE A: queues 19 & 20; NPE B: 24 & 26; NPE B: 25 & 27 */ if (ixOsalIrqBind(IX_OSAL_IXP400_QM1_IRQ_LVL, (IxOsalVoidFnVoidPtr)ixDmaAccCodeletDispatcherFunc, (void *)IX_QMGR_QUELOW_GROUP) != IX_SUCCESS) { printf("\nFailed to bind to QM1 interrupt"); return (IX_FAIL); } } else /* Polled mode */ { threadAttr.name = pThreadName; threadAttr.stackSize = IX_DMA_CODELET_QMGR_STACK_SIZE; threadAttr.priority = IX_DMA_CODELET_QMR_PRIORITY; if (ixOsalThreadCreate(&ixDmaAccCodeletDispatchId, &threadAttr, (IxOsalVoidFnVoidPtr)ixDmaAccCodeletDispatcherPoll, NULL ) != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "\nError spawning dispatch task", 0,0,0,0,0,0); return (IX_FAIL); } if (ixOsalThreadStart (&ixDmaAccCodeletDispatchId) != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "\nError starting spawing dispatch task", 0,0,0,0,0,0); return (IX_FAIL); } } return (IX_SUCCESS); }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, char *label) * * @brief Spawn a thread to execute given function * * @param * func IxOsalVoidFnPtr [in] - pointer to the function that will be * executed after the thread is spawned. * @param * label char* [in] - pointer to the Thread name's buffer * * @return IX_STATUS * @li IX_SUCCESS - create and start Thread successfully * @li IX_FAIL - fail */ PRIVATE IX_STATUS ixTimeSyncAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, char *label) { IxOsalThread threadId; IxOsalThreadAttr threadAttr; /* check the validity of function pointer */ if (NULL == func) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: NULL function pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* check the validity of Thread name's buffer pointer */ if (NULL == label) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: NULL Thread name's pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* zero out the thread attribute buffer */ ixOsalMemSet ((void *)&threadAttr, 0, sizeof (IxOsalThreadAttr)); /* setup thread attribute */ threadAttr.name = label; threadAttr.priority = IX_OSAL_DEFAULT_THREAD_PRIORITY; if (IX_SUCCESS != ixOsalThreadCreate (&threadId, &threadAttr, (IxOsalVoidFnVoidPtr)func, NULL)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: Failed to spawn %s thread\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } if (IX_SUCCESS != ixOsalThreadStart (&threadId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: Failed to start %s thread\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } return IX_SUCCESS; } /* end of ixTimeSyncAccCodeletNewThreadCreate function */
/* * Function definition: ixEthAccCodeletDBMaintenanceStart() * * Start the EDB Maintenance task */ IX_STATUS ixEthAccCodeletDBMaintenanceStart(void) { IxOsalThread maintenanceThread; IxOsalThreadAttr threadAttr; threadAttr.name = "Codelet EDB Maintenance"; threadAttr.stackSize = 32 * 1024; /* 32kbytes */ threadAttr.priority = IX_ETHACC_CODELET_DB_PRIORITY; if (!ixEthAccCodeletDBMaintenanceInitialized) { /* this should be initialized once */ ixOsalMutexInit (&ixEthAccCodeletDBMaintenanceTaskRunning); ixEthAccCodeletDBMaintenanceInitialized = TRUE; ixEthAccCodeletDBMaintenanceTaskStopTrigger = TRUE; } if (ixEthAccCodeletDBMaintenanceTaskStopTrigger) { /* Polled mode based on a task running a loop */ if (ixOsalThreadCreate(&maintenanceThread, &threadAttr, (IxOsalVoidFnVoidPtr) ixEthAccCodeletDBMaintenanceTask, NULL) != IX_SUCCESS) { ixOsalMutexDestroy(&ixEthAccCodeletDBMaintenanceTaskRunning); printf("DBLearning: Error spawning DB maintenance task\n"); return (IX_FAIL); } /* Start the thread */ if (ixOsalThreadStart(&maintenanceThread) != IX_SUCCESS) { ixOsalMutexDestroy(&ixEthAccCodeletDBMaintenanceTaskRunning); printf("DBLearning: Error failed to start the maintenance thread\n"); return IX_FAIL; } } return (IX_SUCCESS); }
PRIVATE IX_STATUS ixAtmmRxLoPriorityInit (void) { IxOsalThreadAttr ixAtmmRxLoPriorityThreadAttr; IX_STATUS retval = IX_SUCCESS; IX_STATUS retStatus; char *threadName = "Atmm Rx Low Priority Thread"; /* Initialization done in first call to Init, * subsequent calls do nothing */ if (!ixAtmmRxLoPriorityInitDone) { /* * Rx Low priority queue will be processed from * a timer. */ ixAtmmRxLoPriorityThreadAttr.name = threadName; ixAtmmRxLoPriorityThreadAttr.stackSize = 0; ixAtmmRxLoPriorityThreadAttr.priority = IX_ATMM_THREAD_PRI_HIGH; if ((retStatus = ixOsalThreadCreate( &ixAtmmTaskIds.rxLoPriorityId, &ixAtmmRxLoPriorityThreadAttr, (IxOsalVoidFnVoidPtr) ixAtmmRxLoPriorityLoop, NULL)) == IX_SUCCESS ) { /* start the thread */ ixAtmmRxLoPriorityInitDone = TRUE; retStatus |= ixOsalThreadStart(&ixAtmmTaskIds.rxLoPriorityId); } if (IX_SUCCESS != retStatus) { ixAtmmRxLoPriorityInitDone = FALSE; retval = IX_FAIL; } } return retval; }
/** * @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; }
void ixHssAccCodeletChannelisedServiceConfigure ( IxHssAccHssPort hssPortId) { IX_STATUS status; unsigned bytesPerTSTrigger; UINT8 *rxCircular; unsigned numRxBytesPerTS; UINT32 *txPtrList; unsigned numTxPtrLists; unsigned numTxBytesPerBlk; IxHssAccChanRxCallback rxCallback; unsigned channelIndex; unsigned i; ClientInfo *pClientInfo = &clientInfo[hssPortId]; ChannelInfo *pChannelInfo; IxOsalThreadAttr ixHssAccCodeletChanThreadAttr; /* initialise client infor structure for this client */ pClientInfo->hssPortId = hssPortId; pClientInfo->lastTxOffset = -1; pClientInfo->nextRxOffset = 0; /* 1st rxOffset we receive to */ pClientInfo->lastRxOffset = -1; /* initially invalid */ pClientInfo->readyToLoopback = FALSE; /* no samples Rx'ed yet */ for (channelIndex = 0; channelIndex < IX_HSSACC_CODELET_CHAN_NUM_CHANS; channelIndex++) { pChannelInfo = &pClientInfo->channelInfo[channelIndex]; /* not receiving non-idle data yet */ pChannelInfo->receivingNonIdleData = FALSE; /* initialise the tx/rx sample data values (to channel number) */ pChannelInfo->txSampleData = channelIndex + 1; pChannelInfo->rxSampleData = channelIndex + 1; } /****************/ /* START THREAD */ /****************/ /* initialise message queue to empty */ pClientInfo->qHead = 0; pClientInfo->qTail = 0; /* initialise the rx semaphore */ (void) ixOsalSemaphoreInit ( &pClientInfo->messageSem, IX_HSSACC_CODELET_SEM_UNAVAILABLE); /* create the thread for processing callbacks */ /* when running both packetised and channelised services, the */ /* channelised service needs to be serviced in a higher priority */ /* thread (high) than the packetised service (low) */ ixHssAccCodeletChanThreadAttr.name = "HSS Codelet Chan CB"; ixHssAccCodeletChanThreadAttr.stackSize = 10240; ixHssAccCodeletChanThreadAttr.priority = IX_HSSACC_CODELET_THREAD_PRI_HIGH; (void) ixOsalThreadCreate ( &pClientInfo->threadId, /* threadId */ &ixHssAccCodeletChanThreadAttr, /* threadAttr */ (IxOsalVoidFnVoidPtr)ixHssAccCodeletChanThreadMain, /* startRoutine */ pClientInfo); /* arg */ /* start the thread for processing callbacks */ (void) ixOsalThreadStart ( &pClientInfo->threadId); /* threadId */ /********************/ /* ALLOCATE BUFFERS */ /********************/ /* allocate channelised RX buffers */ if (pClientInfo->rxBuffers == 0) { pClientInfo->rxBuffers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->rxBuffers)); if (pClientInfo->rxBuffers == 0) { printf("Failed to allocated Rx buffers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->rxBuffers, 0x00, sizeof (*pClientInfo->rxBuffers)); /* allocate channelised TX buffers */ if (pClientInfo->txBuffers == 0) { pClientInfo->txBuffers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->txBuffers)); if (pClientInfo->txBuffers == 0) { printf("Failed to allocated Tx buffers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->txBuffers, 0x00, sizeof (*pClientInfo->txBuffers)); /* allocate channelised TX pointer lists */ if (pClientInfo->txPointers == 0) { pClientInfo->txPointers = IX_OSAL_CACHE_DMA_MALLOC( sizeof (*pClientInfo->txPointers)); if (pClientInfo->txPointers == 0) { printf("Failed to allocated Tx pointers\n"); return; } } /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH (pClientInfo->txPointers, 0x00, sizeof (*pClientInfo->txPointers)); /**********************/ /* CONNECT TO SERVICE */ /**********************/ /* Bytes per timeslot trigger = 8 */ bytesPerTSTrigger = IX_HSSACC_CODELET_CHAN_BYTES_PER_TS_TRIG; /* RX circular buffer = RX buffer */ rxCircular = (UINT8 *)(*pClientInfo->rxBuffers); /* Number of RX bytes per timeslot = 176 (RX buf size per channel) */ numRxBytesPerTS = IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN; /* TX pointer list = TX pointer array */ txPtrList = (UINT32 *)(*pClientInfo->txPointers); /* Number of TX pointer lists = 8 (latency factor) */ numTxPtrLists = IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR; /* Number of TX bytes per block = 44 (bytes per sample) */ numTxBytesPerBlk = IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE; /* Receive callback */ rxCallback = ixHssAccCodeletChanRxCallback; /* connect this client to the Channelised Service */ status = ixHssAccChanConnect ( hssPortId, /* hssPortId */ bytesPerTSTrigger, /* bytesPerTSTrigger */ rxCircular, /* rxCircular */ numRxBytesPerTS, /* numRxBytesPerTS */ txPtrList, /* txPtrList */ numTxPtrLists, /* numTxPtrLists */ numTxBytesPerBlk, /* numTxBytesPerBlk */ rxCallback); /* rxCallback */ /* if there was any problem then update stats */ if (status != IX_SUCCESS) { stats[hssPortId].chan.connectFails++; return; } /*******************/ /* PREPARE TX DATA */ /*******************/ /* prepare data for transmit */ for (i = 1; i <= IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR; i++) { /* by passing in txOffsets from 1 to the tx latency factor, we */ /* can reuse our transmit function to initially fill up the tx */ /* buffer with data */ ixHssAccCodeletChannelisedDataTransmit (hssPortId, i); } }
PUBLIC IX_STATUS ixOamCodeletInit (UINT32 numPorts) { IX_STATUS retval; UINT32 txRate[IX_UTOPIA_MAX_PORTS]; UINT32 rxRate; IxAtmmVc txVc; IxAtmmVc rxVc; IxAtmLogicalPort port; IxAtmSchedulerVcId rxVcId; IxAtmSchedulerVcId txVcId; IxAtmNpeRxVcId npeRxVcId; IxOsalThread tid; IxOsalThreadAttr threadAttr; char *pThreadName = "OAM Receive"; if (ixOamCodeletInitialized) { IX_OAM_CODELET_LOG_ERROR("Already initialized"); return IX_FAIL; } /* Check parameters */ if (numPorts < 1 || numPorts > IX_UTOPIA_MAX_PORTS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) invalid\n", numPorts); return IX_FAIL; } ixOamCodeletNumPorts = numPorts; /* Check how many ports have been configured, rxRate not used */ for (port =0; port< (IxAtmLogicalPort)numPorts; port++) { if (ixAtmmPortQuery (port, &txRate[port], &rxRate) != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) not configured, %u ports configured\n", numPorts, port); } } /* Initialize stats */ for (port = 0; port < IX_UTOPIA_MAX_PORTS; port++) { parentLbCellTxCount[port] = 0; childLbCellTxCount[port] = 0; parentLbCellRxCount[port] = 0; childLbCellRxCount[port] = 0; childLbCellRxErrCount[port] = 0; parentLbCellRxErrCount[port] = 0; unsupportedOamRxCount[port] = 0; txDoneCallbackCount[port] = 0; } replenishCallbackCount = 0; /* 1 for all ports */ /* Setup the OAM Tx Port Channels */ for (port=0; port< (IxAtmLogicalPort)numPorts; port++) { ixOsalMemSet(&txVc, 0, sizeof(txVc)); /* Setup Tx Vc descriptor */ txVc.vpi = IX_ATMDACC_OAM_TX_VPI; txVc.vci = IX_ATMDACC_OAM_TX_VCI; txVc.direction = IX_ATMM_VC_DIRECTION_TX; txVc.trafficDesc.atmService = IX_ATM_UBR; txVc.trafficDesc.pcr = txRate[port]; /* Setup tx VC, N.B. TxVcId not used in this codelet, * would typically be used for Vc Deregister */ retval = ixAtmmVcRegister (port, &txVc, &txVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Tx Port VC\n"); return IX_FAIL; } retval = ixAtmdAccTxVcConnect (port, IX_ATMDACC_OAM_TX_VPI, IX_ATMDACC_OAM_TX_VCI, IX_ATMDACC_OAM, port, /* set userId to port */ ixOamTxDoneCallback, &oamTxConnId[port]); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR ("Failed to connect Tx Port Channel\n"); return IX_FAIL; } /* setup the Rx sw queues */ ixOamQueueInit( port ); } /* * Setup OAM Rx Channel * N.B. OAM traffic for all ports is received on this VC */ /*Set thread attributes*/ threadAttr.name = pThreadName; threadAttr.stackSize = IX_ATMCODELET_QMGR_DISPATCHER_THREAD_STACK_SIZE; threadAttr.priority = IX_ATMCODELET_QMGR_DISPATCHER_PRIORITY; /* start a receive task */ if (ixOsalThreadCreate(&tid, &threadAttr, (IxOsalVoidFnVoidPtr)ixOamCellRxTask, NULL) != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR ("Error spawning SduSend task\n"); return IX_FAIL; } if(IX_SUCCESS != ixOsalThreadStart(&tid)) { printf("Error starting dispatch task\n"); return IX_FAIL; } ixOsalMemSet(&rxVc, 0, sizeof(rxVc)); /* Setup Rx Vc descriptor */ rxVc.vpi = IX_ATMDACC_OAM_RX_VPI; rxVc.vci = IX_ATMDACC_OAM_RX_VCI; rxVc.direction = IX_ATMM_VC_DIRECTION_RX; rxVc.trafficDesc.atmService = IX_ATM_UBR; rxVc.trafficDesc.pcr = 0; /* Ignored for Rx */ /* Setup rx VC, N.B. RxVcId not used in this codelet, * would typically be used for Vc Deregister */ retval = ixAtmmVcRegister (IX_ATMDACC_OAM_RX_PORT, &rxVc, &rxVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Rx Channel\n"); return IX_FAIL; } /* Connect Rx VC, N.B. npeRxVcId not used again */ retval = ixAtmdAccRxVcConnect (IX_ATMDACC_OAM_RX_PORT, IX_ATMDACC_OAM_RX_VPI, IX_ATMDACC_OAM_RX_VCI, IX_ATMDACC_OAM, IX_ATM_RX_B, /* low priority Q */ oamRxUserId, ixOamCellRxCallback, IX_ATMDACC_DEFAULT_REPLENISH_COUNT, &oamRxConnId, &npeRxVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to connect Rx Channel\n"); return IX_FAIL; } /* Replenish Rx then register replenish callback */ ixOamRxFreeLowReplenishCallback (oamRxUserId); retval = ixAtmdAccRxVcFreeLowCallbackRegister (oamRxConnId, IX_OAM_REPLENISH_WATERMARK, ixOamRxFreeLowReplenishCallback); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Rx replenish callback\n"); return IX_FAIL; } /* enable the oam vc */ retval = ixAtmdAccRxVcEnable (oamRxConnId); if (retval != IX_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR,IX_OSAL_LOG_DEV_STDERR, "Failed to enable Rx VC \n", 0, 0, 0, 0, 0, 0); return retval; } /* Set the number of ports configured */ ixOamCodeletNumPortsConfigured = numPorts; /* set initialised flag */ ixOamCodeletInitialized = TRUE; IX_OAM_CODELET_LOG ("Initialization Phase Complete\n"); return IX_SUCCESS; }
PUBLIC IxPerfProfAccStatus ixPerfProfAccXcycleStart (UINT32 numMeasurementsRequested) { #ifdef __linuxapp UINT32 result; /* result of thread creation */ int priority; /* used to remember priority of current process */ pthread_attr_t threadAttribute; /* used to setup thread attribute */ #elif defined (__vxworks) IxOsalThreadAttr threadAttr; IX_STATUS retStatus; #endif /* ifdef __linuxapp */ ixPerfProfAccXcycleStopMeasurement = FALSE; /* * Check if baseline had been run. If not, terminate. */ if (0 == ixPerfProfAccXcycleCurrentBaseline) { return IX_PERFPROF_ACC_STATUS_XCYCLE_NO_BASELINE; } /* * Range checking for numMeasurementsRequested */ if (IX_PERFPROF_ACC_XCYCLE_MAX_NUM_OF_MEASUREMENTS < numMeasurementsRequested) { return IX_PERFPROF_ACC_STATUS_XCYCLE_MEASUREMENT_REQUEST_OUT_OF_RANGE; } /* * Check if Xcycle is already running, do not allow another start * if Xcycle is running. */ if (ixPerfProfAccXcycleMeasurementInProgress) { return IX_PERFPROF_ACC_STATUS_XCYCLE_MEASUREMENT_IN_PROGRESS; } /* * Xcycle is not running, set the flag to indicate that * a measurement is in progress */ else { ixPerfProfAccXcycleMeasurementInProgress = TRUE ; } /* * Check to see if any other PMU utilities besides Xcycle is running * If yes, we abort to avoid inaccurate results due to load introduce * by other tools. */ if (IX_PERFPROF_ACC_STATUS_ANOTHER_UTIL_IN_PROGRESS == ixPerfProfAccLock()) { return IX_PERFPROF_ACC_STATUS_ANOTHER_UTIL_IN_PROGRESS; } #ifdef __linuxapp /* * Set current priority to lowest possible */ priority = getpriority(PRIO_PROCESS,0); if(0 != setpriority (PRIO_PROCESS, 0, IX_PERFPROF_ACC_XCYCLE_LINUXAPP_PRIORITY_LOWEST)) { ixPerfProfAccUnlock(); ixPerfProfAccXcycleMeasurementInProgress = FALSE ; return IX_PERFPROF_ACC_STATUS_XCYCLE_PRIORITY_SET_FAIL; } /* * Preparing to create a new thread of ixPerfProfAccXcycleNumPeriodRun() * Start with setting thread attribute with state DETACHED */ result = pthread_attr_init (&threadAttribute); result |= pthread_attr_setdetachstate (&threadAttribute, PTHREAD_CREATE_DETACHED); result |= pthread_create (&xcycleThreadId, &threadAttribute, (void *) &ixPerfProfAccXcycleNumPeriodRun , (void *)numMeasurementsRequested); if (0 != result) { ixPerfProfAccUnlock(); ixPerfProfAccXcycleMeasurementInProgress = FALSE ; return IX_PERFPROF_ACC_STATUS_XCYCLE_THREAD_CREATE_FAIL; }/* end of if (result) */ /* * Successful in creating a new thread with lowest priority. * Restore priority of calling thread to original level */ if (0 != setpriority (PRIO_PROCESS, 0, priority)) { ixPerfProfAccUnlock(); return IX_PERFPROF_ACC_STATUS_XCYCLE_PRIORITY_SET_FAIL; } #else /* ifdef __linuxapp */ /* * Create a new thread of ixPerfProfAccXcycleNumPeriodRun() * Set the priority level of new thread to lowest possible * If fail, set ixPerfProfAccXcycleMeasurementInProgress * back to FALSE and return error. */ threadAttr.name = "PerfProf Xcycle thread"; threadAttr.stackSize = 0; threadAttr.priority = IX_PERFPROF_ACC_XCYCLE_VXWORKS_PRIORITY_LOWEST; if ((retStatus = ixOsalThreadCreate( &xcycleThreadId, &threadAttr, (IxOsalVoidFnVoidPtr) ixPerfProfAccXcycleNumPeriodRun, (void*) numMeasurementsRequested)) == IX_SUCCESS) { if ((retStatus = ixOsalThreadStart(&xcycleThreadId)) != IX_SUCCESS) { ixPerfProfAccUnlock(); ixPerfProfAccXcycleMeasurementInProgress = FALSE; return IX_PERFPROF_ACC_STATUS_XCYCLE_THREAD_CREATE_FAIL; } } else { ixPerfProfAccUnlock(); ixPerfProfAccXcycleMeasurementInProgress = FALSE ; return IX_PERFPROF_ACC_STATUS_XCYCLE_THREAD_CREATE_FAIL; } /* end of if (result) */ #endif /* ifdef __linuxapp */ return IX_PERFPROF_ACC_STATUS_SUCCESS; } /* end of ixPerfProfAccXcycleStart() */
/* -------------------------------------------------------------- Initialise system components used by the Atm Codelet. -------------------------------------------------------------- */ PUBLIC IX_STATUS ixAtmCodeletSystemInit (UINT32 numPorts, IxAtmCodeletMode mode) { IX_STATUS retval = IX_SUCCESS; #if IX_UTOPIAMODE == 1 IxAtmmPhyMode phyMode = IX_ATMM_SPHY_MODE; #else IxAtmmPhyMode phyMode = IX_ATMM_MPHY_MODE; #endif IxOsalThread dispatchtid; IxOsalThreadAttr threadAttr; char *pThreadName = "QMgr Dispatcher"; #ifdef __vxworks if (endFindByName ("ixe", 0) != NULL) { IX_ATMCODELET_LOG ("FAIL : Driver ixe0 detected\n"); printf("FAIL : Driver ixe0 detected\n"); return IX_FAIL; } if (endFindByName ("ixe", 1) != NULL) { IX_ATMCODELET_LOG ("FAIL : Driver ixe1 detected\\n"); printf("FAIL : Driver ixe1 detected\n"); return IX_FAIL; } #endif /**************** System initialisation ****************/ /* * The IxQMgr component provides interfaces for configuring and accessing the IXP4XX * AQM hardware queues used to facilitate communication of data between the NPEs and * the xscale. IxAtmdAcc configures these queues. The IxQMgr component provides a * dispatcher that will call registered callback functions will specified queue events * occur. */ IX_ATMCODELET_COMP_INIT(ixQMgrInit()); ixQMgrDispatcherLoopGet(&dispatcherFunc); /* This next section sets up how the IxQMgrDispatcher is called. * For the purposes of demonstration under vxWorks the IxQMgrDispatcher * is polled, and under Linux intterrupts are used. * This offers the best performance respectively. */ if (IX_ATMCODELET_USE_QMGR_INT) { /* Running IxQMgrDispatcher from interrupt level */ /* * Bind the IxQMgr dispatcher to interrupt. The IX_QMGR_QUELOW_GROUP group * of queues concern ATM Transmit , Receive, Transmit Done queues */ retval = ixOsalIrqBind(IX_OSAL_IXP400_QM1_IRQ_LVL, (IxOsalVoidFnVoidPtr)(dispatcherFunc), (void *)IX_QMGR_QUELOW_GROUP); if (IX_SUCCESS != retval) { IX_ATMCODELET_LOG ("Failed to bind to QM1 interrupt\n"); return IX_FAIL; } /* * Bind the IxQMgr dispatcher to interrupt. The IX_QMGR_QUELOW_GROUP group * of queues concern ATM Receive Free queues. */ retval = ixOsalIrqBind(IX_OSAL_IXP400_QM2_IRQ_LVL, (IxOsalVoidFnVoidPtr)(dispatcherFunc), (void *)IX_QMGR_QUEUPP_GROUP); if (IX_SUCCESS != retval) { IX_ATMCODELET_LOG ("Failed to bind to QM2 interrupt\n"); return IX_FAIL; } } else /* Running IxQMgrDispatcher from task level */ { threadAttr.name = pThreadName; threadAttr.stackSize = IX_ATMCODELET_QMGR_DISPATCHER_THREAD_STACK_SIZE; threadAttr.priority = IX_ATMCODELET_QMGR_DISPATCHER_PRIORITY; if (ixOsalThreadCreate(&dispatchtid, &threadAttr, (IxOsalVoidFnVoidPtr)ixAtmCodeletDispatchTask, NULL) != IX_SUCCESS) { IX_ATMCODELET_LOG ("Error spawning dispatch task\n"); return IX_FAIL; } if(IX_SUCCESS != ixOsalThreadStart(&dispatchtid)) { IX_ATMCODELET_LOG ("Error starting dispatch task\n"); return IX_FAIL; } } /* Initialise IxNpeMh */ IX_ATMCODELET_COMP_INIT(ixNpeMhInitialize (IX_NPEMH_NPEINTERRUPTS_YES)); /* Download NPE image */ retval = ixAtmUtilsAtmImageDownload (numPorts, &phyMode); if (retval != IX_SUCCESS) { IX_ATMCODELET_LOG ("NPE download failed\n"); return IX_FAIL; } ixAtmCodeletMode = mode; return IX_SUCCESS; }
/* * Function definition: ixEthAccCodeletInit() * * See header file for documentation. */ IX_STATUS ixEthAccCodeletInit(IxEthAccCodeletOperation operationType, IxEthAccPortId inPort, IxEthAccPortId outPort) { IxEthAccPortId portId; IxOsalThread statsPollThread; IxOsalThreadAttr threadAttr; threadAttr.name = "Codelet Stats"; threadAttr.stackSize = 32 * 1024; /* 32kbytes */ threadAttr.priority = 128; #ifdef __ixp46X /* Set the expansion bus fuse register to enable MUX for NPEA MII */ { UINT32 expbusCtrlReg; expbusCtrlReg = ixFeatureCtrlRead (); expbusCtrlReg |= ((unsigned long)1<<8); ixFeatureCtrlWrite (expbusCtrlReg); } #endif /* check the component is already initialized */ if(ixEthAccCodeletInitialised) { printf("CodeletMain: Ethernet codelet already initialised\n"); return(IX_SUCCESS); } #ifdef __vxworks /* When the ixe drivers are running, the codelets * cannot run. */ for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (endFindByName ("ixe", portId) != NULL) { printf("CodeletMain: FAIL: Driver ixe%d detected\n",portId); return IX_FAIL; } } #endif /* Initialize NPE IMAGE ID here again to prevent confusion in multiple * ixEthAccCodeletMain() calls with different operationType. */ ETH_NPEA_IMAGEID = IX_NPEDL_NPEIMAGE_NPEA_ETH_MACFILTERLEARN_HSSCHAN_COEXIST; ETH_NPEB_IMAGEID = IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB; ETH_NPEC_IMAGEID = IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB; /* Create mutexes for thread control */ ixEthAccCodeletStatsPollTaskStop = TRUE; ixOsalMutexInit (&ixEthAccCodeletStatsPollTaskRunning); /* Initialise MBUF pool */ if(ixEthAccCodeletMemPoolInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising mBuf pool\n"); return (IX_FAIL); } /* Check Silicon stepping */ printf("Checking Silicon stepping...\n"); if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X) { if ((ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) == IX_FEATURE_CTRL_SILICON_TYPE_B0) { /* * If it is B0 Silicon, we only enable port when its corresponding * Eth Coprocessor is available. */ if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_ENABLED) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; } if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == IX_FEATURE_CTRL_COMPONENT_ENABLED) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; } } else if ((ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) == IX_FEATURE_CTRL_SILICON_TYPE_A0) { /* * If it is A0 Silicon, we enable both as both Eth Coprocessors * are available. */ ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; } else { printf("CodeletMain: Error. Operation for other silicon stepping is undefined!.\n"); return (IX_FAIL); } } else if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; #ifdef __ixp46X ixEthAccCodeletHardwareExists[IX_ETH_PORT_3] = TRUE; #endif } /*********************************************************************** * * System initialisation done. Now initialise Access components. * ***********************************************************************/ /* Initialise Queue Manager */ printf("Initialising Queue Manager...\n"); if (ixQMgrInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising queue manager!\n"); return (IX_FAIL); } /* Start the Queue Manager dispatcher */ if(ixEthAccCodeletDispatcherStart(IX_ETH_CODELET_QMGR_DISPATCH_MODE) != IX_SUCCESS) { printf("CodeletMain: Error starting queue manager dispatch loop!\n"); return (IX_FAIL); } /* Initialise NPE Message handler */ printf("\nStarting NPE message handler...\n"); if(ixNpeMhInitialize(IX_NPEMH_NPEINTERRUPTS_YES) != IX_SUCCESS) { printf("CodeletMain: Error initialising NPE Message handler!\n"); return (IX_FAIL); } /* Initialise NPEs firmware */ printf ("Initialising NPEs...\n"); if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_1]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_1)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE B\n"); ETH_NPEB_IMAGEID = IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEB_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE B!\n"); return (IX_FAIL); } } if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_2]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_2)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE C\n"); ETH_NPEC_IMAGEID = IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEC_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE C!\n"); return (IX_FAIL); } } #ifdef __ixp46X if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_3]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_3)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE A\n"); ETH_NPEA_IMAGEID = IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEA_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE A!\n"); return (IX_FAIL); } } #endif printf ("Initialising Access Layers\n"); /* Enable QoS on ethDB. This has to be done before ethAcc initialisation */ if (operationType == IX_ETHACC_CODELET_BRIDGE_QOS) { printf("Enabling QoS\n"); if (IX_ETH_DB_SUCCESS != ixEthDBInit()) { printf ("CodeletMain: Error initialising EthDB\n"); return (IX_FAIL); } (void)ixEthDBPortInit(inPort); if (IX_ETH_DB_SUCCESS != ixEthDBFeatureEnable(inPort, IX_ETH_DB_VLAN_QOS, TRUE)) { printf("CodeletMain: Error enabling QoS on port %d\n",inPort); return (IX_FAIL); } } /* initialise ethAcc : QoS, if needed is already configured */ if (ixEthAccInit() != IX_ETH_ACC_SUCCESS) { printf("CodeletMain: Error initialising Ethernet access driver!\n"); return (IX_FAIL); } /*********************************************************************** * * Access components initialisation done. Now initialize the ports * ***********************************************************************/ /* Configure all available ports */ for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (ixEthAccCodeletHardwareExists[portId]) { if(ixEthAccCodeletPortInit(portId) != IX_ETH_ACC_SUCCESS) { printf("CodeletMain: Error setup port %u\n", portId); return (IX_FAIL); } } } /* Find and initialise all available PHYs */ printf ("Discover and reset the PHYs...\n"); if(ixEthAccCodeletPhyInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising Ethernet phy(s)!\n"); return (IX_FAIL); } /*********************************************************************** * * PortInitialization done. Now start the codelet features * ***********************************************************************/ /* starts ethDB maintenance running from a different task */ if (ixEthAccCodeletDBMaintenanceStart() != IX_SUCCESS) { printf("CodeletMain: Error spawning DB maintenance task\n"); return (IX_FAIL); } /* Starts the traffic display (in a different task) this is initially * set to FALSE in order to allow the traffic stats to start only * once traffic is started to be received */ ixEthAccCodeletTrafficPollEnabled = FALSE; if (ixOsalThreadCreate(&statsPollThread, &threadAttr, (IxOsalVoidFnVoidPtr) ixEthAccCodeletStatsPollTask, NULL) != IX_SUCCESS) { printf("CodeletMain: Error spawning stats task\n"); return (IX_FAIL); } /* Start the thread */ if (ixOsalThreadStart(&statsPollThread) != IX_SUCCESS) { printf("CodeletMain: Error failed to start the stats thread\n"); return IX_FAIL; } ixEthAccCodeletInitialised = TRUE; return (IX_SUCCESS); }
IX_STATUS ixEthAccCodeletDispatcherStart(BOOL useInterrupt) { IxOsalThread qDispatchThread; IxOsalThreadAttr threadAttr; threadAttr.name = "Codelet Q Dispatcher"; threadAttr.stackSize = 32 * 1024; /* 32kbytes */ threadAttr.priority = IX_ETHACC_CODELET_QMR_PRIORITY; if (!ixEthAccCodeletDispatcherInitialized) { /* this should be initialized once */ ixQMgrDispatcherLoopGet(&ixEthAccCodeletDispatcherFunc); ixOsalMutexInit (&ixEthAccCodeletDispatcherPollRunning); ixEthAccCodeletDispatcherPollStopTrigger = TRUE; ixEthAccCodeletDispatcherInitialized = TRUE; } if(useInterrupt) /* Interrupt mode */ { /* * Hook the QM QLOW dispatcher to the interrupt controller. */ if (ixOsalIrqBind(IX_ETH_CODELET_QMGR_IRQ, (IxOsalVoidFnVoidPtr)(ixEthAccCodeletDispatcherFunc), (void *)IX_QMGR_QUELOW_GROUP) != IX_SUCCESS) { ixOsalMutexDestroy(&ixEthAccCodeletDispatcherPollRunning); printf("Dispatcher: Failed to bind to QM1 interrupt\n"); return (IX_FAIL); } } else { if (ixEthAccCodeletDispatcherPollStopTrigger) { /* Polled mode based on a task running a loop */ if (ixOsalThreadCreate(&qDispatchThread, &threadAttr, (IxOsalVoidFnVoidPtr) ixEthAccCodeletDispatcherPoll, NULL) != IX_SUCCESS) { ixOsalMutexDestroy(&ixEthAccCodeletDispatcherPollRunning); printf("Dispatcher: Error spawning Q Dispatcher task\n"); return (IX_FAIL); } /* Start the thread */ if (ixOsalThreadStart(&qDispatchThread) != IX_SUCCESS) { ixOsalMutexDestroy(&ixEthAccCodeletDispatcherPollRunning); printf("Dispatcher: Error failed to start the Q Dispatcher thread\n"); return IX_FAIL; } } } return (IX_SUCCESS); }