////////////////////////////////////////////////////////////////////////// // BmaRemoveDevice() // // This routine is called once for every CA device being removed. Nothing // is performed in this function. All cleanup is performed in the BmaUnload // function. // // INPUTS: // CaGuid - the channel adapters GUID // Context - driver defined unique context for this CA // // OUTPUTS: // // None. // // RETURNS: // // FSUCCESS - Indicates a successful initialization. // // FSTATUS BmaRemoveDevice( IN EUI64 CaGuid, IN void *Context ) { FSTATUS status = FSUCCESS; BMA_DEV_INFO *pDevInfo=NULL; _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaRemoveDevice); ASSERT(g_BmaGlobalInfo); SpinLockAcquire( &g_BmaGlobalInfo->DevListLock ); pDevInfo = g_BmaGlobalInfo->DevList; if ( g_BmaGlobalInfo->DevList->CaGuid == CaGuid ) { g_BmaGlobalInfo->DevList = pDevInfo->Next; } else { while ( pDevInfo->Next ) { if ( pDevInfo->Next->CaGuid == CaGuid ) { BMA_DEV_INFO *Found = pDevInfo->Next; pDevInfo->Next = Found->Next; pDevInfo = Found; break; } pDevInfo = pDevInfo->Next; } } SpinLockRelease( &g_BmaGlobalInfo->DevListLock ); if (pDevInfo && pDevInfo->CaGuid == CaGuid) { MemoryDeallocate( pDevInfo->Port ); MemoryDeallocate( pDevInfo ); } else { _DBG_ERROR(("Unable to find Ca with GUID 0x%"PRIx64"\n", CaGuid)); status = FERROR; } _DBG_LEAVE_LVL(_DBG_LVL_MAIN); return status; } // BmaRemoveDevice()
// reaper callback static void ReapTrapReference(LIST_ITEM *pItem) { // Reaper uses QListObj, so we must use PARENT_STRUCT TRAP_REFERENCE *pTrapReference = PARENT_STRUCT(pItem, TRAP_REFERENCE, ListItem); TimerDestroy(&pTrapReference->Timer); MemoryDeallocate(pTrapReference); }
// // SmaUnload // // This routine should release resources allocated in the SmaLoad function. // // INPUTS: // // None. // // OUTPUTS: // // None. // // RETURNS: // // FSUCCESS - Successful unload of SMA. // // This routine is called at IRQL_PASSIVE_LEVEL. // void SMAUnload(void) { GLOBAL_MEM_LIST *pMemList; _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaUnload); // there should be no CAs at this point, all VPD must be unloaded // before IbAccess ASSERT(0 == g_Sma->NumCa); ASSERT(NULL == g_Sma->CaObj); // Free up global memory // //Note: Global Grh gets freed automatically here for (pMemList = g_Sma->Bin.MemList; NULL != pMemList; ) { GLOBAL_MEM_LIST *pMemListNext; pMemListNext = (GLOBAL_MEM_LIST*)pMemList->Next; MemoryDeallocate( pMemList->VirtualAddr ); // registered SMP emm if (pMemList->HdrAddr ) MemoryDeallocate( pMemList->HdrAddr ); // SmpBlock memory MemoryDeallocate( pMemList ); pMemList = pMemListNext; } _TRC_UNREGISTER(); // Remove user list if ( NULL != g_Sma->SmUserTbl ) MemoryDeallocate( g_Sma->SmUserTbl ); IbtDestroyNotifyGroup(); // Locks MutexDestroy( &g_Sma->Bin.Mutex ); SpinLockDestroy( &g_Sma->Bin.Lock ); SpinLockDestroy( &g_Sma->RQ.Lock ); SpinLockDestroy( &g_Sma->CaListLock ); MemoryDeallocate( g_Sma ); _DBG_LEAVE_LVL(_DBG_LVL_MAIN); }
void KeyboardDeallocate(struct UsbDevice *device) { struct KeyboardDevice *data; data = (struct KeyboardDevice*)((struct HidDevice*)device->DriverData)->DriverData; if (data != NULL) { MemoryDeallocate(data); ((struct HidDevice*)device->DriverData)->DriverData = NULL; } ((struct HidDevice*)device->DriverData)->HidDeallocate = NULL; ((struct HidDevice*)device->DriverData)->HidDetached = NULL; }
// must be called with SubscribedTrapsListLock held static void IssueTrapUnSubscribe(TRAP_REFERENCE *pTrapReference) { FSTATUS Status; FABRIC_OPERATION_DATA *pFabOp; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IssueTrapUnSubscribe); pFabOp = (FABRIC_OPERATION_DATA*)MemoryAllocate2AndClear( sizeof(FABRIC_OPERATION_DATA), IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG ); if ( pFabOp == NULL ) { _DBG_ERROR(("SubscribeForTrap MemoryAllocateError\n")); QueueTrapTimer(pTrapReference, RETRY_DELAY); // try again later } else { pFabOp->Type = FabOpSetInformInfo; memset(&pFabOp->Value.InformInfo.GID, 0, sizeof(pFabOp->Value.InformInfo.GID)); pFabOp->Value.InformInfo.LIDRangeBegin = LID_PERMISSIVE; pFabOp->Value.InformInfo.LIDRangeEnd = 0; pFabOp->Value.InformInfo.Reserved = 0; pFabOp->Value.InformInfo.IsGeneric = 1; pFabOp->Value.InformInfo.Subscribe = 0; pFabOp->Value.InformInfo.Type = IB_NOTICE_ALL; pFabOp->Value.InformInfo.u.Generic.TrapNumber = pTrapReference->TrapNumber; pFabOp->Value.InformInfo.u.Generic.u2.s.QPNumber = GSI_QP; pFabOp->Value.InformInfo.u.Generic.u2.s.RespTimeValue = 18; pFabOp->Value.InformInfo.u.Generic.u.s.ProducerType = STL_NODE_FI; Status = iba_sd_port_fabric_operation( SdClientHandle, pTrapReference->PortGuid, pFabOp, ProcessTrapSubscribeResponse, NULL, pTrapReference ); if ((Status != FPENDING) && (Status != FSUCCESS)) { /* Port may not yet be active. * ReRegisterTrapSubscriptions will be called when it goes active * but we queue a slow timer just in case operation failed for * another reason (such as low memory, etc) */ /* _DBG_ERROR(("PortFabricOperation Status = %d\n", Status)); */ QueueTrapTimer(pTrapReference, PORT_DOWN_DELAY);// try again later } else { // to be conservative, assume we are unsubscribed, just in case // SA processes request, but delivers response late // also avoids us retrying unsubscribe in event SM is down pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags & ~TRAP_REF_FLAGS_SUBSCRIBED); pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags | TRAP_REF_FLAGS_OPQUEUED); } MemoryDeallocate( pFabOp ); } _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); }
// // BmaUnload // // This routine should release resources allocated in the BmaLoad function. // Also, since their is a single instance of the service for all channel // adapters in the system, it will also release resources allocated in the // BmaAddDevice function. // // INPUTS: // // None. // // OUTPUTS: // // None. // // RETURNS: // // None // // void BmaUnload(void) { _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaUnload); _TRC_UNREGISTER(); if ( g_BmaGlobalInfo ) { // Destroy the datagram pool if ( g_BmaGlobalInfo->DgrmPoolHandle ) iba_gsi_destroy_dgrm_pool( g_BmaGlobalInfo->DgrmPoolHandle ); // Deregister this class agent with the GSA if ( g_BmaGlobalInfo->GsaHandle ) iba_gsi_deregister_class(g_BmaGlobalInfo->GsaHandle); // // Recv Thread // CmdThreadDestroy(&g_BmaGlobalInfo->RecvThread); // // Ca List Members // while ( g_BmaGlobalInfo->DevList ) { BmaRemoveDevice( g_BmaGlobalInfo->DevList->CaGuid, NULL ); } // // Ca List Lock // SpinLockDestroy( &g_BmaGlobalInfo->DevListLock ); // // Free up global memory // MemoryDeallocate( g_BmaGlobalInfo ); g_BmaGlobalInfo = NULL; } // if g_BmaGlobalInfo _DBG_LEAVE_LVL(_DBG_LVL_MAIN); }
FSTATUS iba_sd_trap_notice_unsubscribe(CLIENT_HANDLE ClientHandle, uint16 TrapNumber, EUI64 PortGuid) { FSTATUS Status; CLIENT_CONTROL_PARAMETERS ClientParams; ClientListEntry *pClientEntry = (ClientListEntry *)ClientHandle; CLIENT_TRAP_INFO *pClientTrapInfo; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_trap_notice_unsubscribe); Status = ValidateClientHandle(ClientHandle, &ClientParams); if (Status != FSUCCESS) { _DBG_ERROR(("Invalid Client Handle Specified\n")); goto exit; } SpinLockAcquire(pClientListLock); pClientTrapInfo = FindClientTrapInfo(&pClientEntry->ClientTraps, TrapNumber, PortGuid); if (pClientTrapInfo == NULL) { // Not Found Status = FERROR; SpinLockRelease(pClientListLock); goto exit; } QListRemoveItem(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); SpinLockRelease(pClientListLock); MemoryDeallocate(pClientTrapInfo); DecrementTrapUsageCount(TrapNumber, PortGuid); exit: _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return Status; }
/** ========================================================================= */ int oib_open_port_by_num (struct oib_port **port, int hfiNum, uint8_t port_num) { FSTATUS fstatus; char name[IBV_SYSFS_NAME_MAX]; int num = -1; uint32_t ca_count; uint32_t port_count; IB_PORT_ATTRIBUTES *attrib = NULL; int ret_code; fstatus = oib_get_portguid(hfiNum, port_num, NULL, NULL, NULL, NULL, &attrib, &ca_count, &port_count, name, &num, NULL); if (fstatus != FSUCCESS) { if (fstatus != FNOT_FOUND || (ca_count == 0 || port_count == 0) || hfiNum > ca_count || port_num > port_count) { ret_code=EIO; goto done; } /* no active port was found for wildcard ca/port. * return EAGAIN so caller could query specific port/ca */ ret_code=EAGAIN; goto done; } ret_code = oib_open_port(port, name, num); // Remember the local guid for pa client if (ret_code >= 0 && port && *port && attrib) { (*port)->local_gid = attrib->GIDTable[0]; } done: if (attrib) MemoryDeallocate(attrib); return ret_code; }
void GsaUpdateCaList(void) { if (g_GsaGlobalInfo) { SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); if ( g_GsaGlobalInfo->SmObj.CaTbl ) { MemoryDeallocate( g_GsaGlobalInfo->SmObj.CaTbl ); g_GsaGlobalInfo->SmObj.CaTbl = NULL; /* for final RemoveDevice, NumCa = 0 and SmaCreateObj is a Noop * for AddDevice SmaCreateSmaObj will reinitialize NumCa */ g_GsaGlobalInfo->SmObj.NumCa--; } SmaCreateSmaObj( &g_GsaGlobalInfo->SmObj ); SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); } }
// client is deregistering from SD, remove all their trap registrations void UnsubscribeClient(ClientListEntry *pClientEntry) { LIST_ITEM *pClientTrapItem = QListRemoveHead(&pClientEntry->ClientTraps); _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, UnsubscribeClient); while (pClientTrapItem != NULL) { CLIENT_TRAP_INFO *pClientTrapInfo = (CLIENT_TRAP_INFO *)QListObj(pClientTrapItem); ASSERT(pClientTrapInfo != NULL); DecrementTrapUsageCount(pClientTrapInfo->TrapNumber, pClientTrapInfo->PortGuid); MemoryDeallocate(pClientTrapInfo); pClientTrapItem = QListRemoveHead(&pClientEntry->ClientTraps); } QListDestroy(&pClientEntry->ClientTraps); _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); }
void SubscribeTerminate() { LIST_ITEM *pTrapReferenceListItem; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SubscribeTerminate); SpinLockAcquire(&SubscribedTrapsListLock); SubscribeInitialized = 0; SpinLockRelease(&SubscribedTrapsListLock); iba_sd_deregister(SdClientHandle); /* no more SD callbacks will occur now, so OPQUEUED is not important */ SpinLockAcquire(&SubscribedTrapsListLock); while ( NULL != (pTrapReferenceListItem = QListRemoveHead(&SubscribedTrapsList))) { TRAP_REFERENCE *pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); ASSERT(pTrapReference != NULL); TimerStop(&pTrapReference->Timer); // release lock so TimerDestroy can wait for callback SpinLockRelease(&SubscribedTrapsListLock); TimerDestroy(&pTrapReference->Timer); MemoryDeallocate(pTrapReference); SpinLockAcquire(&SubscribedTrapsListLock); } SpinLockRelease(&SubscribedTrapsListLock); QListDestroy(&SubscribedTrapsList); SpinLockDestroy(&SubscribedTrapsListLock); _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); }
FSTATUS SMALoad( IN IBT_COMPONENT_INFO *ComponentInfo ) { FSTATUS status = FSUCCESS; _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaLoad); _DBG_INIT; _TRC_REGISTER(); #if !defined(VXWORKS) _DBG_PRINT(_DBG_LVL_MAIN, (" InfiniBand Subnet Management Agent. Built %s %s\n",\ __DATE__, __TIME__ )); #else _DBG_PRINT(_DBG_LVL_MAIN, (" InfiniBand Subnet Management Agent. Built %s %s\n",\ _DBG_PTR(__DATE__), _DBG_PTR(__TIME__) )); #endif // Establish dispatch entry points for the functions supported. MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) ); ComponentInfo->AddDevice = SmaAddDevice; ComponentInfo->RemoveDevice = SmaRemoveDevice; ComponentInfo->Unload = SMAUnload; // Read Global settings for the driver which may be set in a // OS specific way. SmaInitGlobalSettings(); // Allocate space for Global data g_Sma = (SMA_GLOBAL_INFO*)MemoryAllocate2AndClear(sizeof(SMA_GLOBAL_INFO), IBA_MEM_FLAG_PREMPTABLE, SMA_MEM_TAG); if ( NULL == g_Sma ) { _DBG_ERROR(("MemAlloc failed for g_Sma!\n")); goto done; } // initialize global data g_Sma->NumCa = 0; g_Sma->CaObj = NULL; g_Sma->WorkReqRecv = g_Sma->WorkReqSend = NULL; g_Sma->SmUserTbl = NULL; g_Sma->NumUser = 0; // SpinLockInitState( &g_Sma->Lock ) // SpinLockInit( &g_Sma->Lock ) // Init Storage area for MADs g_Sma->Bin.NumBlocks = 0; g_Sma->Bin.Head = g_Sma->Bin.Tail = NULL; g_Sma->Bin.MemList = NULL; g_Sma->Bin.CurrentIndex = 0; // set start mem index // Locks SpinLockInitState( &g_Sma->CaListLock ); SpinLockInit( &g_Sma->CaListLock ); SpinLockInitState( &g_Sma->Bin.Lock ); SpinLockInit( &g_Sma->Bin.Lock ); MutexInitState( &g_Sma->Bin.Mutex ); MutexInit( &g_Sma->Bin.Mutex ); SpinLockInitState( &g_Sma->RQ.Lock ); SpinLockInit( &g_Sma->RQ.Lock ); // Init Global Ibt user group for notifications IbtInitNotifyGroup(NotifyIbtCallback); // Allocate memory for Global GRH since the SMA does not need a GRH. // This memory will automatically get mapped to all CA registrations. g_Sma->GlobalGrh = CreateGlobalMemList( 0, sizeof(IB_GRH), 0, FALSE ); if ( NULL == g_Sma->GlobalGrh ) { status = FINSUFFICIENT_RESOURCES; goto failmemlist; } g_Sma->GlobalGrh->VirtualAddr = MemoryAllocate2AndClear(sizeof(IB_GRH), IBA_MEM_FLAG_PREMPTABLE, SMA_MEM_TAG); if ( NULL == g_Sma->GlobalGrh->VirtualAddr ) { status = FINSUFFICIENT_RESOURCES; goto failgrhvirt; } g_Sma->GlobalGrh->AccessControl.AsUINT16 = 0; g_Sma->GlobalGrh->AccessControl.s.LocalWrite = 1; g_Sma->GlobalGrh->CaMemIndex = 0; // Increment index for future allocations g_Sma->Bin.CurrentIndex++; done: _DBG_LEAVE_LVL(_DBG_LVL_MAIN); return status; failgrhvirt: MemoryDeallocate( g_Sma->GlobalGrh ); failmemlist: IbtDestroyNotifyGroup(); SpinLockDestroy( &g_Sma->RQ.Lock ); MutexDestroy( &g_Sma->Bin.Mutex ); SpinLockDestroy( &g_Sma->Bin.Lock ); SpinLockDestroy( &g_Sma->CaListLock ); MemoryDeallocate( g_Sma ); goto done; }
FSTATUS SmaAddDevice( IN EUI64 CaGuid, OUT void **Context ) { FSTATUS status = FSUCCESS; SMA_CA_OBJ_PRIVATE *pCaObj=NULL; uint32 i; _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaAddDevice); pCaObj = (SMA_CA_OBJ_PRIVATE*)MemoryAllocateAndClear(sizeof(SMA_CA_OBJ_PRIVATE), FALSE, SMA_MEM_TAG); if ( NULL == pCaObj ) { _DBG_ERROR(("MemAlloc failed for pCaObj/WorkReq!\n")); status = FINSUFFICIENT_MEMORY; goto done; } pCaObj->CaPublic.CaGuid = CaGuid; pCaObj->CaPublic.SmaCaContext = pCaObj; EventThreadInitState(&pCaObj->SmaEventThread); if (! EventThreadCreate(&pCaObj->SmaEventThread, "Smi", THREAD_PRI_VERY_HIGH, SmaCompletionCallback, pCaObj)) { _DBG_ERROR(("Sma Event Thread Create FAILED\n")); goto failsmathread; } EventThreadInitState(&pCaObj->GsaEventThread); if (! EventThreadCreate(&pCaObj->GsaEventThread, "Gsi", THREAD_PRI_VERY_HIGH, GsaCompletionThreadCallback, pCaObj)) { _DBG_ERROR(("Gsa Event Thread Create FAILED\n")); goto failgsathread; } status = iba_open_ca( CaGuid, SmaGsaCompletionCallback, SmaAsyncEventCallback, pCaObj/*Context*/, &pCaObj->CaHandle); if ( FSUCCESS != status ) { _DBG_ERROR(("OpenCA() failed!\n")); goto failopen; } status = SetCAInternal(pCaObj->CaHandle); if ( FSUCCESS != status ) { _DBG_ERROR(("SetCAInternal() failed!\n")); goto failinternal; } // Reserve CQ/QP/PD... status = SmaDeviceReserve( pCaObj ); if ( FSUCCESS != status ) { goto failreserve; } // we hold the Mutex across Bind and addition to Ca list // so that CreateDgrmPool cannot race and cause double // registration of memory in new DgrmPool AcquireMemListMutex(); status = SmaBindGlobalMem( pCaObj ); if (status != FSUCCESS) { ReleaseMemListMutex(); // TBD need to undo SmaDeviceReserve goto failreserve; } // lock // update global info SpinLockAcquire(&g_Sma->CaListLock); g_Sma->NumCa++; pCaObj->Next = g_Sma->CaObj; pCaObj->Prev = NULL; if ( NULL != g_Sma->CaObj ) g_Sma->CaObj->Prev = pCaObj; g_Sma->CaObj = pCaObj; pCaObj->UseCount++; // hold reference so we can use object below SpinLockRelease(&g_Sma->CaListLock); ReleaseMemListMutex(); // QPConfig status = SmaDeviceConfig( pCaObj, QPTypeSMI ); status = SmaDeviceConfig( pCaObj, QPTypeGSI ); // Create GSA data structures GsaUpdateCaList(); // Preallocate Buffers based on per device. // If we know the amount of buffers we need per device and go ahead // and allocate them in advance, subnet sweeps will not allocate // any buffers in the speed path // // NOTE: This call can fail if there are no system resources SmaAllocToBin( g_Settings.PreAllocSMPsPerDevice, FALSE ); // post some descriptors on recv side if port is up or something... for (i=0; i<pCaObj->CaPublic.Ports; i++) { status = iba_smi_post_recv( NULL, pCaObj, (uint8)(i+1), g_Settings.MinSMPsToPostPerPort ); } // Set Port capabilities across all CA's SetPortCapabilities(); // Rearm CQ to receive event notifications. // The next Work Completion written to the CQ // will generate an event status = iba_rearm_cq( pCaObj->CqHandle, CQEventSelNextWC); SpinLockAcquire(&g_Sma->CaListLock); pCaObj->UseCount--; SpinLockRelease(&g_Sma->CaListLock); // Bind // unlock // notify users through callbacks! IbtNotifyGroup( CaGuid, IB_NOTIFY_CA_ADD ); // TBD - failure above causes bad status return here, can confuse caller // also does not cleanup QPs, CQ, PD, MRs, buffers // SmaRemoveCaObj might solve, but not clear if safe to call it // need some peers to the SmaDeviceReserve and SmaDeviceConfig routines // to undo their effects done: _DBG_LEAVE_LVL(_DBG_LVL_MAIN); return status; failreserve: failinternal: iba_close_ca( pCaObj->CaHandle ); failopen: EventThreadDestroy(&pCaObj->GsaEventThread); failgsathread: EventThreadDestroy(&pCaObj->SmaEventThread); failsmathread: MemoryDeallocate( pCaObj ); goto done; }
FSTATUS MulticastTerminate(void) { FSTATUS Status; CLIENT_HANDLE McSdHandleTemp; LIST_ITEM *pListItem; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, MulticastTerminate); /* Just in case maintenance routine is running */ SpinLockAcquire(&MulticastLock); McSdHandleTemp = McSdHandle; McSdHandle = NULL; SpinLockRelease(&MulticastLock); if (McSdHandleTemp == NULL) { _DBG_ERROR(("Multicast Module Not A Registered Subnet Driver " "Client Process.\n")); Status = FINVALID_STATE; goto exit; } if (MaintenanceTimerActivated == TRUE) { TimerStop(&MaintenanceTimer); MaintenanceTimerActivated = FALSE; } Status = iba_sd_deregister(McSdHandleTemp); if (Status != FSUCCESS) { _DBG_ERROR(("Cannot Deregister With " "Subnet Data Interface.\n")); } for (pListItem = QListRemoveHead(&MasterMcGroupList); pListItem != NULL; pListItem = QListRemoveHead(&MasterMcGroupList)) { MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); ASSERT(pMcGroup != NULL); TimerStop(&pMcGroup->Timer); TimerDestroy(&pMcGroup->Timer); QListDestroy(&pMcGroup->McClientList); MemoryDeallocate(pMcGroup); } for (pListItem = QListRemoveHead(&MasterMcClientList); pListItem != NULL; pListItem = QListRemoveHead(&MasterMcClientList)) { MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); ASSERT(pMcClient != NULL); MemoryDeallocate(pMcClient); } QListDestroy(&MasterMcGroupList); QListDestroy(&MasterMcClientList); TimerDestroy(&MaintenanceTimer); SpinLockDestroy(&MulticastLock); exit: _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return Status; }
FSTATUS iba_sd_trap_notice_subscribe(CLIENT_HANDLE ClientHandle, uint16 TrapNumber, EUI64 PortGuid, void *pContext, SD_REPORT_NOTICE_CALLBACK *pReportNoticeCallback) { FSTATUS Status; CLIENT_CONTROL_PARAMETERS ClientParams; ClientListEntry *pClientEntry = (ClientListEntry *)ClientHandle; CLIENT_TRAP_INFO *pClientTrapInfo; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_trap_notice_subscribe); Status = ValidateClientHandle(ClientHandle, &ClientParams); if (Status != FSUCCESS) { _DBG_ERROR(("Invalid Client Handle Specified\n")); goto exit; } SpinLockAcquire(pClientListLock); pClientTrapInfo = FindClientTrapInfo(&pClientEntry->ClientTraps, TrapNumber, PortGuid); if (pClientTrapInfo != NULL) { // Already Subscribed Status = FDUPLICATE; SpinLockRelease(pClientListLock); goto exit; } SpinLockRelease(pClientListLock); pClientTrapInfo = (CLIENT_TRAP_INFO*)MemoryAllocate2AndClear(sizeof(CLIENT_TRAP_INFO), IBA_MEM_FLAG_NONE, SUBNET_DRIVER_TAG); if (pClientTrapInfo == NULL) { Status = FINSUFFICIENT_MEMORY; goto exit; } pClientTrapInfo->TrapNumber = TrapNumber; pClientTrapInfo->PortGuid = PortGuid; pClientTrapInfo->pContext = pContext; pClientTrapInfo->pReportNoticeCallback = pReportNoticeCallback; QListSetObj(&pClientTrapInfo->ListItem, pClientTrapInfo); SpinLockAcquire(pClientListLock); QListInsertTail(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); SpinLockRelease(pClientListLock); Status = IncrementTrapUsageCount(TrapNumber, PortGuid); if (Status != FSUCCESS) { SpinLockAcquire(pClientListLock); QListRemoveItem(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); SpinLockRelease(pClientListLock); MemoryDeallocate(pClientTrapInfo); } exit: _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return Status; }
static FSTATUS IncrementMcGroupUsageCount(CLIENT_HANDLE SdClientHandle, void *pContext, SD_MULTICAST_CALLBACK *pMulticastCallback, uint16 McFlags, uint64 ComponentMask, IB_MCMEMBER_RECORD *pMcMemberRecord, MC_GROUP_ID *pMcGroupId) { MC_CLIENT *pMcClientTemp; MC_CLIENT *pMcClient = NULL; MC_GROUP *pMcGroupTemp; MC_GROUP *pMcGroup = NULL; boolean StartTrapNotification; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IncrementMcGroupUsageCount); /* Allocate Everything up front to avoid locking issues */ pMcClientTemp = (MC_CLIENT *)MemoryAllocate2AndClear(sizeof(MC_CLIENT), IBA_MEM_FLAG_NONE, SUBNET_DRIVER_TAG); if (pMcClientTemp == NULL) { _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return FINSUFFICIENT_MEMORY; } pMcClientTemp->SdClientHandle = SdClientHandle; pMcClientTemp->pContext = pContext; pMcClientTemp->McFlags = McFlags; pMcClientTemp->pMulticastCallback = pMulticastCallback; pMcGroupTemp = (MC_GROUP*)MemoryAllocate2AndClear(sizeof(MC_GROUP), IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); if (pMcGroupTemp == NULL) { _DBG_ERROR(("IncrementMcGroupUsageCount MemoryAllocateError\n")); MemoryDeallocate(pMcClientTemp); _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return FINSUFFICIENT_MEMORY; } SpinLockAcquire(&MulticastLock); pMcClient = FindMcClient(SdClientHandle, pMcGroupId); if (pMcClient == NULL) { pMcClient= pMcClientTemp; pMcClientTemp = NULL; } else { _DBG_ERROR(("IncrementMcGroupUsageCount Client already exists.\n")); /*SpinLockRelease(&MulticastLock); MemoryDeallocate(pMcGroupTemp); MemoryDeallocate(pMcClient); _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return FDUPLICATE;*/ // continue anyway } StartTrapNotification = QListIsEmpty(&MasterMcGroupList); pMcGroup = FindMcGroup(pMcGroupId); if (pMcGroup == NULL) { // didn't find Mcgroup in list, let us add one pMcGroupTemp->McGroupState = MC_GROUP_STATE_REQUEST_JOIN; pMcGroupTemp->ComponentMask = ComponentMask; pMcGroupTemp->McMemberRecord = *pMcMemberRecord; pMcGroupTemp->McGroupId = *pMcGroupId; QListInit(&pMcGroupTemp->McClientList); QListSetObj(&pMcGroupTemp->ListItem, pMcGroupTemp); pMcGroup = pMcGroupTemp; pMcGroupTemp = NULL; QListInsertTail(&MasterMcGroupList, &pMcGroup->ListItem); TimerInitState(&pMcGroup->Timer); TimerInit(&pMcGroup->Timer, IssueSubnetDriverCall, pMcGroup ); } else { // group already exists - check state if ( (pMcGroup->McGroupState != MC_GROUP_STATE_REQUEST_JOIN) && (pMcGroup->McGroupState != MC_GROUP_STATE_AVAILABLE) ) { if (pMcGroup->McGroupState == MC_GROUP_STATE_JOIN_FAILED) { _DBG_ERROR(("Prior attempt to join Multicast Group failed\n")); } else { _DBG_ERROR(("IncrementMcGroupUsageCount McGroup invalid state:%d.\n", pMcGroup->McGroupState)); } SpinLockRelease(&MulticastLock); MemoryDeallocate(pMcGroupTemp); if(pMcClientTemp) MemoryDeallocate(pMcClientTemp); _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return FDUPLICATE; } } pMcClient->pMcGroup = pMcGroup; QListSetObj(&pMcClient->ListItem, pMcClient); QListInsertTail(&MasterMcClientList, &pMcClient->ListItem); QListSetObj(&pMcClient->McGroupListItem, pMcClient); QListInsertTail(&pMcGroup->McClientList, &pMcClient->McGroupListItem); if (pMcGroupTemp == NULL) { /* First client joining the group - Get The Process Started */ _DBG_INFO(("new mcgroup - queuing join\n")); QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); } else { _DBG_INFO(("existing mcgroup - checking flags %d\n", pMcGroup->McGroupState)); if ((McJoinFlagsAdjusted(pMcGroup, pMcMemberRecord) == TRUE) && (pMcGroup->McGroupState == MC_GROUP_STATE_AVAILABLE)) // TODO: Check Concurrency Here /* we had already joined and the flags changes - so rejoin */ { _DBG_INFO(("flags changed after we joined - rejoining \n")); QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); } else if (pMcGroup->McGroupState == MC_GROUP_STATE_AVAILABLE) { // we already had joined but we got a new client - issue callbacks _DBG_INFO(("someone joined when state is available - issuing callbacks \n")); CallMcClients(pMcGroup, FSUCCESS, MC_GROUP_STATE_AVAILABLE); } // NOTE if state is JOIN, then when that completes all clients // including new one will be notified via callback } if (MaintenanceTimerActivated == FALSE) { MaintenanceTimerActivated = TRUE; TimerStart(&MaintenanceTimer, 5000); } SpinLockRelease(&MulticastLock); if (StartTrapNotification) { McSubscribeForTraps(); } if (pMcGroupTemp) { TimerDestroy(&pMcGroupTemp->Timer); QListDestroy(&pMcGroupTemp->McClientList); MemoryDeallocate(pMcGroupTemp); } if (pMcClientTemp) { MemoryDeallocate(pMcClientTemp); } _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); return FSUCCESS; }
////////////////////////////////////////////////////////////////////////// // BmaAddDevice() // // This routine is called once for every new device added. // // INPUTS: // CaGuid - the channel adapters GUID // // OUTPUTS: // // None. Although function is defined to return context value, this // value is not set since their is nothing specifically allocated for // each new channel adapter, so nothing is done in the BmaRemoveDevice // function that needs the context. // // RETURNS: // // FSUCCESS - Indicates a successful initialization. // // FSTATUS BmaAddDevice( IN EUI64 CaGuid, OUT void **Context ) { FSTATUS status = FSUCCESS; uint32 BufferSize; BMA_DEV_INFO *pDevInfo=NULL; _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaAddDevice); ASSERT(g_BmaGlobalInfo); if (!g_BmaGlobalInfo->binitsuccess) { // Create the datagram pool BufferSize = sizeof(PERF_MAD); status = iba_gsi_create_dgrm_pool(g_BmaGlobalInfo->GsaHandle, g_BmaSettings.MaxNDgrm, 1, &BufferSize, 0, //1, &g_BmaGlobalInfo->DgrmPoolHandle ); if (status != FSUCCESS) { // Cleanup iba_gsi_deregister_class(g_BmaGlobalInfo->GsaHandle); MemoryDeallocate(g_BmaGlobalInfo); g_BmaGlobalInfo = NULL; _DBG_ERROR(("Unable to create BMA datagram pool!!! <status %d>\n", status)); } else { g_BmaGlobalInfo->binitsuccess = TRUE; } } if (g_BmaGlobalInfo->binitsuccess) { pDevInfo = (BMA_DEV_INFO*)MemoryAllocateAndClear(sizeof(BMA_DEV_INFO), FALSE, BMA_TAG ); if (pDevInfo) { IB_CA_ATTRIBUTES CaAttributes; pDevInfo->CaGuid = CaGuid; status = iba_query_ca_by_guid_alloc(CaGuid, &CaAttributes); if ( status == FSUCCESS ) { pDevInfo->NumPorts = CaAttributes.Ports; pDevInfo->Port = (BMA_PORT_INFO*) MemoryAllocateAndClear(sizeof(BMA_PORT_INFO)*pDevInfo->NumPorts, FALSE, BMA_TAG); if (pDevInfo->Port) { IB_PORT_ATTRIBUTES *pPortAttr; unsigned i; for ( i = 0, pPortAttr = CaAttributes.PortAttributesList; i < pDevInfo->NumPorts; i++, pPortAttr = pPortAttr->Next ) { // Traps disabled by default, Trap settings are all zero // BKey, BKeyProtect, BKeyViolations, and BKeyLease all init to zero pDevInfo->Port[i].Guid = pPortAttr->GUID; } MemoryDeallocate(CaAttributes.PortAttributesList); // Success, add this CA to the list SpinLockAcquire( &g_BmaGlobalInfo->DevListLock ); pDevInfo->Next = g_BmaGlobalInfo->DevList; g_BmaGlobalInfo->DevList = pDevInfo; SpinLockRelease( &g_BmaGlobalInfo->DevListLock ); } else { _DBG_ERROR(("MemAlloc failed for Port List!\n")); status = FINSUFFICIENT_MEMORY; } } else { _DBG_ERROR(("CA Query Failed!\n")); MemoryDeallocate(pDevInfo); } } else { _DBG_ERROR(("MemAlloc failed for pDevInfo!\n")); status = FINSUFFICIENT_MEMORY; } } _DBG_LEAVE_LVL(_DBG_LVL_MAIN); return status; } // BmaAddDevice()
uint32 iba_gsi_coalesce_dgrm2( IN IBT_DGRM_ELEMENT *DgrmElement, IN uint8 **ppBuffer, IN uint32 ClassHeaderSize, IN uint32 MemAllocFlags ) { uint32 messageSize = 0; uint32 byteCount, totalBytesToCopy; IBT_ELEMENT *pElement; IBT_BUFFER *pBufferHdr; uint8 *pBuffer; MAD_RMPP *pMadRmpp; #ifdef TEST_DUMP static int counter; #endif _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_coalesce_dgrm); pElement = &DgrmElement->Element; pBufferHdr = pElement->pBufferList; pMadRmpp = (MAD_RMPP*)pBufferHdr->pNextBuffer->pData;// 2nd buffer is MAD // Calculate total bytes to copy. // Each buffer has a GRH+Mad Common Header+RMPP Header+ClassHeader+RMPP Data // // We copy only one copy of the headers and coalesce the data messageSize = totalBytesToCopy = iba_gsi_dgrm_len(DgrmElement, ClassHeaderSize); if (! messageSize) goto fail; _DBG_PRINT(_DBG_LVL_POOL,("Total bytes to copy: %d\n", totalBytesToCopy)); if (*ppBuffer == NULL) { *ppBuffer = (uint8*)MemoryAllocate2(totalBytesToCopy, MemAllocFlags, GSA_MEM_TAG); if (*ppBuffer == NULL) goto fail; } pBuffer = *ppBuffer; // Copy GRH if (pBufferHdr->ByteCount != sizeof(IB_GRH)) { _DBG_ERROR(("Bad buffer header size: %u expected %u\n", pBufferHdr->ByteCount, (unsigned)sizeof(IB_GRH))); messageSize = 0; // indicate invalid packets goto fail; } byteCount = pBufferHdr->ByteCount; MemoryCopy( pBuffer, pBufferHdr->pData, byteCount ); pBuffer += byteCount; totalBytesToCopy -= byteCount; // keep count pBufferHdr = pBufferHdr->pNextBuffer; // Copy Mad Common + RMPP Header + class header + first data area byteCount = (totalBytesToCopy > pBufferHdr->ByteCount) ? \ pBufferHdr->ByteCount:totalBytesToCopy; MemoryCopy( pBuffer, pBufferHdr->pData, byteCount ); pBuffer += byteCount; totalBytesToCopy -= byteCount; // keep count // Walk all elements of RMPP list while ( totalBytesToCopy ) { pElement = pElement->pNextElement; if ( NULL == pElement ) { _DBG_ERROR(("LIST ERROR DgrmElement %p ClassHeaderSize %d messageSize %d BytesLeft %d\n", _DBG_PTR(DgrmElement), ClassHeaderSize, messageSize, totalBytesToCopy)); DumpDgrmElement(DgrmElement); messageSize = 0; // indicate invalid packets/buffers goto fail; } else { #ifdef TEST_DUMP if ((++counter%50) == 0) { _DBG_ERROR(("LIST ERROR DgrmElement %p ClassHeaderSize %d messageSize %d BytesLeft %d\n", _DBG_PTR(DgrmElement), ClassHeaderSize, messageSize, totalBytesToCopy)); DumpDgrmElement(DgrmElement); messageSize = 0; // indicate invalid packets/buffers goto fail; } #endif } // skip GRH pBufferHdr = pElement->pBufferList->pNextBuffer; pMadRmpp = (MAD_RMPP *)pBufferHdr->pData; // copy as much class data as is left in packet // subtract common headers, if packet too small, don't copy anything byteCount = (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + ClassHeaderSize); byteCount = (byteCount > pBufferHdr->ByteCount)? \ 0:(pBufferHdr->ByteCount - byteCount); byteCount = (totalBytesToCopy > byteCount)?byteCount:totalBytesToCopy; if (byteCount) { MemoryCopy( pBuffer, &pMadRmpp->Data[ClassHeaderSize], byteCount); pBuffer += byteCount; totalBytesToCopy -= byteCount; // keep count } } _DBG_LEAVE_LVL(_DBG_LVL_POOL); return messageSize; fail: if (*ppBuffer) { MemoryDeallocate(*ppBuffer); *ppBuffer = NULL; } _DBG_LEAVE_LVL(_DBG_LVL_POOL); return messageSize; }
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; }
static void McMaintenance(void *pContext) { LIST_ITEM *pListItem; _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McMaintenance); if (McSdHandle != NULL) { SpinLockAcquire(&MulticastLock); if (TimerCallbackStopped(&MaintenanceTimer)) { // stale timer callback SpinLockRelease(&MulticastLock); goto done; } // Loop Through MasterMcClientList pListItem = QListHead(&MasterMcClientList); while(pListItem != NULL) { MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); ASSERT(pMcClient != NULL); pListItem = QListNext(&MasterMcClientList, pListItem); if ((pMcClient->McClientDelete == TRUE) && (pMcClient->McClientInUse == 0)) { QListRemoveItem(&MasterMcClientList, &pMcClient->ListItem); SpinLockRelease(&MulticastLock); MemoryDeallocate(pMcClient); if (McSdHandle == NULL) { break; } SpinLockAcquire(&MulticastLock); } } } if (McSdHandle != NULL) { // Loop Through MasterMcGroupList pListItem = QListHead(&MasterMcGroupList); while(pListItem != NULL) { MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); ASSERT(pMcGroup != NULL); pListItem = QListNext(&MasterMcGroupList, pListItem); if ((pMcGroup->McGroupDelete == TRUE) && (pMcGroup->McGroupInUse == 0)) { TimerDestroy(&pMcGroup->Timer); QListDestroy(&pMcGroup->McClientList); QListRemoveItem(&MasterMcGroupList, &pMcGroup->ListItem); SpinLockRelease(&MulticastLock); MemoryDeallocate(pMcGroup); if (McSdHandle == NULL) { break; } SpinLockAcquire(&MulticastLock); } } } if (McSdHandle != NULL) { if (!QListIsEmpty(&MasterMcGroupList) || !QListIsEmpty(&MasterMcClientList)) { /* Only Start It If There Is A Possibility Of Something To Do */ TimerStart(&MaintenanceTimer, 5000); SpinLockRelease(&MulticastLock); } else { McUnsubscribeForTraps(); MaintenanceTimerActivated = FALSE; SpinLockRelease(&MulticastLock); } } done: _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); }