Blame IbAccess/Common/Ibt/Sma/ibnotify.c

Packit Service 3470d1
/* BEGIN_ICS_COPYRIGHT4 ****************************************
Packit Service 3470d1
Packit Service 3470d1
Copyright (c) 2015, Intel Corporation
Packit Service 3470d1
Packit Service 3470d1
Redistribution and use in source and binary forms, with or without
Packit Service 3470d1
modification, are permitted provided that the following conditions are met:
Packit Service 3470d1
Packit Service 3470d1
    * Redistributions of source code must retain the above copyright notice,
Packit Service 3470d1
      this list of conditions and the following disclaimer.
Packit Service 3470d1
    * Redistributions in binary form must reproduce the above copyright
Packit Service 3470d1
      notice, this list of conditions and the following disclaimer in the
Packit Service 3470d1
     documentation and/or other materials provided with the distribution.
Packit Service 3470d1
    * Neither the name of Intel Corporation nor the names of its contributors
Packit Service 3470d1
      may be used to endorse or promote products derived from this software
Packit Service 3470d1
      without specific prior written permission.
Packit Service 3470d1
Packit Service 3470d1
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit Service 3470d1
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 3470d1
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit Service 3470d1
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit Service 3470d1
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 3470d1
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit Service 3470d1
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit Service 3470d1
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit Service 3470d1
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 3470d1
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 3470d1
Packit Service 3470d1
** END_ICS_COPYRIGHT4   ****************************************/
Packit Service 3470d1
Packit Service 3470d1
#include "ibnotify.h"
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// Globals
Packit Service 3470d1
//
Packit Service 3470d1
IBT_NOTIFY_GROUP	NotifyGroup;
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// Initialize the Notify Group
Packit Service 3470d1
//
Packit Service 3470d1
//INPUT:
Packit Service 3470d1
// 	Callback - when a new User is added to the Notify group, this routine
Packit Service 3470d1
//		is called to distribute initial events to User
Packit Service 3470d1
void
Packit Service 3470d1
IbtInitNotifyGroup (
Packit Service 3470d1
   IN	IB_ROOT_CALLBACK		Callback
Packit Service 3470d1
   )
Packit Service 3470d1
{
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtInitNotifyGroup );
Packit Service 3470d1
Packit Service 3470d1
	ASSERT(! NotifyGroup.Initialized);
Packit Service 3470d1
Packit Service 3470d1
	MapInitState( &NotifyGroup.Lists );
