14e1bc9a0SAchim Leubner /*******************************************************************************
24e1bc9a0SAchim Leubner **
34e1bc9a0SAchim Leubner *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
44e1bc9a0SAchim Leubner *
54e1bc9a0SAchim Leubner *Redistribution and use in source and binary forms, with or without modification, are permitted provided
64e1bc9a0SAchim Leubner *that the following conditions are met:
74e1bc9a0SAchim Leubner *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
84e1bc9a0SAchim Leubner *following disclaimer.
94e1bc9a0SAchim Leubner *2. Redistributions in binary form must reproduce the above copyright notice,
104e1bc9a0SAchim Leubner *this list of conditions and the following disclaimer in the documentation and/or other materials provided
114e1bc9a0SAchim Leubner *with the distribution.
124e1bc9a0SAchim Leubner *
134e1bc9a0SAchim Leubner *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
144e1bc9a0SAchim Leubner *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
154e1bc9a0SAchim Leubner *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
164e1bc9a0SAchim Leubner *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
174e1bc9a0SAchim Leubner *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
184e1bc9a0SAchim Leubner *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
194e1bc9a0SAchim Leubner *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
204e1bc9a0SAchim Leubner *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
214e1bc9a0SAchim Leubner
224e1bc9a0SAchim Leubner ********************************************************************************/
234e1bc9a0SAchim Leubner
244e1bc9a0SAchim Leubner /*******************************************************************************/
254e1bc9a0SAchim Leubner /*! \file mpi.c
264e1bc9a0SAchim Leubner * \brief The file is a MPI Libraries to implement the MPI functions
274e1bc9a0SAchim Leubner *
284e1bc9a0SAchim Leubner * The file implements the MPI Library functions.
294e1bc9a0SAchim Leubner *
304e1bc9a0SAchim Leubner */
314e1bc9a0SAchim Leubner /*******************************************************************************/
324e1bc9a0SAchim Leubner #include <sys/cdefs.h>
334e1bc9a0SAchim Leubner #include <dev/pms/config.h>
344e1bc9a0SAchim Leubner
354e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
364e1bc9a0SAchim Leubner
374e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
384e1bc9a0SAchim Leubner #ifdef siTraceFileID
394e1bc9a0SAchim Leubner #undef siTraceFileID
404e1bc9a0SAchim Leubner #endif
414e1bc9a0SAchim Leubner #define siTraceFileID 'A'
424e1bc9a0SAchim Leubner #endif
434e1bc9a0SAchim Leubner
444e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
454e1bc9a0SAchim Leubner extern int loopback;
464e1bc9a0SAchim Leubner #endif
474e1bc9a0SAchim Leubner /*******************************************************************************/
484e1bc9a0SAchim Leubner
494e1bc9a0SAchim Leubner /*******************************************************************************/
504e1bc9a0SAchim Leubner /*******************************************************************************/
514e1bc9a0SAchim Leubner /* FUNCTIONS */
524e1bc9a0SAchim Leubner /*******************************************************************************/
534e1bc9a0SAchim Leubner /*******************************************************************************/
544e1bc9a0SAchim Leubner /** \fn void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
554e1bc9a0SAchim Leubner * \brief Retrieves the MPI layer resource requirements
564e1bc9a0SAchim Leubner * \param config MPI configuration for the Host MPI Message Unit
574e1bc9a0SAchim Leubner * \param memoryRequirement Returned data structure as defined by mpiMemReq_t
584e1bc9a0SAchim Leubner * that holds the different chunks of memory that are required
594e1bc9a0SAchim Leubner *
604e1bc9a0SAchim Leubner * The mpiRequirementsGet() function is used to determine the resource requirements
614e1bc9a0SAchim Leubner * for the SPC device interface
624e1bc9a0SAchim Leubner *
634e1bc9a0SAchim Leubner * Return: None
644e1bc9a0SAchim Leubner */
654e1bc9a0SAchim Leubner /*******************************************************************************/
mpiRequirementsGet(mpiConfig_t * config,mpiMemReq_t * memoryRequirement)664e1bc9a0SAchim Leubner void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
674e1bc9a0SAchim Leubner {
684e1bc9a0SAchim Leubner bit32 qIdx, numq;
694e1bc9a0SAchim Leubner mpiMemReq_t* memoryMap;
704e1bc9a0SAchim Leubner SA_DBG2(("Entering function:mpiRequirementsGet\n"));
714e1bc9a0SAchim Leubner SA_ASSERT((NULL != config), "config argument cannot be null");
724e1bc9a0SAchim Leubner
734e1bc9a0SAchim Leubner memoryMap = memoryRequirement;
744e1bc9a0SAchim Leubner memoryMap->count = 0;
754e1bc9a0SAchim Leubner
764e1bc9a0SAchim Leubner /* MPI Memory region 0 for MSGU(AAP1) Event Log for fw */
774e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
784e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.eventLogSize;
794e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.eventLogSize;
804e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 32;
814e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
824e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
834e1bc9a0SAchim Leubner memoryMap->count++;
844e1bc9a0SAchim Leubner
854e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
864e1bc9a0SAchim Leubner /* MPI Memory region 1 for IOP Event Log for fw */
874e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
884e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
894e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
904e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 32;
914e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
924e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet:IOPeventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
934e1bc9a0SAchim Leubner memoryMap->count++;
944e1bc9a0SAchim Leubner
954e1bc9a0SAchim Leubner /* MPI Memory region 2 for consumer Index of inbound queues */
964e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
974e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numInboundQueues;
984e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numInboundQueues;
994e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 4;
1004e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
1014e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet:numInboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
1024e1bc9a0SAchim Leubner memoryMap->count++;
1034e1bc9a0SAchim Leubner
1044e1bc9a0SAchim Leubner /* MPI Memory region 3 for producer Index of outbound queues */
1054e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
1064e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numOutboundQueues;
1074e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numOutboundQueues;
1084e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 4;
1094e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
1104e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet:numOutboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
1114e1bc9a0SAchim Leubner memoryMap->count++;
1124e1bc9a0SAchim Leubner
1134e1bc9a0SAchim Leubner /* MPI Memory regions 4, ... for the inbound queues - depends on configuration */
1144e1bc9a0SAchim Leubner numq = 0;
1154e1bc9a0SAchim Leubner for(qIdx = 0; qIdx < config->numInboundQueues; qIdx++)
1164e1bc9a0SAchim Leubner {
1174e1bc9a0SAchim Leubner if(0 != config->inboundQueues[qIdx].numElements)
1184e1bc9a0SAchim Leubner {
1194e1bc9a0SAchim Leubner bit32 memSize = config->inboundQueues[qIdx].numElements * config->inboundQueues[qIdx].elementSize;
1204e1bc9a0SAchim Leubner bit32 remainder = memSize & 127;
1214e1bc9a0SAchim Leubner
1224e1bc9a0SAchim Leubner /* Calculate the size of this queue padded to 128 bytes */
1234e1bc9a0SAchim Leubner if (remainder > 0)
1244e1bc9a0SAchim Leubner {
1254e1bc9a0SAchim Leubner memSize += (128 - remainder);
1264e1bc9a0SAchim Leubner }
1274e1bc9a0SAchim Leubner
1284e1bc9a0SAchim Leubner if (numq == 0)
1294e1bc9a0SAchim Leubner {
1304e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
1314e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = memSize;
1324e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = memSize;
1334e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 128;
1344e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
1354e1bc9a0SAchim Leubner }
1364e1bc9a0SAchim Leubner else
1374e1bc9a0SAchim Leubner {
1384e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize += memSize;
1394e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength += memSize;
1404e1bc9a0SAchim Leubner }
1414e1bc9a0SAchim Leubner
1424e1bc9a0SAchim Leubner numq++;
1434e1bc9a0SAchim Leubner
1444e1bc9a0SAchim Leubner if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
1454e1bc9a0SAchim Leubner (qIdx == (bit32)(config->numInboundQueues - 1)))
1464e1bc9a0SAchim Leubner {
1474e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].elementSize = %d\n",
1484e1bc9a0SAchim Leubner memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
1494e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].numElements = %d\n",
1504e1bc9a0SAchim Leubner memoryMap->count, memoryMap->region[memoryMap->count].numElements));
1514e1bc9a0SAchim Leubner
1524e1bc9a0SAchim Leubner memoryMap->count++;
1534e1bc9a0SAchim Leubner numq = 0;
1544e1bc9a0SAchim Leubner }
1554e1bc9a0SAchim Leubner }
1564e1bc9a0SAchim Leubner }
1574e1bc9a0SAchim Leubner
1584e1bc9a0SAchim Leubner /* MPI Memory regions for the outbound queues - depends on configuration */
1594e1bc9a0SAchim Leubner numq = 0;
1604e1bc9a0SAchim Leubner for(qIdx = 0; qIdx < config->numOutboundQueues; qIdx++)
1614e1bc9a0SAchim Leubner {
1624e1bc9a0SAchim Leubner if(0 != config->outboundQueues[qIdx].numElements)
1634e1bc9a0SAchim Leubner {
1644e1bc9a0SAchim Leubner bit32 memSize = config->outboundQueues[qIdx].numElements * config->outboundQueues[qIdx].elementSize;
1654e1bc9a0SAchim Leubner bit32 remainder = memSize & 127;
1664e1bc9a0SAchim Leubner
1674e1bc9a0SAchim Leubner /* Calculate the size of this queue padded to 128 bytes */
1684e1bc9a0SAchim Leubner if (remainder > 0)
1694e1bc9a0SAchim Leubner {
1704e1bc9a0SAchim Leubner memSize += (128 - remainder);
1714e1bc9a0SAchim Leubner }
1724e1bc9a0SAchim Leubner
1734e1bc9a0SAchim Leubner if (numq == 0)
1744e1bc9a0SAchim Leubner {
1754e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].numElements = 1;
1764e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize = memSize;
1774e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength = memSize;
1784e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].alignment = 128;
1794e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
1804e1bc9a0SAchim Leubner }
1814e1bc9a0SAchim Leubner else
1824e1bc9a0SAchim Leubner {
1834e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].elementSize += memSize;
1844e1bc9a0SAchim Leubner memoryMap->region[memoryMap->count].totalLength += memSize;
1854e1bc9a0SAchim Leubner }
1864e1bc9a0SAchim Leubner
1874e1bc9a0SAchim Leubner numq++;
1884e1bc9a0SAchim Leubner
1894e1bc9a0SAchim Leubner if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
1904e1bc9a0SAchim Leubner (qIdx == (bit32)(config->numOutboundQueues - 1)))
1914e1bc9a0SAchim Leubner {
1924e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].elementSize = %d\n",
1934e1bc9a0SAchim Leubner memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
1944e1bc9a0SAchim Leubner SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].numElements = %d\n",
1954e1bc9a0SAchim Leubner memoryMap->count, memoryMap->region[memoryMap->count].numElements));
1964e1bc9a0SAchim Leubner
1974e1bc9a0SAchim Leubner
1984e1bc9a0SAchim Leubner memoryMap->count++;
1994e1bc9a0SAchim Leubner numq = 0;
2004e1bc9a0SAchim Leubner }
2014e1bc9a0SAchim Leubner }
2024e1bc9a0SAchim Leubner }
2034e1bc9a0SAchim Leubner
2044e1bc9a0SAchim Leubner }
2054e1bc9a0SAchim Leubner
2064e1bc9a0SAchim Leubner /*******************************************************************************/
2074e1bc9a0SAchim Leubner /** \fn mpiMsgFreeGet(mpiICQueue_t *circularQ, bit16 messageSize, void** messagePtr)
2084e1bc9a0SAchim Leubner * \brief Retrieves a free message buffer from an inbound queue
2094e1bc9a0SAchim Leubner * \param circularQ Pointer to an inbound circular queue
2104e1bc9a0SAchim Leubner * \param messageSize Requested message size in bytes - only support 64 bytes/element
2114e1bc9a0SAchim Leubner * \param messagePtr Pointer to the free message buffer payload (not including message header) or NULL if no free message buffers are available
2124e1bc9a0SAchim Leubner *
2134e1bc9a0SAchim Leubner * This function is used to retrieve a free message buffer for the given inbound queue of at least
2144e1bc9a0SAchim Leubner * messageSize bytes.
2154e1bc9a0SAchim Leubner * The caller can use the returned buffer to construct the message and then call mpiMsgProduce()
2164e1bc9a0SAchim Leubner * to deliver the message to the device message unit or mpiMsgInvalidate() if the message buffer
2174e1bc9a0SAchim Leubner * is not going to be used
2184e1bc9a0SAchim Leubner *
2194e1bc9a0SAchim Leubner * Return:
2204e1bc9a0SAchim Leubner * AGSA_RC_SUCCESS if messagePtr contains a valid message buffer pointer
2214e1bc9a0SAchim Leubner * AGSA_RC_FAILURE if messageSize larger than the elementSize of queue
2224e1bc9a0SAchim Leubner * AGSA_RC_BUSY if there are not free message buffers (Queue full)
2234e1bc9a0SAchim Leubner */
2244e1bc9a0SAchim Leubner /*******************************************************************************/
2254e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
2264e1bc9a0SAchim Leubner bit32
mpiMsgFreeGet(mpiICQueue_t * circularQ,bit16 messageSize,void ** messagePtr)2274e1bc9a0SAchim Leubner mpiMsgFreeGet(
2284e1bc9a0SAchim Leubner mpiICQueue_t *circularQ,
2294e1bc9a0SAchim Leubner bit16 messageSize,
2304e1bc9a0SAchim Leubner void** messagePtr
2314e1bc9a0SAchim Leubner )
2324e1bc9a0SAchim Leubner {
2334e1bc9a0SAchim Leubner bit32 offset;
2344e1bc9a0SAchim Leubner agsaRoot_t *agRoot=circularQ->agRoot;
2354e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
2364e1bc9a0SAchim Leubner bit8 bcCount = 1; /* only support single buffer */
2374e1bc9a0SAchim Leubner
2384e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
2394e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
2404e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
2414e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
2424e1bc9a0SAchim Leubner
2434e1bc9a0SAchim Leubner /* Checks is the requested message size can be allocated in this queue */
2444e1bc9a0SAchim Leubner if(messageSize > circularQ->elementSize)
2454e1bc9a0SAchim Leubner {
2464e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgFreeGet: Message Size (%d) is larger than Q element size (%d)\n",messageSize,circularQ->elementSize));
2474e1bc9a0SAchim Leubner return AGSA_RC_FAILURE;
2484e1bc9a0SAchim Leubner }
2494e1bc9a0SAchim Leubner
2504e1bc9a0SAchim Leubner /* Stores the new consumer index */
2514e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
2524e1bc9a0SAchim Leubner /* if inbound queue is full, return busy */
2534e1bc9a0SAchim Leubner /* This queue full logic may only works for bc == 1 ( == ) */
2544e1bc9a0SAchim Leubner /* ( pi + bc ) % size > ci not fully works for bc > 1 */
2554e1bc9a0SAchim Leubner /* To do - support bc > 1 case and wrap around case */
2564e1bc9a0SAchim Leubner if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
2574e1bc9a0SAchim Leubner {
2584e1bc9a0SAchim Leubner *messagePtr = NULL;
2594e1bc9a0SAchim Leubner smTrace(hpDBG_VERY_LOUD,"Za", (((circularQ->producerIdx & 0xFFF) << 16) | (circularQ->consumerIdx & 0xFFF) ));
2604e1bc9a0SAchim Leubner /* TP:Za IQ PI CI */
2614e1bc9a0SAchim Leubner ossaHwRegRead(agRoot, MSGU_HOST_SCRATCH_PAD_0);
2624e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgFreeGet: %d + %d == %d AGSA_RC_BUSY\n",circularQ->producerIdx,bcCount,circularQ->consumerIdx));
2634e1bc9a0SAchim Leubner
2644e1bc9a0SAchim Leubner return AGSA_RC_BUSY;
2654e1bc9a0SAchim Leubner }
2664e1bc9a0SAchim Leubner
2674e1bc9a0SAchim Leubner smTrace(hpDBG_VERY_LOUD,"Zb", (((circularQ->producerIdx & 0xFFF) << 16) | (circularQ->consumerIdx & 0xFFF) ));
2684e1bc9a0SAchim Leubner /* TP:Zb IQ PI CI */
2694e1bc9a0SAchim Leubner
2704e1bc9a0SAchim Leubner
2714e1bc9a0SAchim Leubner /* get memory IOMB buffer address */
2724e1bc9a0SAchim Leubner offset = circularQ->producerIdx * circularQ->elementSize;
2734e1bc9a0SAchim Leubner /* increment to next bcCount element */
2744e1bc9a0SAchim Leubner circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
2754e1bc9a0SAchim Leubner
2764e1bc9a0SAchim Leubner /* Adds that distance to the base of the region virtual address plus the message header size*/
2774e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
2784e1bc9a0SAchim Leubner
2794e1bc9a0SAchim Leubner SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
2804e1bc9a0SAchim Leubner
2814e1bc9a0SAchim Leubner /* Sets the message buffer in "allocated" state */
2824e1bc9a0SAchim Leubner /* bc always is 1 for inbound queue */
2834e1bc9a0SAchim Leubner /* temporarily store it in the native endian format, when the rest of the */
2844e1bc9a0SAchim Leubner /* header is filled, this would be converted to Little Endian */
2854e1bc9a0SAchim Leubner msgHeader->Header = (1<<24);
2864e1bc9a0SAchim Leubner *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
2874e1bc9a0SAchim Leubner
2884e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
2894e1bc9a0SAchim Leubner }
2904e1bc9a0SAchim Leubner
2914e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
mpiMsgFreeGetOQ(mpiOCQueue_t * circularQ,bit16 messageSize,void ** messagePtr)2924e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgFreeGetOQ(mpiOCQueue_t *circularQ, bit16 messageSize, void** messagePtr)
2934e1bc9a0SAchim Leubner {
2944e1bc9a0SAchim Leubner bit32 offset;
2954e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
2964e1bc9a0SAchim Leubner bit8 bcCount = 1; /* only support single buffer */
2974e1bc9a0SAchim Leubner
2984e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
2994e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
3004e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
3014e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
3024e1bc9a0SAchim Leubner
3034e1bc9a0SAchim Leubner /* Checks is the requested message size can be allocated in this queue */
3044e1bc9a0SAchim Leubner if(messageSize > circularQ->elementSize)
3054e1bc9a0SAchim Leubner {
3064e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgFreeGet: Message Size is not fit in\n"));
3074e1bc9a0SAchim Leubner return AGSA_RC_FAILURE;
3084e1bc9a0SAchim Leubner }
3094e1bc9a0SAchim Leubner
3104e1bc9a0SAchim Leubner /* Stores the new consumer index */
3114e1bc9a0SAchim Leubner //OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
3124e1bc9a0SAchim Leubner /* if inbound queue is full, return busy */
3134e1bc9a0SAchim Leubner /* This queue full logic may only works for bc == 1 ( == ) */
3144e1bc9a0SAchim Leubner /* ( pi + bc ) % size > ci not fully works for bc > 1 */
3154e1bc9a0SAchim Leubner /* To do - support bc > 1 case and wrap around case */
3164e1bc9a0SAchim Leubner if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
3174e1bc9a0SAchim Leubner {
3184e1bc9a0SAchim Leubner *messagePtr = NULL;
3194e1bc9a0SAchim Leubner return AGSA_RC_BUSY;
3204e1bc9a0SAchim Leubner }
3214e1bc9a0SAchim Leubner
3224e1bc9a0SAchim Leubner /* get memory IOMB buffer address */
3234e1bc9a0SAchim Leubner offset = circularQ->producerIdx * circularQ->elementSize;
3244e1bc9a0SAchim Leubner /* increment to next bcCount element */
3254e1bc9a0SAchim Leubner circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
3264e1bc9a0SAchim Leubner
3274e1bc9a0SAchim Leubner /* Adds that distance to the base of the region virtual address plus the message header size*/
3284e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
3294e1bc9a0SAchim Leubner
3304e1bc9a0SAchim Leubner SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
3314e1bc9a0SAchim Leubner
3324e1bc9a0SAchim Leubner /* Sets the message buffer in "allocated" state */
3334e1bc9a0SAchim Leubner /* bc always is 1 for inbound queue */
3344e1bc9a0SAchim Leubner /* temporarily store it in the native endian format, when the rest of the */
3354e1bc9a0SAchim Leubner /* header is filled, this would be converted to Little Endian */
3364e1bc9a0SAchim Leubner msgHeader->Header = (1<<24);
3374e1bc9a0SAchim Leubner *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
3384e1bc9a0SAchim Leubner
3394e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
3404e1bc9a0SAchim Leubner }
3414e1bc9a0SAchim Leubner #endif
3424e1bc9a0SAchim Leubner
3434e1bc9a0SAchim Leubner /*******************************************************************************/
3444e1bc9a0SAchim Leubner /** \fn mpiMsgProduce(mpiICQueue_t *circularQ, void *messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue)
3454e1bc9a0SAchim Leubner * \brief Add a header of IOMB then send to a inbound queue and update the Producer index
3464e1bc9a0SAchim Leubner * \param circularQ Pointer to an inbound queue
3474e1bc9a0SAchim Leubner * \param messagePtr Pointer to the message buffer payload (not including message header))
3484e1bc9a0SAchim Leubner * \param category Message category (ETHERNET, FC, SAS-SATA, SCSI)
3494e1bc9a0SAchim Leubner * \param opCode Message operation code
3504e1bc9a0SAchim Leubner * \param responseQueue If the message requires response, this paramater indicates the outbound queue for the response
3514e1bc9a0SAchim Leubner *
3524e1bc9a0SAchim Leubner * This function is used to sumit a message buffer, previously obtained from mpiMsgFreeGet()
3534e1bc9a0SAchim Leubner * function call, to the given Inbound queue
3544e1bc9a0SAchim Leubner *
3554e1bc9a0SAchim Leubner * Return:
3564e1bc9a0SAchim Leubner * AGSA_RC_SUCCESS if the message has been posted succesfully
3574e1bc9a0SAchim Leubner */
3584e1bc9a0SAchim Leubner /*******************************************************************************/
3594e1bc9a0SAchim Leubner #ifdef FAST_IO_TEST
mpiMsgPrepare(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)3604e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgPrepare(
3614e1bc9a0SAchim Leubner mpiICQueue_t *circularQ,
3624e1bc9a0SAchim Leubner void *messagePtr,
3634e1bc9a0SAchim Leubner mpiMsgCategory_t category,
3644e1bc9a0SAchim Leubner bit16 opCode,
3654e1bc9a0SAchim Leubner bit8 responseQueue,
3664e1bc9a0SAchim Leubner bit8 hiPriority
3674e1bc9a0SAchim Leubner )
3684e1bc9a0SAchim Leubner {
3694e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
3704e1bc9a0SAchim Leubner bit32 bc;
3714e1bc9a0SAchim Leubner bit32 Header = 0;
3724e1bc9a0SAchim Leubner bit32 hpriority = 0;
3734e1bc9a0SAchim Leubner
3744e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgProduce\n"));
3754e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
3764e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
3774e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
3784e1bc9a0SAchim Leubner " is 0");
3794e1bc9a0SAchim Leubner SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
3804e1bc9a0SAchim Leubner
3814e1bc9a0SAchim Leubner /* Obtains the address of the entire message buffer, including the header */
3824e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
3834e1bc9a0SAchim Leubner /* Read the BC from header, its stored in native endian format when message
3844e1bc9a0SAchim Leubner was allocated */
3854e1bc9a0SAchim Leubner /* intially */
3864e1bc9a0SAchim Leubner bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
3874e1bc9a0SAchim Leubner SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
3884e1bc9a0SAchim Leubner if (circularQ->priority)
3894e1bc9a0SAchim Leubner hpriority = 1;
3904e1bc9a0SAchim Leubner
3914e1bc9a0SAchim Leubner /* Checks the message is in "allocated" state */
3924e1bc9a0SAchim Leubner SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
3934e1bc9a0SAchim Leubner "(bc == 0)");
3944e1bc9a0SAchim Leubner
3954e1bc9a0SAchim Leubner Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30) |
3964e1bc9a0SAchim Leubner ((bc & BC_MASK) << SHIFT24) |
3974e1bc9a0SAchim Leubner ((responseQueue & OBID_MASK) << SHIFT16) |
3984e1bc9a0SAchim Leubner ((category & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
3994e1bc9a0SAchim Leubner
4004e1bc9a0SAchim Leubner /* pre flush the IOMB cache line */
4014e1bc9a0SAchim Leubner ossaCachePreFlush(circularQ->agRoot,
4024e1bc9a0SAchim Leubner (void *)circularQ->memoryRegion.appHandle,
4034e1bc9a0SAchim Leubner (void *)msgHeader, circularQ->elementSize * bc);
4044e1bc9a0SAchim Leubner OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
4054e1bc9a0SAchim Leubner Header), Header);
4064e1bc9a0SAchim Leubner /* flush the IOMB cache line */
4074e1bc9a0SAchim Leubner ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
4084e1bc9a0SAchim Leubner (void *)msgHeader, circularQ->elementSize * bc);
4094e1bc9a0SAchim Leubner
4104e1bc9a0SAchim Leubner MPI_DEBUG_TRACE( circularQ->qNumber,
4114e1bc9a0SAchim Leubner ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
4124e1bc9a0SAchim Leubner MPI_DEBUG_TRACE_IBQ,
4134e1bc9a0SAchim Leubner (void *)msgHeader,
4144e1bc9a0SAchim Leubner circularQ->elementSize);
4154e1bc9a0SAchim Leubner
4164e1bc9a0SAchim Leubner ossaLogIomb(circularQ->agRoot,
4174e1bc9a0SAchim Leubner circularQ->qNumber,
4184e1bc9a0SAchim Leubner TRUE,
4194e1bc9a0SAchim Leubner (void *)msgHeader,
4204e1bc9a0SAchim Leubner circularQ->elementSize);
4214e1bc9a0SAchim Leubner
4224e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
4234e1bc9a0SAchim Leubner } /* mpiMsgPrepare */
4244e1bc9a0SAchim Leubner
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)4254e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgProduce(
4264e1bc9a0SAchim Leubner mpiICQueue_t *circularQ,
4274e1bc9a0SAchim Leubner void *messagePtr,
4284e1bc9a0SAchim Leubner mpiMsgCategory_t category,
4294e1bc9a0SAchim Leubner bit16 opCode,
4304e1bc9a0SAchim Leubner bit8 responseQueue,
4314e1bc9a0SAchim Leubner bit8 hiPriority
4324e1bc9a0SAchim Leubner )
4334e1bc9a0SAchim Leubner {
4344e1bc9a0SAchim Leubner bit32 ret;
4354e1bc9a0SAchim Leubner
4364e1bc9a0SAchim Leubner ret = mpiMsgPrepare(circularQ, messagePtr, category, opCode, responseQueue,
4374e1bc9a0SAchim Leubner hiPriority);
4384e1bc9a0SAchim Leubner if (ret == AGSA_RC_SUCCESS)
4394e1bc9a0SAchim Leubner {
4404e1bc9a0SAchim Leubner /* update PI of inbound queue */
4414e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
4424e1bc9a0SAchim Leubner circularQ->PIPCIBar,
4434e1bc9a0SAchim Leubner circularQ->PIPCIOffset,
4444e1bc9a0SAchim Leubner circularQ->producerIdx);
4454e1bc9a0SAchim Leubner }
4464e1bc9a0SAchim Leubner return ret;
4474e1bc9a0SAchim Leubner }
4484e1bc9a0SAchim Leubner
mpiIBQMsgSend(mpiICQueue_t * circularQ)4494e1bc9a0SAchim Leubner GLOBAL void mpiIBQMsgSend(mpiICQueue_t *circularQ)
4504e1bc9a0SAchim Leubner {
4514e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
4524e1bc9a0SAchim Leubner circularQ->PIPCIBar,
4534e1bc9a0SAchim Leubner circularQ->PIPCIOffset,
4544e1bc9a0SAchim Leubner circularQ->producerIdx);
4554e1bc9a0SAchim Leubner }
4564e1bc9a0SAchim Leubner #else /* FAST_IO_TEST */
4574e1bc9a0SAchim Leubner
4584e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
4594e1bc9a0SAchim Leubner bit32
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)4604e1bc9a0SAchim Leubner mpiMsgProduce(
4614e1bc9a0SAchim Leubner mpiICQueue_t *circularQ,
4624e1bc9a0SAchim Leubner void *messagePtr,
4634e1bc9a0SAchim Leubner mpiMsgCategory_t category,
4644e1bc9a0SAchim Leubner bit16 opCode,
4654e1bc9a0SAchim Leubner bit8 responseQueue,
4664e1bc9a0SAchim Leubner bit8 hiPriority
4674e1bc9a0SAchim Leubner )
4684e1bc9a0SAchim Leubner {
4694e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
4704e1bc9a0SAchim Leubner bit32 bc;
4714e1bc9a0SAchim Leubner bit32 Header = 0;
4724e1bc9a0SAchim Leubner bit32 hpriority = 0;
4734e1bc9a0SAchim Leubner
4744e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
4754e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4764e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
4774e1bc9a0SAchim Leubner
4784e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
4794e1bc9a0SAchim Leubner bit32 i;
4804e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4814e1bc9a0SAchim Leubner #endif /* SA_ENABLE_TRACE_FUNCTIONS */
4824e1bc9a0SAchim Leubner
4834e1bc9a0SAchim Leubner #ifdef MPI_DEBUG_TRACE_ENABLE
4844e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4854e1bc9a0SAchim Leubner #endif /* MPI_DEBUG_TRACE_ENABLE */
4864e1bc9a0SAchim Leubner
4874e1bc9a0SAchim Leubner #ifdef Need_agRootDefined
4884e1bc9a0SAchim Leubner agsaRoot_t *agRoot=circularQ->agRoot;
4894e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
4904e1bc9a0SAchim Leubner agsaLLRoot_t *saRoot = agNULL;
4914e1bc9a0SAchim Leubner saRoot = agRoot->sdkData;
4924e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
4934e1bc9a0SAchim Leubner
4944e1bc9a0SAchim Leubner #undef Need_agRootDefined
4954e1bc9a0SAchim Leubner #endif /* Need_agRootDefined */
4964e1bc9a0SAchim Leubner
4974e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgProduce\n"));
4984e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
4994e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
5004e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
5014e1bc9a0SAchim Leubner SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
5024e1bc9a0SAchim Leubner
5034e1bc9a0SAchim Leubner /* REB Start extra trace */
5044e1bc9a0SAchim Leubner smTraceFuncEnter(hpDBG_VERY_LOUD,"22");
5054e1bc9a0SAchim Leubner /* REB End extra trace */
5064e1bc9a0SAchim Leubner
5074e1bc9a0SAchim Leubner /* Obtains the address of the entire message buffer, including the header */
5084e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
5094e1bc9a0SAchim Leubner /* Read the BC from header, its stored in native endian format when message was allocated */
5104e1bc9a0SAchim Leubner /* intially */
5114e1bc9a0SAchim Leubner bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
5124e1bc9a0SAchim Leubner SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
5134e1bc9a0SAchim Leubner if (circularQ->priority)
5144e1bc9a0SAchim Leubner {
5154e1bc9a0SAchim Leubner hpriority = 1;
5164e1bc9a0SAchim Leubner }
5174e1bc9a0SAchim Leubner
5184e1bc9a0SAchim Leubner /* Checks the message is in "allocated" state */
5194e1bc9a0SAchim Leubner SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state (bc == 0)");
5204e1bc9a0SAchim Leubner
5214e1bc9a0SAchim Leubner Header = ((V_BIT << SHIFT31) |
5224e1bc9a0SAchim Leubner (hpriority << SHIFT30) |
5234e1bc9a0SAchim Leubner ((bc & BC_MASK) << SHIFT24) |
5244e1bc9a0SAchim Leubner ((responseQueue & OBID_MASK) << SHIFT16) |
5254e1bc9a0SAchim Leubner ((category & CAT_MASK) << SHIFT12 ) |
5264e1bc9a0SAchim Leubner (opCode & OPCODE_MASK));
5274e1bc9a0SAchim Leubner
5284e1bc9a0SAchim Leubner /* pre flush the cache line */
5294e1bc9a0SAchim Leubner ossaCachePreFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
5304e1bc9a0SAchim Leubner OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), Header);
5314e1bc9a0SAchim Leubner /* flush the cache line for IOMB */
5324e1bc9a0SAchim Leubner ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
5334e1bc9a0SAchim Leubner
5344e1bc9a0SAchim Leubner MPI_DEBUG_TRACE( circularQ->qNumber,
5354e1bc9a0SAchim Leubner ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
5364e1bc9a0SAchim Leubner MPI_DEBUG_TRACE_IBQ,
5374e1bc9a0SAchim Leubner (void *)msgHeader,
5384e1bc9a0SAchim Leubner circularQ->elementSize);
5394e1bc9a0SAchim Leubner
5404e1bc9a0SAchim Leubner ossaLogIomb(circularQ->agRoot,
5414e1bc9a0SAchim Leubner circularQ->qNumber,
5424e1bc9a0SAchim Leubner TRUE,
5434e1bc9a0SAchim Leubner (void *)msgHeader,
5444e1bc9a0SAchim Leubner circularQ->elementSize);
5454e1bc9a0SAchim Leubner
5464e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
5474e1bc9a0SAchim Leubner MPI_IBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
5484e1bc9a0SAchim Leubner #endif /* SALLSDK_DEBUG */
5494e1bc9a0SAchim Leubner /* REB Start extra trace */
5504e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
5514e1bc9a0SAchim Leubner smTrace(hpDBG_IOMB,"M1",circularQ->qNumber);
5524e1bc9a0SAchim Leubner /* TP:M1 circularQ->qNumber */
5534e1bc9a0SAchim Leubner for (i=0; i<((bit32)bc*(circularQ->elementSize/4)); i++)
5544e1bc9a0SAchim Leubner {
5554e1bc9a0SAchim Leubner /* The -sizeof(mpiMsgHeader_t) is to account for mpiMsgProduce adding the header to the pMessage pointer */
5564e1bc9a0SAchim Leubner smTrace(hpDBG_IOMB,"MD",*( ((bit32 *)((bit8 *)messagePtr - sizeof(mpiMsgHeader_t))) + i));
5574e1bc9a0SAchim Leubner /* TP:MD Inbound IOMB Dword */
5584e1bc9a0SAchim Leubner }
5594e1bc9a0SAchim Leubner #endif /* SA_ENABLE_TRACE_FUNCTIONS */
5604e1bc9a0SAchim Leubner
5614e1bc9a0SAchim Leubner /* update PI of inbound queue */
5624e1bc9a0SAchim Leubner
5634e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
5644e1bc9a0SAchim Leubner if(saRoot->BunchStarts_Enable)
5654e1bc9a0SAchim Leubner {
5664e1bc9a0SAchim Leubner if (circularQ->BunchStarts_QPending == 0)
5674e1bc9a0SAchim Leubner {
5684e1bc9a0SAchim Leubner // store tick value for 1st deferred IO only
5694e1bc9a0SAchim Leubner circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
5704e1bc9a0SAchim Leubner }
5714e1bc9a0SAchim Leubner // update queue's pending count
5724e1bc9a0SAchim Leubner circularQ->BunchStarts_QPending++;
5734e1bc9a0SAchim Leubner
5744e1bc9a0SAchim Leubner // update global pending count
5754e1bc9a0SAchim Leubner saRoot->BunchStarts_Pending++;
5764e1bc9a0SAchim Leubner
5774e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgProduce: BunchStarts - Global Pending %d\n", saRoot->BunchStarts_Pending));
5784e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgProduce: BunchStarts - QPending %d, Q-%d\n", circularQ->BunchStarts_QPending, circularQ->qNumber));
5794e1bc9a0SAchim Leubner smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "22");
5804e1bc9a0SAchim Leubner
5814e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
5824e1bc9a0SAchim Leubner }
5834e1bc9a0SAchim Leubner
5844e1bc9a0SAchim Leubner saRoot->BunchStarts_Pending = 0;
5854e1bc9a0SAchim Leubner circularQ->BunchStarts_QPending = 0;
5864e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
5874e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
5884e1bc9a0SAchim Leubner circularQ->PIPCIBar,
5894e1bc9a0SAchim Leubner circularQ->PIPCIOffset,
5904e1bc9a0SAchim Leubner circularQ->producerIdx);
5914e1bc9a0SAchim Leubner
5924e1bc9a0SAchim Leubner smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "22");
5934e1bc9a0SAchim Leubner
5944e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
5954e1bc9a0SAchim Leubner } /* mpiMsgProduce */
5964e1bc9a0SAchim Leubner #endif /* FAST_IO_TEST */
5974e1bc9a0SAchim Leubner
5984e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
5994e1bc9a0SAchim Leubner
mpiMsgProduceBunch(agsaLLRoot_t * saRoot)6004e1bc9a0SAchim Leubner void mpiMsgProduceBunch( agsaLLRoot_t *saRoot)
6014e1bc9a0SAchim Leubner {
6024e1bc9a0SAchim Leubner mpiICQueue_t *circularQ;
6034e1bc9a0SAchim Leubner bit32 inq;
6044e1bc9a0SAchim Leubner
6054e1bc9a0SAchim Leubner for(inq=0; ((inq < saRoot->QueueConfig.numInboundQueues) && saRoot->BunchStarts_Pending); inq++)
6064e1bc9a0SAchim Leubner {
6074e1bc9a0SAchim Leubner circularQ= &saRoot->inboundQueue[inq];
6084e1bc9a0SAchim Leubner /* If any pending IOs present then either process if BunchStarts_Threshold
6094e1bc9a0SAchim Leubner * IO limit reached or if the timer has popped
6104e1bc9a0SAchim Leubner */
6114e1bc9a0SAchim Leubner if (circularQ->BunchStarts_QPending &&
6124e1bc9a0SAchim Leubner ((circularQ->BunchStarts_QPending >= saRoot->BunchStarts_Threshold) ||
6134e1bc9a0SAchim Leubner ((saRoot->timeTick - circularQ->BunchStarts_QPendingTick) >= saRoot->BunchStarts_TimeoutTicks))
6144e1bc9a0SAchim Leubner )
6154e1bc9a0SAchim Leubner {
6164e1bc9a0SAchim Leubner if(circularQ->qNumber != inq)
6174e1bc9a0SAchim Leubner {
6184e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgProduceBunch:circularQ->qNumber(%d) != inq(%d)\n",circularQ->qNumber, inq));
6194e1bc9a0SAchim Leubner }
6204e1bc9a0SAchim Leubner
6214e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgProduceBunch: IQ=%d, PI=%d\n", inq, circularQ->producerIdx));
6224e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgProduceBunch: Qpending=%d, TotPending=%d\n", circularQ->BunchStarts_QPending, saRoot->BunchStarts_Pending));
6234e1bc9a0SAchim Leubner
6244e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
6254e1bc9a0SAchim Leubner circularQ->PIPCIBar,
6264e1bc9a0SAchim Leubner circularQ->PIPCIOffset,
6274e1bc9a0SAchim Leubner circularQ->producerIdx);
6284e1bc9a0SAchim Leubner
6294e1bc9a0SAchim Leubner // update global pending count
6304e1bc9a0SAchim Leubner saRoot->BunchStarts_Pending -= circularQ->BunchStarts_QPending;
6314e1bc9a0SAchim Leubner
6324e1bc9a0SAchim Leubner // clear current queue's pending count after processing
6334e1bc9a0SAchim Leubner circularQ->BunchStarts_QPending = 0;
6344e1bc9a0SAchim Leubner circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
6354e1bc9a0SAchim Leubner }
6364e1bc9a0SAchim Leubner }
6374e1bc9a0SAchim Leubner }
6384e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
6394e1bc9a0SAchim Leubner
6404e1bc9a0SAchim Leubner /*******************************************************************************/
6414e1bc9a0SAchim Leubner /** \fn mpiMsgConsume(mpiOCQueue_t *circularQ, void *messagePtr1,
6424e1bc9a0SAchim Leubner * mpiMsgCategory_t * pCategory, bit16 * pOpCode, bit8 * pBC)
6434e1bc9a0SAchim Leubner * \brief Get a received message
6444e1bc9a0SAchim Leubner * \param circularQ Pointer to a outbound queue
6454e1bc9a0SAchim Leubner * \param messagePtr1 Pointer to the returned message buffer or NULL if no valid message
6464e1bc9a0SAchim Leubner * \param pCategory Pointer to Message category (ETHERNET, FC, SAS-SATA, SCSI)
6474e1bc9a0SAchim Leubner * \param pOpCode Pointer to Message operation code
6484e1bc9a0SAchim Leubner * \param pBC Pointer to buffer count
6494e1bc9a0SAchim Leubner *
6504e1bc9a0SAchim Leubner * Consume a receive message in the specified outbound queue
6514e1bc9a0SAchim Leubner *
6524e1bc9a0SAchim Leubner * Return:
6534e1bc9a0SAchim Leubner * AGSA_RC_SUCCESS if the message has been retrieved succesfully
6544e1bc9a0SAchim Leubner * AGSA_RC_BUSY if the circular is empty
6554e1bc9a0SAchim Leubner */
6564e1bc9a0SAchim Leubner /*******************************************************************************/
6574e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
6584e1bc9a0SAchim Leubner bit32
mpiMsgConsume(mpiOCQueue_t * circularQ,void ** messagePtr1,mpiMsgCategory_t * pCategory,bit16 * pOpCode,bit8 * pBC)6594e1bc9a0SAchim Leubner mpiMsgConsume(
6604e1bc9a0SAchim Leubner mpiOCQueue_t *circularQ,
6614e1bc9a0SAchim Leubner void ** messagePtr1,
6624e1bc9a0SAchim Leubner mpiMsgCategory_t *pCategory,
6634e1bc9a0SAchim Leubner bit16 *pOpCode,
6644e1bc9a0SAchim Leubner bit8 *pBC
6654e1bc9a0SAchim Leubner )
6664e1bc9a0SAchim Leubner {
6674e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
6684e1bc9a0SAchim Leubner bit32 msgHeader_tmp;
6694e1bc9a0SAchim Leubner
6704e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
6714e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
6724e1bc9a0SAchim Leubner SA_ASSERT(NULL != pCategory, "pCategory argument cannot be null");
6734e1bc9a0SAchim Leubner SA_ASSERT(NULL != pOpCode, "pOpCode argument cannot be null");
6744e1bc9a0SAchim Leubner SA_ASSERT(NULL != pBC, "pBC argument cannot be null");
6754e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
6764e1bc9a0SAchim Leubner
6774e1bc9a0SAchim Leubner do
6784e1bc9a0SAchim Leubner {
6794e1bc9a0SAchim Leubner /* If there are not-yet-delivered messages ... */
6804e1bc9a0SAchim Leubner if(circularQ->producerIdx != circularQ->consumerIdx)
6814e1bc9a0SAchim Leubner {
6824e1bc9a0SAchim Leubner /* Get the pointer to the circular queue buffer element */
6834e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*) ((bit8 *)(circularQ->memoryRegion.virtPtr) + circularQ->consumerIdx * circularQ->elementSize);
6844e1bc9a0SAchim Leubner
6854e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
6864e1bc9a0SAchim Leubner if (!loopback)
6874e1bc9a0SAchim Leubner #endif
6884e1bc9a0SAchim Leubner /* invalidate the cache line of IOMB */
6894e1bc9a0SAchim Leubner ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize);
6904e1bc9a0SAchim Leubner
6914e1bc9a0SAchim Leubner
6924e1bc9a0SAchim Leubner /* read header */
6934e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &msgHeader_tmp, msgHeader, 0);
6944e1bc9a0SAchim Leubner
6954e1bc9a0SAchim Leubner SA_DBG4(("mpiMsgConsume: process an IOMB, header=0x%x\n", msgHeader_tmp));
6964e1bc9a0SAchim Leubner
6974e1bc9a0SAchim Leubner SA_ASSERT(0 != (msgHeader_tmp & HEADER_BC_MASK), "The bc field in the header is 0");
6984e1bc9a0SAchim Leubner #ifdef TEST
6994e1bc9a0SAchim Leubner /* for debugging */
7004e1bc9a0SAchim Leubner if (0 == (msgHeader_tmp & HEADER_BC_MASK))
7014e1bc9a0SAchim Leubner {
7024e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
7034e1bc9a0SAchim Leubner circularQ->consumerIdx = (circularQ->consumerIdx + 1) % circularQ->numElements;
7044e1bc9a0SAchim Leubner /* update the CI of outbound queue - skip this blank IOMB, for test only */
7054e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
7064e1bc9a0SAchim Leubner circularQ->CIPCIBar,
7074e1bc9a0SAchim Leubner circularQ->CIPCIOffset,
7084e1bc9a0SAchim Leubner circularQ->consumerIdx);
7094e1bc9a0SAchim Leubner return AGSA_RC_FAILURE;
7104e1bc9a0SAchim Leubner }
7114e1bc9a0SAchim Leubner #endif
7124e1bc9a0SAchim Leubner /* get message pointer of valid entry */
7134e1bc9a0SAchim Leubner if (0 != (msgHeader_tmp & HEADER_V_MASK))
7144e1bc9a0SAchim Leubner {
7154e1bc9a0SAchim Leubner SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap around");
7164e1bc9a0SAchim Leubner
7174e1bc9a0SAchim Leubner if (OPC_OUB_SKIP_ENTRY != (msgHeader_tmp & OPCODE_MASK))
7184e1bc9a0SAchim Leubner {
7194e1bc9a0SAchim Leubner /* ... return the message payload */
7204e1bc9a0SAchim Leubner *messagePtr1 = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
7214e1bc9a0SAchim Leubner *pCategory = (mpiMsgCategory_t)(msgHeader_tmp >> SHIFT12) & CAT_MASK;
7224e1bc9a0SAchim Leubner *pOpCode = (bit16)(msgHeader_tmp & OPCODE_MASK);
7234e1bc9a0SAchim Leubner *pBC = (bit8)((msgHeader_tmp >> SHIFT24) & BC_MASK);
7244e1bc9a0SAchim Leubner
7254e1bc9a0SAchim Leubner /* invalidate the cache line for IOMB */
7264e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
7274e1bc9a0SAchim Leubner if (!loopback)
7284e1bc9a0SAchim Leubner #endif
7294e1bc9a0SAchim Leubner ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, (*pBC - 1) * circularQ->elementSize);
7304e1bc9a0SAchim Leubner
7314e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
7324e1bc9a0SAchim Leubner SA_DBG3(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
7334e1bc9a0SAchim Leubner MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
7344e1bc9a0SAchim Leubner #endif
7354e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
7364e1bc9a0SAchim Leubner }
7374e1bc9a0SAchim Leubner else
7384e1bc9a0SAchim Leubner {
7394e1bc9a0SAchim Leubner SA_DBG3(("mpiMsgConsume: SKIP_ENTRIES_IOMB BC=%d\n", (msgHeader_tmp >> SHIFT24) & BC_MASK));
7404e1bc9a0SAchim Leubner /* Updated comsumerIdx and skip it */
7414e1bc9a0SAchim Leubner circularQ->consumerIdx = (circularQ->consumerIdx + ((msgHeader_tmp >> SHIFT24) & BC_MASK)) % circularQ->numElements;
7424e1bc9a0SAchim Leubner /* clean header to 0 */
7434e1bc9a0SAchim Leubner msgHeader_tmp = 0;
7444e1bc9a0SAchim Leubner /*ossaSingleThreadedEnter(agRoot, LL_IOREQ_OBQ_LOCK);*/
7454e1bc9a0SAchim Leubner
7464e1bc9a0SAchim Leubner OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
7474e1bc9a0SAchim Leubner
7484e1bc9a0SAchim Leubner /* update the CI of outbound queue */
7494e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
7504e1bc9a0SAchim Leubner circularQ->CIPCIBar,
7514e1bc9a0SAchim Leubner circularQ->CIPCIOffset,
7524e1bc9a0SAchim Leubner circularQ->consumerIdx);
7534e1bc9a0SAchim Leubner /* Update the producer index */
7544e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
7554e1bc9a0SAchim Leubner /*ossaSingleThreadedLeave(agRoot, LL_IOREQ_OBQ_LOCK); */
7564e1bc9a0SAchim Leubner }
7574e1bc9a0SAchim Leubner }
7584e1bc9a0SAchim Leubner else
7594e1bc9a0SAchim Leubner {
7604e1bc9a0SAchim Leubner /* V bit is not set */
7614e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
7624e1bc9a0SAchim Leubner agsaRoot_t *agRoot=circularQ->agRoot;
7634e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgConsume: V bit not set, PI=%d CI=%d msgHeader=%p\n", circularQ->producerIdx, circularQ->consumerIdx,(void *)msgHeader));
7644e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgConsume: V bit not set, 0x%08X Q=%d \n", msgHeader_tmp, circularQ->qNumber));
7654e1bc9a0SAchim Leubner
7664e1bc9a0SAchim Leubner MPI_DEBUG_TRACE(MPI_DEBUG_TRACE_QNUM_ERROR + circularQ->qNumber,
7674e1bc9a0SAchim Leubner ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
7684e1bc9a0SAchim Leubner MPI_DEBUG_TRACE_OBQ,
7694e1bc9a0SAchim Leubner (void *)(((bit8*)msgHeader) - sizeof(mpiMsgHeader_t)),
7704e1bc9a0SAchim Leubner circularQ->elementSize);
7714e1bc9a0SAchim Leubner
7724e1bc9a0SAchim Leubner circularQ->consumerIdx = circularQ->consumerIdx % circularQ->numElements;
7734e1bc9a0SAchim Leubner circularQ->consumerIdx ++;
7744e1bc9a0SAchim Leubner OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
7754e1bc9a0SAchim Leubner ossaHwRegWriteExt(agRoot,
7764e1bc9a0SAchim Leubner circularQ->CIPCIBar,
7774e1bc9a0SAchim Leubner circularQ->CIPCIOffset,
7784e1bc9a0SAchim Leubner circularQ->consumerIdx);
7794e1bc9a0SAchim Leubner MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
7804e1bc9a0SAchim Leubner #endif
7814e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgConsume: V bit is not set!!!!! HW CI=%d\n", ossaHwRegReadExt(circularQ->agRoot, circularQ->CIPCIBar, circularQ->CIPCIOffset) ));
7824e1bc9a0SAchim Leubner SA_ASSERT(0, "V bit is not set");
7834e1bc9a0SAchim Leubner return AGSA_RC_FAILURE;
7844e1bc9a0SAchim Leubner }
7854e1bc9a0SAchim Leubner }
7864e1bc9a0SAchim Leubner else
7874e1bc9a0SAchim Leubner {
7884e1bc9a0SAchim Leubner /* Update the producer index from SPC */
7894e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
7904e1bc9a0SAchim Leubner }
7914e1bc9a0SAchim Leubner } while(circularQ->producerIdx != circularQ->consumerIdx); /* while we don't have any more not-yet-delivered message */
7924e1bc9a0SAchim Leubner
7934e1bc9a0SAchim Leubner #ifdef TEST
7944e1bc9a0SAchim Leubner SA_DBG4(("mpiMsgConsume: Outbound queue is empty.\n"));
7954e1bc9a0SAchim Leubner #endif
7964e1bc9a0SAchim Leubner
7974e1bc9a0SAchim Leubner /* report empty */
7984e1bc9a0SAchim Leubner return AGSA_RC_BUSY;
7994e1bc9a0SAchim Leubner }
8004e1bc9a0SAchim Leubner
8014e1bc9a0SAchim Leubner /*******************************************************************************/
8024e1bc9a0SAchim Leubner /** \fn mpiMsgFreeSet(mpiOCQueue_t *circularQ, void *messagePtr)
8034e1bc9a0SAchim Leubner * \brief Returns a received message to the outbound queue
8044e1bc9a0SAchim Leubner * \param circularQ Pointer to an outbound queue
8054e1bc9a0SAchim Leubner * \param messagePtr1 Pointer to the returned message buffer to free
8064e1bc9a0SAchim Leubner * \param messagePtr2 Pointer to the returned message buffer to free if bc > 1
8074e1bc9a0SAchim Leubner *
808*cef367e6SEitan Adler * Returns consumed and processed message to the specified outbounf queue
8094e1bc9a0SAchim Leubner *
8104e1bc9a0SAchim Leubner * Return:
8114e1bc9a0SAchim Leubner * AGSA_RC_SUCCESS if the message has been returned succesfully
8124e1bc9a0SAchim Leubner */
8134e1bc9a0SAchim Leubner /*******************************************************************************/
8144e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
8154e1bc9a0SAchim Leubner bit32
mpiMsgFreeSet(mpiOCQueue_t * circularQ,void * messagePtr1,bit8 bc)8164e1bc9a0SAchim Leubner mpiMsgFreeSet(
8174e1bc9a0SAchim Leubner mpiOCQueue_t *circularQ,
8184e1bc9a0SAchim Leubner void *messagePtr1,
8194e1bc9a0SAchim Leubner bit8 bc
8204e1bc9a0SAchim Leubner )
8214e1bc9a0SAchim Leubner {
8224e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
8234e1bc9a0SAchim Leubner
8244e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgFreeSet\n"));
8254e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
8264e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
8274e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
8284e1bc9a0SAchim Leubner
8294e1bc9a0SAchim Leubner /* Obtains the address of the entire message buffer, including the header */
8304e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr1) - sizeof(mpiMsgHeader_t));
8314e1bc9a0SAchim Leubner
8324e1bc9a0SAchim Leubner if ( ((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize)) != msgHeader)
8334e1bc9a0SAchim Leubner {
8344e1bc9a0SAchim Leubner /* IOMB of CI points mismatch with Message Header - should never happened */
8354e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgFreeSet: Wrong CI, Q %d ConsumeIdx = %d msgHeader 0x%08x\n",circularQ->qNumber, circularQ->consumerIdx ,msgHeader->Header));
8364e1bc9a0SAchim Leubner SA_DBG1(("mpiMsgFreeSet: msgHeader %p != %p\n", msgHeader,((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize))));
8374e1bc9a0SAchim Leubner
8384e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
8394e1bc9a0SAchim Leubner if (!loopback)
8404e1bc9a0SAchim Leubner #endif
8414e1bc9a0SAchim Leubner /* Update the producer index from SPC */
8424e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
8434e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
8444e1bc9a0SAchim Leubner SA_DBG3(("mpiMsgFreeSet: ProducerIdx = %d\n", circularQ->producerIdx));
8454e1bc9a0SAchim Leubner #endif
8464e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
8474e1bc9a0SAchim Leubner }
8484e1bc9a0SAchim Leubner
8494e1bc9a0SAchim Leubner /* ... free the circular queue buffer elements associated with the message ... */
8504e1bc9a0SAchim Leubner /*... by incrementing the consumer index (with wrap arround) */
8514e1bc9a0SAchim Leubner circularQ->consumerIdx = (circularQ->consumerIdx + bc) % circularQ->numElements;
8524e1bc9a0SAchim Leubner
8534e1bc9a0SAchim Leubner /* Invalidates this circular queue buffer element */
8544e1bc9a0SAchim Leubner
8554e1bc9a0SAchim Leubner msgHeader->Header &= ~HEADER_V_MASK; /* Clear Valid bit to indicate IOMB consumed by host */
8564e1bc9a0SAchim Leubner SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap arround");
8574e1bc9a0SAchim Leubner
8584e1bc9a0SAchim Leubner /* update the CI of outbound queue */
8594e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
8604e1bc9a0SAchim Leubner if (!loopback)
8614e1bc9a0SAchim Leubner #endif
8624e1bc9a0SAchim Leubner {
8634e1bc9a0SAchim Leubner ossaHwRegWriteExt(circularQ->agRoot,
8644e1bc9a0SAchim Leubner circularQ->CIPCIBar,
8654e1bc9a0SAchim Leubner circularQ->CIPCIOffset,
8664e1bc9a0SAchim Leubner circularQ->consumerIdx);
8674e1bc9a0SAchim Leubner
8684e1bc9a0SAchim Leubner /* Update the producer index from SPC */
8694e1bc9a0SAchim Leubner OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
8704e1bc9a0SAchim Leubner }
8714e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
8724e1bc9a0SAchim Leubner SA_DBG5(("mpiMsgFreeSet: CI=%d PI=%d\n", circularQ->consumerIdx, circularQ->producerIdx));
8734e1bc9a0SAchim Leubner #endif
8744e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
8754e1bc9a0SAchim Leubner }
8764e1bc9a0SAchim Leubner
8774e1bc9a0SAchim Leubner #ifdef TEST
mpiRotateQnumber(agsaRoot_t * agRoot)8784e1bc9a0SAchim Leubner GLOBAL bit32 mpiRotateQnumber(agsaRoot_t *agRoot)
8794e1bc9a0SAchim Leubner {
8804e1bc9a0SAchim Leubner agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
8814e1bc9a0SAchim Leubner bit32 denom;
8824e1bc9a0SAchim Leubner bit32 ret = 0;
8834e1bc9a0SAchim Leubner
8844e1bc9a0SAchim Leubner /* inbound queue number */
8854e1bc9a0SAchim Leubner saRoot->IBQnumber++;
8864e1bc9a0SAchim Leubner denom = saRoot->QueueConfig.numInboundQueues;
8874e1bc9a0SAchim Leubner if (saRoot->IBQnumber % denom == 0) /* % Qnumber*/
8884e1bc9a0SAchim Leubner {
8894e1bc9a0SAchim Leubner saRoot->IBQnumber = 0;
8904e1bc9a0SAchim Leubner }
8914e1bc9a0SAchim Leubner SA_DBG3(("mpiRotateQnumber: IBQnumber %d\n", saRoot->IBQnumber));
8924e1bc9a0SAchim Leubner
8934e1bc9a0SAchim Leubner /* outbound queue number */
8944e1bc9a0SAchim Leubner saRoot->OBQnumber++;
8954e1bc9a0SAchim Leubner denom = saRoot->QueueConfig.numOutboundQueues;
8964e1bc9a0SAchim Leubner if (saRoot->OBQnumber % denom == 0) /* % Qnumber*/
8974e1bc9a0SAchim Leubner {
8984e1bc9a0SAchim Leubner saRoot->OBQnumber = 0;
8994e1bc9a0SAchim Leubner }
9004e1bc9a0SAchim Leubner SA_DBG3(("mpiRotateQnumber: OBQnumber %d\n", saRoot->OBQnumber));
9014e1bc9a0SAchim Leubner
9024e1bc9a0SAchim Leubner ret = (saRoot->OBQnumber << SHIFT16) | saRoot->IBQnumber;
9034e1bc9a0SAchim Leubner return ret;
9044e1bc9a0SAchim Leubner }
9054e1bc9a0SAchim Leubner #endif
9064e1bc9a0SAchim Leubner
9074e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
mpiMsgProduceOQ(mpiOCQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)9084e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgProduceOQ(
9094e1bc9a0SAchim Leubner mpiOCQueue_t *circularQ,
9104e1bc9a0SAchim Leubner void *messagePtr,
9114e1bc9a0SAchim Leubner mpiMsgCategory_t category,
9124e1bc9a0SAchim Leubner bit16 opCode,
9134e1bc9a0SAchim Leubner bit8 responseQueue,
9144e1bc9a0SAchim Leubner bit8 hiPriority
9154e1bc9a0SAchim Leubner )
9164e1bc9a0SAchim Leubner {
9174e1bc9a0SAchim Leubner mpiMsgHeader_t *msgHeader;
9184e1bc9a0SAchim Leubner bit32 bc;
9194e1bc9a0SAchim Leubner bit32 Header = 0;
9204e1bc9a0SAchim Leubner bit32 hpriority = 0;
9214e1bc9a0SAchim Leubner
9224e1bc9a0SAchim Leubner SA_DBG4(("Entering function:mpiMsgProduceOQ\n"));
9234e1bc9a0SAchim Leubner SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
9244e1bc9a0SAchim Leubner SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
9254e1bc9a0SAchim Leubner SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
9264e1bc9a0SAchim Leubner " is 0");
9274e1bc9a0SAchim Leubner SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
9284e1bc9a0SAchim Leubner
9294e1bc9a0SAchim Leubner /* REB Start extra trace */
9304e1bc9a0SAchim Leubner smTraceFuncEnter(hpDBG_VERY_LOUD, "2I");
9314e1bc9a0SAchim Leubner /* REB End extra trace */
9324e1bc9a0SAchim Leubner
9334e1bc9a0SAchim Leubner /* Obtains the address of the entire message buffer, including the header */
9344e1bc9a0SAchim Leubner msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
9354e1bc9a0SAchim Leubner /* Read the BC from header, its stored in native endian format when message
9364e1bc9a0SAchim Leubner was allocated */
9374e1bc9a0SAchim Leubner /* intially */
9384e1bc9a0SAchim Leubner SA_DBG4(("mpiMsgProduceOQ: msgHeader %p opcode %d pi/ci %d / %d\n", msgHeader, opCode, circularQ->producerIdx, circularQ->consumerIdx));
9394e1bc9a0SAchim Leubner bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
9404e1bc9a0SAchim Leubner SA_DBG6(("mpiMsgProduceOQ: msgHeader bc %d\n", bc));
9414e1bc9a0SAchim Leubner if (circularQ->priority)
9424e1bc9a0SAchim Leubner hpriority = 1;
9434e1bc9a0SAchim Leubner
9444e1bc9a0SAchim Leubner /* Checks the message is in "allocated" state */
9454e1bc9a0SAchim Leubner SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
9464e1bc9a0SAchim Leubner "(bc == 0)");
9474e1bc9a0SAchim Leubner
9484e1bc9a0SAchim Leubner Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30) |
9494e1bc9a0SAchim Leubner ((bc & BC_MASK) << SHIFT24) |
9504e1bc9a0SAchim Leubner ((responseQueue & OBID_MASK) << SHIFT16) |
9514e1bc9a0SAchim Leubner ((category & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
9524e1bc9a0SAchim Leubner /* pre flush the IOMB cache line */
9534e1bc9a0SAchim Leubner //ossaCachePreFlush(circularQ->agRoot,
9544e1bc9a0SAchim Leubner // (void *)circularQ->memoryRegion.appHandle,
9554e1bc9a0SAchim Leubner // (void *)msgHeader, circularQ->elementSize * bc);
9564e1bc9a0SAchim Leubner OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
9574e1bc9a0SAchim Leubner Header), Header);
9584e1bc9a0SAchim Leubner
9594e1bc9a0SAchim Leubner /* flush the IOMB cache line */
9604e1bc9a0SAchim Leubner //ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
9614e1bc9a0SAchim Leubner // (void *)msgHeader, circularQ->elementSize * bc);
9624e1bc9a0SAchim Leubner
9634e1bc9a0SAchim Leubner MPI_DEBUG_TRACE( circularQ->qNumber,
9644e1bc9a0SAchim Leubner ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
9654e1bc9a0SAchim Leubner MPI_DEBUG_TRACE_OBQ,
9664e1bc9a0SAchim Leubner (void *)msgHeader,
9674e1bc9a0SAchim Leubner circularQ->elementSize);
9684e1bc9a0SAchim Leubner
9694e1bc9a0SAchim Leubner ossaLogIomb(circularQ->agRoot,
9704e1bc9a0SAchim Leubner circularQ->qNumber,
9714e1bc9a0SAchim Leubner TRUE,
9724e1bc9a0SAchim Leubner (void *)msgHeader,
9734e1bc9a0SAchim Leubner circularQ->elementSize);
9744e1bc9a0SAchim Leubner
9754e1bc9a0SAchim Leubner smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2I");
9764e1bc9a0SAchim Leubner return AGSA_RC_SUCCESS;
9774e1bc9a0SAchim Leubner } /* mpiMsgProduceOQ */
9784e1bc9a0SAchim Leubner #endif
9794e1bc9a0SAchim Leubner
980