Blame IbAccess/Common/Ibt/Cm/cm_passive.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
// Public header file
Packit 857059
#include "ib_cm.h"
Packit 857059
Packit 857059
// Private header file
Packit 857059
#include "cm_private.h"
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// Listen
Packit 857059
//
Packit 857059
// Prepare CEP for Listening and put on ListenMap
Packit 857059
//
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS.
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//	Called with ListLock held, which protects lists and all CEPs
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
Listen(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	IN CM_LISTEN_INFO*			pListenInfo,
Packit 857059
	IN PFN_CM_CALLBACK			pfnListenCB,
Packit 857059
	IN void*					Context
Packit 857059
	)
Packit 857059
{
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, Listen);
Packit 857059
Packit 857059
	// If we are binding to a specific port, we need the CaGUID of the port
Packit 857059
	// so that during CmRemoveDevice(), we can cancel this listen
Packit 857059
	pCEP->LocalEndPoint.CaGUID = pListenInfo->CaGUID;
Packit 857059
	ASSERT(! pCEP->bPeer);
Packit 857059
Packit 857059
	// Bind address is based on SID with secondary optional
Packit 857059
	// Local/Remote GID/LID and the Private Data Discriminator
Packit 857059
	// (set via CmModifyCEP)
Packit 857059
	// Hence more than one CEP could use the same SID, provided they have unique
Packit 857059
	// combinations of values for the other fields.  Values of 0
Packit 857059
	// represent wildcarding the given field (SID can't be wildcarded)
Packit 857059
	pCEP->SID = pListenInfo->ListenAddr.EndPt.SID;
Packit 857059
	pCEP->PrimaryPath.LocalLID = pListenInfo->ListenAddr.Port.LID;
Packit 857059
	pCEP->PrimaryPath.LocalGID = pListenInfo->ListenAddr.Port.GID;
Packit 857059
Packit 857059
	pCEP->PrimaryPath.RemoteLID = pListenInfo->RemoteAddr.Port.LID;
Packit 857059
	pCEP->PrimaryPath.RemoteGID = pListenInfo->RemoteAddr.Port.GID;
Packit 857059
Packit 857059
	pCEP->LocalEndPoint.QPN = pCEP->LocalEndPoint.EECN = 0;
Packit 857059
	pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0;
Packit 857059
Packit 857059
	// add to ListenMap and make sure bound address is unique
Packit 857059
	if (! CM_MapTryInsert(&gCM->ListenMap, (uintn)pCEP, &pCEP->MapEntry, "LISTEN_LIST", pCEP))
Packit 857059
	{
Packit 857059
		_DBG_WARNING(("<cep 0x%p> Address in use!!!\n", _DBG_PTR(pCEP)));
Packit 857059
		// clear out CEP fields
Packit 857059
		MemoryClear(&pCEP->LocalEndPoint, sizeof(pCEP->LocalEndPoint));
Packit 857059
		MemoryClear(&pCEP->RemoteEndPoint, sizeof(pCEP->RemoteEndPoint));
Packit 857059
		MemoryClear(&pCEP->PrimaryPath, sizeof(pCEP->PrimaryPath));
Packit 857059
		pCEP->LocalEndPoint.CaGUID = 0;
Packit 857059
		pCEP->SID = 0;
Packit 857059
Packit 857059
		_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
		return FCM_ADDR_INUSE;
Packit 857059
	}
Packit 857059
Packit 857059
	// LocalCommID for listening CEP is used only for debugging purposes
Packit 857059
	AssignLocalCommID(pCEP);
Packit 857059
	pCEP->TransactionID = 0;	// not used, will use TID of remote client
Packit 857059
Packit 857059
	_DBG_INFO(("<cep 0x%p> Comm ID set at <lcid 0x%x>.\n",
Packit 857059
			_DBG_PTR(pCEP), pCEP->LocalCommID));
Packit 857059
	
Packit 857059
	pCEP->Mode = CM_MODE_PASSIVE;
Packit 857059
	pCEP->LocalCMTimeout = 0;
Packit 857059
	pCEP->RemoteCMTimeout = 0;
Packit 857059
	pCEP->MaxCMRetries = 0;
Packit 857059
	pCEP->EventFlags = 0;
Packit 857059
	pCEP->RetryCount = 0;
Packit 857059
	//pCEP->pWaitEvent = NULL;
Packit 857059
	DListInit(&pCEP->PendingList);
Packit 857059
Packit 857059
	if (pCEP->pDgrmElement)
Packit 857059
	{
Packit 857059
		// Return the datagram since listen objects do not use it
Packit 857059
		_DBG_INFO(("<cep 0x%p> Releasing the dgrm <dgrm 0x%p>.\n", 
Packit 857059
						_DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement)));
Packit 857059
		CmDgrmRelease(pCEP->pDgrmElement);
Packit 857059
	}
Packit 857059
Packit 857059
	// Save user callback info
Packit 857059
	pCEP->pfnUserCallback = pfnListenCB;
Packit 857059
	pCEP->UserContext = Context;
Packit 857059
Packit 857059
	CepSetState(pCEP, CMS_LISTEN);
Packit 857059
Packit 857059
	_DBG_INFO(("<cep 0x%p> *** Listening on <sid 0x%"PRIx64" lid 0x%x gid 0x%"PRIx64":0x%"PRIx64">.***\n",
Packit 857059
				_DBG_PTR(pCEP), pListenInfo->ListenAddr.EndPt.SID,
Packit 857059
				pListenInfo->ListenAddr.Port.LID,
Packit 857059
				pCEP->PrimaryPath.LocalGID.Type.Global.SubnetPrefix,
Packit 857059
				pCEP->PrimaryPath.LocalGID.Type.Global.InterfaceID));
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	// At this point, we are listening for incoming connections on this obj.
Packit 857059
	return FPENDING;
Packit 857059
Packit 857059
} // Listen()
Packit 857059
Packit 857059
Packit 857059
// See GetConnInfo in cm_active.c for callback processing
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// WaitP
Packit 857059
//
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS or FTIMEOUT.
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
WaitP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	OUT CM_CONN_INFO*			pConnInfo,
Packit 857059
	uint32						Timeout_us	// TODO: Put a max limit on this in addition to infinite
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Status=FSUCCESS;
Packit 857059
Packit 857059
	uint32 WaitTimeUs=Timeout_us;
Packit 857059
	uint64 TimeoutUs=Timeout_us;
Packit 857059
	uint64 StartTimeUs=GetTimeStamp();
Packit 857059
Packit 857059
	uint64 CurrTimeUs=0;
Packit 857059
	uint64 TimeElapsedUs=0;
Packit 857059
Packit 857059
	//CMM_MSG* pMsg=&((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->payload;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, WaitP);
Packit 857059
Packit 857059
waitagain:
Packit 857059
Packit 857059
	// Update the timeout
Packit 857059
	if ((int32)WaitTimeUs != EVENT_NO_TIMEOUT)
