Blame IbAccess/Common/SubnetDriver/infop.c

Packit 857059
/* BEGIN_ICS_COPYRIGHT4 ****************************************
Packit 857059
Packit 857059
Copyright (c) 2015, Intel Corporation
Packit 857059
Packit 857059
Redistribution and use in source and binary forms, with or without
Packit 857059
modification, are permitted provided that the following conditions are met:
Packit 857059
Packit 857059
    * Redistributions of source code must retain the above copyright notice,
Packit 857059
      this list of conditions and the following disclaimer.
Packit 857059
    * Redistributions in binary form must reproduce the above copyright
Packit 857059
      notice, this list of conditions and the following disclaimer in the
Packit 857059
     documentation and/or other materials provided with the distribution.
Packit 857059
    * Neither the name of Intel Corporation nor the names of its contributors
Packit 857059
      may be used to endorse or promote products derived from this software
Packit 857059
      without specific prior written permission.
Packit 857059
Packit 857059
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 857059
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 857059
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 857059
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 857059
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 857059
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 857059
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 857059
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 857059
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 857059
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 857059
Packit 857059
** END_ICS_COPYRIGHT4   ****************************************/
Packit 857059
Packit 857059
#include <datatypes.h>
Packit 857059
#include <imemory.h>
Packit 857059
#include <ilist.h>
Packit 857059
#include <ievent.h>
Packit 857059
#include <stl_sd.h>
Packit 857059
#include <sdi.h>
Packit 857059
#include <query.h>
Packit 857059
#include <subscribe.h>
Packit 857059
#include <multicast.h>
Packit 857059
Packit 857059
extern uint32 SADisable;
Packit 857059
Packit 857059
ATOMIC_UINT Outstanding;	// number of queries/operations in progress
Packit 857059
Packit 857059
uint32 NumLocalCAs = 0;
Packit 857059
uint32 NumTotalPorts = 0;
Packit 857059
EUI64 *pLocalCaGuidList = NULL;
Packit 857059
IB_CA_ATTRIBUTES *pLocalCaInfo = NULL;
Packit 857059
SPIN_LOCK *pLocalCaInfoLock = NULL; 
Packit 857059
IB_HANDLE CaNotifyHandle = NULL;
Packit 857059
SPIN_LOCK *pCaPortListLock = NULL;
Packit 857059
QUICK_LIST *pCaPortList = NULL;
Packit 857059
Packit 857059
LIST_ITEM*
Packit 857059
GetCaPortListItem(
Packit 857059
	EUI64 PortGuid
Packit 857059
	)
Packit 857059
{
Packit 857059
	LIST_ITEM *pCaPortListItem;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetCaPortListItem);
Packit 857059
Packit 857059
	_DBG_INFO(("Searching for Ca Port (GUID: %"PRIx64").\n", PortGuid));
Packit 857059
Packit 857059
	for (pCaPortListItem = QListHead(pCaPortList);
Packit 857059
		pCaPortListItem != NULL;
Packit 857059
		pCaPortListItem = QListNext(pCaPortList, pCaPortListItem)
Packit 857059
		)
Packit 857059
	{
Packit 857059
		CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem);
Packit 857059
		ASSERT(pCaPort != NULL);
Packit 857059
Packit 857059
		if (pCaPort->PortGuid == PortGuid)
