1 /*******************************************************************************
2 **
3 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
4 *
5 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 *that the following conditions are met:
7 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8 *following disclaimer.
9 *2. Redistributions in binary form must reproduce the above copyright notice,
10 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
11 *with the distribution.
12 *
13 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
18 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21
22 ********************************************************************************/
23
24 /*******************************************************************************/
25 /*! \file mpi.c
26 * \brief The file is a MPI Libraries to implement the MPI functions
27 *
28 * The file implements the MPI Library functions.
29 *
30 */
31 /*******************************************************************************/
32 #include <sys/cdefs.h>
33 #include <dev/pms/config.h>
34
35 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
36
37 #ifdef SA_ENABLE_TRACE_FUNCTIONS
38 #ifdef siTraceFileID
39 #undef siTraceFileID
40 #endif
41 #define siTraceFileID 'A'
42 #endif
43
44 #ifdef LOOPBACK_MPI
45 extern int loopback;
46 #endif
47 /*******************************************************************************/
48
49 /*******************************************************************************/
50 /*******************************************************************************/
51 /* FUNCTIONS */
52 /*******************************************************************************/
53 /*******************************************************************************/
54 /** \fn void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
55 * \brief Retrieves the MPI layer resource requirements
56 * \param config MPI configuration for the Host MPI Message Unit
57 * \param memoryRequirement Returned data structure as defined by mpiMemReq_t
58 * that holds the different chunks of memory that are required
59 *
60 * The mpiRequirementsGet() function is used to determine the resource requirements
61 * for the SPC device interface
62 *
63 * Return: None
64 */
65 /*******************************************************************************/
mpiRequirementsGet(mpiConfig_t * config,mpiMemReq_t * memoryRequirement)66 void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
67 {
68 bit32 qIdx, numq;
69 mpiMemReq_t* memoryMap;
70 SA_DBG2(("Entering function:mpiRequirementsGet\n"));
71 SA_ASSERT((NULL != config), "config argument cannot be null");
72
73 memoryMap = memoryRequirement;
74 memoryMap->count = 0;
75
76 /* MPI Memory region 0 for MSGU(AAP1) Event Log for fw */
77 memoryMap->region[memoryMap->count].numElements = 1;
78 memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.eventLogSize;
79 memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.eventLogSize;
80 memoryMap->region[memoryMap->count].alignment = 32;
81 memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
82 SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
83 memoryMap->count++;
84
85 SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
86 /* MPI Memory region 1 for IOP Event Log for fw */
87 memoryMap->region[memoryMap->count].numElements = 1;
88 memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
89 memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
90 memoryMap->region[memoryMap->count].alignment = 32;
91 memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
92 SA_DBG2(("mpiRequirementsGet:IOPeventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
93 memoryMap->count++;
94
95 /* MPI Memory region 2 for consumer Index of inbound queues */
96 memoryMap->region[memoryMap->count].numElements = 1;
97 memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numInboundQueues;
98 memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numInboundQueues;
99 memoryMap->region[memoryMap->count].alignment = 4;
100 memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
101 SA_DBG2(("mpiRequirementsGet:numInboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
102 memoryMap->count++;
103
104 /* MPI Memory region 3 for producer Index of outbound queues */
105 memoryMap->region[memoryMap->count].numElements = 1;
106 memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numOutboundQueues;
107 memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numOutboundQueues;
108 memoryMap->region[memoryMap->count].alignment = 4;
109 memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
110 SA_DBG2(("mpiRequirementsGet:numOutboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
111 memoryMap->count++;
112
113 /* MPI Memory regions 4, ... for the inbound queues - depends on configuration */
114 numq = 0;
115 for(qIdx = 0; qIdx < config->numInboundQueues; qIdx++)
116 {
117 if(0 != config->inboundQueues[qIdx].numElements)
118 {
119 bit32 memSize = config->inboundQueues[qIdx].numElements * config->inboundQueues[qIdx].elementSize;
120 bit32 remainder = memSize & 127;
121
122 /* Calculate the size of this queue padded to 128 bytes */
123 if (remainder > 0)
124 {
125 memSize += (128 - remainder);
126 }
127
128 if (numq == 0)
129 {
130 memoryMap->region[memoryMap->count].numElements = 1;
131 memoryMap->region[memoryMap->count].elementSize = memSize;
132 memoryMap->region[memoryMap->count].totalLength = memSize;
133 memoryMap->region[memoryMap->count].alignment = 128;
134 memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
135 }
136 else
137 {
138 memoryMap->region[memoryMap->count].elementSize += memSize;
139 memoryMap->region[memoryMap->count].totalLength += memSize;
140 }
141
142 numq++;
143
144 if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
145 (qIdx == (bit32)(config->numInboundQueues - 1)))
146 {
147 SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].elementSize = %d\n",
148 memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
149 SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].numElements = %d\n",
150 memoryMap->count, memoryMap->region[memoryMap->count].numElements));
151
152 memoryMap->count++;
153 numq = 0;
154 }
155 }
156 }
157
158 /* MPI Memory regions for the outbound queues - depends on configuration */
159 numq = 0;
160 for(qIdx = 0; qIdx < config->numOutboundQueues; qIdx++)
161 {
162 if(0 != config->outboundQueues[qIdx].numElements)
163 {
164 bit32 memSize = config->outboundQueues[qIdx].numElements * config->outboundQueues[qIdx].elementSize;
165 bit32 remainder = memSize & 127;
166
167 /* Calculate the size of this queue padded to 128 bytes */
168 if (remainder > 0)
169 {
170 memSize += (128 - remainder);
171 }
172
173 if (numq == 0)
174 {
175 memoryMap->region[memoryMap->count].numElements = 1;
176 memoryMap->region[memoryMap->count].elementSize = memSize;
177 memoryMap->region[memoryMap->count].totalLength = memSize;
178 memoryMap->region[memoryMap->count].alignment = 128;
179 memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
180 }
181 else
182 {
183 memoryMap->region[memoryMap->count].elementSize += memSize;
184 memoryMap->region[memoryMap->count].totalLength += memSize;
185 }
186
187 numq++;
188
189 if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
190 (qIdx == (bit32)(config->numOutboundQueues - 1)))
191 {
192 SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].elementSize = %d\n",
193 memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
194 SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].numElements = %d\n",
195 memoryMap->count, memoryMap->region[memoryMap->count].numElements));
196
197
198 memoryMap->count++;
199 numq = 0;
200 }
201 }
202 }
203
204 }
205
206 /*******************************************************************************/
207 /** \fn mpiMsgFreeGet(mpiICQueue_t *circularQ, bit16 messageSize, void** messagePtr)
208 * \brief Retrieves a free message buffer from an inbound queue
209 * \param circularQ Pointer to an inbound circular queue
210 * \param messageSize Requested message size in bytes - only support 64 bytes/element
211 * \param messagePtr Pointer to the free message buffer payload (not including message header) or NULL if no free message buffers are available
212 *
213 * This function is used to retrieve a free message buffer for the given inbound queue of at least
214 * messageSize bytes.
215 * The caller can use the returned buffer to construct the message and then call mpiMsgProduce()
216 * to deliver the message to the device message unit or mpiMsgInvalidate() if the message buffer
217 * is not going to be used
218 *
219 * Return:
220 * AGSA_RC_SUCCESS if messagePtr contains a valid message buffer pointer
221 * AGSA_RC_FAILURE if messageSize larger than the elementSize of queue
222 * AGSA_RC_BUSY if there are not free message buffers (Queue full)
223 */
224 /*******************************************************************************/
225 GLOBAL FORCEINLINE
226 bit32
mpiMsgFreeGet(mpiICQueue_t * circularQ,bit16 messageSize,void ** messagePtr)227 mpiMsgFreeGet(
228 mpiICQueue_t *circularQ,
229 bit16 messageSize,
230 void** messagePtr
231 )
232 {
233 bit32 offset;
234 agsaRoot_t *agRoot=circularQ->agRoot;
235 mpiMsgHeader_t *msgHeader;
236 bit8 bcCount = 1; /* only support single buffer */
237
238 SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
239 SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
240 SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
241 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
242
243 /* Checks is the requested message size can be allocated in this queue */
244 if(messageSize > circularQ->elementSize)
245 {
246 SA_DBG1(("mpiMsgFreeGet: Message Size (%d) is larger than Q element size (%d)\n",messageSize,circularQ->elementSize));
247 return AGSA_RC_FAILURE;
248 }
249
250 /* Stores the new consumer index */
251 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
252 /* if inbound queue is full, return busy */
253 /* This queue full logic may only works for bc == 1 ( == ) */
254 /* ( pi + bc ) % size > ci not fully works for bc > 1 */
255 /* To do - support bc > 1 case and wrap around case */
256 if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
257 {
258 *messagePtr = NULL;
259 smTrace(hpDBG_VERY_LOUD,"Za", (((circularQ->producerIdx & 0xFFF) << 16) | (circularQ->consumerIdx & 0xFFF) ));
260 /* TP:Za IQ PI CI */
261 ossaHwRegRead(agRoot, MSGU_HOST_SCRATCH_PAD_0);
262 SA_DBG1(("mpiMsgFreeGet: %d + %d == %d AGSA_RC_BUSY\n",circularQ->producerIdx,bcCount,circularQ->consumerIdx));
263
264 return AGSA_RC_BUSY;
265 }
266
267 smTrace(hpDBG_VERY_LOUD,"Zb", (((circularQ->producerIdx & 0xFFF) << 16) | (circularQ->consumerIdx & 0xFFF) ));
268 /* TP:Zb IQ PI CI */
269
270
271 /* get memory IOMB buffer address */
272 offset = circularQ->producerIdx * circularQ->elementSize;
273 /* increment to next bcCount element */
274 circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
275
276 /* Adds that distance to the base of the region virtual address plus the message header size*/
277 msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
278
279 SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
280
281 /* Sets the message buffer in "allocated" state */
282 /* bc always is 1 for inbound queue */
283 /* temporarily store it in the native endian format, when the rest of the */
284 /* header is filled, this would be converted to Little Endian */
285 msgHeader->Header = (1<<24);
286 *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
287
288 return AGSA_RC_SUCCESS;
289 }
290
291 #ifdef LOOPBACK_MPI
mpiMsgFreeGetOQ(mpiOCQueue_t * circularQ,bit16 messageSize,void ** messagePtr)292 GLOBAL bit32 mpiMsgFreeGetOQ(mpiOCQueue_t *circularQ, bit16 messageSize, void** messagePtr)
293 {
294 bit32 offset;
295 mpiMsgHeader_t *msgHeader;
296 bit8 bcCount = 1; /* only support single buffer */
297
298 SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
299 SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
300 SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
301 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
302
303 /* Checks is the requested message size can be allocated in this queue */
304 if(messageSize > circularQ->elementSize)
305 {
306 SA_DBG1(("mpiMsgFreeGet: Message Size is not fit in\n"));
307 return AGSA_RC_FAILURE;
308 }
309
310 /* Stores the new consumer index */
311 //OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
312 /* if inbound queue is full, return busy */
313 /* This queue full logic may only works for bc == 1 ( == ) */
314 /* ( pi + bc ) % size > ci not fully works for bc > 1 */
315 /* To do - support bc > 1 case and wrap around case */
316 if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
317 {
318 *messagePtr = NULL;
319 return AGSA_RC_BUSY;
320 }
321
322 /* get memory IOMB buffer address */
323 offset = circularQ->producerIdx * circularQ->elementSize;
324 /* increment to next bcCount element */
325 circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
326
327 /* Adds that distance to the base of the region virtual address plus the message header size*/
328 msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
329
330 SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
331
332 /* Sets the message buffer in "allocated" state */
333 /* bc always is 1 for inbound queue */
334 /* temporarily store it in the native endian format, when the rest of the */
335 /* header is filled, this would be converted to Little Endian */
336 msgHeader->Header = (1<<24);
337 *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
338
339 return AGSA_RC_SUCCESS;
340 }
341 #endif
342
343 /*******************************************************************************/
344 /** \fn mpiMsgProduce(mpiICQueue_t *circularQ, void *messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue)
345 * \brief Add a header of IOMB then send to a inbound queue and update the Producer index
346 * \param circularQ Pointer to an inbound queue
347 * \param messagePtr Pointer to the message buffer payload (not including message header))
348 * \param category Message category (ETHERNET, FC, SAS-SATA, SCSI)
349 * \param opCode Message operation code
350 * \param responseQueue If the message requires response, this paramater indicates the outbound queue for the response
351 *
352 * This function is used to sumit a message buffer, previously obtained from mpiMsgFreeGet()
353 * function call, to the given Inbound queue
354 *
355 * Return:
356 * AGSA_RC_SUCCESS if the message has been posted succesfully
357 */
358 /*******************************************************************************/
359 #ifdef FAST_IO_TEST
mpiMsgPrepare(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)360 GLOBAL bit32 mpiMsgPrepare(
361 mpiICQueue_t *circularQ,
362 void *messagePtr,
363 mpiMsgCategory_t category,
364 bit16 opCode,
365 bit8 responseQueue,
366 bit8 hiPriority
367 )
368 {
369 mpiMsgHeader_t *msgHeader;
370 bit32 bc;
371 bit32 Header = 0;
372 bit32 hpriority = 0;
373
374 SA_DBG4(("Entering function:mpiMsgProduce\n"));
375 SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
376 SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
377 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
378 " is 0");
379 SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
380
381 /* Obtains the address of the entire message buffer, including the header */
382 msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
383 /* Read the BC from header, its stored in native endian format when message
384 was allocated */
385 /* intially */
386 bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
387 SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
388 if (circularQ->priority)
389 hpriority = 1;
390
391 /* Checks the message is in "allocated" state */
392 SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
393 "(bc == 0)");
394
395 Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30) |
396 ((bc & BC_MASK) << SHIFT24) |
397 ((responseQueue & OBID_MASK) << SHIFT16) |
398 ((category & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
399
400 /* pre flush the IOMB cache line */
401 ossaCachePreFlush(circularQ->agRoot,
402 (void *)circularQ->memoryRegion.appHandle,
403 (void *)msgHeader, circularQ->elementSize * bc);
404 OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
405 Header), Header);
406 /* flush the IOMB cache line */
407 ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
408 (void *)msgHeader, circularQ->elementSize * bc);
409
410 MPI_DEBUG_TRACE( circularQ->qNumber,
411 ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
412 MPI_DEBUG_TRACE_IBQ,
413 (void *)msgHeader,
414 circularQ->elementSize);
415
416 ossaLogIomb(circularQ->agRoot,
417 circularQ->qNumber,
418 TRUE,
419 (void *)msgHeader,
420 circularQ->elementSize);
421
422 return AGSA_RC_SUCCESS;
423 } /* mpiMsgPrepare */
424
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)425 GLOBAL bit32 mpiMsgProduce(
426 mpiICQueue_t *circularQ,
427 void *messagePtr,
428 mpiMsgCategory_t category,
429 bit16 opCode,
430 bit8 responseQueue,
431 bit8 hiPriority
432 )
433 {
434 bit32 ret;
435
436 ret = mpiMsgPrepare(circularQ, messagePtr, category, opCode, responseQueue,
437 hiPriority);
438 if (ret == AGSA_RC_SUCCESS)
439 {
440 /* update PI of inbound queue */
441 ossaHwRegWriteExt(circularQ->agRoot,
442 circularQ->PIPCIBar,
443 circularQ->PIPCIOffset,
444 circularQ->producerIdx);
445 }
446 return ret;
447 }
448
mpiIBQMsgSend(mpiICQueue_t * circularQ)449 GLOBAL void mpiIBQMsgSend(mpiICQueue_t *circularQ)
450 {
451 ossaHwRegWriteExt(circularQ->agRoot,
452 circularQ->PIPCIBar,
453 circularQ->PIPCIOffset,
454 circularQ->producerIdx);
455 }
456 #else /* FAST_IO_TEST */
457
458 GLOBAL FORCEINLINE
459 bit32
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)460 mpiMsgProduce(
461 mpiICQueue_t *circularQ,
462 void *messagePtr,
463 mpiMsgCategory_t category,
464 bit16 opCode,
465 bit8 responseQueue,
466 bit8 hiPriority
467 )
468 {
469 mpiMsgHeader_t *msgHeader;
470 bit32 bc;
471 bit32 Header = 0;
472 bit32 hpriority = 0;
473
474 #ifdef SA_FW_TEST_BUNCH_STARTS
475 #define Need_agRootDefined 1
476 #endif /* SA_FW_TEST_BUNCH_STARTS */
477
478 #ifdef SA_ENABLE_TRACE_FUNCTIONS
479 bit32 i;
480 #define Need_agRootDefined 1
481 #endif /* SA_ENABLE_TRACE_FUNCTIONS */
482
483 #ifdef MPI_DEBUG_TRACE_ENABLE
484 #define Need_agRootDefined 1
485 #endif /* MPI_DEBUG_TRACE_ENABLE */
486
487 #ifdef Need_agRootDefined
488 agsaRoot_t *agRoot=circularQ->agRoot;
489 #ifdef SA_FW_TEST_BUNCH_STARTS
490 agsaLLRoot_t *saRoot = agNULL;
491 saRoot = agRoot->sdkData;
492 #endif /* SA_FW_TEST_BUNCH_STARTS */
493
494 #undef Need_agRootDefined
495 #endif /* Need_agRootDefined */
496
497 SA_DBG4(("Entering function:mpiMsgProduce\n"));
498 SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
499 SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
500 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
501 SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
502
503 /* REB Start extra trace */
504 smTraceFuncEnter(hpDBG_VERY_LOUD,"22");
505 /* REB End extra trace */
506
507 /* Obtains the address of the entire message buffer, including the header */
508 msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
509 /* Read the BC from header, its stored in native endian format when message was allocated */
510 /* intially */
511 bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
512 SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
513 if (circularQ->priority)
514 {
515 hpriority = 1;
516 }
517
518 /* Checks the message is in "allocated" state */
519 SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state (bc == 0)");
520
521 Header = ((V_BIT << SHIFT31) |
522 (hpriority << SHIFT30) |
523 ((bc & BC_MASK) << SHIFT24) |
524 ((responseQueue & OBID_MASK) << SHIFT16) |
525 ((category & CAT_MASK) << SHIFT12 ) |
526 (opCode & OPCODE_MASK));
527
528 /* pre flush the cache line */
529 ossaCachePreFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
530 OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), Header);
531 /* flush the cache line for IOMB */
532 ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
533
534 MPI_DEBUG_TRACE( circularQ->qNumber,
535 ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
536 MPI_DEBUG_TRACE_IBQ,
537 (void *)msgHeader,
538 circularQ->elementSize);
539
540 ossaLogIomb(circularQ->agRoot,
541 circularQ->qNumber,
542 TRUE,
543 (void *)msgHeader,
544 circularQ->elementSize);
545
546 #if defined(SALLSDK_DEBUG)
547 MPI_IBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
548 #endif /* SALLSDK_DEBUG */
549 /* REB Start extra trace */
550 #ifdef SA_ENABLE_TRACE_FUNCTIONS
551 smTrace(hpDBG_IOMB,"M1",circularQ->qNumber);
552 /* TP:M1 circularQ->qNumber */
553 for (i=0; i<((bit32)bc*(circularQ->elementSize/4)); i++)
554 {
555 /* The -sizeof(mpiMsgHeader_t) is to account for mpiMsgProduce adding the header to the pMessage pointer */
556 smTrace(hpDBG_IOMB,"MD",*( ((bit32 *)((bit8 *)messagePtr - sizeof(mpiMsgHeader_t))) + i));
557 /* TP:MD Inbound IOMB Dword */
558 }
559 #endif /* SA_ENABLE_TRACE_FUNCTIONS */
560
561 /* update PI of inbound queue */
562
563 #ifdef SA_FW_TEST_BUNCH_STARTS
564 if(saRoot->BunchStarts_Enable)
565 {
566 if (circularQ->BunchStarts_QPending == 0)
567 {
568 // store tick value for 1st deferred IO only
569 circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
570 }
571 // update queue's pending count
572 circularQ->BunchStarts_QPending++;
573
574 // update global pending count
575 saRoot->BunchStarts_Pending++;
576
577 SA_DBG1(("mpiMsgProduce: BunchStarts - Global Pending %d\n", saRoot->BunchStarts_Pending));
578 SA_DBG1(("mpiMsgProduce: BunchStarts - QPending %d, Q-%d\n", circularQ->BunchStarts_QPending, circularQ->qNumber));
579 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "22");
580
581 return AGSA_RC_SUCCESS;
582 }
583
584 saRoot->BunchStarts_Pending = 0;
585 circularQ->BunchStarts_QPending = 0;
586 #endif /* SA_FW_TEST_BUNCH_STARTS */
587 ossaHwRegWriteExt(circularQ->agRoot,
588 circularQ->PIPCIBar,
589 circularQ->PIPCIOffset,
590 circularQ->producerIdx);
591
592 smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "22");
593
594 return AGSA_RC_SUCCESS;
595 } /* mpiMsgProduce */
596 #endif /* FAST_IO_TEST */
597
598 #ifdef SA_FW_TEST_BUNCH_STARTS
599
mpiMsgProduceBunch(agsaLLRoot_t * saRoot)600 void mpiMsgProduceBunch( agsaLLRoot_t *saRoot)
601 {
602 mpiICQueue_t *circularQ;
603 bit32 inq;
604
605 for(inq=0; ((inq < saRoot->QueueConfig.numInboundQueues) && saRoot->BunchStarts_Pending); inq++)
606 {
607 circularQ= &saRoot->inboundQueue[inq];
608 /* If any pending IOs present then either process if BunchStarts_Threshold
609 * IO limit reached or if the timer has popped
610 */
611 if (circularQ->BunchStarts_QPending &&
612 ((circularQ->BunchStarts_QPending >= saRoot->BunchStarts_Threshold) ||
613 ((saRoot->timeTick - circularQ->BunchStarts_QPendingTick) >= saRoot->BunchStarts_TimeoutTicks))
614 )
615 {
616 if(circularQ->qNumber != inq)
617 {
618 SA_DBG1(("mpiMsgProduceBunch:circularQ->qNumber(%d) != inq(%d)\n",circularQ->qNumber, inq));
619 }
620
621 SA_DBG1(("mpiMsgProduceBunch: IQ=%d, PI=%d\n", inq, circularQ->producerIdx));
622 SA_DBG1(("mpiMsgProduceBunch: Qpending=%d, TotPending=%d\n", circularQ->BunchStarts_QPending, saRoot->BunchStarts_Pending));
623
624 ossaHwRegWriteExt(circularQ->agRoot,
625 circularQ->PIPCIBar,
626 circularQ->PIPCIOffset,
627 circularQ->producerIdx);
628
629 // update global pending count
630 saRoot->BunchStarts_Pending -= circularQ->BunchStarts_QPending;
631
632 // clear current queue's pending count after processing
633 circularQ->BunchStarts_QPending = 0;
634 circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
635 }
636 }
637 }
638 #endif /* SA_FW_TEST_BUNCH_STARTS */
639
640 /*******************************************************************************/
641 /** \fn mpiMsgConsume(mpiOCQueue_t *circularQ, void *messagePtr1,
642 * mpiMsgCategory_t * pCategory, bit16 * pOpCode, bit8 * pBC)
643 * \brief Get a received message
644 * \param circularQ Pointer to a outbound queue
645 * \param messagePtr1 Pointer to the returned message buffer or NULL if no valid message
646 * \param pCategory Pointer to Message category (ETHERNET, FC, SAS-SATA, SCSI)
647 * \param pOpCode Pointer to Message operation code
648 * \param pBC Pointer to buffer count
649 *
650 * Consume a receive message in the specified outbound queue
651 *
652 * Return:
653 * AGSA_RC_SUCCESS if the message has been retrieved succesfully
654 * AGSA_RC_BUSY if the circular is empty
655 */
656 /*******************************************************************************/
657 GLOBAL FORCEINLINE
658 bit32
mpiMsgConsume(mpiOCQueue_t * circularQ,void ** messagePtr1,mpiMsgCategory_t * pCategory,bit16 * pOpCode,bit8 * pBC)659 mpiMsgConsume(
660 mpiOCQueue_t *circularQ,
661 void ** messagePtr1,
662 mpiMsgCategory_t *pCategory,
663 bit16 *pOpCode,
664 bit8 *pBC
665 )
666 {
667 mpiMsgHeader_t *msgHeader;
668 bit32 msgHeader_tmp;
669
670 SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
671 SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
672 SA_ASSERT(NULL != pCategory, "pCategory argument cannot be null");
673 SA_ASSERT(NULL != pOpCode, "pOpCode argument cannot be null");
674 SA_ASSERT(NULL != pBC, "pBC argument cannot be null");
675 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
676
677 do
678 {
679 /* If there are not-yet-delivered messages ... */
680 if(circularQ->producerIdx != circularQ->consumerIdx)
681 {
682 /* Get the pointer to the circular queue buffer element */
683 msgHeader = (mpiMsgHeader_t*) ((bit8 *)(circularQ->memoryRegion.virtPtr) + circularQ->consumerIdx * circularQ->elementSize);
684
685 #ifdef LOOPBACK_MPI
686 if (!loopback)
687 #endif
688 /* invalidate the cache line of IOMB */
689 ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize);
690
691
692 /* read header */
693 OSSA_READ_LE_32(circularQ->agRoot, &msgHeader_tmp, msgHeader, 0);
694
695 SA_DBG4(("mpiMsgConsume: process an IOMB, header=0x%x\n", msgHeader_tmp));
696
697 SA_ASSERT(0 != (msgHeader_tmp & HEADER_BC_MASK), "The bc field in the header is 0");
698 #ifdef TEST
699 /* for debugging */
700 if (0 == (msgHeader_tmp & HEADER_BC_MASK))
701 {
702 SA_DBG1(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
703 circularQ->consumerIdx = (circularQ->consumerIdx + 1) % circularQ->numElements;
704 /* update the CI of outbound queue - skip this blank IOMB, for test only */
705 ossaHwRegWriteExt(circularQ->agRoot,
706 circularQ->CIPCIBar,
707 circularQ->CIPCIOffset,
708 circularQ->consumerIdx);
709 return AGSA_RC_FAILURE;
710 }
711 #endif
712 /* get message pointer of valid entry */
713 if (0 != (msgHeader_tmp & HEADER_V_MASK))
714 {
715 SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap around");
716
717 if (OPC_OUB_SKIP_ENTRY != (msgHeader_tmp & OPCODE_MASK))
718 {
719 /* ... return the message payload */
720 *messagePtr1 = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
721 *pCategory = (mpiMsgCategory_t)(msgHeader_tmp >> SHIFT12) & CAT_MASK;
722 *pOpCode = (bit16)(msgHeader_tmp & OPCODE_MASK);
723 *pBC = (bit8)((msgHeader_tmp >> SHIFT24) & BC_MASK);
724
725 /* invalidate the cache line for IOMB */
726 #ifdef LOOPBACK_MPI
727 if (!loopback)
728 #endif
729 ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, (*pBC - 1) * circularQ->elementSize);
730
731 #if defined(SALLSDK_DEBUG)
732 SA_DBG3(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
733 MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
734 #endif
735 return AGSA_RC_SUCCESS;
736 }
737 else
738 {
739 SA_DBG3(("mpiMsgConsume: SKIP_ENTRIES_IOMB BC=%d\n", (msgHeader_tmp >> SHIFT24) & BC_MASK));
740 /* Updated comsumerIdx and skip it */
741 circularQ->consumerIdx = (circularQ->consumerIdx + ((msgHeader_tmp >> SHIFT24) & BC_MASK)) % circularQ->numElements;
742 /* clean header to 0 */
743 msgHeader_tmp = 0;
744 /*ossaSingleThreadedEnter(agRoot, LL_IOREQ_OBQ_LOCK);*/
745
746 OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
747
748 /* update the CI of outbound queue */
749 ossaHwRegWriteExt(circularQ->agRoot,
750 circularQ->CIPCIBar,
751 circularQ->CIPCIOffset,
752 circularQ->consumerIdx);
753 /* Update the producer index */
754 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
755 /*ossaSingleThreadedLeave(agRoot, LL_IOREQ_OBQ_LOCK); */
756 }
757 }
758 else
759 {
760 /* V bit is not set */
761 #if defined(SALLSDK_DEBUG)
762 agsaRoot_t *agRoot=circularQ->agRoot;
763 SA_DBG1(("mpiMsgConsume: V bit not set, PI=%d CI=%d msgHeader=%p\n", circularQ->producerIdx, circularQ->consumerIdx,(void *)msgHeader));
764 SA_DBG1(("mpiMsgConsume: V bit not set, 0x%08X Q=%d \n", msgHeader_tmp, circularQ->qNumber));
765
766 MPI_DEBUG_TRACE(MPI_DEBUG_TRACE_QNUM_ERROR + circularQ->qNumber,
767 ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
768 MPI_DEBUG_TRACE_OBQ,
769 (void *)(((bit8*)msgHeader) - sizeof(mpiMsgHeader_t)),
770 circularQ->elementSize);
771
772 circularQ->consumerIdx = circularQ->consumerIdx % circularQ->numElements;
773 circularQ->consumerIdx ++;
774 OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
775 ossaHwRegWriteExt(agRoot,
776 circularQ->CIPCIBar,
777 circularQ->CIPCIOffset,
778 circularQ->consumerIdx);
779 MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
780 #endif
781 SA_DBG1(("mpiMsgConsume: V bit is not set!!!!! HW CI=%d\n", ossaHwRegReadExt(circularQ->agRoot, circularQ->CIPCIBar, circularQ->CIPCIOffset) ));
782 SA_ASSERT(0, "V bit is not set");
783 return AGSA_RC_FAILURE;
784 }
785 }
786 else
787 {
788 /* Update the producer index from SPC */
789 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
790 }
791 } while(circularQ->producerIdx != circularQ->consumerIdx); /* while we don't have any more not-yet-delivered message */
792
793 #ifdef TEST
794 SA_DBG4(("mpiMsgConsume: Outbound queue is empty.\n"));
795 #endif
796
797 /* report empty */
798 return AGSA_RC_BUSY;
799 }
800
801 /*******************************************************************************/
802 /** \fn mpiMsgFreeSet(mpiOCQueue_t *circularQ, void *messagePtr)
803 * \brief Returns a received message to the outbound queue
804 * \param circularQ Pointer to an outbound queue
805 * \param messagePtr1 Pointer to the returned message buffer to free
806 * \param messagePtr2 Pointer to the returned message buffer to free if bc > 1
807 *
808 * Returns consumed and processed message to the specified outbounf queue
809 *
810 * Return:
811 * AGSA_RC_SUCCESS if the message has been returned succesfully
812 */
813 /*******************************************************************************/
814 GLOBAL FORCEINLINE
815 bit32
mpiMsgFreeSet(mpiOCQueue_t * circularQ,void * messagePtr1,bit8 bc)816 mpiMsgFreeSet(
817 mpiOCQueue_t *circularQ,
818 void *messagePtr1,
819 bit8 bc
820 )
821 {
822 mpiMsgHeader_t *msgHeader;
823
824 SA_DBG4(("Entering function:mpiMsgFreeSet\n"));
825 SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
826 SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
827 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
828
829 /* Obtains the address of the entire message buffer, including the header */
830 msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr1) - sizeof(mpiMsgHeader_t));
831
832 if ( ((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize)) != msgHeader)
833 {
834 /* IOMB of CI points mismatch with Message Header - should never happened */
835 SA_DBG1(("mpiMsgFreeSet: Wrong CI, Q %d ConsumeIdx = %d msgHeader 0x%08x\n",circularQ->qNumber, circularQ->consumerIdx ,msgHeader->Header));
836 SA_DBG1(("mpiMsgFreeSet: msgHeader %p != %p\n", msgHeader,((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize))));
837
838 #ifdef LOOPBACK_MPI
839 if (!loopback)
840 #endif
841 /* Update the producer index from SPC */
842 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
843 #if defined(SALLSDK_DEBUG)
844 SA_DBG3(("mpiMsgFreeSet: ProducerIdx = %d\n", circularQ->producerIdx));
845 #endif
846 return AGSA_RC_SUCCESS;
847 }
848
849 /* ... free the circular queue buffer elements associated with the message ... */
850 /*... by incrementing the consumer index (with wrap arround) */
851 circularQ->consumerIdx = (circularQ->consumerIdx + bc) % circularQ->numElements;
852
853 /* Invalidates this circular queue buffer element */
854
855 msgHeader->Header &= ~HEADER_V_MASK; /* Clear Valid bit to indicate IOMB consumed by host */
856 SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap arround");
857
858 /* update the CI of outbound queue */
859 #ifdef LOOPBACK_MPI
860 if (!loopback)
861 #endif
862 {
863 ossaHwRegWriteExt(circularQ->agRoot,
864 circularQ->CIPCIBar,
865 circularQ->CIPCIOffset,
866 circularQ->consumerIdx);
867
868 /* Update the producer index from SPC */
869 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
870 }
871 #if defined(SALLSDK_DEBUG)
872 SA_DBG5(("mpiMsgFreeSet: CI=%d PI=%d\n", circularQ->consumerIdx, circularQ->producerIdx));
873 #endif
874 return AGSA_RC_SUCCESS;
875 }
876
877 #ifdef TEST
mpiRotateQnumber(agsaRoot_t * agRoot)878 GLOBAL bit32 mpiRotateQnumber(agsaRoot_t *agRoot)
879 {
880 agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
881 bit32 denom;
882 bit32 ret = 0;
883
884 /* inbound queue number */
885 saRoot->IBQnumber++;
886 denom = saRoot->QueueConfig.numInboundQueues;
887 if (saRoot->IBQnumber % denom == 0) /* % Qnumber*/
888 {
889 saRoot->IBQnumber = 0;
890 }
891 SA_DBG3(("mpiRotateQnumber: IBQnumber %d\n", saRoot->IBQnumber));
892
893 /* outbound queue number */
894 saRoot->OBQnumber++;
895 denom = saRoot->QueueConfig.numOutboundQueues;
896 if (saRoot->OBQnumber % denom == 0) /* % Qnumber*/
897 {
898 saRoot->OBQnumber = 0;
899 }
900 SA_DBG3(("mpiRotateQnumber: OBQnumber %d\n", saRoot->OBQnumber));
901
902 ret = (saRoot->OBQnumber << SHIFT16) | saRoot->IBQnumber;
903 return ret;
904 }
905 #endif
906
907 #ifdef LOOPBACK_MPI
mpiMsgProduceOQ(mpiOCQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)908 GLOBAL bit32 mpiMsgProduceOQ(
909 mpiOCQueue_t *circularQ,
910 void *messagePtr,
911 mpiMsgCategory_t category,
912 bit16 opCode,
913 bit8 responseQueue,
914 bit8 hiPriority
915 )
916 {
917 mpiMsgHeader_t *msgHeader;
918 bit32 bc;
919 bit32 Header = 0;
920 bit32 hpriority = 0;
921
922 SA_DBG4(("Entering function:mpiMsgProduceOQ\n"));
923 SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
924 SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
925 SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
926 " is 0");
927 SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
928
929 /* REB Start extra trace */
930 smTraceFuncEnter(hpDBG_VERY_LOUD, "2I");
931 /* REB End extra trace */
932
933 /* Obtains the address of the entire message buffer, including the header */
934 msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
935 /* Read the BC from header, its stored in native endian format when message
936 was allocated */
937 /* intially */
938 SA_DBG4(("mpiMsgProduceOQ: msgHeader %p opcode %d pi/ci %d / %d\n", msgHeader, opCode, circularQ->producerIdx, circularQ->consumerIdx));
939 bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
940 SA_DBG6(("mpiMsgProduceOQ: msgHeader bc %d\n", bc));
941 if (circularQ->priority)
942 hpriority = 1;
943
944 /* Checks the message is in "allocated" state */
945 SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
946 "(bc == 0)");
947
948 Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30) |
949 ((bc & BC_MASK) << SHIFT24) |
950 ((responseQueue & OBID_MASK) << SHIFT16) |
951 ((category & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
952 /* pre flush the IOMB cache line */
953 //ossaCachePreFlush(circularQ->agRoot,
954 // (void *)circularQ->memoryRegion.appHandle,
955 // (void *)msgHeader, circularQ->elementSize * bc);
956 OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
957 Header), Header);
958
959 /* flush the IOMB cache line */
960 //ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
961 // (void *)msgHeader, circularQ->elementSize * bc);
962
963 MPI_DEBUG_TRACE( circularQ->qNumber,
964 ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
965 MPI_DEBUG_TRACE_OBQ,
966 (void *)msgHeader,
967 circularQ->elementSize);
968
969 ossaLogIomb(circularQ->agRoot,
970 circularQ->qNumber,
971 TRUE,
972 (void *)msgHeader,
973 circularQ->elementSize);
974
975 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2I");
976 return AGSA_RC_SUCCESS;
977 } /* mpiMsgProduceOQ */
978 #endif
979
980