Exemplo n.º 1
0
void
ixQMgrShow (void)
{
    IxQMgrQCfgStats *qCfgStats = NULL;
    IxQMgrDispatcherStats *dispatcherStats = NULL;
    int i;
    UINT32 lowIntRegRead, upIntRegRead;

    qCfgStats = ixQMgrQCfgStatsGet ();
    dispatcherStats = ixQMgrDispatcherStatsGet ();
    ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUELOW_GROUP, &lowIntRegRead);
    ixQMgrAqmIfQInterruptRegRead (IX_QMGR_QUEUPP_GROUP, &upIntRegRead);
    printf("Generic Stats........\n");
    printf("=====================\n");
    printf("Loop Run Count..........%u\n",dispatcherStats->loopRunCnt);
    printf("Watermark set count.....%d\n", qCfgStats->wmSetCnt);
    printf("===========================================\n");
    printf("On the fly Interrupt Register Stats........\n");
    printf("===========================================\n");
    printf("Lower Interrupt Register............0x%08x\n",lowIntRegRead);
    printf("Upper Interrupt Register............0x%08x\n",upIntRegRead);
    printf("==============================================\n");
    printf("Queue Specific Stats........\n");
    printf("============================\n");

    for (i=0; i<IX_QMGR_MAX_NUM_QUEUES; i++)
    {
	if (ixQMgrQIsConfigured(i))
	{
	    ixQMgrQShow(i);
	}
    }

    printf("============================\n");
}
Exemplo n.º 2
0
void
ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group)
{
    UINT32 intRegVal;                /* Interrupt reg val */
    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
    IxQMgrQInfo *currDispatchQInfo;


    int priorityTableIndex; /* Priority table index */
    int qIndex;             /* Current queue being processed */

#ifndef NDEBUG
    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
              (group == IX_QMGR_QUELOW_GROUP));
    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 
	      (group == IX_QMGR_QUELOW_GROUP));
#endif

    /* Read the interrupt register */
    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);


    /* No queue has interrupt register set */
    if (intRegVal != 0)
    {

            /* Write it back to clear the interrupt */
            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);

            /* get the first queue Id from the interrupt register value */
            qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);

            if (IX_QMGR_QUEUPP_GROUP == group)
            {
                /* Set the queue range based on the queue group to proccess */
                qIndex += IX_QMGR_MIN_QUEUPP_QID;
            }

            /* check if the interrupt register contains
             * only 1 bit set
             * For example:
             *                                        intRegVal = 0x0010
             *               currDispatchQInfo->intRegCheckMask = 0x0010
             *    intRegVal == currDispatchQInfo->intRegCheckMask is TRUE.
             */
             currDispatchQInfo = &dispatchQInfo[qIndex];
             if (intRegVal == currDispatchQInfo->intRegCheckMask)
             {
                /* only 1 queue event triggered a notification *
                 * Call the callback function for this queue
                 */
                currDispatchQInfo->callback (qIndex,
                                     currDispatchQInfo->callbackId);
#ifndef NDEBUG
                /* Update statistics */
                dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
             }
             else
             {
                 /* the event is triggered by more than 1 queue,
                  * the queue search will be starting from the beginning
                  * or the middle of the priority table
                  *
                  * the serach will end when all the bits of the interrupt
                  * register are cleared. There is no need to maintain
                  * a seperate value and test it at each iteration.
                  */
                 if (IX_QMGR_QUELOW_GROUP == group)
                 {
                     /* check if any bit related to queues in the first
                      * half of the priority table is set
                      */
                     if (intRegVal & lowPriorityTableFirstHalfMask)
                     {
                         priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
                     }
                     else
                     {
                         priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
                     }
                 }
                else
                 {
                     /* check if any bit related to queues in the first
                      * half of the priority table is set
                      */
                     if (intRegVal & uppPriorityTableFirstHalfMask)
                     {
                         priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
                     }
                     else
                     {
                         priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
                     }
                 }

                 /* iterate following the priority table until all the bits
                  * of the interrupt register are cleared.
                  */
                 do
                 {
                     qIndex = priorityTable[priorityTableIndex++];
                     currDispatchQInfo = &dispatchQInfo[qIndex];
                     intRegCheckMask = currDispatchQInfo->intRegCheckMask;

                     /* If this queue caused this interrupt to be raised */
                     if (intRegVal & intRegCheckMask)
                     {
                         /* Call the callback function for this queue */
                         currDispatchQInfo->callback (qIndex,
                                              currDispatchQInfo->callbackId);
#ifndef NDEBUG
                         /* Update statistics */
                         dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif

                         /* Clear the interrupt register bit */
                         intRegVal &= ~intRegCheckMask;
                     }
                  }
                  while(intRegVal);
             } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
     } /* End of intRegVal != 0 */