Packit 857059
		{
Packit 857059
			_DBG_INFO(("Found Ca Port (GUID: %"PRIx64").\n", PortGuid));
Packit 857059
			_DBG_INFO(("SubnetAdm   Ca Port (GUID: %"PRIx64").\n", pCaPort->SaPortGuid));
Packit 857059
			_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
			return pCaPortListItem;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_INFO(("Ca Port (GUID: %"PRIx64") not found.\n", PortGuid));
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
Packit 857059
CA_PORT*
Packit 857059
GetCaPort(
Packit 857059
	EUI64 PortGuid
Packit 857059
	)
Packit 857059
{
Packit 857059
	LIST_ITEM *pCaPortListItem = GetCaPortListItem(PortGuid);
Packit 857059
	CA_PORT *pCaPort = NULL;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetCaPort);
Packit 857059
Packit 857059
	if (pCaPortListItem != NULL)
Packit 857059
	{
Packit 857059
		pCaPort = (CA_PORT *) QListObj(pCaPortListItem);
Packit 857059
		ASSERT(pCaPort != NULL);
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return pCaPort;
Packit 857059
}
Packit 857059
Packit 857059
void
Packit 857059
AddCa(
Packit 857059
	EUI64 CaGuid
Packit 857059
	)
Packit 857059
{
Packit 857059
	IB_CA_ATTRIBUTES *pNewCaInfo = NULL;
Packit 857059
	uint32 ii;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AddCa);
Packit 857059
Packit 857059
	_DBG_INFO(("Adding Ports for Channel Adapter (GUID: %"PRIx64").\n",
Packit 857059
		CaGuid));
Packit 857059
Packit 857059
	if (pLocalCaInfo != NULL)
Packit 857059
	{
Packit 857059
		SpinLockAcquire(pLocalCaInfoLock);
Packit 857059
Packit 857059
		_DBG_INFO(("NumLocalCAs (%d).\n", NumLocalCAs));
Packit 857059
Packit 857059
		for (ii = 0; ii < NumLocalCAs; ii++)
Packit 857059
		{
Packit 857059
			if (pLocalCaInfo[ii].GUID == CaGuid)
Packit 857059
			{
Packit 857059
				_DBG_INFO(
Packit 857059
					("Channel Adapter (GUID: %"PRIx64") Found @ Index (%d).\n",
Packit 857059
					pLocalCaInfo[ii].GUID, ii));
Packit 857059
				pNewCaInfo = &pLocalCaInfo[ii];
Packit 857059
				break;
Packit 857059
			}
Packit 857059
		}
Packit 857059
Packit 857059
		if (pNewCaInfo != NULL)
Packit 857059
		{
Packit 857059
			IB_PORT_ATTRIBUTES	*pPortAttr;
Packit 857059
Packit 857059
			_DBG_INFO(("Channel Adapter (GUID: %"PRIx64") Port Count (%d).\n",
Packit 857059
				pNewCaInfo->GUID, pNewCaInfo->Ports));
Packit 857059
Packit 857059
			for (ii = 0,  pPortAttr = pNewCaInfo->PortAttributesList;
Packit 857059
				ii < pNewCaInfo->Ports;
Packit 857059
				ii++, pPortAttr = pPortAttr->Next
Packit 857059
				)
Packit 857059
			{
Packit 857059
				CA_PORT* pCaPort = (CA_PORT*)MemoryAllocateAndClear(sizeof(CA_PORT),
Packit 857059
					TRUE, SUBNET_DRIVER_TAG);
Packit 857059
				ASSERT(pCaPort != NULL);
Packit 857059
Packit 857059
				pCaPort->CaGuid = CaGuid;
Packit 857059
				pCaPort->PortGuid = pPortAttr->GUID;
Packit 857059
				if (! LookupPKey(pPortAttr, DEFAULT_P_KEY, TRUE, &pCaPort->DefaultPkeyIndex))
Packit 857059
					pCaPort->DefaultPkeyIndex = 0;
Packit 857059
				QListSetObj(&pCaPort->CaPortListItem, pCaPort);
Packit 857059
Packit 857059
				SpinLockAcquire(pCaPortListLock);
Packit 857059
Packit 857059
				QListInsertTail(pCaPortList, &pCaPort->CaPortListItem);
Packit 857059
Packit 857059
				_DBG_INFO(("Added Port (Number %d) (GUID: %"PRIx64
Packit 857059
					") (Channel Adapter GUID: %"PRIx64").\n", 
Packit 857059
					ii, 
Packit 857059
					pCaPort->PortGuid,
Packit 857059
					pCaPort->CaGuid));
Packit 857059
Packit 857059
				SpinLockRelease(pCaPortListLock);
Packit 857059
Packit 857059
				InitializeCaPortInfo(pPortAttr->GUID);
Packit 857059
			}
Packit 857059
		}
Packit 857059
Packit 857059
		SpinLockRelease(pLocalCaInfoLock);
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
}
Packit 857059
Packit 857059
void
Packit 857059
RemoveCa(
Packit 857059
	EUI64 CaGuid
Packit 857059
	)
Packit 857059
{
Packit 857059
	LIST_ITEM *pCaPortListItem;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RemoveCa);
Packit 857059
Packit 857059
	SpinLockAcquire(pCaPortListLock);
Packit 857059
Packit 857059
	pCaPortListItem = QListHead(pCaPortList);
Packit 857059
Packit 857059
	while (pCaPortListItem != NULL)
Packit 857059
	{
Packit 857059
		CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem);
Packit 857059
		ASSERT(pCaPort != NULL);
Packit 857059
Packit 857059
		pCaPortListItem = QListNext(pCaPortList, pCaPortListItem);
Packit 857059
Packit 857059
		if (pCaPort->CaGuid == CaGuid)
Packit 857059
		{
Packit 857059
			QListRemoveItem(pCaPortList, &pCaPort->CaPortListItem);
Packit 857059
			MemoryDeallocate(pCaPort);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	SpinLockRelease(pCaPortListLock);
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
}
Packit 857059
Packit 857059
uint32
Packit 857059
GetNumTotalPorts(
Packit 857059
	IN void
Packit 857059
	)
Packit 857059
{
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetNumTotalPorts);
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return (NumTotalPorts);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS
Packit 857059
iba_sd_get_local_port_guids_alloc(
Packit 857059
	IN OUT uint64 **ppLocalPortGuidsList,
Packit 857059
	IN OUT uint32 *LocalPortGuidsCount
Packit 857059
	)
Packit 857059
{
Packit 857059
	return iba_sd_get_local_port_guids_alloc2(ppLocalPortGuidsList, NULL,
Packit 857059
							LocalPortGuidsCount);
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS
Packit 857059
iba_sd_get_local_port_guids_alloc2(
Packit 857059
	IN OUT uint64 **ppLocalPortGuidsList,
Packit 857059
	IN OUT uint64 **ppLocalPortSubnetPrefixList,
Packit 857059
	IN OUT uint32 *LocalPortGuidsCount
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Fstatus = FNOT_DONE;
Packit 857059
	LIST_ITEM *pCaPortListItem;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_get_local_port_guids_alloc2);
Packit 857059
Packit 857059
	if (ppLocalPortGuidsList) {
Packit 857059
		*ppLocalPortGuidsList = NULL;
Packit 857059
	} else {
Packit 857059
		Fstatus = FINVALID_PARAMETER;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
Packit 857059
	if (ppLocalPortSubnetPrefixList)
Packit 857059
		*ppLocalPortSubnetPrefixList = NULL;
Packit 857059
Packit 857059
	if (LocalPortGuidsCount) {
Packit 857059
		*LocalPortGuidsCount = 0;
Packit 857059
	} else {
Packit 857059
		Fstatus = FINVALID_PARAMETER;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
Packit 857059
	if (NumTotalPorts == 0)
Packit 857059
	{
Packit 857059
		_DBG_INFO(("No LocalPortGuids allocated.\n"));
Packit 857059
		Fstatus = FSUCCESS;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
Packit 857059
	*ppLocalPortGuidsList = 
Packit 857059
		(EUI64*)MemoryAllocate2AndClear((sizeof(EUI64)*NumTotalPorts),
Packit 857059
						IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG);
Packit 857059
	if (*ppLocalPortGuidsList == NULL)
Packit 857059
	{
Packit 857059
		_DBG_ERROR(("Cannot allocate memory for LocalPortGuids\n"));
Packit 857059
		Fstatus = FINSUFFICIENT_MEMORY;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
	if (ppLocalPortSubnetPrefixList)
Packit 857059
	{
Packit 857059
		*ppLocalPortSubnetPrefixList = 
Packit 857059
			(EUI64*)MemoryAllocate2AndClear((sizeof(EUI64)*NumTotalPorts),
Packit 857059
						IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG);
Packit 857059
		if (*ppLocalPortSubnetPrefixList == NULL)
Packit 857059
		{
Packit 857059
			_DBG_ERROR(("Cannot allocate memory for LocalPortSubnetPrefix\n"));
Packit 857059
			Fstatus = FINSUFFICIENT_MEMORY;
Packit 857059
			goto fail;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	SpinLockAcquire(pCaPortListLock);
Packit 857059
Packit 857059
	for (pCaPortListItem = QListHead(pCaPortList);
Packit 857059
		pCaPortListItem != NULL;
Packit 857059
		pCaPortListItem = QListNext(pCaPortList, pCaPortListItem)
Packit 857059
		)
Packit 857059
	{
Packit 857059
		IB_PORT_ATTRIBUTES *pPortAttr;
Packit 857059
		FSTATUS status;
Packit 857059
Packit 857059
		CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem);
Packit 857059
		ASSERT(pCaPort != NULL);
Packit 857059
Packit 857059
		status = iba_query_port_by_guid_alloc(pCaPort->PortGuid, &pPortAttr);
Packit 857059
		if (FSUCCESS != status)
Packit 857059
		{
Packit 857059
			Fstatus = status;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
Packit 857059
		_DBG_INFO(("The port state is %d\n",pPortAttr->PortState));
Packit 857059
		_DBG_INFO(("BaseLid <%d>\n",pPortAttr->Address.BaseLID));
Packit 857059
		if ((pPortAttr->Address.BaseLID != /*IB_INVALID_LID*/ 0) &&
Packit 857059
			(pPortAttr->PortState == PortStateActive))
Packit 857059
		{
Packit 857059
			//NOTENOTE: Return only active ports
Packit 857059
			(*ppLocalPortGuidsList)[*LocalPortGuidsCount] = pPortAttr->GUID;
Packit 857059
			if (ppLocalPortSubnetPrefixList)
Packit 857059
				(*ppLocalPortSubnetPrefixList)[*LocalPortGuidsCount] = pPortAttr->GIDTable[0].Type.Global.SubnetPrefix;
Packit 857059
			(*LocalPortGuidsCount)++;
Packit 857059
			Fstatus = FSUCCESS;
Packit 857059
		}
Packit 857059
Packit 857059
		MemoryDeallocate(pPortAttr);
Packit 857059
	}
Packit 857059
Packit 857059
	SpinLockRelease(pCaPortListLock);
Packit 857059
Packit 857059
fail:
Packit 857059
	if (Fstatus != FSUCCESS) {
Packit 857059
		if (*ppLocalPortGuidsList != NULL) {
Packit 857059
			MemoryDeallocate(*ppLocalPortGuidsList);
Packit 857059
			*ppLocalPortGuidsList = 0;
Packit 857059
		}
Packit 857059
		*LocalPortGuidsCount = 0;
Packit 857059
		if (ppLocalPortSubnetPrefixList && *ppLocalPortSubnetPrefixList)
Packit 857059
		{
Packit 857059
			MemoryDeallocate(*ppLocalPortSubnetPrefixList);
Packit 857059
			*ppLocalPortSubnetPrefixList = 0;
Packit 857059
		}
Packit 857059
		// enable this code in the future,
Packit 857059
		// for now for backward compatibility
Packit 857059
		// return an error code for no ports found (FNOT_DONE above)
Packit 857059
		//if (Fstatus == FNOT_DONE)
Packit 857059
		//	Fstatus = FSUCCESS;
Packit 857059
	}
Packit 857059
Packit 857059
done:
Packit 857059
	_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return Fstatus;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
FSTATUS
Packit 857059
GetLocalCaInfo(
Packit 857059
	void
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Fstatus;
Packit 857059
	uint32 ii;
Packit 857059
	uint32 OldNumLocalCAs = NumLocalCAs;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetLocalCaInfo);
Packit 857059
Packit 857059
	// This function has been called by holding a pLocalCaInfoLock spinlock
Packit 857059
Packit 857059
	if (pLocalCaGuidList)  
Packit 857059
	{
Packit 857059
		MemoryDeallocate(pLocalCaGuidList);
Packit 857059
		pLocalCaGuidList = NULL;
Packit 857059
	}
Packit 857059
Packit 857059
	NumLocalCAs = 0;
Packit 857059
	Fstatus = iba_get_caguids_alloc(&NumLocalCAs, &pLocalCaGuidList);
Packit 857059
	if (Fstatus != FSUCCESS) 
Packit 857059
	{
Packit 857059
		_DBG_ERROR(("Fstatus <0x%x> getting local CA GUIDs\n", Fstatus));
Packit 857059
		pLocalCaGuidList = NULL;
Packit 857059
		NumLocalCAs = 0;
Packit 857059
		_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
Packit 857059
		return(Fstatus);
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_INFO(("Number of Channel Adapters present <%d>\n", NumLocalCAs));
Packit 857059
	if (NumLocalCAs <= 0) {
Packit 857059
		_DBG_INFO(("No CA reported by GetCaGuids\n"));
Packit 857059
		return FSUCCESS;
Packit 857059
	}
Packit 857059
Packit 857059
	if (pLocalCaInfo)  
Packit 857059
	{
Packit 857059
		uint32 count;
Packit 857059
		for(count=0; count
Packit 857059
		{
Packit 857059
			if(pLocalCaInfo[count].PortAttributesList)
Packit 857059
				MemoryDeallocate(pLocalCaInfo[count].PortAttributesList);
Packit 857059
		}
Packit 857059
		MemoryDeallocate(pLocalCaInfo);
Packit 857059
	}
Packit 857059
	pLocalCaInfo = (IB_CA_ATTRIBUTES*)MemoryAllocateAndClear(
Packit 857059
		(sizeof(IB_CA_ATTRIBUTES) * NumLocalCAs), FALSE, SUBNET_DRIVER_TAG);
Packit 857059
	if (pLocalCaInfo == NULL)  
Packit 857059
	{
Packit 857059
		_DBG_ERROR(("Cannot allocate memory for local CA info\n"));
Packit 857059
		MemoryDeallocate(pLocalCaGuidList);
Packit 857059
		pLocalCaGuidList = NULL;
Packit 857059
		NumLocalCAs = 0;
Packit 857059
		_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
Packit 857059
		return(FINSUFFICIENT_MEMORY);
Packit 857059
	}
Packit 857059
Packit 857059
	//Clear the number of Ports
Packit 857059
	NumTotalPorts = 0;
Packit 857059
	for (ii=0; ii
Packit 857059
	{
Packit 857059
		Fstatus = iba_query_ca_by_guid_alloc(pLocalCaGuidList[ii], &pLocalCaInfo[ii]);
Packit 857059
		if (Fstatus == FSUCCESS) 
Packit 857059
		{
Packit 857059
			NumTotalPorts += pLocalCaInfo[ii].Ports;
Packit 857059
		} else {
Packit 857059
			_DBG_ERROR(("Fstatus 0x%x Query CA by Guid failed.\n", Fstatus));
Packit 857059
		}
Packit 857059
	} //end for(; ; ;);
Packit 857059
Packit 857059
	_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return(FSUCCESS);
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
void
Packit 857059
LocalCaChangeCallback(
Packit 857059
	IB_NOTIFY_RECORD NotifyRecord
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Status;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, LocalCaChangeCallback);
Packit 857059
Packit 857059
	if (SdUnloading)
Packit 857059
	{
Packit 857059
		_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
Packit 857059
		return;
Packit 857059
	}
Packit 857059
Packit 857059
	//
Packit 857059
	// re-collect the information only if there is a change that impacts us.
Packit 857059
	//
Packit 857059
Packit 857059
	SpinLockAcquire(pLocalCaInfoLock);
Packit 857059
	Status = GetLocalCaInfo();
Packit 857059
	SpinLockRelease(pLocalCaInfoLock);
Packit 857059
	if (Status != FSUCCESS)  
Packit 857059
	{
Packit 857059
		_DBG_ERROR(
Packit 857059
			("GetLocalCaInfo failed during localcachange callback<%d>\n",
Packit 857059
			Status));
Packit 857059
		_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
		return;
Packit 857059
	}
Packit 857059
Packit 857059
	switch (NotifyRecord.EventType)
Packit 857059
	{
Packit 857059
	case IB_NOTIFY_CA_ADD:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_CA_ADD (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		AddCa(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	case IB_NOTIFY_CA_REMOVE:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_CA_REMOVE (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		RemoveCa(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	case IB_NOTIFY_LID_EVENT:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_LID_EVENT (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		InitializeCaPortInfo(NotifyRecord.Guid);
Packit 857059
		ReRegisterTrapSubscriptions(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	case IB_NOTIFY_SM_EVENT:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_SM_EVENT (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		InitializeCaPortInfo(NotifyRecord.Guid);
Packit 857059
		ReRegisterTrapSubscriptions(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	case IB_NOTIFY_PORT_DOWN:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_PORT_DOWN (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		InitializeCaPortInfo(NotifyRecord.Guid);
Packit 857059
		InvalidatePortTrapSubscriptions(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	case IB_NOTIFY_PKEY_EVENT:
Packit 857059
		_DBG_INFO(("IB_NOTIFY_PKEY_EVENT (GUID: %"PRIx64").\n",
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		InitializeCaPortInfo(NotifyRecord.Guid);
Packit 857059
		ReRegisterTrapSubscriptions(NotifyRecord.Guid);
Packit 857059
		break;
Packit 857059
Packit 857059
	default:
Packit 857059
		_DBG_INFO(("Someother Event (%lu) (GUID: %"PRIx64").\n", 
Packit 857059
			NotifyRecord.EventType, 
Packit 857059
			NotifyRecord.Guid));
Packit 857059
		break;
Packit 857059
	}
Packit 857059
#ifdef USE_SD_MULTICAST	
Packit 857059
	McPortNotifyCallback(&NotifyRecord);
Packit 857059
#endif	
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return;
Packit 857059
}
Packit 857059
Packit 857059
FSTATUS
Packit 857059
InitializeCaPortInfo(
Packit 857059
	EUI64 PortGuid
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Fstatus = FERROR;
Packit 857059
	CA_PORT *pCaPort;
Packit 857059
	IB_PORT_ATTRIBUTES	*pPortAttr = NULL;
Packit 857059
	boolean bInitialized;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeCaPortInfo);
Packit 857059
Packit 857059
	if (SdUnloading)
Packit 857059
	{
Packit 857059
		_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
Packit 857059
		return(FINVALID_STATE);
Packit 857059
	}
Packit 857059
	_DBG_INFO(("Number of Local CA are %d\n",NumLocalCAs));
Packit 857059
Packit 857059
	SpinLockAcquire(pCaPortListLock);
Packit 857059
Packit 857059
	pCaPort = GetCaPort(PortGuid);
Packit 857059
	if (pCaPort == NULL)
Packit 857059
	{
Packit 857059
		SpinLockRelease(pCaPortListLock);
Packit 857059
		/* there is a rare possibility during shutdown that the port could go
Packit 857059
		 * up/down after the Subnet Driver Remove Device has been called but
Packit 857059
		 * before SMARemoveDevice is called.  In which case IbtNotifyGroup is
Packit 857059
		 * still enabled for the given CA and the SubnetDriver could get a port
Packit 857059
		 * state change which will put is here.  In this rare case we
Packit 857059
		 * could fail to find the CaGuid and should ignore the callback
Packit 857059
		 */
Packit 857059
		_DBG_INFO(("GetCaPort returned NULL for Port (GUID: %"PRIx64").\n", PortGuid));
Packit 857059
		_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
Packit 857059
		return (Fstatus);
Packit 857059
	}
Packit 857059
Packit 857059
	//
Packit 857059
	// Note: The calling function should not fail driver load if this
Packit 857059
	// function returns error. It is possible that this function is called
Packit 857059
	// before the local CA has been initialized by a remote subnet manager
Packit 857059
	// In that case, this function will fail but will register for a local
Packit 857059
	// CA change callback. When the local CA does get initialized, this 
Packit 857059
	// registered callback will be invoked and the callback will call this
Packit 857059
	// function again.
Packit 857059
	//
Packit 857059
Packit 857059
	//
Packit 857059
	// LID for the information provider is initially set to the LID of the
Packit 857059
	// subnet manager. This can be subsequently redirected. Get the SM LID
Packit 857059
	// using local IBT calls
Packit 857059
	//
Packit 857059
Packit 857059
	Fstatus = iba_query_port_by_guid_alloc(PortGuid, &pPortAttr);
Packit 857059
	ASSERT(Fstatus == FSUCCESS);
Packit 857059
Packit 857059
	_DBG_INFO(("The port state is %d\n",pPortAttr->PortState));
Packit 857059
	_DBG_INFO(("BaseLid <%d>\n",pPortAttr->Address.BaseLID));
Packit 857059
Packit 857059
	if (! LookupPKey(pPortAttr, DEFAULT_P_KEY, TRUE, &pCaPort->DefaultPkeyIndex))
Packit 857059
		pCaPort->DefaultPkeyIndex = 0;
Packit 857059
Packit 857059
	pCaPort->Lid = pPortAttr->SMAddress.LID;
Packit 857059
	pCaPort->ServiceLevel = pPortAttr->SMAddress.ServiceLevel;
Packit 857059
	pCaPort->RemoteQp = GSI_QP;
Packit 857059
	pCaPort->RemoteQKey = GSI_QKEY;
Packit 857059
	// IB does not have Static rate in UD LRH
Packit 857059
	// so we can't be sure what rate of remote port is
Packit 857059
	// we use a constant value for GSI QPs
Packit 857059
	pCaPort->StaticRate = IB_STATIC_RATE_GSI;
Packit 857059
	pCaPort->PkeyIndex = pCaPort->DefaultPkeyIndex;
Packit 857059
	pCaPort->SaPortGuid = pPortAttr->GUID;
Packit 857059
	if(pPortAttr->NumGIDs > 0)
Packit 857059
		pCaPort->SubnetPrefix = pPortAttr->GIDTable[0].Type.Global.SubnetPrefix;
Packit 857059
	// default redirect to default location
Packit 857059
	pCaPort->RedirectedQP = pCaPort->RemoteQp;
Packit 857059
	pCaPort->RedirectedQKey = pCaPort->RemoteQKey;
Packit 857059
	pCaPort->RedirectedLid = pCaPort->Lid;
Packit 857059
	pCaPort->RedirectedSL = pCaPort->ServiceLevel;
Packit 857059
	pCaPort->RedirectedStaticRate = pCaPort->StaticRate;
Packit 857059
	pCaPort->RedirectedPkeyIndex = pCaPort->PkeyIndex;
Packit 857059
Packit 857059
	if ((pPortAttr->Address.BaseLID != /*IB_INVALID_LID*/ 0) &&
Packit 857059
		(pPortAttr->PortState == PortStateActive))
Packit 857059
		//NOTENOTE: Check for pPortAttr->SMAddress.LID != 0
Packit 857059
	{
Packit 857059
		pCaPort->SdSMAddressValid = TRUE;
Packit 857059
		Fstatus = FSUCCESS;
Packit 857059
	}
Packit 857059
Packit 857059
	// Free the port attributes buffer.
Packit 857059
	MemoryDeallocate( pPortAttr );
Packit 857059
Packit 857059
	if (Fstatus != FSUCCESS)  
Packit 857059
	{	
Packit 857059
		//
Packit 857059
		// It is possible that local ports have not yet been initialized by
Packit 857059
		// a remote subnet manager. This is OK - we have registered for a
Packit 857059
		// callback when that happens and we will initialize the service
Packit 857059
		// provider at that time
Packit 857059
		//        
Packit 857059
Packit 857059
		pCaPort->bInitialized = FALSE;
Packit 857059
Packit 857059
		_DBG_INFO(("No local port currently available\n"));
Packit 857059
		pCaPort->SdSMAddressValid = FALSE;
Packit 857059
Packit 857059
		SpinLockRelease(pCaPortListLock);
Packit 857059
Packit 857059
		//
Packit 857059
		// We haven't collected enough information to send any message to the
Packit 857059
		// information provider, so simply return for now.
Packit 857059
		//
Packit 857059
		_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
		return(Fstatus);
Packit 857059
	}
Packit 857059
Packit 857059
	bInitialized = pCaPort->bInitialized;
Packit 857059
Packit 857059
	SpinLockRelease(pCaPortListLock);
Packit 857059
Packit 857059
	if (! SADisable)
Packit 857059
	{
Packit 857059
		if(bInitialized == FALSE)
Packit 857059
			SubnetAdmInit();
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return(FSUCCESS);
Packit 857059
}