/** * \brief Builds the necessary headers and analises the ADSserver ADSstate response * This is an interface to AdsAPI.c. * Used by AdsSyncReadStateReq(). * \param dc ADSConection handler * \param ADSstate Address of a variable that will receive the ADS status (see data type ADSSTATE). * \param devState Address of a variable that will receive the device status. * \return Error code */ int ADSreadState(ADSConnection * dc, unsigned short *ADSstate, unsigned short *devState) { AMSheader *h1; // AMS_TCPheader *h2; not used ADSpacket *p1; ADSpacket *p2; ADSstateResponse *StateResponse; int rc; int nErr; MsgOut(MSG_TRACE, "ADSreadState() called\n"); p1 = (ADSpacket *) dc->msgOut; h1 = &(p1->amsHeader); // h2 = &(p1->adsHeader); not used _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSreadState; h1->dataLength = 0; p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength; p1->adsHeader.reserved = 0; MsgAnalyzePacket("ADSreadState()", p1); /* sends the the packet */ rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadState() failed()."); #endif MsgOut(MSG_ERROR, "ADSreadState failed().\n"); return( _ADStranslateWrError(rc, nErr)); } /*Read the answer */ dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); MsgDumpPacket("ADSreadState()", dc->msgIn, dc->AnswLen); MsgAnalyzePacket("ADSreadState()", (ADSpacket*)dc->msgIn); if (dc->AnswLen > 0 && nErr == 0 ) { p2 = (ADSpacket *) dc->msgIn; if (p2->amsHeader.commandId == cmdADSreadState) { MsgAnalyzePacket("ADSreadState()", p2); StateResponse = (ADSstateResponse *) (dc->msgIn + 38); *ADSstate = StateResponse->ADSstate;; *devState = StateResponse->devState; MsgOut(MSG_TRACE, MsgStr("ADSreadState() returns 0x%x (0 means OK)\n", StateResponse->result)); return StateResponse->result; } else return p2->amsHeader.errorCode; } /* if there is an error */ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadState failed()."); #endif MsgOut(MSG_ERROR, "ADSreadState failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
/** * This is an interface to AdsAPI.c. * Used by ADSreadDeviceInfo(). */ int ADSreadDeviceInfo(ADSConnection * dc, char *pDevName, PAdsVersion pVersion) { AMSheader *h1; // AMS_TCPheader *h2; not used ADSpacket *p1; ADSpacket *p2; ADSdeviceInfo *DeviceInfo; int rc; int nErr; MsgOut(MSG_TRACE, "ADSreadDeviceInfo() called\n"); p1 = (ADSpacket *) dc->msgOut; h1 = &(p1->amsHeader); // h2 = &(p1->adsHeader); not used _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSreadDevInfo; h1->dataLength = 0; p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength; p1->adsHeader.reserved = 0; MsgAnalyzePacket("ADSreadDeviceInfo()", p1); rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadDeviceInfo() failed()."); #endif MsgOut(MSG_ERROR, "ADSreadDeviceInfo() failed().\n"); return( _ADStranslateWrError(rc, nErr)); } /*Reads the answer */ dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); if (dc->AnswLen > 0 && nErr == 0 ) { p2 = (ADSpacket *) dc->msgIn; if (p2->amsHeader.commandId == cmdADSreadDevInfo) { MsgAnalyzePacket("ADSreadDeviceInfo()", (ADSpacket*)dc->msgIn); DeviceInfo = (ADSdeviceInfo *) (dc->msgIn + 38); *pVersion = DeviceInfo->Version; memcpy(pDevName, DeviceInfo->name, 16); MsgOut(MSG_TRACE, MsgStr("ADSreadDeviceInfo() returns 0x%x (0 means OK)\n", DeviceInfo->result)); return DeviceInfo->result; } else return p2->amsHeader.errorCode; } /* if there is an error */ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadDeviceInfo() failed()."); #endif MsgOut(MSG_ERROR, "ADSreadDeviceInfo() failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
static int MemoryTrackerTrackDeallocate( IN void *pMemory ) { MEM_ALLOC_HDR *pHdr; LIST_ITEM *pListItem; int result = 0; if( pMemTracker ) { SpinLockAcquire( &pMemTracker->Lock ); // Removes an item from the allocation tracking list given a pointer // To the user's data and returns the pointer to header referencing the // allocated memory block. pListItem = QListFindFromTail( &pMemTracker->AllocList, NULL, pMemory ); if( pListItem ) { // Get the pointer to the header. pHdr = PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ); #ifdef MEM_TRACK_FTR MemoryTrackerCheckOverrun(pHdr); #endif // MEM_TRACK_FTR if (pHdr->displaying) { pHdr->deallocate = TRUE; } else { // Remove the item from the list. MemoryTrackerUnlink(pHdr); } } else { int ii; for (ii=0; ii<unTindex; ii++) { if (unTAddr[ii] == pMemory) { unTAddr[ii] = 0; /* found it */ break; } } if (ii == unTindex) { result = 1; #if defined(VXWORKS) MsgOut( "UNMATCHED FREE %p ra=%p\n", pMemory, __builtin_return_address(0)); #else MsgOut( "BAD FREE %p\n", pMemory); #endif DumpStack(); } } SpinLockRelease( &pMemTracker->Lock ); } return result; }
static void MemoryTrackerDereference(MemoryTrackerFileName_t *trk) { if (trk == NULL) { MsgOut("Could not find reference to trk=%p\n", trk); } else { --trk->referenceCount; } }
// // Allocate and initialize the memory tracker object. // static __inline boolean CreateMemTracker( void ) { MEM_TRACKER *tmp; if( pMemTracker ) return TRUE; // Allocate the memory tracker object. Don't update global until we're done tmp = (MEM_TRACKER*)MEMORY_ALLOCATE_PRIV( sizeof(MEM_TRACKER), IBA_MEM_FLAG_LEGACY, TRK_TAG ); if( !tmp ) return FALSE; // Pre-initialize all objects in the memory tracker object. QListInitState( &tmp->AllocList ); SpinLockInitState( &tmp->Lock ); QListInitState( &tmp->FreeHrdList ); // Initialize the list. if( !QListInit( &tmp->AllocList ) ) { /* global isn't initialize, don't call Destroy func; do the clean up */ MEMORY_DEALLOCATE_PRIV( tmp ); return FALSE; } // Initialize the spin lock to protect list operations. if( !SpinLockInit( &tmp->Lock ) ) { /* global isn't initialize, don't call Destroy func; do the clean up */ QListDestroy( &tmp->AllocList ); SpinLockDestroy( &tmp->Lock ); MEMORY_DEALLOCATE_PRIV( tmp ); return FALSE; } // Initialize the free list. if( !QListInit( &tmp->FreeHrdList ) ) { /* global isn't initialize, don't call Destroy func; do the clean up */ QListDestroy( &tmp->AllocList ); SpinLockDestroy( &tmp->Lock ); MEMORY_DEALLOCATE_PRIV( tmp ); return FALSE; } // MsgOut( "\n\n\n*** Memory tracker object address = %p ***\n\n\n", tmp ); MsgOut( "\n*** Memory tracker enabled ***\n" ); /* NOW update the global */ pMemTracker = tmp; return TRUE; }
static void MemoryTrackerShow( IN char *prefix, IN MEM_ALLOC_HDR *pHdr, IN char *suffix) { #if defined(VXWORKS) if ((int)pHdr->LineNum >= 0x00408000) { MsgOut( "%s%p(%u) %s ra=%p tick=%u%s\n", prefix, pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, (void *)pHdr->LineNum, pHdr->tick, suffix ); } else MsgOut( "%s%p(%u) in file %s line %d tick=%u%s\n", prefix, pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, pHdr->LineNum, pHdr->tick, suffix ); #else MsgOut( "%s%p(%u) in file %s line %d%s\n", prefix, pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, pHdr->LineNum, suffix ); #endif }
/** * This is an internal function * Input: netIDstring, something like "127.0.0.1.1.1" * Output: id, the input converted to an AmsNetID struct. */ int _ADSparseNetID(const char *netIDstring, AmsNetId *id) { const char *p; char *q; int i; MsgOut(MSG_TRACE, "_ADSparseNetID() called\n"); q = (char *) id; p = netIDstring; for (i = 0; i < 6; i++) { q[i] = atoi(p); MsgOut(MSG_TRACE_V, MsgStr("%d: %d\n", i, q[i])); p = strchr(p, '.'); if (p == NULL){ MsgOut(MSG_TRACE_V, MsgStr("_ADSparseNetID() returns %d\n", 5 - i)); return 5 - i; } p++; } MsgOut(MSG_TRACE, MsgStr("_ADSparseNetID() returns %d\n", 0)); return 0; }
// // Clean up memory tracking. // static __inline void MemoryTrackStop( void ) { #if defined(MEM_TRACK_ON) LIST_ITEM *pListItem; if( !pMemTracker ) return; if( QListCount( &pMemTracker->AllocList ) ) { // There are still items in the list. Print them out. MemoryDisplayUsage(1, 0, 0); } else { MsgOut( "\n*** Memory tracker stopped, no leaks detected ***\n" ); MsgOut("IbAccess max allocations=%u bytes=%u\n", max_allocations, max_allocated); } // Free all allocated headers. SpinLockAcquire( &pMemTracker->Lock ); while( (pListItem = QListRemoveHead( &pMemTracker->AllocList )) != NULL ) { SpinLockRelease( &pMemTracker->Lock ); MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) ); SpinLockAcquire( &pMemTracker->Lock ); } while( (pListItem = QListRemoveHead( &pMemTracker->FreeHrdList )) != NULL ) { SpinLockRelease( &pMemTracker->Lock ); MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) ); SpinLockAcquire( &pMemTracker->Lock ); } SpinLockRelease( &pMemTracker->Lock ); DestroyMemTracker(); #endif // MEM_TRACK_ON }
/** * @brief Returns the local NetId and port number. * @param port port number of an Ads port that had previously been opened with * AdsPortOpenEx or AdsPortOpen.. * @param pAddr Pointer to the structure of type AmsAddr. * @return Returns the function's error status. */ int32_t AdsGetLocalAddressEx(int32_t port, PAmsAddr pAddr) { if(port <= 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "AdsGetMeAddress(): returns 0x18, port %d not valid.", port); #endif MsgOut(MSG_ERROR, MsgStr("AdsGetMeAddress(): returns 0x18, port %d not valid.\n", port)); return(0x18); } return AdsGetMeAddress(pAddr, AMSPORT_R0_PLC_RTS1); }
FSTATUS BmaLoad( IN IBT_COMPONENT_INFO *ComponentInfo ) { FSTATUS status = FSUCCESS; extern uint32 BmaDbg; #ifdef IB_TRACE extern uint32 BmaTrace; #endif _DBG_ENTER_LVL(_DBG_LVL_MAIN, BMALoad); _DBG_INIT; __DBG_LEVEL__ = BmaDbg; #ifdef IB_TRACE __DBG_TRACE_LEVEL__ = BmaTrace; #endif #if defined(IB_DEBUG) || defined(DBG) MsgOut ("Bma:DebugFlags = 0x%8x\n", __DBG_LEVEL__); #endif #if defined(VXWORKS) _DBG_PRINT(_DBG_LVL_MAIN, (" InfiniBand Baseboard Management Class agent. Built %s %s\n",\ __DATE__, __TIME__ )); #else _DBG_PRINT(_DBG_LVL_MAIN, (" InfiniBand Baseboard Management Class agent. Built %s %s\n",\ _DBG_PTR(__DATE__), _DBG_PTR(__TIME__) )); #endif _TRC_REGISTER(); // // Establish dispatch entry points for the functions supported. // MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) ); ComponentInfo->AddDevice = BmaAddDevice; ComponentInfo->RemoveDevice = BmaRemoveDevice; ComponentInfo->Unload = BmaUnload; // // Read any registry parameters for the driver which may be present. // //BmaReadRegistryParameters(); // // This function is called to initialize the GSA subsystem. This must be // called only once and if the function does not return success, the // caller must unload the component containing GSA or else not use the // GSA functionality since GSA will not be available. // // We are being asked to do a one-time initialization. Here we initialize // the list of channel adapters as well as initialize the list of service // classes as well as initialize the spin locks guarding these lists. // // // Allocate space for Global data // g_BmaGlobalInfo = (BMA_GLOBAL_INFO*)MemoryAllocateAndClear( sizeof(BMA_GLOBAL_INFO), FALSE, BMA_TAG ); if ( NULL != g_BmaGlobalInfo ) { // // initialize global data // g_BmaGlobalInfo->binitsuccess = FALSE; SpinLockInitState( &g_BmaGlobalInfo->DevListLock ); if( !SpinLockInit( &g_BmaGlobalInfo->DevListLock ) ) { _DBG_ERROR(( "Unable to initialize spin locks!\n" )); status = FINSUFFICIENT_RESOURCES; goto fail_lock; } // // Recv Queue and Thread // CmdThreadInitState(&g_BmaGlobalInfo->RecvThread); if ( ! CmdThreadCreate(&g_BmaGlobalInfo->RecvThread, THREAD_PRI_HIGH, "Bma", (CMD_THREAD_CALLBACK)BmaThreadCallback, (CMD_THREAD_CALLBACK)BmaFreeCallback, (void*)g_BmaGlobalInfo)) { _DBG_ERROR(("BmaMain: Unable to Create RecvThread\n")); status = FINSUFFICIENT_RESOURCES; goto fail_thread; } // initialize this general service class manager with GSI status = iba_gsi_register_class(MCLASS_BM, IB_BM_CLASS_VERSION, GSI_REGISTER_RESPONDER, // Register as a Responder FALSE, // No SAR cap needed g_BmaGlobalInfo, // Context BmaSendCallback, BmaRecvCallback, &g_BmaGlobalInfo->GsaHandle); if (status != FSUCCESS) { CmdThreadDestroy(&g_BmaGlobalInfo->RecvThread); fail_thread: SpinLockDestroy( &g_BmaGlobalInfo->DevListLock ); fail_lock: MemoryDeallocate(g_BmaGlobalInfo); g_BmaGlobalInfo = NULL; _DBG_ERROR(("BmaMain: Unable to register with GSA!!! <status %d>\n", status)); _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); return status; } } else { status = FINSUFFICIENT_RESOURCES; _DBG_PRINT(_DBG_LVL_MAIN,("Not enough memory!\n")); } _DBG_LEAVE_LVL(_DBG_LVL_MAIN); return status; }
/** * This is an interface to AdsAPI.c. * Used by AdsSyncReadStateReq(). */ int ADSwriteControl(ADSConnection *dc, int ADSstate, int devState, void *data, int length) { AMSheader *h1; // AMS_TCPheader *h2; not used ADSpacket *p1; ADSpacket *p2; ADSwriteControlRequest *rq; ADSwriteResponse *wr; int rc; int nErr; MsgOut(MSG_TRACE, "ADSwriteControl() called\n"); p1 = (ADSpacket *) dc->msgOut; h1 = &(p1->amsHeader); // h2 = &(p1->adsHeader); not used _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSwriteControl; h1->dataLength = sizeof(ADSwriteControlRequest); p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength; p1->adsHeader.reserved = 0; rq = (ADSwriteControlRequest *) & p1->data; rq->ADSstate = ADSstate; rq->devState = devState; rq->length = 0; if (data != NULL) { memcpy(rq->data, data, length); rq->length = length; h1->dataLength += length; } MsgAnalyzePacket("ADSwriteControl()", p1); rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSwriteControl() failed()."); #endif MsgOut(MSG_ERROR, "ADSwriteControl() failed().\n"); return( _ADStranslateWrError(rc, nErr)); } dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); p2 = (ADSpacket *) dc->msgIn; if (dc->AnswLen > 0 && nErr == 0 ) { MsgAnalyzePacket("ADSwriteControl()", p2); wr = (ADSwriteResponse *) (dc->msgIn + 38); MsgOut(MSG_TRACE, MsgStr("ADSwriteControl() returns 0x%x (0 means OK)\n", wr->result)); return wr->result; } else{ return p2->amsHeader.errorCode; } /* if there is an error */ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSwriteControl() failed()."); #endif MsgOut(MSG_ERROR, "ADSwriteControl() failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
/** * This is an interface to AdsAPI.c. * Used by AdsSyncReadWriteReqEx(). */ int ADSreadWriteBytes(ADSConnection * dc, uint32_t indexGroup, uint32_t offset, uint32_t readLength, void *readBuffer, uint32_t writeLength, void *writeBuffer, uint32_t* pnRead) { AMSheader *h1; AMS_TCPheader *h2; ADSreadWriteRequest *rq; ADSreadWriteResponse *rr; int rc; int nErr; ADSpacket *p1 = (ADSpacket *) dc->msgOut; ADSpacket *p2; MsgOut(MSG_TRACE, "ADSreadWriteBytes() called\n"); h1 = &(p1->amsHeader); h2 = &(p1->adsHeader); _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSreadWrite; h1->dataLength = sizeof(ADSreadWriteRequest) - MAXDATALEN + writeLength; h2->length = h1->dataLength + sizeof(AMSheader); h2->reserved = 0; rq = (ADSreadWriteRequest *) & p1->data; rq->indexGroup = indexGroup; rq->indexOffset = offset; rq->writeLength = writeLength; rq->readLength = readLength; if (writeBuffer != NULL) { memcpy(rq->data, writeBuffer, writeLength); } MsgOut(MSG_PACKET_V, MsgStr("Index Group: 0x%x\n", rq->indexGroup)); MsgOut(MSG_PACKET_V, MsgStr("Index Offset: %d\n", rq->indexOffset)); MsgOut(MSG_PACKET_V, MsgStr("Data length: %d\n", rq->writeLength)); MsgAnalyzePacket("ADSreadWriteBytes()", p1); rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ MsgOut(MSG_ERROR, "ADSreadWriteBytes() failed().\n"); return( _ADStranslateWrError(rc, nErr)); } /*Reads the answer */ dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); if (dc->AnswLen > 0 && nErr == 0 ) { p2 = (ADSpacket *) dc->msgIn; if (p2->amsHeader.commandId == cmdADSreadWrite) { MsgAnalyzePacket("ADSreadWriteBytes()", p2); rr = (ADSreadWriteResponse *) (dc->msgIn + 38); if(rr->length > readLength){ char strBuf[256]; sprintf(strBuf, "ADSreadWriteBytes() failed(): Max Read: %lu, got %u", readLength, rr->length); return(0x705); // parameter size not correct } // memcpy(readBuffer, rr->data, readLength); memcpy(readBuffer, rr->data, rr->length); if(pnRead != NULL) *pnRead = rr->length; MsgOut(MSG_TRACE, MsgStr("ADSreadBytes() returns 0x%x (0 means OK)\n", rr->result)); return rr->result; } else return p2->amsHeader.errorCode; } /* if there is an error */ MsgOut(MSG_ERROR, "ADSreadWriteBytes() failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
/** * This is an interface to AdsAPI.c. * Used by AdsSyncWriteReq(). */ int ADSwriteBytes(ADSConnection *dc, int indexGroup, int offset, int length, void *data) { ADSpacket *p1; ADSpacket *p2; AMSheader *h1; // AMS_TCPheader *h2; not used ADSwriteRequest *rq; ADSwriteResponse *wr; int rc; int nErr; MsgOut(MSG_TRACE, "ADSwriteBytes() called\n"); p1 = (ADSpacket *) dc->msgOut; h1 = &(p1->amsHeader); // h2 = &(p1->adsHeader); not used _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSwrite; h1->dataLength = sizeof(ADSwriteRequest) - MAXDATALEN + length; p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength; p1->adsHeader.reserved = 0; rq = (ADSwriteRequest *) & p1->data; rq->indexGroup = indexGroup; rq->indexOffset = offset; rq->length = length; if (data != NULL) memcpy(rq->data, data, length); MsgOut(MSG_PACKET_V, MsgStr("Index Group: %x\n", rq->indexGroup)); MsgOut(MSG_PACKET_V, MsgStr("Index Offset: %d\n", rq->indexOffset)); MsgOut(MSG_PACKET_V, MsgStr("Data length: %d\n", rq->length)); MsgAnalyzePacket("ADSwriteBytes()", p1); rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ MsgOut(MSG_ERROR, "ADSwriteBytes() failed().\n"); return( _ADStranslateWrError(rc, nErr)); } /*Reads the answer */ dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); if (dc->AnswLen >= (sizeof(AMS_TCPheader) + sizeof(AMSheader))) { p2 = (ADSpacket *) dc->msgIn; if(nErr == 0 ) { MsgAnalyzePacket("ADSwriteBytes()", (ADSpacket*)dc->msgIn); wr = (ADSwriteResponse *) (dc->msgIn + 38); MsgOut(MSG_TRACE, MsgStr("ADSwriteBytes() returns 0x%x (0 means OK)\n", wr->result)); return wr->result; } else return p2->amsHeader.errorCode; } /* if there is an error */ MsgOut(MSG_ERROR, "ADSwriteBytes() failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
/** * This is an interface to AdsAPI.c. * Used by AdsSyncReadReqEx() */ int ADSreadBytes(ADSConnection *dc, uint32_t indexGroup, uint32_t offset, uint32_t length, void *buffer, uint32_t *pnRead) { AMSheader *h1; // AMS_TCPheader *h2; not used ADSpacket *p1; ADSpacket *p2; ADSreadRequest *rq; ADSreadResponse *rr; int rc; int nErr; MsgOut(MSG_TRACE, "ADSreadBytes() called\n"); p1 = (ADSpacket *) dc->msgOut; h1 = &(p1->amsHeader); // h2 = &(p1->adsHeader); not used _ADSsetupAmsHeader(dc, h1); h1->commandId = cmdADSread; h1->dataLength = sizeof(ADSreadRequest); p1->adsHeader.length = sizeof(AMSheader) + h1->dataLength; p1->adsHeader.reserved = 0; rq = (ADSreadRequest *) &p1->data; rq->indexGroup = indexGroup; rq->indexOffset = offset; rq->length = length; MsgOut(MSG_PACKET_V, MsgStr("Index Group: 0x%x\n", rq->indexGroup)); MsgOut(MSG_PACKET_V, MsgStr("Index Offset: %d\n", rq->indexOffset)); MsgOut(MSG_PACKET_V, MsgStr("Data length: %d\n", rq->length)); MsgAnalyzePacket("ADSreadBytes", p1); rc = _ADSWritePacket(dc->iface, p1, &nErr); if(rc <= 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadBytes() failed()."); #endif MsgOut(MSG_ERROR, "ADSreadBytes() failed().\n"); return( _ADStranslateWrError(rc, nErr)); } dc->AnswLen = _ADSReadPacket(dc->iface, dc->msgIn, &nErr); if (dc->AnswLen > 0 && nErr == 0 ) { p2 = (ADSpacket *) dc->msgIn; // if (p2->amsHeader.commandId == cmdADSread && p2->amsHeader.errorCode == 0) { if (p2->amsHeader.commandId == cmdADSread) { MsgDumpPacket("ADSreadBytes", dc->msgIn, dc->AnswLen); MsgAnalyzePacket("ADSreadBytes", (ADSpacket *)dc->msgIn); rr = (ADSreadResponse *) (dc->msgIn + 38); /* if (rr->result != 0){ #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadBytes(): ADSreadResponse() failed with error 0x%x.", rr->result); #endif MsgOut(MSG_ERROR, MsgStr("ADSreadBytes(): ADSreadResponse() failed with error 0x%x.\n", rr->result)); return rr->result; }*/ dc->dataPointer = dc->msgIn + 46; dc->AnswLen = rr->length; if (buffer != NULL) { if(rr->length > length){ char strBuf[256]; sprintf(strBuf, "ADSreadBytes() failed(): Buffer sized %lu bytes, got %u bytes.", length, rr->length); #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, strBuf); #endif MsgOut(MSG_ERROR, MsgStr("%s\n", strBuf)); return(0x705); // parameter size not correct } memcpy(buffer, dc->dataPointer, rr->length); } if(pnRead != NULL) *pnRead = rr->length; MsgOut(MSG_DEVEL, MsgStr("ADSreadBytes() invokeId=%d\n", p2->amsHeader.invokeId)); MsgOut(MSG_TRACE, "ADSreadBytes() returns 0 (OK)\n"); // return 0; // printf("rr->result=0x%x, p2->amsHeader.errorCode=0x%x\n", rr->result, p2->amsHeader.errorCode); return rr->result; } else return p2->amsHeader.errorCode; } #ifdef LOG_ALL_MESSAGES syslog(LOG_USER | LOG_ERR, "ADSreadBytes() failed()."); #endif MsgOut(MSG_ERROR, "ADSreadBytes() failed().\n"); return(_ADStranslateRdError(dc->AnswLen, nErr)); }
// // Display memory usage. // void MemoryDisplayUsage( int method, uint32 minSize, uint32 minTick ) { #if defined(MEM_TRACK_ON) uint32 allocated = 0; uint32 allocations = 0; MEM_ALLOC_HDR *pHdr; LIST_ITEM *item, *next, *tail, *head; unsigned int allocations_per_sec = 0; uint32 currentTime; boolean all = (method == 1); if( !pMemTracker ) { MsgOut( "*** IbAccess Memory Tracking is disabled ***\n" ); return; } /* "lock" present allocations by setting * displaying flag, so other allocates/frees will not affect them * This gives us a snapshot while permitting the system to run * while we perform the output (the output itself may use memory allocate) * However, our report loop below must stay within head/tail */ SpinLockAcquire( &pMemTracker->Lock ); tail = QListTail(&pMemTracker->AllocList); head = QListHead(&pMemTracker->AllocList); for(item = head; item != NULL; item = QListNext(&pMemTracker->AllocList, item)) { pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem ); pHdr->displaying = TRUE; } SpinLockRelease (&pMemTracker->Lock); MsgOut( "*** IbAccess Memory Usage %s minSize=%d minTick=%d ***\n", all?"All":"Unreported", minSize, minTick ); if (head && tail) { item = head; do { next = QListNext(&pMemTracker->AllocList, item); pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem ); #ifdef MEM_TRACK_FTR // Check that the user did not overrun his memory allocation. if (pHdr->deallocate == FALSE) { MemoryTrackerCheckOverrun(pHdr); } #endif // MEM_TRACK_FTR if ((pHdr->Bytes >= minSize) && (pHdr->tick >= minTick) && (all || (pHdr->reported == 0))) { // method 2 just marks all current allocations as reported, without actually reporting them // method 3 displays the items without changing their reported state (allows us to avoid the FREED messages) if (method != 2) MemoryTrackerShow("", pHdr, ""); if (method != 3) pHdr->reported = 1; } allocated += pHdr->Bytes; ++allocations; SpinLockAcquire( &pMemTracker->Lock ); pHdr->displaying = FALSE; if (pHdr->deallocate) { MemoryTrackerUnlink(pHdr); } SpinLockRelease (&pMemTracker->Lock); item = next; } while (&pHdr->ListItem != tail && item != NULL); } currentTime = GetTimeStampSec(); if (last_reported_secs && currentTime != last_reported_secs) { allocations_per_sec = (total_allocations - last_reported_allocations) / (currentTime - last_reported_secs); } last_reported_secs = currentTime; last_reported_allocations = total_allocations; MsgOut("IbAccess current allocations=%u bytes=%u max allocations=%u bytes=%u p/s=%d\n", allocations, allocated, max_allocations, max_allocated, allocations_per_sec); #endif // MEM_TRACK_ON }
// called in a thread context, so can preempt void GsaCompletionCallback( IN void *CaContext, IN IB_HANDLE CqHandle ) { FSTATUS status; IBT_DGRM_ELEMENT *pDgrm = NULL; boolean bRearmed = FALSE; IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; GSA_POST_SEND_LIST *pPostList; MAD_COMMON *pMadHdr; GSA_SERVICE_CLASS_INFO *classInfo; IB_WORK_COMPLETION workCompletion; uint8 clientId; uint64 portGuid; _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, GsaCompletionCallback); // // Processing completions on the CQ is done as follows: // 1. Repeatedly Poll till all entries are done. // 2. Rearm CQ and Poll again. If there are no more completions bail out. // 3. If there are completions go back to step 1. // 4. Skip step 2 and loop through 3. // // We follow these steps to optimize on hardware events and race // conditions. // while (1) { #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Callback\n"); #endif // // Loop and pull out all sends and receives // while ( FSUCCESS == (status = iba_poll_cq( CqHandle, &workCompletion )) ) { // fill in common values pDgrm = (IBT_DGRM_ELEMENT *)((uintn)MASK_WORKREQID(workCompletion.WorkReqId)); // This should never happen. test for bad hardware ASSERT ( pDgrm ); if ( NULL == pDgrm ) { // // This is for debug only. We should remove this conditional // once the problem is debugged // _DBG_ERROR (("Spurious CQ Event!!!\n" "\tCompleted WQE.....:(%s)\n" "\tSTATUS............:x%x\n" "\tLength............:x%x\n", _DBG_PTR(((WCTypeSend == workCompletion.WcType) ? \ "Send":"Recv")), workCompletion.Status, workCompletion.Length)); if ( WCTypeRecv == workCompletion.WcType ) { _DBG_ERROR (("\n" "\tQP Number.........:x%x\n" "\tSourceLID.........:x%x\n", workCompletion.Req.RecvUD.SrcQPNumber, workCompletion.Req.RecvUD.SrcLID)); } _DBG_BREAK; break; } // process work completion pDgrm->Element.Status = workCompletion.Status; pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pDgrm; _DBG_PRINT (_DBG_LVL_CALLBACK,( "Completed %s WQE (%p):\n" "\tSTATUS.......:x%X (%s)\n", _DBG_PTR(((WCTypeSend == workCompletion.WcType) ? "Send":"Recv")), _DBG_PTR(pDgrm), workCompletion.Status, _DBG_PTR(iba_wc_status_msg(workCompletion.Status)) )); if (IS_SQ_WORKREQID(workCompletion.WorkReqId)) { #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl\n"); #endif if (! pDgrm->Allocated) { _DBG_ERROR(("GSI ERROR: Send Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d OnrecvQ=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->OnRecvQ)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(pDgrm->Allocated); } DEBUG_ASSERT(pDgrm->Allocated); continue; } if (pDgrm->OnRecvQ) { _DBG_ERROR(("GSI ERROR: Send Completion for Recv Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(! pDgrm->OnRecvQ); } DEBUG_ASSERT(! pDgrm->OnRecvQ); continue; } if (! pDgrm->OnSendQ) { _DBG_ERROR(("GSI ERROR: Send Completion for non-OnSendQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(pDgrm->OnSendQ); } DEBUG_ASSERT(pDgrm->OnSendQ); continue; } pDgrm->OnSendQ = FALSE; // Handle common send completion. Only for SendInvalid // will a Recv Pool Dgrm be used, we get correct pMadHdr // mainly so log messages below are correct if (((IBT_DGRM_ELEMENT_PRIV *)pDgrm)->MemPoolHandle->ReceivePool ) pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); else pMadHdr = (MAD_COMMON *)GsiDgrmGetSendMad(pDgrm); BSWAP_MAD_HEADER ((MAD*)pMadHdr); pPostList = pDgrmPrivate->Base; AtomicIncrementVoid( &pPostList->DgrmOut); #ifdef ICS_LOGGING _DBG_PRINT (_DBG_LVL_CALLBACK,( "Send Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Local\n" "\tPathBits.....:x%X\n" "Remote:\n" "\tLID..........:x%X\n" "\tQP...........:x%X\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, pDgrmPrivate->DgrmElement.PathBits, pDgrmPrivate->DgrmElement.RemoteLID, pDgrmPrivate->DgrmElement.RemoteQP )); _DBG_PRINT (_DBG_LVL_CALLBACK,( "Send Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Local\n" "\tQKey.........:x%X\n" "\tServiceLvl...:x%X\n" "\tGlobalRoute..:%s\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, pDgrmPrivate->DgrmElement.RemoteQKey, pDgrmPrivate->DgrmElement.ServiceLevel, _DBG_PTR((pDgrmPrivate->DgrmElement.GlobalRoute ? "TRUE":"FALSE") ) )); #else _DBG_PRINT (_DBG_LVL_CALLBACK,( "Send Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Local\n" "\tPathBits.....:x%X\n" "Remote:\n" "\tLID..........:x%X\n" "\tQP...........:x%X\n" "\tQKey.........:x%X\n" "\tServiceLvl...:x%X\n" "\tRate.........:x%d\n" "\tGlobalRoute..:%s\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, pDgrmPrivate->DgrmElement.PathBits, pDgrmPrivate->DgrmElement.RemoteLID, pDgrmPrivate->DgrmElement.RemoteQP, pDgrmPrivate->DgrmElement.RemoteQKey, pDgrmPrivate->DgrmElement.ServiceLevel, pDgrmPrivate->DgrmElement.StaticRate, (pDgrmPrivate->DgrmElement.GlobalRoute ? "TRUE":"FALSE") )); #endif // Send completion for Send initiated by RMPP protocol if( pPostList->SARRequest) { #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: SAR\n"); #endif // send was posted by RMPP protocol handler // let it process the completion ProcessSARSendCompletion((MAD*)pMadHdr, pDgrm); continue; } // The datagram has been successfully sent. Reset the // transaction ID to that specified by the user if this is // not a response. Responses use the transaction ID from // the original request. if (MAD_IS_REQUEST((MAD*)pMadHdr)) { // Restore the original TID from the user. We cannot // use the context manager here, since we may have already // completed the request. (The associated receive may // be processed before the send is completed.) pMadHdr->TransactionID = pDgrmPrivate->SavedSendTid; } // Free resources ASSERT ( pDgrmPrivate->AvHandle ); status = PutAV( NULL, pDgrmPrivate->AvHandle ); classInfo = (GSA_SERVICE_CLASS_INFO*)pDgrmPrivate->MemPoolHandle->ServiceHandle; if ( NULL == classInfo ) { // no associated class, must be a GSI initiated MAD DEBUG_ASSERT(pPostList->DgrmIn == AtomicRead(&pPostList->DgrmOut)); status = DgrmPoolPut( pPostList->DgrmList ); continue; } // Match all sends before callback if ( pPostList->DgrmIn != AtomicRead(&pPostList->DgrmOut) ) { #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: more to do\n"); #endif _DBG_PRINT (_DBG_LVL_CALLBACK,( "All sends not completed in send list:\n" "\tTotal.....:%d\n" "\tDone......:%d\n", pPostList->DgrmIn, AtomicRead(&pPostList->DgrmOut) )); continue; } // Call user's send completion #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: class callback: %p\n", classInfo->SendCompletionCallback); #endif if ( classInfo->SendCompletionCallback ) { (classInfo->SendCompletionCallback)( classInfo->ServiceClassContext, pPostList->DgrmList ); } else { status = DgrmPoolPut( pPostList->DgrmList ); } // Class Callback } else { // Receive Completion processing uint32 post_count; IBT_BUFFER *Current = NULL; uint32 Length = 0; #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl\n"); #endif if (pDgrm->OnSendQ) { _DBG_ERROR(("GSI ERROR: Recv Completion for Send Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(! pDgrm->OnSendQ); } DEBUG_ASSERT(! pDgrm->OnSendQ); continue; } if (! pDgrm->OnRecvQ) { _DBG_ERROR(("GSI ERROR: Recv Completion for non-OnRecvQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(pDgrm->OnRecvQ); } DEBUG_ASSERT(pDgrm->OnRecvQ); continue; } if (! pDgrm->Allocated) { _DBG_ERROR(("GSI ERROR: Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) { ASSERT(pDgrm->Allocated); } DEBUG_ASSERT(pDgrm->Allocated); pDgrm->OnRecvQ = FALSE; continue; } pDgrm->OnRecvQ = FALSE; status = DecrementGsiRecvQPostedForPortGuid( pDgrm->PortGuid, &post_count); _DBG_PRINT (_DBG_LVL_CALLBACK,("0x%"PRIx64": got post count of %u: %d\n",pDgrm->PortGuid, post_count, status)); if (FSUCCESS == status && post_count < g_GsaSettings.MinBuffersToPostPerPort ) { // replenish to desired min post_count = g_GsaSettings.MinBuffersToPostPerPort - post_count; } else { // can't be sure, just repost 1 post_count = 1; } _DBG_PRINT (_DBG_LVL_CALLBACK,("computed post count of %u\n", post_count)); // Do not callback for QpFlush if ( WRStatusWRFlushed == workCompletion.Status ) { #ifdef SA_ALLOC_DEBUG if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl: Flush\n"); #endif _DBG_PRINT (_DBG_LVL_CALLBACK,("WRFlushed: skip users.\n")); status = DgrmPoolPut( pDgrm ); continue; } /* MADs can be of variable length */ if ( workCompletion.Length > (sizeof(IB_GRH) + sizeof(MAD))) { _DBG_ERROR (( "Invalid MAD receive length (%d bytes)! <Discard>\n", workCompletion.Length )); status = DgrmPoolPut( pDgrm ); continue; } // Overload base with SAR field pDgrmPrivate->Base = 0; // not a SAR Receive Dgrm // Fill in bytes rcvd pDgrm->TotalRecvSize = workCompletion.Length; pDgrm->Element.RecvByteCount = workCompletion.Length; // Save GUID for a post since the user may FPENDING the Dgrm portGuid = pDgrm->PortGuid; // GRH is first buffer, MAD is second pDgrm->Element.pBufferList->ByteCount = sizeof(IB_GRH); Current = pDgrm->Element.pBufferList->pNextBuffer; Length = workCompletion.Length - sizeof(IB_GRH); pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); while (Length && Current) { Current->ByteCount = (pMadHdr->BaseVersion == IB_BASE_VERSION) ? MIN(Length, IB_MAD_BLOCK_SIZE) : MIN(Length, STL_MAD_BLOCK_SIZE); if (__DBG_LEVEL__ & _DBG_LVL_PKTDUMP) { _DBG_DUMP_MEMORY(_DBG_LVL_PKTDUMP, ("Recv GSI MAD Packet"), Current->pData, MIN(Current->ByteCount, Length)); } Length -= Current->ByteCount; Current = Current->pNextBuffer; } BSWAP_MAD_HEADER ((MAD*)pMadHdr); #ifdef ICS_LOGGING _DBG_PRINT (_DBG_LVL_CALLBACK,( "Receive Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Local\n" "\tPathBits.....:x%X\n" "Remote:\n" "\tLID..........:x%X\n" "\tQP...........:x%X\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, workCompletion.Req.RecvUD.DestPathBits, workCompletion.Req.RecvUD.SrcLID, workCompletion.Req.RecvUD.SrcQPNumber )); _DBG_PRINT (_DBG_LVL_CALLBACK,( "Receive Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Remote:\n" "\tPKeyIndex....:x%X\n" "\tServiceLvl...:x%X\n" "\tGlobalRoute..:%s\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, workCompletion.Req.RecvUD.PkeyIndex, workCompletion.Req.RecvUD.ServiceLevel, _DBG_PTR((workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE")) )); #else _DBG_PRINT (_DBG_LVL_CALLBACK,( "Receive Info:\n" "\tClass........:x%x\n" "\tResponseBit..:x%x\n" "\tTID..........:x%"PRIx64"\n" "Local\n" "\tPathBits.....:x%X\n" "Remote:\n" "\tLID..........:x%X\n" "\tQP...........:x%X\n" "\tPKeyIndex....:x%X\n" "\tServiceLvl...:x%X\n" "\tGlobalRoute..:%s\n", (uint8)pMadHdr->MgmtClass, pMadHdr->mr.s.R, pMadHdr->TransactionID, workCompletion.Req.RecvUD.DestPathBits, workCompletion.Req.RecvUD.SrcLID, workCompletion.Req.RecvUD.SrcQPNumber, workCompletion.Req.RecvUD.PkeyIndex, workCompletion.Req.RecvUD.ServiceLevel, (workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE") )); #endif // Port Number and Q pair are filled-up during // Gsa's PostRecv pDgrm->PathBits = workCompletion.Req.RecvUD.DestPathBits; pDgrm->RemoteLID = workCompletion.Req.RecvUD.SrcLID; pDgrm->RemoteQP = workCompletion.Req.RecvUD.SrcQPNumber; pDgrm->RemoteQKey = QP1_WELL_KNOWN_Q_KEY; pDgrm->PkeyIndex = workCompletion.Req.RecvUD.PkeyIndex; pDgrm->ServiceLevel = workCompletion.Req.RecvUD.ServiceLevel; // IB does not have Static rate in UD LRH // so we can't be sure what rate of remote port is // we use a constant value for GSI QPs pDgrm->StaticRate = IB_STATIC_RATE_GSI; pDgrm->GlobalRoute = workCompletion.Req.RecvUD.Flags.s.GlobalRoute; if (workCompletion.Req.RecvUD.Flags.s.GlobalRoute) { IB_GRH *pGrh = GsiDgrmGetRecvGrh(pDgrm); BSWAP_IB_GRH ( pGrh); pDgrm->GRHInfo.DestGID = pGrh->SGID; pDgrm->GRHInfo.FlowLabel = pGrh->u1.s.FlowLabel; pDgrm->GRHInfo.SrcGIDIndex = 0; // BUGBUG - lookup DGID pDgrm->GRHInfo.HopLimit = pGrh->HopLimit; pDgrm->GRHInfo.TrafficClass = pGrh->u1.s.TClass; _DBG_PRINT (_DBG_LVL_CALLBACK,( "GRH Info:\n" "\tDGID.........:x%"PRIx64":%"PRIx64"\n" "\tSGID.........:x%"PRIx64":%"PRIx64"\n" "\tPayload......:%d bytes\n", pGrh->DGID.Type.Global.SubnetPrefix, pGrh->DGID.Type.Global.InterfaceID, pGrh->SGID.Type.Global.SubnetPrefix, pGrh->SGID.Type.Global.InterfaceID, pGrh->PayLen )); } // //TBD: // Chain replies to process later // //pDgrm->pNextCompDgrm // For RMPP R bit be set in all packets which compose a response // message Even ABORT, STOP, etc. // transaction ID will be consistent in all packets for // a given request/respone message pair. // R bit be 0 in all packets which compose a request message // event ACK, ABORT, STOP, etc // See if the received MAD was in response to a previously // sent MAD request. if (MAD_IS_RESPONSE((MAD*)pMadHdr)) { // Response to clients. client id was a field // in the transaction ID sent on wire clientId = (uint8)(pMadHdr->TransactionID & 0xff); } else { // This is a new request or not a request/response pair // TID unmodified TID is visible to client (for a request // TID was remotely generated and we can't modify) clientId = MAX_CLIENT_ID; status = FSUCCESS; } // Validate Attributes to be processed if( status == FSUCCESS ) { // Does the Client want us to do RMPP protocol for it? if( IsSarClient( clientId, pMadHdr->MgmtClass ) ) { // Process the segment. If all segments have been // received, pDgrm will be updated to point to the // first segment. status = ProcessSARRecvCompletion((MAD*)pMadHdr,&pDgrm); if( status == FCOMPLETED ) { // remove clientid from all TIDs before give to user IBT_ELEMENT *pElement; for (pElement = &pDgrm->Element; pElement != NULL; pElement = pElement->pNextElement) { // first buffer is GRH, 2nd is start of MAD RemoveClientIdFromTID( (MAD_COMMON *) pElement->pBufferList->pNextBuffer->pData); } // adjust pMadHdr to be first in list of Dgrms, // pDgrm could have been changed by SAR processing pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); } } else { // No SAR is needed. // remove clientid from TID before give to user RemoveClientIdFromTID(pMadHdr); status = FCOMPLETED; } // Notify the user of fully received MADs. if( status == FCOMPLETED ) { status = GsaNotifyClients( clientId, pMadHdr, pDgrm ); } if (status == FNOT_FOUND) { // no client found if (MAD_EXPECT_GET_RESP((MAD*)pMadHdr)) { // reply with a bad class version response GsiSendInvalid(pDgrm); } status = FREJECT; // free dgrm below } // Free the datagram(s) if not required for SAR and not // being used by the client. if( status == FCOMPLETED || status == FREJECT ) { DgrmPoolPut( pDgrm ); } } // Post back a recv to Q status = PostRecvMsgToPort( post_count, portGuid ); } // recv } // while loop if ( FNOT_DONE != status ) { _DBG_ERROR (("Got %s Status!!!\n", _DBG_PTR(FSTATUS_MSG(status)) )); } // Rearm CQ for race conditions if ( FALSE == bRearmed ) { status = iba_rearm_cq( CqHandle, CQEventSelNextWC ); bRearmed = TRUE; } else { break; } } // while 1 _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); }