#ifndef NDEBUG
    /* Update statistics */
    dispatcherStats.loopRunCnt++;
#endif

    /* Rebuild the priority table if needed */
    if (rebuildTable)
    {
        ixQMgrDispatcherReBuildPriorityTable ();
    }
}
Exemplo n.º 3
0
void
ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group)
{
    UINT32 intRegVal =0;                /* Interrupt reg val */
    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
    IxQMgrQInfo *currDispatchQInfo;

    int priorityTableIndex; /* Priority table index */
    int qIndex;             /* Current queue being processed */

    UINT32 intRegValCopy = 0;
    UINT32 intEnableRegVal = 0;
    UINT8 i = 0;

#ifndef NDEBUG
    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
              (group == IX_QMGR_QUELOW_GROUP));
#endif

    /* Read the interrupt register */
    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);

    /* 
     * mask any interrupts that are not enabled 
     */
    ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal);
    intRegVal &= intEnableRegVal;

    /* No queue has interrupt register set */
    if (intRegVal != 0)
    {
        if (IX_QMGR_QUELOW_GROUP == group)
        {
            /*
             * As the sticky bit is set, the interrupt register will 
             * not clear if write back at this point because the condition
             * has not been cleared. Take a copy and write back later after
             * the condition has been cleared
             */
            intRegValCopy = intRegVal;
        }
        else
        {
            /* no sticky for upper Q's, so write back now */
            ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
        }

        /* get the first queue Id from the interrupt register value */
        qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);

        if (IX_QMGR_QUEUPP_GROUP == group)
        {
            /* Set the queue range based on the queue group to proccess */
            qIndex += IX_QMGR_MIN_QUEUPP_QID;
        }

        /* check if the interrupt register contains
        * only 1 bit set
        * For example:
        *                                        intRegVal = 0x0010
        *               currDispatchQInfo->intRegCheckMask = 0x0010
        *    intRegVal == currDispatchQInfo->intRegCheckMask is TRUE.
        */
        currDispatchQInfo = &dispatchQInfo[qIndex];
        if (intRegVal == currDispatchQInfo->intRegCheckMask)
        {

            /* 
             * check if Q type periodic -  only lower queues can
             * have there type set to periodic 
             */
            if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
            {
                /* 
                 * Disable the notifications on any sporadics 
                 */
                for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
                {
                    if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i])
                    {
                        ixQMgrNotificationDisable(i);
#ifndef NDEBUG
                        /* Update statistics */
                        dispatcherStats.queueStats[i].disableCount++;
#endif
                    }
                }
            }

            currDispatchQInfo->callback (qIndex,
                                         currDispatchQInfo->callbackId);