Packit Service 3470d1
	SpinLockInitState( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	if (MapInit( &NotifyGroup.Lists ) != FSUCCESS)
Packit Service 3470d1
	{
Packit Service 3470d1
		_DBG_ERROR (("Failed to Initialize Notification Map\n"));
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (SpinLockInit( &NotifyGroup.Lock ) == FALSE)
Packit Service 3470d1
	{
Packit Service 3470d1
		_DBG_ERROR (("Failed to Initialize Notification lock\n"));
Packit Service 3470d1
		goto faillock;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// Add root callback for new users
Packit Service 3470d1
	ASSERT ( Callback );
Packit Service 3470d1
	NotifyGroup.RootCallback = Callback;
Packit Service 3470d1
Packit Service 3470d1
	NotifyGroup.Initialized = TRUE;
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
	return;
Packit Service 3470d1
Packit Service 3470d1
faillock:
Packit Service 3470d1
	MapDestroy ( &NotifyGroup.Lists );
Packit Service 3470d1
	goto done;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// Cleanup for shutdown
Packit Service 3470d1
void
Packit Service 3470d1
IbtDestroyNotifyGroup ( void )
Packit Service 3470d1
{
Packit Service 3470d1
	QUICK_LIST				*pList;
Packit Service 3470d1
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtDestroyNotifyGroup );
Packit Service 3470d1
Packit Service 3470d1
	if (! NotifyGroup.Initialized)
Packit Service 3470d1
		goto done;
Packit Service 3470d1
Packit Service 3470d1
	// Empty list contents
Packit Service 3470d1
	SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	while (NULL != (pList = (QUICK_LIST*)MapRemoveHead(&NotifyGroup.Lists)))
Packit Service 3470d1
	{
Packit Service 3470d1
		LIST_ITEM				*pListItem;
Packit Service 3470d1
Packit Service 3470d1
		while (NULL != (pListItem = QListRemoveHead(pList)))
Packit Service 3470d1
		{
Packit Service 3470d1
			IBT_NOTIFY_USER_BLOCK	*pUser = (IBT_NOTIFY_USER_BLOCK *)pListItem;
Packit Service 3470d1
			MemoryDeallocate( pUser );
Packit Service 3470d1
		}	
Packit Service 3470d1
		QListDestroy(pList);
Packit Service 3470d1
		MemoryDeallocate(pList);
Packit Service 3470d1
	}
Packit Service 3470d1
	NotifyGroup.Initialized = FALSE;
Packit Service 3470d1
Packit Service 3470d1
	SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	MapDestroy( &NotifyGroup.Lists );
Packit Service 3470d1
	SpinLockDestroy( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Notify all users in pList of pRec event
Packit Service 3470d1
void
Packit Service 3470d1
IbtNotifyList(
Packit Service 3470d1
	QUICK_LIST				*pList,
Packit Service 3470d1
	IB_NOTIFY_RECORD		*pRec
Packit Service 3470d1
	 )
Packit Service 3470d1
{
Packit Service 3470d1
	LIST_ITEM				*pListFirst;
Packit Service 3470d1
	IBT_NOTIFY_USER_BLOCK	*pUser;
Packit Service 3470d1
Packit Service 3470d1
	pListFirst = QListHead( pList );
Packit Service 3470d1
			
Packit Service 3470d1
	while (pListFirst)
Packit Service 3470d1
	{
Packit Service 3470d1
		// If event has been subscribed by user, notify
Packit Service 3470d1
		if ( pRec->EventType & ((IBT_NOTIFY_USER_BLOCK *)pListFirst)->EventMask)
Packit Service 3470d1
		{
Packit Service 3470d1
			pUser = (IBT_NOTIFY_USER_BLOCK *)pListFirst;
Packit Service 3470d1
			pRec->Context = pUser->Context;
Packit Service 3470d1
			if (pUser->Locking == IB_NOTIFY_ASYNC)
Packit Service 3470d1
			{
Packit Service 3470d1
				pUser->RefCount++;
Packit Service 3470d1
				SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
				( pUser->Callback )( *pRec );
Packit Service 3470d1
				SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
				pListFirst = QListNext( pList, pListFirst );
Packit Service 3470d1
				if (--(pUser->RefCount) == 0)
Packit Service 3470d1
				{
Packit Service 3470d1
					QListRemoveItem ( pList, &pUser->ListItem );
Packit Service 3470d1
					MemoryDeallocate( pUser );
Packit Service 3470d1
				}
Packit Service 3470d1
				continue;
Packit Service 3470d1
			} else {
Packit Service 3470d1
				ASSERT(pUser->RefCount);
Packit Service 3470d1
				( pUser->Callback )( *pRec );
Packit Service 3470d1
			}
Packit Service 3470d1
		}
Packit Service 3470d1
		pListFirst = QListNext( pList, pListFirst );
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Notify all registered clients of an event against the given Guid
Packit Service 3470d1
void
Packit Service 3470d1
IbtNotifyGroup (
Packit Service 3470d1
	IN	EUI64				Guid,			// Port/Node GUID
Packit Service 3470d1
	IN	IB_NOTIFY_TYPE		EventType		// Type of event being reported
Packit Service 3470d1
	)
Packit Service 3470d1
{
Packit Service 3470d1
	IB_NOTIFY_RECORD		Rec;
Packit Service 3470d1
	QUICK_LIST*				pList;
Packit Service 3470d1
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtNotifyGroup );
Packit Service 3470d1
Packit Service 3470d1
	_DBG_PRINT( _DBG_LVL_IBT_API,(
Packit Service 3470d1
				"NotifyGroup\n"
Packit Service 3470d1
				"\tEventType...:%"PRIxN"\n"
Packit Service 3470d1
				"\tGUID........:x%016"PRIx64"\n",
Packit Service 3470d1
				EventType, 
Packit Service 3470d1
				Guid ));
Packit Service 3470d1
Packit Service 3470d1
	if (! NotifyGroup.Initialized)
Packit Service 3470d1
		goto done;
Packit Service 3470d1
Packit Service 3470d1
	// Fill in common record info
Packit Service 3470d1
	Rec.Guid = Guid;
Packit Service 3470d1
	Rec.EventType = EventType;
Packit Service 3470d1
Packit Service 3470d1
	SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
		
Packit Service 3470d1
	// iterate on List in Map for Guid, then map for Guid==0
Packit Service 3470d1
	pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, Guid);
Packit Service 3470d1
	if (pList != NULL)
Packit Service 3470d1
	{
Packit Service 3470d1
		IbtNotifyList(pList, &Rec;;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, 0);
Packit Service 3470d1
	if (pList != NULL)
Packit Service 3470d1
	{
Packit Service 3470d1
		IbtNotifyList(pList, &Rec;;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Send a notification to a single registered notify client
Packit Service 3470d1
// used as part of RootCallback to send initial events to a newly
Packit Service 3470d1
// registered client
Packit Service 3470d1
// returns FALSE if client has deregistered itself in callback
Packit Service 3470d1
boolean
Packit Service 3470d1
IbtNotifyUserEvent (
Packit Service 3470d1
	IN	void				*UserContext,
Packit Service 3470d1
	IN	EUI64				Guid,			// Port/Node GUID
Packit Service 3470d1
	IN	IB_NOTIFY_TYPE		EventType		// Type of event being reported
Packit Service 3470d1
	)
Packit Service 3470d1
{
Packit Service 3470d1
	IB_NOTIFY_RECORD		Rec;
Packit Service 3470d1
	IBT_NOTIFY_USER_BLOCK	*pUser = (IBT_NOTIFY_USER_BLOCK*)UserContext;
Packit Service 3470d1
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtNotifyUserEvent );
Packit Service 3470d1
Packit Service 3470d1
	_DBG_PRINT( _DBG_LVL_IBT_API,(
Packit Service 3470d1
			"NotifyGroup\n"
Packit Service 3470d1
			"\tEventType...:%"PRIxN"\n"
Packit Service 3470d1
			"\tGUID........:x%016"PRIx64"\n",
Packit Service 3470d1
			EventType, 
Packit Service 3470d1
			Guid ));
Packit Service 3470d1
Packit Service 3470d1
	if (! NotifyGroup.Initialized)
Packit Service 3470d1
	{
Packit Service 3470d1
		pUser = NULL;	// no more notifications needed
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// Fill in common record info
Packit Service 3470d1
	Rec.Guid = Guid;
Packit Service 3470d1
	Rec.EventType = EventType;
Packit Service 3470d1
Packit Service 3470d1
	SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	// If event has been subscribed by user, notify
Packit Service 3470d1
	if ( ( EventType & pUser->EventMask )
Packit Service 3470d1
		&& (pUser->Guid == 0 || pUser->Guid == Guid))
Packit Service 3470d1
	{
Packit Service 3470d1
		Rec.Context = pUser->Context;
Packit Service 3470d1
		if (pUser->Locking == IB_NOTIFY_ASYNC)
Packit Service 3470d1
		{
Packit Service 3470d1
			pUser->RefCount++;
Packit Service 3470d1
			SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
			( pUser->Callback )( Rec );
Packit Service 3470d1
			SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
			if (--(pUser->RefCount) == 0)
Packit Service 3470d1
			{
Packit Service 3470d1
				QUICK_LIST*				pList;
Packit Service 3470d1
Packit Service 3470d1
				pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, pUser->Guid);
Packit Service 3470d1
				if (pList != NULL)
Packit Service 3470d1
					QListRemoveItem ( pList, &pUser->ListItem );
Packit Service 3470d1
				MemoryDeallocate( pUser );
Packit Service 3470d1
				pUser = NULL;
Packit Service 3470d1
			}
Packit Service 3470d1
		} else {
Packit Service 3470d1
			ASSERT(pUser->RefCount);
Packit Service 3470d1
			( pUser->Callback )( Rec );
Packit Service 3470d1
		}
Packit Service 3470d1
	} 
Packit Service 3470d1
Packit Service 3470d1
	SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
	return (pUser != NULL);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// iba_register_notify
Packit Service 3470d1
//
Packit Service 3470d1
//	The caller uses this API to register for notifications of IB type events
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// INPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//	Callback		-Callback routine to be registered for notifications
Packit Service 3470d1
//
Packit Service 3470d1
//	Context			-User specified context to return in callbacks
Packit Service 3470d1
//	
Packit Service 3470d1
//	EventMask		-Mask to subscribe to event types
Packit Service 3470d1
//
Packit Service 3470d1
//	Locking			-locking model for callback
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// OUTPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//	NotifyHandle	-Notification handle on successful registration
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// RETURNS:
Packit Service 3470d1
//
Packit Service 3470d1
//	FSUCCESS
Packit Service 3470d1
//	FINSUFFICIENT_MEMORY
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
FSTATUS
Packit Service 3470d1
iba_register_notify (
Packit Service 3470d1
	IN	IB_NOTIFY_CALLBACK	Callback,
Packit Service 3470d1
	IN	void				*Context,
Packit Service 3470d1
	IN	IB_NOTIFY_TYPE		EventMask,
Packit Service 3470d1
	IN	IB_NOTIFY_LOCKING	Locking,
Packit Service 3470d1
	OUT	IB_HANDLE			*NotifyHandle
Packit Service 3470d1
	)
Packit Service 3470d1
{
Packit Service 3470d1
	FSTATUS					status	= FSUCCESS;
Packit Service 3470d1
	
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_register_notify );
Packit Service 3470d1
	status = iba_register_guid_notify(0, Callback, Context, EventMask, Locking, NotifyHandle);
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
	return status;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// iba_register_guid_notify
Packit Service 3470d1
//
Packit Service 3470d1
//	The caller uses this API to register for notifications of IB type events
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// INPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//	Guid			-Guid user is interested in
Packit Service 3470d1
//
Packit Service 3470d1
//	Callback		-Callback routine to be registered for notifications
Packit Service 3470d1
//
Packit Service 3470d1
//	Context			-User specified context to return in callbacks
Packit Service 3470d1
//	
Packit Service 3470d1
//	EventMask		-Mask to subscribe to event types
Packit Service 3470d1
//
Packit Service 3470d1
//	Locking			-locking model for callback
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// OUTPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//	NotifyHandle	-Notification handle on successful registration
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// RETURNS:
Packit Service 3470d1
//
Packit Service 3470d1
//	FSUCCESS
Packit Service 3470d1
//	FINSUFFICIENT_MEMORY
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
FSTATUS
Packit Service 3470d1
iba_register_guid_notify (
Packit Service 3470d1
	IN  EUI64				Guid,
Packit Service 3470d1
	IN	IB_NOTIFY_CALLBACK	Callback,
Packit Service 3470d1
	IN	void				*Context,
Packit Service 3470d1
	IN	IB_NOTIFY_TYPE		EventMask,
Packit Service 3470d1
	IN	IB_NOTIFY_LOCKING	Locking,
Packit Service 3470d1
	OUT	IB_HANDLE			*NotifyHandle
Packit Service 3470d1
	)
Packit Service 3470d1
{
Packit Service 3470d1
	FSTATUS					status	= FSUCCESS;
Packit Service 3470d1
	IBT_NOTIFY_USER_BLOCK	*pUser;
Packit Service 3470d1
	QUICK_LIST *pList;
Packit Service 3470d1
	
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_register_notify );
Packit Service 3470d1
Packit Service 3470d1
	if (! NotifyGroup.Initialized)
Packit Service 3470d1
	{
Packit Service 3470d1
		status = FINVALID_STATE;
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// Allocate memory to hold user registration
Packit Service 3470d1
	pUser = (IBT_NOTIFY_USER_BLOCK*)MemoryAllocateAndClear(
Packit Service 3470d1
										sizeof(IBT_NOTIFY_USER_BLOCK), FALSE,
Packit Service 3470d1
										IBT_NOTIFY_TAG );
Packit Service 3470d1
	if ( !pUser )
Packit Service 3470d1
	{
Packit Service 3470d1
		status = FINSUFFICIENT_MEMORY;
Packit Service 3470d1
		_DBG_ERROR(("%s\n", _DBG_PTR(FSTATUS_MSG(status))));
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// Fill in user details
Packit Service 3470d1
	pUser->Guid = Guid;	// all Guids
Packit Service 3470d1
	pUser->Callback = Callback;
Packit Service 3470d1
	pUser->Context = Context;
Packit Service 3470d1
	pUser->RefCount = 1;
Packit Service 3470d1
	pUser->EventMask = EventMask;
Packit Service 3470d1
	pUser->Locking = Locking;
Packit Service 3470d1
Packit Service 3470d1
	// Save user list in group
Packit Service 3470d1
	SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
	pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, Guid);
Packit Service 3470d1
	if (pList == NULL)
Packit Service 3470d1
	{
Packit Service 3470d1
		pList = (QUICK_LIST*)MemoryAllocateAndClear( sizeof(QUICK_LIST), FALSE,
Packit Service 3470d1
										IBT_NOTIFY_TAG );
Packit Service 3470d1
		QListInitState(pList);
Packit Service 3470d1
		if (! QListInit(pList))
Packit Service 3470d1
		{
Packit Service 3470d1
			status = FINSUFFICIENT_RESOURCES;
Packit Service 3470d1
			goto faillist;
Packit Service 3470d1
		}
Packit Service 3470d1
		status = MapInsert(&NotifyGroup.Lists, Guid, pList);
Packit Service 3470d1
		if (status != FSUCCESS)
Packit Service 3470d1
		{
Packit Service 3470d1
			goto failmap;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	QListInsertHead( pList, &pUser->ListItem );
Packit Service 3470d1
	SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	*NotifyHandle = pUser;
Packit Service 3470d1
Packit Service 3470d1
	_DBG_PRINT(_DBG_LVL_IBT_API,("Created entry x%p\n", _DBG_PTR(pUser)));
Packit Service 3470d1
Packit Service 3470d1
	if (EventMask & IB_NOTIFY_ON_REGISTER)
Packit Service 3470d1
	{
Packit Service 3470d1
		// Notify Root to pass user initial events
Packit Service 3470d1
		ASSERT (( NotifyGroup.RootCallback ));
Packit Service 3470d1
		( NotifyGroup.RootCallback )( pUser );
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
	return status;
Packit Service 3470d1
Packit Service 3470d1
failmap:
Packit Service 3470d1
	QListDestroy(pList);
Packit Service 3470d1
faillist:
Packit Service 3470d1
	MemoryDeallocate(pList);
Packit Service 3470d1
	goto done;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
//
Packit Service 3470d1
// iba_deregister_notify 
Packit Service 3470d1
//
Packit Service 3470d1
//	The caller uses this API to Deregister previously registered notifications
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// INPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//	NotifyHandle		-Handle returned on successful registration
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// OUTPUTS:
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
// RETURNS:
Packit Service 3470d1
//
Packit Service 3470d1
//	FSUCCESS
Packit Service 3470d1
//	FINVALID_PARAMETER
Packit Service 3470d1
//	FINSUFFICIENT_MEMORY
Packit Service 3470d1
//
Packit Service 3470d1
//
Packit Service 3470d1
FSTATUS
Packit Service 3470d1
iba_deregister_notify (
Packit Service 3470d1
	IN 	IB_HANDLE			NotifyHandle
Packit Service 3470d1
	)
Packit Service 3470d1
{
Packit Service 3470d1
	FSTATUS					status	= FSUCCESS;
Packit Service 3470d1
	IBT_NOTIFY_USER_BLOCK	*pUser	= (IBT_NOTIFY_USER_BLOCK*)NotifyHandle;
Packit Service 3470d1
	QUICK_LIST				*pList;
Packit Service 3470d1
Packit Service 3470d1
Packit Service 3470d1
	_DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_deregister_notify );
Packit Service 3470d1
Packit Service 3470d1
	if (! NotifyGroup.Initialized)
Packit Service 3470d1
	{
Packit Service 3470d1
		// could have never registered if we didn't initialize
Packit Service 3470d1
		status = FINVALID_PARAMETER;
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	SpinLockAcquire( &NotifyGroup.Lock );
Packit Service 3470d1
	pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, pUser->Guid);
Packit Service 3470d1
	ASSERT(pList);
Packit Service 3470d1
	if ( !QListIsItemInList( pList, &pUser->ListItem ) )
Packit Service 3470d1
	{
Packit Service 3470d1
		status = FINVALID_PARAMETER;
Packit Service 3470d1
		_DBG_ERROR(("Could not deregister. Notification is not in List!!!\n"));
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (pUser->Locking == IB_NOTIFY_ASYNC)
Packit Service 3470d1
	{
Packit Service 3470d1
		if (--(pUser->RefCount) != 0)
Packit Service 3470d1
		{
Packit Service 3470d1
			// in use in callback
Packit Service 3470d1
			goto done;
Packit Service 3470d1
		}
Packit Service 3470d1
	} else {
Packit Service 3470d1
		ASSERT(pUser->RefCount == 1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	QListRemoveItem ( pList, &pUser->ListItem );
Packit Service 3470d1
	MemoryDeallocate( pUser );
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	SpinLockRelease( &NotifyGroup.Lock );
Packit Service 3470d1
Packit Service 3470d1
	_DBG_LEAVE_LVL(_DBG_LVL_IBT_API);
Packit Service 3470d1
	return status;
Packit Service 3470d1
}