Packit 857059
	{
Packit 857059
		if (CurrTimeUs >= StartTimeUs)
Packit 857059
		{
Packit 857059
			TimeElapsedUs = (CurrTimeUs - StartTimeUs);
Packit 857059
		}
Packit 857059
		else // wrap-around
Packit 857059
		{
Packit 857059
			TimeElapsedUs = (CurrTimeUs + ((uint64)(-1) - StartTimeUs));
Packit 857059
		}
Packit 857059
Packit 857059
		if (TimeoutUs > TimeElapsedUs)
Packit 857059
		{
Packit 857059
			WaitTimeUs = (uint32) (TimeoutUs - TimeElapsedUs);
Packit 857059
		}
Packit 857059
		else
Packit 857059
		{
Packit 857059
			WaitTimeUs = 0;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	//_DBG_INFO(("<cep 0x%p> Waiting on obj... <timeout %ums lcid 0x%x %s>\n", 
Packit 857059
	//			_DBG_PTR(pCEP), WaitTimeUs/1000, pCEP->LocalCommID,
Packit 857059
	//			_DBG_PTR(CmGetStateString(pCEP->State))));
Packit 857059
Packit 857059
	Status = EventWaitOn(pCEP->pEventObj, WaitTimeUs);
Packit 857059
Packit 857059
	//_DBG_INFO(("<cep 0x%p> Waiting on obj... complete <%s %s>\n", 
Packit 857059
	//			_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)),
Packit 857059
	//			_DBG_PTR(CmGetStateString(pCEP->State))));
Packit 857059
Packit 857059
	if (Status == FTIMEOUT)
Packit 857059
	{
Packit 857059
		if (Timeout_us == 0)
Packit 857059
		{
Packit 857059
			//_DBG_INFO(("<cep 0x%p> Obj state is nonsignaled.\n", _DBG_PTR(pCEP)));
Packit 857059
		}
Packit 857059
		else
Packit 857059
		{
Packit 857059
			_DBG_WARNING(("<cep 0x%p> EventWaitOn() returns FTIMEOUT!\n", _DBG_PTR(pCEP)));
Packit 857059
		}
Packit 857059
		_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
		return FTIMEOUT;
Packit 857059
	}
Packit 857059
Packit 857059
	ASSERT(Status == FSUCCESS);
Packit 857059
Packit 857059
	_DBG_INFO(("<cep 0x%p> Obj state is signaled <%s>.\n",
Packit 857059
				_DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State))));
Packit 857059
Packit 857059
	// Get mutual ex to the object
Packit 857059
	SpinLockAcquire(&gCM->ListLock);
Packit 857059
Packit 857059
	Status = GetConnInfo(pCEP, pConnInfo);
Packit 857059
Packit 857059
	if (Status != FSUCCESS)