#ifndef NDEBUG
            /* Update statistics */
            dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
        }
        else
        {
            /* the event is triggered by more than 1 queue,
            * the queue search will be starting from the beginning
            * or the middle of the priority table
            *
            * the serach will end when all the bits of the interrupt
            * register are cleared. There is no need to maintain
            * a seperate value and test it at each iteration.
            */
            if (IX_QMGR_QUELOW_GROUP == group)
            {
                /* check if any bit related to queues in the first
                 * half of the priority table is set
                 */
                if (intRegVal & lowPriorityTableFirstHalfMask)
                {
                    priorityTableIndex =
                                       IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
                }
                else
                {
                    priorityTableIndex =
                                       IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
                }
            }
            else
            {
                /* check if any bit related to queues in the first
                 * half of the priority table is set
                 */
                if (intRegVal & uppPriorityTableFirstHalfMask)
                {
                    priorityTableIndex =
                                       IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
                }
                else
                {
                    priorityTableIndex =
                                       IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
                }
            }

            /* iterate following the priority table until all the bits
             * of the interrupt register are cleared.
             */
            do
            {
                qIndex = priorityTable[priorityTableIndex++];
                currDispatchQInfo = &dispatchQInfo[qIndex];
                intRegCheckMask = currDispatchQInfo->intRegCheckMask;

                /* If this queue caused this interrupt to be raised */
                if (intRegVal & intRegCheckMask)
                {
                    /* 
                     * check if Q type periodic - only lower queues can
                     * have there type set to periodic. There can only be one
                     * periodic queue, so the sporadics are only disabled once.
                     */
                    if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
                    {
                        /* 
                         * Disable the notifications on any sporadics 
                         */
                        for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
                        {
                            if (IX_QMGR_TYPE_REALTIME_SPORADIC == 
                                    ixQMgrQTypes[i])
                            {
                                ixQMgrNotificationDisable(i);
                                /* 
                                 * remove from intRegVal as we don't want 
                                 * to service any sporadics now
                                 */
                                intRegVal &= ~dispatchQInfo[i].intRegCheckMask;
#ifndef NDEBUG
                                /* Update statistics */
                                dispatcherStats.queueStats[i].disableCount++;
#endif
                            }
                        }
                    }

                    currDispatchQInfo->callback (qIndex,
                                                 currDispatchQInfo->callbackId);
#ifndef NDEBUG
                    /* Update statistics */
                    dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
                    /* Clear the interrupt register bit */
                    intRegVal &= ~intRegCheckMask;
                }
            }
            while(intRegVal);
        } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
    } /* End of intRegVal != 0 */

#ifndef NDEBUG
    /* Update statistics */
    dispatcherStats.loopRunCnt++;
#endif

    if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group))
    {
        /* 
         * lower groups (therefore sticky) AND at least one enabled interrupt
         * Write back to clear the interrupt 
         */
        ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy);
    }

    /* Rebuild the priority table if needed */
    if (rebuildTable)
    {
        ixQMgrDispatcherReBuildPriorityTable ();
    }
}
Exemplo n.º 4
0
void
ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group)
{
    UINT32 intRegVal;                /* Interrupt reg val */
    UINT32 intRegValAfterWrite;      /* Interrupt reg val after writing back */
    UINT32 intRegCheckMask;          /* Mask for checking interrupt bits */
    UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS];  /* Status b4 interrupt write */
    UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */
    IxQMgrQInfo *currDispatchQInfo;
    BOOL statusChangeFlag;

    int priorityTableIndex;/* Priority table index */
    int qIndex;            /* Current queue being processed */
    int endIndex;          /* Index of last queue to process */

#ifndef NDEBUG
    IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || 
	      (group == IX_QMGR_QUELOW_GROUP));