Packit 857059
	{
Packit 857059
		// Handle the case when we get signal but we already process the event
Packit 857059
		// with the previous signal
Packit 857059
		// eg evt1 --> signal; evt2 --> signal
Packit 857059
		//							->wait() returned
Packit 857059
		_DBG_WARNING(("<cep 0x%p> GetConnInfo() returns %s!\n",
Packit 857059
						_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
		
Packit 857059
		ASSERT(pConnInfo->Status == 0);
Packit 857059
Packit 857059
		SpinLockRelease(&gCM->ListLock);
Packit 857059
Packit 857059
		goto waitagain;
Packit 857059
	}
Packit 857059
Packit 857059
	SpinLockRelease(&gCM->ListLock);
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // WaitP()
Packit 857059
Packit 857059
// given a CEP for which a FCM_CONNECT_REQUEST has been reported
Packit 857059
// fetch the head of the pending list
Packit 857059
static FSTATUS
Packit 857059
GetPendingCEP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	OUT CM_CEP_OBJECT**			ppCEPEntry
Packit 857059
	)
Packit 857059
{
Packit 857059
	CM_CEP_OBJECT* pCEPEntry = NULL;
Packit 857059
Packit 857059
	DLIST_ENTRY* pListEntry=NULL;
Packit 857059
	FSTATUS		Status=FSUCCESS;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetPendingCEP);
Packit 857059
Packit 857059
	switch (pCEP->State)
Packit 857059
	{
Packit 857059
	case CMS_IDLE:
Packit 857059
Packit 857059
		if (BitTest(pCEP->EventFlags, USRE_CANCEL))
Packit 857059
		{
Packit 857059
			// User cancelled the listen, but hasn't gotten callback yet
Packit 857059
			Status = FCM_CONNECT_CANCEL;
Packit 857059
		} else {
Packit 857059
			Status = FERROR;
Packit 857059
		}
Packit 857059
		break;
Packit 857059
Packit 857059
	case CMS_LISTEN:
Packit 857059
	case CMS_REQ_RCVD:	// separate out for Peer, no PendingList need then
Packit 857059
	case CMS_MRA_REQ_SENT:	// separate out for Peer, no PendingList need then
Packit 857059
			// could have listen get the pCEPEntry and then have common code
Packit 857059
			// with Peer REQ_RCVD/MRA_REQ_SENT cases
Packit 857059
		//
Packit 857059
		// Accepting new client or peer connection 
Packit 857059
		//
Packit 857059
		if (pCEP->bPeer)
Packit 857059
		{
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Accepting peer connection ***\n", _DBG_PTR(pCEP)));
Packit 857059
		} else {
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Accepting client connection ***\n", _DBG_PTR(pCEP)));
Packit 857059
		}
Packit 857059
Packit 857059
		if (DListIsEmpty(&pCEP->PendingList))	
Packit 857059
		{
Packit 857059
			// If user reject() or cancel() and then call accept()
Packit 857059
			_DBG_WARNING(("<cep 0x%p> Pending list is empty!\n", _DBG_PTR(pCEP)));
Packit 857059
			Status = FNOT_FOUND;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
		
Packit 857059
		// Note: For peer-to-peer connection (bPeer == TRUE), the entry in the PENDING list 
Packit 857059
		// is the same as the one passed in i.e. pCEP == pCEPEntry
Packit 857059
		pListEntry = DListGetNext(&pCEP->PendingList);
Packit 857059
		pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
Packit 857059
		ASSERT(pCEPEntry->pParentCEP == pCEP);
Packit 857059
		if (pCEP->bPeer)
Packit 857059
		{
Packit 857059
			ASSERT(pCEPEntry == pCEP);
Packit 857059
		} else {
Packit 857059
			ASSERT(pCEPEntry != pCEP);
Packit 857059
		}
Packit 857059
Packit 857059
		// Cannot accept until the user has been notify thru wait
Packit 857059
		/*
Packit 857059
		if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT))
Packit 857059
		{
Packit 857059
			_DBG_WARNING(("<cep 0x%p> Cannot accept - User must call wait() before accept()!\n",
Packit 857059
							_DBG_PTR(pCEP)));
Packit 857059
			// Re-signal
Packit 857059
			EventSet(pCEP, CME_RCVD_REQ);
Packit 857059
Packit 857059
			Status = FUNAVAILABLE;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
		
Packit 857059
		BitClear(pCEPEntry->EventFlags, USRE_WAIT);
Packit 857059
		*/
Packit 857059
Packit 857059
		// Make sure we havent timed-out or receive a reject
Packit 857059
		switch (pCEPEntry->State)
Packit 857059
		{
Packit 857059
		case CMS_REQ_RCVD:
Packit 857059
		case CMS_MRA_REQ_SENT:
Packit 857059
			*ppCEPEntry = pCEPEntry;
Packit 857059
			Status = FSUCCESS;
Packit 857059
			break;
Packit 857059
		
Packit 857059
		default:
Packit 857059
			Status = FINVALID_STATE;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
		break;
Packit 857059
	default:
Packit 857059
		Status = FINVALID_STATE;
Packit 857059
		break;
Packit 857059
	} // switch()
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // GetPendingCEP
Packit 857059
Packit 857059
// process an inbound REQ for a passive CEP
Packit 857059
FSTATUS
Packit 857059
ProcessRequestP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	IN CM_REP_FAILOVER 			Failover,
Packit 857059
	OUT CM_PROCESS_REQUEST_INFO *Info
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Status;
Packit 857059
	IB_CA_ATTRIBUTES *pCaAttr = NULL;
Packit 857059
	CM_CEP_OBJECT*			pCEPEntry;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRequestP);
Packit 857059
Packit 857059
	// TBD - RD code here is not complete/accurate
Packit 857059
	ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
Packit 857059
Packit 857059
	Status = GetPendingCEP(pCEP, &pCEPEntry);
Packit 857059
	if (Status != FSUCCESS)
Packit 857059
		goto done;
Packit 857059
	if (pCEPEntry->Type == CM_UD_TYPE)
Packit 857059
	{
Packit 857059
		Status = FINVALID_STATE;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
	if (Info == NULL)
Packit 857059
	{
Packit 857059
		Status = FINVALID_PARAMETER;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
	MemoryClear(Info, sizeof(*Info));	// just to be safe
Packit 857059
 
Packit 857059
	// Child must inherit parent's setting for now
Packit 857059
	// Will be saved again when AcceptP
Packit 857059
	pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported;
Packit 857059
Packit 857059
	// get ca Attr
Packit 857059
	pCaAttr = (IB_CA_ATTRIBUTES*)MemoryAllocate(sizeof(*pCaAttr), FALSE, CM_MEM_TAG);
Packit 857059
	if (pCaAttr == NULL)
Packit 857059
	{
Packit 857059
		Status = FINSUFFICIENT_MEMORY;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
	pCaAttr->PortAttributesListSize = 0;
Packit 857059
	pCaAttr->PortAttributesList = NULL;
Packit 857059
	Status = iba_query_ca_by_guid(pCEPEntry->LocalEndPoint.CaGUID, pCaAttr);
Packit 857059
	if (Status != FINSUFFICIENT_MEMORY && Status != FSUCCESS)
Packit 857059
		goto done;
Packit 857059
Packit 857059
	// set up attributes to move QP to Init
Packit 857059
	GetInitAttrFromCep(pCEPEntry, &Info->QpAttrInit);
Packit 857059
Packit 857059
	// update LocalResponder/Initiator/SendPSN so we are ready in case
Packit 857059
	// application calls iba_cm_prepare_rts before doing iba_cm_accept
Packit 857059
	// Build Reply
Packit 857059
	pCEPEntry->LocalRecvPSN = Info->ReplyInfo.Info.Reply.StartingPSN =
Packit 857059
															GenerateStartPSN();
Packit 857059
	// RDMA Read is not supported for UC, leave zero
Packit 857059
	if (pCEPEntry->Type != CM_UC_TYPE) {
Packit 857059
		pCEPEntry->LocalResponderResources =
Packit 857059
			Info->ReplyInfo.Info.Reply.ArbResponderResources =
Packit 857059
							MIN(pCEPEntry->LocalResponderResources,
Packit 857059
									pCaAttr->MaxQPResponderResources);
Packit 857059
		pCEPEntry->LocalInitiatorDepth =
Packit 857059
			Info->ReplyInfo.Info.Reply.ArbInitiatorDepth =
Packit 857059
							MIN(pCEPEntry->LocalInitiatorDepth,
Packit 857059
									pCaAttr->MaxQPInitiatorDepth);
Packit 857059
	}
Packit 857059
	Info->ReplyInfo.Info.Reply.TargetAckDelay = pCaAttr->LocalCaAckDelay;
Packit 857059
	// spec implies we should say NOT_SUPPORTED even if no alternate path
Packit 857059
	// was provided in REQ
Packit 857059
	if (pCaAttr->PathMigrationLevel == CAPathMigNone
Packit 857059
			|| ! pCEPEntry->bFailoverSupported)
Packit 857059
	{
Packit 857059
		Info->ReplyInfo.Info.Reply.FailoverAccepted = CM_REP_FO_NOT_SUPPORTED;
Packit 857059
	} else {
Packit 857059
		Info->ReplyInfo.Info.Reply.FailoverAccepted = Failover;
Packit 857059
	}
Packit 857059
	// end to end credits and RNR not allowed for UC
Packit 857059
	if (pCEPEntry->Type != CM_UC_TYPE) {
Packit 857059
		// our CA supports RC credits
Packit 857059
		Info->ReplyInfo.Info.Reply.EndToEndFlowControl = TRUE;
Packit 857059
		Info->ReplyInfo.Info.Reply.RnRRetryCount =
Packit 857059
									pCEPEntry->LocalRnrRetryCount; // 1st guess
Packit 857059
		// caller must set approprite RnrRetryCount, this is just
Packit 857059
		// a wild guess, caller can set higher or lower
Packit 857059
	}
Packit 857059
Packit 857059
	// set up attributes to move QP to RTR
Packit 857059
	GetRtrAttrFromCep(pCEPEntry,
Packit 857059
			(Info->ReplyInfo.Info.Reply.FailoverAccepted == CM_REP_FO_ACCEPTED),
Packit 857059
			&Info->QpAttrRtr);
Packit 857059
done:
Packit 857059
	if (pCaAttr)
Packit 857059
		MemoryDeallocate(pCaAttr);
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return Status;
Packit 857059
}
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// AcceptP_Async
Packit 857059
//
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS - The function has completed successfully. For server, this indicates the initialization.
Packit 857059
//		>FCM_CONNECT_ESTABLISHED
Packit 857059
//		>FCM_CONNECT_REJECT
Packit 857059
//		>FCM_CONNECT_TIMEOUT
Packit 857059
//		>FCM_CONNECT_CANCEL
Packit 857059
//
Packit 857059
//	FINVALID_STATE - The endpoint is not in the valid state for this call
Packit 857059
//	FERROR	- Unable to send the reply ack packet
Packit 857059
//	FTIMEOUT - The timeout interval expires
Packit 857059
//
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
AcceptP_Async(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	IN const CM_CONN_INFO*		pSendConnInfo,		// Send REP
Packit 857059
	IN EVENT_HANDLE				hEvent,
Packit 857059
	IN EVENT_HANDLE				hWaitEvent,
Packit 857059
	IN PFN_CM_CALLBACK			pfnCallback,
Packit 857059
	IN void*					Context,
Packit 857059
	IN boolean					willWait,
Packit 857059
	OUT CM_CEP_OBJECT**			ppCEP
Packit 857059
	)
Packit 857059
{
Packit 857059
	CM_CEP_OBJECT* pCEPEntry = NULL;
Packit 857059
Packit 857059
	FSTATUS		Status=FSUCCESS;
Packit 857059
Packit 857059
	uint32		rep_timeout_ms=0;
Packit 857059
	uint64		elapsed_us=0;
Packit 857059
	uint8		timewait;
Packit 857059
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AcceptP_Async);
Packit 857059
Packit 857059
	if (ppCEP)
Packit 857059
	{
Packit 857059
		*ppCEP = NULL;
Packit 857059
	}
Packit 857059
Packit 857059
	// Check QPN/EECN has been supplied
Packit 857059
	if (! pSendConnInfo || (pSendConnInfo->Info.Reply.QPN == 0
Packit 857059
							&& pSendConnInfo->Info.Reply.EECN == 0))
Packit 857059
	{
Packit 857059
		Status = FINVALID_PARAMETER;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
Packit 857059
Packit 857059
	SpinLockAcquire(&gCM->ListLock);
Packit 857059
Packit 857059
	Status = GetPendingCEP(pCEP, &pCEPEntry);
Packit 857059
	if (Status != FSUCCESS)
Packit 857059
		goto unlock;
Packit 857059
Packit 857059
	//BitClear(pCEPEntry->EventFlags, CME_REQ_RCVD);
Packit 857059
Packit 857059
	elapsed_us = CmGetElapsedTime(pCEPEntry);
Packit 857059
Packit 857059
	// Update the turnaround time
Packit 857059
	gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us);
Packit 857059
Packit 857059
	_DBG_INFO(("Update turnaround time <tat %"PRIu64"us>.\n", gCM->turnaround_time_us));
Packit 857059
Packit 857059
	// check RDMA Read parameters have not been incorrectly increased
Packit 857059
	if (pCEPEntry->LocalInitiatorDepth <
Packit 857059
							pSendConnInfo->Info.Reply.ArbInitiatorDepth
Packit 857059
		|| pCEPEntry->LocalResponderResources <
Packit 857059
							pSendConnInfo->Info.Reply.ArbResponderResources)
Packit 857059
	{
Packit 857059
		Status = FINVALID_PARAMETER;
Packit 857059
		goto unlock;
Packit 857059
	}
Packit 857059
Packit 857059
	if (pCEPEntry->bPeer)
Packit 857059
	{
Packit 857059
		// API design decision, must use same EndPoint in CmAccept
Packit 857059
		// as did in original PeerConnect.  We enforce this
Packit 857059
		// (as opposed to blindly replacing Reply or CEP info)
Packit 857059
		// to catch applications which end up with 2 QPs for the CEP
Packit 857059
		if (pCEPEntry->LocalEndPoint.QPN != pSendConnInfo->Info.Reply.QPN
Packit 857059
			|| pCEPEntry->LocalEndPoint.EECN != pSendConnInfo->Info.Reply.EECN)
Packit 857059
		{
Packit 857059
			Status = FINVALID_PARAMETER;
Packit 857059
			goto unlock;
Packit 857059
		}
Packit 857059
	} else {
Packit 857059
		// Save the relevent user reply info to this object
Packit 857059
		pCEPEntry->LocalEndPoint.QPN = pSendConnInfo->Info.Reply.QPN;
Packit 857059
		pCEPEntry->LocalEndPoint.EECN = pSendConnInfo->Info.Reply.EECN;
Packit 857059
		if (! CM_MapTryInsert(&gCM->LocalEndPointMap, (uintn)pCEPEntry,
Packit 857059
				&pCEPEntry->LocalEndPointMapEntry, "LOCAL_END_POINT_LIST", pCEPEntry))
Packit 857059
		{
Packit 857059
			Status = FCM_ADDR_INUSE;
Packit 857059
			pCEPEntry->LocalEndPoint.QPN = 0;
Packit 857059
			pCEPEntry->LocalEndPoint.EECN = 0;
Packit 857059
			goto unlock;
Packit 857059
		}
Packit 857059
Packit 857059
		// Save the disconnect callback
Packit 857059
		pCEPEntry->pfnUserCallback = pfnCallback;
Packit 857059
		pCEPEntry->UserContext = Context;
Packit 857059
Packit 857059
		pCEPEntry->bAsyncAccept = pCEP->bAsyncAccept;
Packit 857059
		pCEPEntry->bTimewaitCallback = pCEP->bTimewaitCallback;
Packit 857059
		pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported;
Packit 857059
		pCEPEntry->turnaround_time_us = pCEP->turnaround_time_us;
Packit 857059
Packit 857059
		// Use this user-specified event obj instead of the one we created internally
Packit 857059
		if (hEvent)
Packit 857059
		{
Packit 857059
			OS_WAIT_OBJ_HANDLE hCEPEventObj = (OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj;
Packit 857059
			boolean            RemoveReference = FALSE;
Packit 857059
Packit 857059
			if (hCEPEventObj)
Packit 857059
			{
Packit 857059
 				if (pCEPEntry->bPrivateEvent)
Packit 857059
				{
Packit 857059
					EventDealloc(pCEPEntry->pEventObj);
Packit 857059
				}
Packit 857059
				else
Packit 857059
				{
Packit 857059
					RemoveReference = TRUE;
Packit 857059
				}
Packit 857059
			}
Packit 857059
Packit 857059
			pCEPEntry->bPrivateEvent = 0;
Packit 857059
Packit 857059
			pCEPEntry->pEventObj = (EVENT*)hEvent;
Packit 857059
Packit 857059
			OsWaitObjAddRef((OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj);
Packit 857059
Packit 857059
			if (RemoveReference)
Packit 857059
			{
Packit 857059
				OsWaitObjRemoveRef(hCEPEventObj);
Packit 857059
			}
Packit 857059
		}
Packit 857059
Packit 857059
		if (hWaitEvent)
Packit 857059
		{
Packit 857059
			pCEPEntry->pWaitEvent = (EVENT*)hWaitEvent;
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	if (pCEP->AlternatePath.LocalLID != 0)
Packit 857059
	{
Packit 857059
		if (pSendConnInfo->Info.Reply.FailoverAccepted != CM_REP_FO_ACCEPTED)
Packit 857059
		{
Packit 857059
			MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath));
Packit 857059
		}
Packit 857059
		pCEPEntry->bFailoverSupported &= IsFailoverSupported(
Packit 857059
							pSendConnInfo->Info.Reply.FailoverAccepted);
Packit 857059
	}
Packit 857059
Packit 857059
	// save arbitrated RDMA Read parameters
Packit 857059
	pCEPEntry->LocalInitiatorDepth =
Packit 857059
							pSendConnInfo->Info.Reply.ArbInitiatorDepth;
Packit 857059
	pCEPEntry->LocalResponderResources =
Packit 857059
							pSendConnInfo->Info.Reply.ArbResponderResources;
Packit 857059
	if (pSendConnInfo->Info.Reply.TargetAckDelay > pCEP->TargetAckDelay)
Packit 857059
	{
Packit 857059
		pCEP->TargetAckDelay = pSendConnInfo->Info.Reply.TargetAckDelay;
Packit 857059
	}
Packit 857059
	pCEP->LocalRecvPSN = pSendConnInfo->Info.Reply.StartingPSN;
Packit 857059
Packit 857059
	// update timewait 
Packit 857059
	// some applications don't set TargetAckDelay properly
Packit 857059
	// and to be safe we want our timewait to be no less than remote end
Packit 857059
	// so be conservative and only increase it, the computation below
Packit 857059
	// due to the round up of PktLifeTime, essentially always
Packit 857059
	// adds TargetAckDelay to the timewait
Packit 857059
	timewait = TimeoutTimeToMult(
Packit 857059
						(TimeoutMultToTimeInUsec(pCEPEntry->PktLifeTime)<<1)
Packit 857059
							+ TimeoutMultToTimeInUsec(pCEP->TargetAckDelay));
Packit 857059
	if (pCEPEntry->Timewait < timewait)
Packit 857059
		pCEPEntry->Timewait = timewait;
Packit 857059
Packit 857059
	FormatREP((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement),
Packit 857059
				&pSendConnInfo->Info.Reply,
Packit 857059
				pCEPEntry->TransactionID,
Packit 857059
				pCEPEntry->LocalCommID,
Packit 857059
				pCEPEntry->RemoteCommID,
Packit 857059
				pCEPEntry->LocalEndPoint.CaGUID);
Packit 857059
Packit 857059
	_DBG_INFO(("<cep 0x%p> REP's dgrm address field <portguid 0x%"PRIx64", dlid 0x%x, slm %d, pathbits %d, rate %d>\n",
Packit 857059
				_DBG_PTR(pCEPEntry), 
Packit 857059
				pCEPEntry->pDgrmElement->PortGuid,
Packit 857059
				pCEPEntry->pDgrmElement->RemoteLID,
Packit 857059
				pCEPEntry->pDgrmElement->ServiceLevel,
Packit 857059
				pCEPEntry->pDgrmElement->PathBits,
Packit 857059
				pCEPEntry->pDgrmElement->StaticRate));
Packit 857059
Packit 857059
	// Send out the REP
Packit 857059
	Status = CmDgrmSend(pCEPEntry->pDgrmElement);
Packit 857059
	if (FSUCCESS != Status)
Packit 857059
	{
Packit 857059
		// fall through and let timer retry the send later
Packit 857059
		_DBG_WARN(("<cep 0x%p> DgrmSend() failed for REP!!! <%s>\n",
Packit 857059
					_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
		Status = FSUCCESS;
Packit 857059
	} else {
Packit 857059
		AtomicIncrementVoid(&gCM->Sent.Rep);
Packit 857059
	}
Packit 857059
	
Packit 857059
	_DBG_INFO(("<cep 0x%p> REP sent <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x>.\n", 
Packit 857059
				_DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID,
Packit 857059
				pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID));
Packit 857059
Packit 857059
	CepRemoveFromPendingList(pCEPEntry);
Packit 857059
Packit 857059
	CepSetState(pCEPEntry, CMS_REP_SENT);
Packit 857059
Packit 857059
	// For peer connection, leave the entry in the LISTEN list
Packit 857059
Packit 857059
	// Start timer to timeout the REP i.e. wait for the RTU msg to arrive
Packit 857059
	pCEPEntry->RetryCount = 0;
Packit 857059
	rep_timeout_ms = TimeoutMultToTimeInMs(pCEPEntry->LocalCMTimeout);
Packit 857059
	CmTimerStart(pCEPEntry, rep_timeout_ms, REP_TIMER);
Packit 857059
Packit 857059
	if (willWait)
Packit 857059
	{
Packit 857059
		// caller will be doing a WaitP
Packit 857059
		// prevent a callback until caller WaitP completes
Packit 857059
		AtomicIncrementVoid(&pCEPEntry->CallbackRefCnt);
Packit 857059
		AtomicIncrementVoid(&gCM->TotalCallbackRefCnt);
Packit 857059
	}
Packit 857059
		
Packit 857059
	// If another connection is pending for this server endpoint, 
Packit 857059
	// we must set it again to wake up the Wait()
Packit 857059
	if (pCEP->PendingCount)
Packit 857059
	{
Packit 857059
		SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ);
Packit 857059
	}
Packit 857059
Packit 857059
	// Return the new CEP object to the user
Packit 857059
	if (ppCEP)
Packit 857059
	{
Packit 857059
		*ppCEP = pCEPEntry;
Packit 857059
	}
Packit 857059
	Status = FPENDING;
Packit 857059
Packit 857059
unlock:
Packit 857059
	SpinLockRelease(&gCM->ListLock);
Packit 857059
done:
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // AcceptP_Asynch()
Packit 857059
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// AcceptP
Packit 857059
//
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FCM_CONNECT_ESTABLISHED - Connection established
Packit 857059
//	FCM_CONNECT_REJECT		- Connection rejected
Packit 857059
//	FCM_CONNECT_TIMEOUT		- Connection timeout
Packit 857059
//	FCM_CONNECT_CANCEL		- Connection cancel
Packit 857059
//
Packit 857059
//	FINVALID_STATE			- The endpoint is not in the valid state for this call
Packit 857059
//	FERROR					- Nothing to accept, cannot accept, or unable to send the reply packet
Packit 857059
//	FTIMEOUT				- The timeout interval expires
Packit 857059
//
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
AcceptP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	IN const CM_CONN_INFO*		pSendConnInfo,		// Send REP
Packit 857059
	OUT CM_CONN_INFO*			pRecvConnInfo,		// Rcvd RTU, REJ or TIMEOUT
Packit 857059
	IN PFN_CM_CALLBACK			pfnCallback,
Packit 857059
	IN void*					Context,
Packit 857059
	OUT CM_CEP_OBJECT**			ppNewCEP
Packit 857059
	)
Packit 857059
{
Packit 857059
	CM_CEP_OBJECT*	pNewCEP=NULL;
Packit 857059
	FSTATUS		Status=FSUCCESS;
Packit 857059
	uint32		rep_timeout_ms=0;
Packit 857059
	boolean bPeer = pCEP->bPeer;	// save in case move Cep to Idle
Packit 857059
Packit 857059
	_DBG_ENTER_EXT(_DBG_LVL_FUNC_TRACE, AcceptP, == PASSIVE);
Packit 857059
Packit 857059
	UNUSED_VAR(rep_timeout_ms);
Packit 857059
Packit 857059
	if (! pRecvConnInfo && ! pCEP->bAsyncAccept)
Packit 857059
	{
Packit 857059
		Status = FINVALID_PARAMETER;
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
	// Accept client or peer connection. Send the REP to the remote client 
Packit 857059
	// use ppNewCEP if not-NULL so caller gets updated while in Lock in
Packit 857059
	// AcceptP_Async
Packit 857059
	Status = AcceptP_Async(pCEP, pSendConnInfo, NULL, NULL, pfnCallback, Context, ! pCEP->bAsyncAccept, ppNewCEP?ppNewCEP:&pNewCEP);
Packit 857059
Packit 857059
	if (Status != FSUCCESS && Status != FPENDING)
Packit 857059
		goto done;
Packit 857059
	if (ppNewCEP)
Packit 857059
		pNewCEP = *ppNewCEP;
Packit 857059
Packit 857059
	if (bPeer)
Packit 857059
	{
Packit 857059
		ASSERT(pNewCEP == pCEP);
Packit 857059
	}
Packit 857059
Packit 857059
	if (pCEP->bAsyncAccept)
Packit 857059
	{
Packit 857059
		// we will provide a callback when RTU or REJ arrives or timeout
Packit 857059
		goto done;
Packit 857059
	}
Packit 857059
Packit 857059
	// Wait for RTU or REJ to arrive or timeout event to occur
Packit 857059
	// TODO: We should put a time limit here in case we dont get the timeout event ??
Packit 857059
	Status = WaitP(pNewCEP, pRecvConnInfo, EVENT_NO_TIMEOUT);
Packit 857059
	//rep_timeout_ms = TimeoutMultToTimeInMs(pNewCEP->LocalCMTimeout);
Packit 857059
	//Status = WaitP(pNewCEP, pRecvConnInfo, 2*rep_timeout_ms, TRUE);
Packit 857059
	ASSERT(Status == FSUCCESS);
Packit 857059
Packit 857059
	// This is the status we returned to the caller
Packit 857059
	Status = pRecvConnInfo->Status;
Packit 857059
Packit 857059
	// Check the status here instead of the state since the status is what
Packit 857059
	// we return to the caller
Packit 857059
	if (Status == FCM_CONNECT_ESTABLISHED)
Packit 857059
	{
Packit 857059
		//
Packit 857059
		// Note: Though the status is established, the pNewCEP state may not be in
Packit 857059
		// CMS_ESTABLISHED since we may have already received a DREQ
Packit 857059
		//
Packit 857059
		_DBG_INFO(("<cep 0x%p> *** Connection established *** <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, 
Packit 857059
					pNewCEP->PrimaryPath.LocalLID, pNewCEP->PrimaryPath.RemoteLID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State))));
Packit 857059
Packit 857059
	} else {
Packit 857059
		switch (Status)
Packit 857059
		{
Packit 857059
		case FCM_CONNECT_CANCEL: // USRE_CANCEL
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Connection cancelled *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			break;
Packit 857059
Packit 857059
		case FCM_CONNECT_REJECT: // CME_RCVD_REJ
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Connection rejected *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			break;
Packit 857059
Packit 857059
		case FCM_CONNECT_TIMEOUT: // CME_TIMEOUT_REP
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Connection timed out *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			break;
Packit 857059
Packit 857059
		case FCM_DISCONNECT_REQUEST:
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Disconnecting *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			break;
Packit 857059
		
Packit 857059
		case FCM_DISCONNECTED:
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Disconnected *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			break;
Packit 857059
Packit 857059
		default:
Packit 857059
			_DBG_INFO(("<cep 0x%p> *** Connection ??? *** <lcid 0x%x rcid 0x%x %s %s>.\n", 
Packit 857059
					_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
Packit 857059
					_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			ASSERT(0);
Packit 857059
			break;
Packit 857059
		
Packit 857059
		} // switch()
Packit 857059
Packit 857059
		if (!bPeer)
Packit 857059
		{
Packit 857059
			// This is the one we created when a new connection request arrived
Packit 857059
			iba_cm_destroy_cep(pNewCEP);
Packit 857059
		}
Packit 857059
		if (ppNewCEP)
Packit 857059
			*ppNewCEP = NULL;
Packit 857059
	}
Packit 857059
	CmDoneCallback(pNewCEP);
Packit 857059
Packit 857059
done:
Packit 857059
	_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // AcceptP()
Packit 857059
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// RejectP
Packit 857059
//
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS.
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
RejectP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP,
Packit 857059
	IN const CM_REJECT_INFO*	pConnectReject
Packit 857059
	)
Packit 857059
{
Packit 857059
	CM_CEP_OBJECT* pCEPEntry = NULL;
Packit 857059
	DLIST_ENTRY* pListEntry=NULL;
Packit 857059
	FSTATUS	Status=FSUCCESS;
Packit 857059
	boolean bPeer = pCEP->bPeer;	// in case move Cep to Idle
Packit 857059
		
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RejectP);
Packit 857059
Packit 857059
	switch (pCEP->State)
Packit 857059
	{
Packit 857059
	case CMS_IDLE:
Packit 857059
		if (BitTest(pCEP->EventFlags, USRE_CANCEL))
Packit 857059
		{
Packit 857059
			// User cancelled the listen, but hasn't gotten callback yet
Packit 857059
			Status = FCM_CONNECT_CANCEL;
Packit 857059
		}
Packit 857059
		else
Packit 857059
		{
Packit 857059
			Status = FERROR;
Packit 857059
		}
Packit 857059
		break;
Packit 857059
Packit 857059
	case CMS_LISTEN:
Packit 857059
	case CMS_REQ_RCVD:	// TBD only occurs for actual CEP (can be Peer), separate out
Packit 857059
	case CMS_MRA_REQ_SENT:	// TBD only occurs for actual CEP (can be Peer), separate out
Packit 857059
		// if separate out above and did same in AcceptP, won't need Peer on PendingList
Packit 857059
Packit 857059
		//
Packit 857059
		// Rejecting the incoming connect or peer request
Packit 857059
		//
Packit 857059
		if (DListIsEmpty(&pCEP->PendingList))
Packit 857059
		{
Packit 857059
			// Nothing to reject
Packit 857059
			_DBG_WARNING(("<cep 0x%p> Pending list is empty!\n", _DBG_PTR(pCEP)));
Packit 857059
Packit 857059
			Status = FNOT_FOUND;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
Packit 857059
		// Pull the incoming connection
Packit 857059
		pListEntry = DListGetNext(&pCEP->PendingList);
Packit 857059
		pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
Packit 857059
		ASSERT(pCEPEntry->pParentCEP == pCEP);
Packit 857059
Packit 857059
		// Cannot reject until the user has been notify thru wait
Packit 857059
		/*
Packit 857059
		if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT))
Packit 857059
		{
Packit 857059
			Status = FUNAVAILABLE;
Packit 857059
			break;
Packit 857059
		}
Packit 857059
Packit 857059
		BitClear(pCEPEntry->EventFlags, USRE_WAIT);
Packit 857059
		*/
Packit 857059
Packit 857059
		ASSERT(pCEPEntry->State == CMS_REQ_RCVD || pCEPEntry->State == CMS_MRA_REQ_SENT);
Packit 857059
		// Format the REJ msg
Packit 857059
		FormatREJ((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement),
Packit 857059
					CM_REJECT_REQUEST,
Packit 857059
					(uint16)pConnectReject->Reason,
Packit 857059
					&pConnectReject->RejectInfo[0],
Packit 857059
					pConnectReject->RejectInfoLen,
Packit 857059
					&pConnectReject->PrivateData[0],
Packit 857059
					CMM_REJ_USER_LEN,
Packit 857059
					pCEPEntry->TransactionID,
Packit 857059
					pCEPEntry->LocalCommID,
Packit 857059
					pCEPEntry->RemoteCommID);
Packit 857059
Packit 857059
		// Send out the REJ. We do not need to check the return since
Packit 857059
		// the other end will eventually timed-out if it does not received
Packit 857059
		// either RTU or REJ
Packit 857059
		Status = CmDgrmSend(pCEPEntry->pDgrmElement);
Packit 857059
		if (FSUCCESS != Status)
Packit 857059
		{
Packit 857059
			// fall through and let timer retry the send later
Packit 857059
			_DBG_WARN(("<cep 0x%p> DgrmSend() failed for REJ!!! <%s>\n",
Packit 857059
							_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
			Status = FSUCCESS;
Packit 857059
		} else {
Packit 857059
			AtomicIncrementVoid(&gCM->Sent.RejReq);
Packit 857059
		}
Packit 857059
		
Packit 857059
		_DBG_INFO(("<cep 0x%p> REJ sent, rejecting REQ <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x reason %d>.\n", 
Packit 857059
					_DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID,
Packit 857059
					pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID,
Packit 857059
					pConnectReject->Reason));
Packit 857059
Packit 857059
		// Move from PENDING to INIT list
Packit 857059
		CepRemoveFromPendingList(pCEPEntry);
Packit 857059
		CepToIdle(pCEPEntry);
Packit 857059
Packit 857059
		if (bPeer)
Packit 857059
		{
Packit 857059
			// For peer request, the user created the obj 
Packit 857059
			ASSERT(pCEPEntry == pCEP);
Packit 857059
		} else {
Packit 857059
			// This is the one we created when a new connection request arrived
Packit 857059
			DestroyCEP(pCEPEntry);
Packit 857059
		}
Packit 857059
Packit 857059
		// If another connection is pending for this server endpoint, 
Packit 857059
		// we must set it again to wake up the Wait()
Packit 857059
		if (pCEP->PendingCount)
Packit 857059
		{
Packit 857059
			SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ);
Packit 857059
		}
Packit 857059
Packit 857059
		break;
Packit 857059
	// TBD case CMS_REP_SENT: - allow and move to TimeWait, see Cancel
Packit 857059
	// TBD case CMS_MRA_REP_RCVD: - allow and move to TimeWait, see Cancel
Packit 857059
Packit 857059
	default:
Packit 857059
Packit 857059
		Status = FINVALID_STATE;
Packit 857059
		break;
Packit 857059
Packit 857059
	} // switch()
Packit 857059
			
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // RejectP()
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// CancelP
Packit 857059
// CmCancel, DestroyCEP or remove CA while connecting
Packit 857059
// 
Packit 857059
// Cancel processing of a passive side connection
Packit 857059
// all local information is dropped, remote end is left to timeout
Packit 857059
// user will get a FCM_CONNECT_CANCEL callback at which point user
Packit 857059
// should destroy the now-idle CEP
Packit 857059
//
Packit 857059
// In general this should be used only to cancel listeners.
Packit 857059
// Internally it is used to do a quick cleanup for a Destroyed CEP
Packit 857059
// or the removal of a CA, hence it does not attempt to send a Reject
Packit 857059
// Applications should generally use CmReject instead of this to
Packit 857059
// properly reject connections.
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS.
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
CancelP(
Packit 857059
	IN CM_CEP_OBJECT*			pCEP
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS			Status=FPENDING;
Packit 857059
Packit 857059
	CM_CEP_OBJECT*	pCEPEntry=NULL;
Packit 857059
	DLIST_ENTRY*		pListEntry=NULL;
Packit 857059
Packit 857059
	switch (pCEP->State)
Packit 857059
	{
Packit 857059
	case CMS_LISTEN:
Packit 857059
		//
Packit 857059
		// Cancel the listen request
Packit 857059
		//
Packit 857059
Packit 857059
		// Clear the pending signal from the event obj since a REQ may be pending
Packit 857059
		// but before the signal is waited on
Packit 857059
		//CmEventReset(pCEP);
Packit 857059
Packit 857059
		//BitSet(pCEP->EventFlags, USRE_CANCEL);
Packit 857059
Packit 857059
		// Clear the pending list
Packit 857059
		while (!DListIsEmpty(&pCEP->PendingList))
Packit 857059
		{
Packit 857059
			pListEntry = DListGetNext(&pCEP->PendingList);
Packit 857059
			pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
Packit 857059
			// Move from PENDING to INIT list and destroy it
Packit 857059
			ASSERT(pCEPEntry->pParentCEP == pCEP);
Packit 857059
			CepRemoveFromPendingList(pCEPEntry);
Packit 857059
			CepToIdle(pCEPEntry);
Packit 857059
Packit 857059
			// This will start the timer in timewait state
Packit 857059
			DestroyCEP(pCEPEntry);
Packit 857059
		}
Packit 857059
		ASSERT(pCEP->PendingCount == 0);
Packit 857059
Packit 857059
		// Move from LISTEN to IDLE
Packit 857059
		CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP);
Packit 857059
		// ClearEndPoint in CepToIdle is benign
Packit 857059
		CepToIdle(pCEP);
Packit 857059
Packit 857059
		// Set the cancel event
Packit 857059
		SetNotification(pCEP, USRE_CANCEL);
Packit 857059
Packit 857059
		// This tells us that a callback is pending or we are in the callback
Packit 857059
		//if (AtomicRead(&pCEP->CallbackRefCnt))
Packit 857059
		//	Status = FPENDING;
Packit 857059
Packit 857059
		break;
Packit 857059
Packit 857059
	case CMS_REQ_RCVD:
Packit 857059
	case CMS_MRA_REQ_SENT:
Packit 857059
		// Internal use, removed CA or cancelling listening CEP
Packit 857059
		ASSERT(!pCEP->bPeer || (pCEP->LocalEndPoint.QPN || pCEP->LocalEndPoint.EECN));
Packit 857059
Packit 857059
#if 0
Packit 857059
		// TBD - call RejectP, will end up in Idle
Packit 857059
#else
Packit 857059
		// Move from PENDING to IDLE
Packit 857059
		CepRemoveFromPendingList(pCEP);
Packit 857059
		CepToIdle(pCEP);
Packit 857059
#endif
Packit 857059
Packit 857059
		// Set the cancel event
Packit 857059
		SetNotification(pCEP, USRE_CANCEL);
Packit 857059
Packit 857059
		break;
Packit 857059
	
Packit 857059
	case CMS_REP_SENT:
Packit 857059
	case CMS_MRA_REP_RCVD:
Packit 857059
		//
Packit 857059
		// Cancel the connection while waiting for the RTU to arrive.
Packit 857059
		// 
Packit 857059
Packit 857059
		// Cancel the timer for REP msg
Packit 857059
		CmTimerStop(pCEP, REP_TIMER);
Packit 857059
Packit 857059
		// Clear the pending signal from the event obj since a RTU may be pending
Packit 857059
		// but before the signal is waited on
Packit 857059
		//CmEventReset(pCEP);
Packit 857059
Packit 857059
		//BitSet(pCEP->EventFlags, USRE_CANCEL);
Packit 857059
#if 0
Packit 857059
		// TBD - we should do this
Packit 857059
		send a REJ (timeout or similar) - use RejectP
Packit 857059
		CepToTimewait(pCEP)
Packit 857059
		// if user wants a FCM_DISCONNECTED at end of timewait, lets not confuse
Packit 857059
		// them with a FCM_CONNECT_CANCEL callback before it
Packit 857059
		if (! pCEP->bTimewaitCallback)
Packit 857059
		{
Packit 857059
			if (pCEP->bAsyncAccept)
Packit 857059
			{
Packit 857059
				SetNotification(pCEP, USRE_CANCEL);	// callback
Packit 857059
			} else {
Packit 857059
				EventSet(pCEP, USRE_CANCEL, FALSE);	// wakeup CmAccept wait
Packit 857059
			}
Packit 857059
		}
Packit 857059
#else
Packit 857059
		CepToIdle(pCEP);
Packit 857059
Packit 857059
		if (pCEP->bAsyncAccept)
Packit 857059
		{
Packit 857059
			SetNotification(pCEP, USRE_CANCEL);	// callback
Packit 857059
		} else {
Packit 857059
			EventSet(pCEP, USRE_CANCEL, FALSE);	// wakeup CmAccept wait
Packit 857059
		}
Packit 857059
#endif
Packit 857059
		// This tells us that a callback is pending or we are in the callback
Packit 857059
		//if (AtomicRead(&pCEP->CallbackRefCnt))
Packit 857059
		//	Status = FPENDING;
Packit 857059
Packit 857059
		//if (BitTest(pCEP->EventFlags, USRE_WAIT))
Packit 857059
		//{
Packit 857059
		//	Status = FPENDING;
Packit 857059
		//}
Packit 857059
Packit 857059
		//EventSet(pCEP, USRE_CANCEL);
Packit 857059
		
Packit 857059
		break;
Packit 857059
Packit 857059
	case CMS_SIDR_REQ_RCVD:
Packit 857059
		// Move from PENDING to INIT list
Packit 857059
		CepRemoveFromPendingList(pCEP);
Packit 857059
		// ClearEndPoint in CepToIdle is benign
Packit 857059
		CepToIdle(pCEP);
Packit 857059
Packit 857059
		// Set the cancel event - this CEP not user visible, so no callback
Packit 857059
		EventSet(pCEP, USRE_CANCEL, FALSE);
Packit 857059
		break;
Packit 857059
Packit 857059
	default:
Packit 857059
Packit 857059
		Status = FINVALID_STATE;
Packit 857059
		break;
Packit 857059
Packit 857059
	} // switch()
Packit 857059
	
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // CancelP()
Packit 857059
Packit 857059
// build QP Attributes to load new alternate path into QP
Packit 857059
// and prepare a Reply
Packit 857059
FSTATUS ProcessAltPathRequestP(
Packit 857059
	IN CM_CEP_OBJECT* pCEP,
Packit 857059
	IN CM_ALTPATH_INFO*			AltPathRequest,
Packit 857059
	OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS Status=FSUCCESS;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessAltPathRequestP);
Packit 857059
Packit 857059
	ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
Packit 857059
	switch (pCEP->State)
Packit 857059
	{
Packit 857059
	case CMS_LAP_RCVD:
Packit 857059
	case CMS_MRA_LAP_SENT:
Packit 857059
		MemoryClear(Info, sizeof(*Info));	// just to be safe
Packit 857059
		Info->QpAttrRts.RequestState = QPStateReadyToSend;
Packit 857059
		Info->QpAttrRts.APMState = APMStateRearm;
Packit 857059
		GetAVFromPath2(0, &AltPathRequest->AlternatePathInfo.Path, NULL,
Packit 857059
						&Info->QpAttrRts.AltDestAV);
Packit 857059
		Info->QpAttrRts.AltDestAV.PortGUID = pCEP->TempAlternateLocalPortGuid;
Packit 857059
		Info->QpAttrRts.AltDestAV.GlobalRouteInfo.SrcGIDIndex =
Packit 857059
											pCEP->TempAlternateLocalGidIndex;
Packit 857059
		Info->QpAttrRts.AltDestAV.PathBits = pCEP->TempAlternateLocalPathBits;
Packit 857059
		Info->QpAttrRts.AltPortGUID = pCEP->TempAlternateLocalPortGuid;
Packit 857059
		Info->QpAttrRts.AltPkeyIndex = pCEP->TempAlternatePkeyIndex;
Packit 857059
		Info->QpAttrRts.Attrs = IB_QP_ATTR_APMSTATE
Packit 857059
						|IB_QP_ATTR_ALTDESTAV|IB_QP_ATTR_ALTPORTGUID
Packit 857059
						| IB_QP_ATTR_ALTPKEYINDEX;
Packit 857059
		if (pCEP->Type != CM_UC_TYPE) {
Packit 857059
			Info->QpAttrRts.AltLocalAckTimeout = AltPathRequest->AlternateAckTimeout;
Packit 857059
			Info->QpAttrRts.Attrs |= IB_QP_ATTR_ALTLOCALACKTIMEOUT;
Packit 857059
		}
Packit 857059
		Info->AltPathReply.APStatus = APS_PATH_LOADED;
Packit 857059
		// caller must iba_modify_qp(...) then iba_altpath_reply
Packit 857059
		break;
Packit 857059
Packit 857059
	default:
Packit 857059
		Status = FINVALID_STATE;
Packit 857059
		break;
Packit 857059
	}
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
Packit 857059
	return Status;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
//////////////////////////////////////////////////////////////////////////
Packit 857059
// AltPathReplyP
Packit 857059
//
Packit 857059
// Reply to an alternate path request
Packit 857059
// Only allowed for Server/Passive side of connection
Packit 857059
//
Packit 857059
// INPUTS:
Packit 857059
//
Packit 857059
//
Packit 857059
//
Packit 857059
// OUTPUTS:
Packit 857059
//
Packit 857059
//	None.
Packit 857059
//
Packit 857059
// RETURNS:
Packit 857059
//
Packit 857059
//	FSUCCESS - APR queued to be sent.
Packit 857059
//	FINVALID_STATE - The endpoint is not in the valid state for this call
Packit 857059
//	FERROR	- Unable to send the apr packet
Packit 857059
//
Packit 857059
//
Packit 857059
// IRQL:
Packit 857059
//
Packit 857059
//	This routine is called at IRQL_PASSIVE_LEVEL.
Packit 857059
//
Packit 857059
FSTATUS
Packit 857059
AltPathReplyP(
Packit 857059
	IN CM_CEP_OBJECT* 			pCEP,
Packit 857059
	IN CM_ALTPATH_REPLY_INFO*	pAprInfo		// Send APR
Packit 857059
	)
Packit 857059
{
Packit 857059
	FSTATUS		Status;
Packit 857059
	CM_MAD*		pMad = NULL;
Packit 857059
	//uint64		elapsed_us=0;
Packit 857059
Packit 857059
	_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AltPathReplyP);
Packit 857059
Packit 857059
	ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
Packit 857059
	switch (pCEP->State)
Packit 857059
	{
Packit 857059
		case CMS_LAP_RCVD:
Packit 857059
		case CMS_MRA_LAP_SENT:
Packit 857059
			pMad = (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement);
Packit 857059
Packit 857059
			if (pAprInfo->APStatus == APS_PATH_LOADED)
Packit 857059
			{
Packit 857059
				// still have the LAP we received, now we have
Packit 857059
				// accepted it as our alternate path
Packit 857059
				ASSERT(pMad->common.AttributeID == MCLASS_ATTRIB_ID_LAP);
Packit 857059
				CopyRcvdLAPToAltPath(&pMad->payload.LAP, &pCEP->AlternatePath);
Packit 857059
				pCEP->AlternatePath.LocalPortGuid = pCEP->TempAlternateLocalPortGuid;
Packit 857059
				pCEP->AlternatePath.LocalGidIndex = pCEP->TempAlternateLocalGidIndex;
Packit 857059
				pCEP->AlternatePath.LocalPathBits = pCEP->TempAlternateLocalPathBits;
Packit 857059
				pCEP->AlternatePath.PkeyIndex = pCEP->TempAlternatePkeyIndex;
Packit 857059
			} else if (pAprInfo->APStatus == APS_UNSUPPORTED_REQ) {
Packit 857059
				// in future no need to notify CEP of LAPs, it doesn't do APM
Packit 857059
				pCEP->bFailoverSupported = FALSE;
Packit 857059
			}
Packit 857059
Packit 857059
			// Update the turnaround time
Packit 857059
			// uncomment the 3 lines below to have LAP/APR response count toward
Packit 857059
			// average turnaround time
Packit 857059
			//elapsed_us = CmGetElapsedTime(pCEPEntry);
Packit 857059
			//gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us);
Packit 857059
			//_DBG_INFO(("Update turnaround time <tat %"PRIu64"us>.\n", gCM->turnaround_time_us));
Packit 857059
Packit 857059
			FormatAPR(pMad, (CM_APR_STATUS) pAprInfo->APStatus,
Packit 857059
						pAprInfo->u.AddInfo.Info,
Packit 857059
						pAprInfo->u.AddInfo.Len,
Packit 857059
						pAprInfo->PrivateData,
Packit 857059
						CM_APR_INFO_USER_LEN,
Packit 857059
						pCEP->TransactionID,
Packit 857059
						pCEP->LocalCommID,
Packit 857059
						pCEP->RemoteCommID);
Packit 857059
Packit 857059
			// Send out the APR
Packit 857059
			Status = CmDgrmSend(pCEP->pDgrmElement);
Packit 857059
			if (FSUCCESS != Status)
Packit 857059
			{
Packit 857059
				// fall through and let timer retry the send later
Packit 857059
				_DBG_WARN(("<cep 0x%p> DgrmSend() failed for APR!!! <%s>\n",
Packit 857059
							_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
Packit 857059
				Status = FSUCCESS;
Packit 857059
			} else {
Packit 857059
				if (pAprInfo->APStatus == APS_PATH_LOADED)
Packit 857059
					AtomicIncrementVoid(&gCM->Sent.AprAcc);
Packit 857059
				else
Packit 857059
					AtomicIncrementVoid(&gCM->Sent.AprRej);
Packit 857059
			}
Packit 857059
	
Packit 857059
			_DBG_INFO(("<cep 0x%p> APR sent <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x>.\n", 
Packit 857059
						_DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID,
Packit 857059
						pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID));
Packit 857059
Packit 857059
			CepSetState(pCEP, CMS_ESTABLISHED);
Packit 857059
			break;
Packit 857059
		default:
Packit 857059
			Status = FINVALID_STATE;
Packit 857059
			break;
Packit 857059
	}
Packit 857059
Packit 857059
	_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
Packit 857059
	return Status;
Packit 857059
Packit 857059
} // AltPathReplyP()
Packit 857059
Packit 857059
// EOF