#endif

    /* Read Q status registers before interrupt status read/write */
    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write);

    /* Read the interrupt register */
    ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);

    /* No bit set : nothing to process (the reaminder of the algorithm is
    * based on the fact that the interrupt register value contains at
    * least one bit set
    */
    if (intRegVal == 0) 
    {
#ifndef NDEBUG
	/* Update statistics */
	dispatcherStats.loopRunCnt++;
#endif

	/* Rebuild the priority table if needed */
	if (rebuildTable)
	{
	    ixQMgrDispatcherReBuildPriorityTable ();
	}

	return;
    }
   
    /* Write it back to clear the interrupt */
    ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);

    /* Read Q status registers after interrupt status read/write */
    ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite);
 
    /* get the first queue Id from the interrupt register value */
    qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);

    /* check if any change occured during hw register modifications */ 
    if (IX_QMGR_QUELOW_GROUP == group)
    {
	statusChangeFlag = 
	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) ||
	    (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) ||
	    (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) ||
	    (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]);
    }
    else
    {
	statusChangeFlag = 
	    (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]);
	/* Set the queue range based on the queue group to proccess */
	qIndex += IX_QMGR_MIN_QUEUPP_QID;
    }

    if (statusChangeFlag == FALSE)
    {
	/* check if the interrupt register contains 
	 * only 1 bit set (happy day scenario)
	 */
	currDispatchQInfo = &dispatchQInfo[qIndex];
	if (intRegVal == currDispatchQInfo->intRegCheckMask)
	{
	    /* only 1 queue event triggered a notification *
	     * Call the callback function for this queue 
	     */
	    currDispatchQInfo->callback (qIndex,
					 currDispatchQInfo->callbackId);  
#ifndef NDEBUG
	    /* Update statistics */
	    dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
	}
	else 
	{
	    /* the event is triggered by more than 1 queue, 
	     * the queue search will be starting from the beginning
	     * or the middle of the priority table
	     *
	     * the serach will end when all the bits of the interrupt
	     * register are cleared. There is no need to maintain
	     * a seperate value and test it at each iteration.
	     */
	    if (IX_QMGR_QUELOW_GROUP == group)
	    {
		/* check if any bit related to queues in the first
		 * half of the priority table is set
		 */
		if (intRegVal & lowPriorityTableFirstHalfMask)
		{
		    priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
		}
		else
		{
		    priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
		}
	    }
	    else 
	    {
		/* check if any bit related to queues in the first
		 * half of the priority table is set
		 */
		if (intRegVal & uppPriorityTableFirstHalfMask)
		{
		    priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
		}
		else
		{
		    priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
		}
	    }
	    
	    /* iterate following the priority table until all the bits 
	     * of the interrupt register are cleared.
	     */
	    do
	    {
		qIndex = priorityTable[priorityTableIndex++];
		currDispatchQInfo = &dispatchQInfo[qIndex];
		intRegCheckMask = currDispatchQInfo->intRegCheckMask;
		
		/* If this queue caused this interrupt to be raised */
		if (intRegVal & intRegCheckMask)
		{
		    /* Call the callback function for this queue */
		    currDispatchQInfo->callback (qIndex,
						 currDispatchQInfo->callbackId);
#ifndef NDEBUG
		    /* Update statistics */
		    dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
		    
		    /* Clear the interrupt register bit */
		    intRegVal &= ~intRegCheckMask;
		}
	    }
	    while(intRegVal);
	}
    }
    else
    {
    /* A change in queue status occured during the hw interrupt
     * register update. To maintain the interrupt consistency, it
     * is necessary to iterate through all queues of the queue group.
     */

    /* Read interrupt status again */
    ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite);

    if (IX_QMGR_QUELOW_GROUP == group)
    {
	priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
	endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX;
    }
    else
    {
	priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
	endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX;
    }

    for ( ; priorityTableIndex<=endIndex; priorityTableIndex++)
    {
	qIndex = priorityTable[priorityTableIndex];
	currDispatchQInfo = &dispatchQInfo[qIndex];
	intRegCheckMask = currDispatchQInfo->intRegCheckMask;

	/* If this queue caused this interrupt to be raised */
	if (intRegVal & intRegCheckMask)
	{  
	    /* Call the callback function for this queue */
	    currDispatchQInfo->callback (qIndex,
					 currDispatchQInfo->callbackId);
#ifndef NDEBUG
	    /* Update statistics */
	    dispatcherStats.queueStats[qIndex].callbackCnt++;
#endif
	    
	} /* if (intRegVal .. */

	/* 
	 * If interrupt bit is set in intRegValAfterWrite don't
	 * proceed as this will be caught in next interrupt
	 */
	else if ((intRegValAfterWrite & intRegCheckMask) == 0)
	{
	    /* Check if an interrupt was lost for this Q */
	    if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write,
					qStatusWordsAfterWrite,
					currDispatchQInfo->statusWordOffset,
					currDispatchQInfo->statusCheckValue,
					currDispatchQInfo->statusMask))
	    {
		/* Call the callback function for this queue */
		currDispatchQInfo->callback (qIndex, 
					     dispatchQInfo[qIndex].callbackId);                 
#ifndef NDEBUG
		/* Update statistics */
		dispatcherStats.queueStats[qIndex].callbackCnt++;
		dispatcherStats.queueStats[qIndex].intLostCallbackCnt++;
#endif
	    } /* if ixQMgrAqmIfQStatusCheck(.. */
	} /* else if ((intRegValAfterWrite ... */
    } /* for (priorityTableIndex=0 ... */
    }

    /* Rebuild the priority table if needed */
    if (rebuildTable)
    {
	ixQMgrDispatcherReBuildPriorityTable ();
    }

#ifndef NDEBUG
    /* Update statistics */
    dispatcherStats.loopRunCnt++;
#endif
}