/* BEGIN_ICS_COPYRIGHT4 ****************************************
Copyright (c) 2015, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** END_ICS_COPYRIGHT4 ****************************************/
#include "smamain.h"
#include "gsi_params.h"
extern uint32 CmMaxDgrms;
FSTATUS
SmaDeviceReserve(
IN SMA_CA_OBJ_PRIVATE *CaObj
)
{
FSTATUS status = FSUCCESS;
IB_CA_ATTRIBUTES *pCaAttributes = NULL;
IB_PORT_ATTRIBUTES *pPortAttributesList= NULL;
SMA_PORT_TABLE_PRIV *pPortTbl = NULL;
uint32 qp0CqSize = 0;
IB_PORT_ATTRIBUTES *pTempPortAttributesList;
IB_QP_ATTRIBUTES_CREATE qpCreateAttributes;
IB_QP_ATTRIBUTES_QUERY qpAttributes;
uint32 i=0;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, DeviceReserve);
// query the device attributes from VCA
pCaAttributes = (IB_CA_ATTRIBUTES*)MemoryAllocateAndClear(sizeof(IB_CA_ATTRIBUTES), FALSE, SMA_MEM_TAG);
if ( !pCaAttributes )
{
status = FINSUFFICIENT_MEMORY;
_DBG_ERROR (("MemAlloc failed for CaAttributes!\n" ));
goto failcaalloc;
}
status = iba_query_ca(CaObj->CaHandle, pCaAttributes, NULL/*pContext*/);
if ( FSUCCESS != status )
{
_DBG_ERROR ((
"iba_query_ca() failed with NULL PortAttribs! :%s\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failquery;
}
pPortAttributesList = (IB_PORT_ATTRIBUTES*)MemoryAllocateAndClear(pCaAttributes->PortAttributesListSize, FALSE, SMA_MEM_TAG);
if ( !pPortAttributesList )
{
status = FINSUFFICIENT_MEMORY;
_DBG_ERROR ((
"MemAlloc failed for PortAttributesList!\n" ));
goto failportalloc;
}
_DBG_PRINT (_DBG_LVL_DEVICE,(
"Processing device CA :GUID(x%"PRIx64")\n",
CaObj->CaPublic.CaGuid ));
// build list and add Port info and tag other requirements
pCaAttributes->PortAttributesList = pPortAttributesList;
pTempPortAttributesList = pPortAttributesList;
status = iba_query_ca(CaObj->CaHandle, pCaAttributes, NULL/*pContext*/);
if ( FSUCCESS != status )
{
_DBG_ERROR ((
"iba_query_ca() failed for PortAttribs!:%s\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failquery2;
}
pPortTbl = (SMA_PORT_TABLE_PRIV*)MemoryAllocateAndClear(sizeof(SMA_PORT_BLOCK_PRIV) * pCaAttributes->Ports, FALSE, SMA_MEM_TAG);
if ( !pPortTbl )
{
status = FINSUFFICIENT_MEMORY;
_DBG_ERROR (("MemAlloc failed for PortList!\n" ));
goto failtblalloc;
}
// Reserve device resources
// Fill in Ca details
CaObj->WorkReqId = 0;
CaObj->Partitions = pCaAttributes->Partitions;
CaObj->AddressVectors = pCaAttributes->AddressVectors;
CaObj->CaPublic.Ports = pCaAttributes->Ports;
CaObj->CaPublic.Capabilities = pCaAttributes->Capabilities;
// add port tables to list
CaObj->CaPublic.PortTbl = (SMA_PORT_TABLE *)pPortTbl;
// Allocate PD Resource
status = iba_alloc_sqp_pd(
CaObj->CaHandle,
// BUGBUG - does not account for send buffers allocated by registering Gsa/Smi managers
// CM is likely to be the largest so we account for its Dgrms
// however for SMI and GSI the Recv buffers will not use AVs, so this is
// a reasonable guess
#ifdef BUILD_CM
g_Settings.MaxSMPs +g_GsaSettings.MaxRecvBuffers
+ CmMaxDgrms,
#else
g_Settings.MaxSMPs +g_GsaSettings.MaxRecvBuffers,
#endif
&CaObj->PdHandle );
if ( FSUCCESS != status )
{
_DBG_ERROR (("AllocatePD() failed! :%s\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failpd;
}
// Create One CQ per CA for SMA
status = iba_create_cq(
CaObj->CaHandle,
// CqReqSize
MIN(pCaAttributes->WorkCompletions,
(CaObj->CaPublic.Ports
* (g_Settings.SendQDepth
+ g_Settings.RecvQDepth))),
(void *)QPTypeSMI, // Context
&CaObj->CqHandle,
&CaObj->CqSize );
if ( FSUCCESS != status )
{
_DBG_ERROR (( "iba_create_cq for SMA failed! :%s\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failcq;
}
// Create One CQ per CA for GSA
status = iba_create_cq(
CaObj->CaHandle,
// CqReqSize
MIN(pCaAttributes->WorkCompletions,
(CaObj->CaPublic.Ports * (g_GsaSettings.SendQDepth+g_GsaSettings.RecvQDepth))),
(void *)QPTypeGSI, // Context
&CaObj->Qp1CqHandle,
&CaObj->Qp1CqSize );
if ( FSUCCESS != status )
{
_DBG_ERROR (( "iba_create_cq for GSA failed! :%s\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failcq2;
}
// Get a Special QP each for SMA and GSA on each port
for ( i=0; i< CaObj->CaPublic.Ports; i++ )
{
_DBG_PRINT(_DBG_LVL_DEVICE,(
"Processing device port(%d) :GUID(x%"PRIx64")\n",
i+1,
pTempPortAttributesList->GUID ));
// Fill in per Port details
pPortTbl->PortBlock[i].Public.PortNumber = (uint8)i+1;
pPortTbl->PortBlock[i].Public.GUID = \
pTempPortAttributesList->GUID;
pPortTbl->PortBlock[i].Public.NumGIDs = \
pTempPortAttributesList->NumGIDs;
pPortTbl->PortBlock[i].Public.NumPKeys = \
pTempPortAttributesList->NumPkeys;
// fill in default Port state
pPortTbl->PortBlock[i].Public.State = \
pTempPortAttributesList->PortState;
// set QP attribs for SMA
qpCreateAttributes.Type = QPTypeSMI;
qpCreateAttributes.PDHandle = CaObj->PdHandle;
qpCreateAttributes.SendCQHandle = CaObj->CqHandle;
qpCreateAttributes.RecvCQHandle = CaObj->CqHandle;
qpCreateAttributes.SendQDepth =
MIN(pCaAttributes->WorkReqs, g_Settings.SendQDepth);
qpCreateAttributes.RecvQDepth =
MIN(pCaAttributes->WorkReqs, g_Settings.RecvQDepth);
qpCreateAttributes.SendDSListDepth = 1;
qpCreateAttributes.RecvDSListDepth = 2;
qpCreateAttributes.CompletionFlags = IB_COMPL_CNTL_SEND;
status = iba_create_special_qp(
CaObj->CaHandle,
pPortTbl->PortBlock[i].Public.GUID,
&qpCreateAttributes,
&pPortTbl->PortBlock[i].QpHandle, // Context
&pPortTbl->PortBlock[i].QpHandle,
&qpAttributes );
if ( FSUCCESS != status )
{
_DBG_ERROR ((
"CreateSpecialQP() failed on port(%d) for SMA :%s!\n",
i+1,
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failsmi;
}
// set QP attribs for GSA
// Note: GSA QP created with fixed settings. Changes
// to QP and CQ size will be done in GSA module if applicable
qpCreateAttributes.Type = QPTypeGSI;
qpCreateAttributes.PDHandle = CaObj->PdHandle;
qpCreateAttributes.SendCQHandle = CaObj->Qp1CqHandle;
qpCreateAttributes.RecvCQHandle = CaObj->Qp1CqHandle;
qpCreateAttributes.RecvDSListDepth = 2; //pCaAttributes->DSListDepth;
qpCreateAttributes.SendDSListDepth = 3; //pCaAttributes->DSListDepth;
qpCreateAttributes.RecvQDepth =
MIN(pCaAttributes->WorkReqs, g_GsaSettings.RecvQDepth);
qpCreateAttributes.SendQDepth =
MIN(pCaAttributes->WorkReqs, g_GsaSettings.SendQDepth);
qpCreateAttributes.CompletionFlags = IB_COMPL_CNTL_SEND;
status = iba_create_special_qp(
CaObj->CaHandle,
pPortTbl->PortBlock[i].Public.GUID,
&qpCreateAttributes,
&pPortTbl->PortBlock[i].Qp1Handle, // Context
&pPortTbl->PortBlock[i].Qp1Handle,
&qpAttributes );
if ( FSUCCESS != status )
{
_DBG_ERROR ((
"CreateSpecialQP() failed on port(%d) for GSA :%s!\n",
i+1,
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failgsi;
}
// Spinlock for Qp0 & Qp1
SpinLockInitState( &pPortTbl->PortBlock[i].Qp0Lock );
SpinLockInitState( &pPortTbl->PortBlock[i].QpLock );
if( !SpinLockInit( &pPortTbl->PortBlock[i].Qp0Lock ) )
{
_DBG_ERROR(( "Unable to initialize spinlocks for Port(%d)!\n", i+1 ));
goto faillock0;
}
if ( !SpinLockInit( &pPortTbl->PortBlock[i].QpLock ) )
{
_DBG_ERROR(( "Unable to initialize spinlocks for Port(%d)!\n", i+1 ));
goto faillock;
}
// update info
pPortTbl->PortBlock[i].Qp0SendQDepth = \
qpAttributes.SendQDepth;
AtomicWrite(&pPortTbl->PortBlock[i].Qp0SendQTop,
qpAttributes.SendQDepth);
pPortTbl->PortBlock[i].Qp0RecvQDepth = \
qpAttributes.RecvQDepth;
AtomicWrite(&pPortTbl->PortBlock[i].Qp0RecvQTop,
qpAttributes.RecvQDepth);
// keep count of All QP depths
qp0CqSize += pPortTbl->PortBlock[i].Qp0SendQDepth + \
pPortTbl->PortBlock[i].Qp0RecvQDepth;
// loop
pTempPortAttributesList = pTempPortAttributesList->Next;
} // i loop
// add port tables to list
CaObj->CaPublic.PortTbl = (SMA_PORT_TABLE *)pPortTbl;
// SMA Only: GSA resize of QP and CQ handled in GSA module
// Resize CQ if necessary
// Validate CQ size depth with all Qp depths
_DBG_PRINT (_DBG_LVL_DEVICE, (
"CqSize: \n"
"\tStored.......:%d\n"
"\tCalculated...:%d\n"
"\tResize.......:%s\n",
MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize),
qp0CqSize,
_DBG_PTR(qp0CqSize < MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize) ? "TRUE":"FALSE") ));
// Update Cqsize only if we have allocated more than
// the h/w can achieve.
if ( qp0CqSize < MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize))
{
status = iba_resize_cq(
CaObj->CqHandle,
MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize),
&CaObj->CqSize );
if (FSUCCESS != status)
{
_DBG_ERROR ((
"iba_resize_cq() failed for SMA :%s!\n",
_DBG_PTR(FSTATUS_MSG (status)) ));
goto failresize;
}
}
MemoryDeallocate ( pPortAttributesList );
MemoryDeallocate ( pCaAttributes );
done:
_DBG_LEAVE_LVL(_DBG_LVL_DEVICE);
return status;
failresize:
--i;
SpinLockDestroy( &pPortTbl->PortBlock[i].QpLock );
faillock:
SpinLockDestroy( &pPortTbl->PortBlock[i].Qp0Lock );
faillock0:
iba_destroy_qp( pPortTbl->PortBlock[i].Qp1Handle );
failgsi:
iba_destroy_qp( pPortTbl->PortBlock[i].QpHandle );
failsmi:
while (i > 0)
{
--i;
SpinLockDestroy( &pPortTbl->PortBlock[i].QpLock );
SpinLockDestroy( &pPortTbl->PortBlock[i].Qp0Lock );
iba_destroy_qp( pPortTbl->PortBlock[i].Qp1Handle );
iba_destroy_qp( pPortTbl->PortBlock[i].QpHandle );
}
iba_destroy_cq( CaObj->Qp1CqHandle );
CaObj->Qp1CqHandle = NULL;
failcq2:
iba_destroy_cq( CaObj->CqHandle );
CaObj->CqHandle = NULL;
failcq:
iba_free_pd( CaObj->PdHandle );
CaObj->PdHandle = NULL;
failpd:
MemoryDeallocate ( pPortTbl );
CaObj->CaPublic.PortTbl = NULL;
failtblalloc:
failquery2:
MemoryDeallocate ( pPortAttributesList );
failportalloc:
failquery:
MemoryDeallocate ( pCaAttributes );
failcaalloc:
goto done;
}
FSTATUS
SmaConfigQp(
IN IB_HANDLE QpHandle,
IN IB_QP_STATE QpState,
IN IB_QP_TYPE QpType
)
{
FSTATUS status = FSUCCESS;
IB_QP_ATTRIBUTES_MODIFY qpModAttributes;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, SmaConfigQp);
// set QP attribs based on transition and QpType
switch (QpState)
{
default:
_DBG_ERROR(("Invalid QP State requested!\n"));
status = FINVALID_SETTING;
goto done;
break;
case QPStateInit:
{
qpModAttributes.RequestState = QPStateInit;
qpModAttributes.Attrs = (IB_QP_ATTR_PKEYINDEX
| IB_QP_ATTR_QKEY);
qpModAttributes.PkeyIndex = 0; // BUGBUG not applicable
if ( QPTypeSMI == QpType )
qpModAttributes.Qkey = 0;
else
qpModAttributes.Qkey = QP1_WELL_KNOWN_Q_KEY;
}
break;
case QPStateReadyToRecv:
{
qpModAttributes.RequestState = QPStateReadyToRecv;
qpModAttributes.Attrs = 0;
}
break;
case QPStateReadyToSend:
{
qpModAttributes.RequestState = QPStateReadyToSend;
qpModAttributes.Attrs = IB_QP_ATTR_SENDPSN;
qpModAttributes.SendPSN = 0x00000001;
}
break;
} // switch
// transition QP states
status = iba_modify_qp( QpHandle, &qpModAttributes, NULL );
if ( FSUCCESS != status )
{
_DBG_ERROR(("Modify Qp failed!\n"));
}
done:
_DBG_LEAVE_LVL(_DBG_LVL_DEVICE);
return status;
}
FSTATUS
SmaDeviceConfig(
IN SMA_CA_OBJ_PRIVATE *CaObj,
IN IB_QP_TYPE QpType
)
{
FSTATUS status = FSUCCESS;
SMA_PORT_TABLE_PRIV *pPortTbl;
uint32 i;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, SmaDeviceConfig);
pPortTbl = (SMA_PORT_TABLE_PRIV *)CaObj->CaPublic.PortTbl;
// Loop thru' all QP0's
for ( i=0; i< CaObj->CaPublic.Ports; i++ )
{
// set QP to Init state
status = SmaConfigQp(
(( QPTypeSMI == QpType ) ? \
pPortTbl->PortBlock[i].QpHandle:pPortTbl->PortBlock[i].Qp1Handle),
QPStateInit,
QpType );
if ( FSUCCESS != status )
{
_DBG_ERROR((
"Could not transition QP%s to Init on port %d!\n",
_DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")),
i+1));
} else {
// transition QP states
// RecvQ to RTR
status = SmaConfigQp(
(( QPTypeSMI == QpType ) ? \
pPortTbl->PortBlock[i].QpHandle : \
pPortTbl->PortBlock[i].Qp1Handle),
QPStateReadyToRecv,
QpType );
if ( FSUCCESS == status )
{
// SendQ to RTS
status = SmaConfigQp(
(( QPTypeSMI == QpType ) ? \
pPortTbl->PortBlock[i].QpHandle : \
pPortTbl->PortBlock[i].Qp1Handle),
QPStateReadyToSend,
QpType );
if ( FSUCCESS != status )
{
// BUGBUG: return module error
_DBG_ERROR((
"Error transitioning QP%s on Port[%d] to RTS!\n",
_DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")),
i+1));
}
} else {
// BUGBUG: return module error
_DBG_ERROR((
"Error transitioning QP%s on Port[%d] to RTR!\n",
_DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")),
i+1));
}
} // modify QP to hold CQ
} // for Port loop
_DBG_LEAVE_LVL(_DBG_LVL_DEVICE);
return status;
}
FSTATUS
GetAV(
IN SMA_CA_OBJ_PRIVATE *CaObj,
IN IB_ADDRESS_VECTOR *AvInfo,
OUT IB_HANDLE *AvHandle
)
{
FSTATUS status = FSUCCESS;
SMA_PORT_TABLE_PRIV *pPortTbl;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, GetAV);
pPortTbl = (SMA_PORT_TABLE_PRIV *)CaObj->CaPublic.PortTbl;
// Create AV if one does not exist
_DBG_PRINT(_DBG_LVL_DEVICE,(
"AV Info:\n"
"Local:\n"
"\tPortGUID.....:x%"PRIx64"\n"
"\tPathBits.....:x%X\n"
"\tServiceLevel.:x%X\n"
"\tStaticRate...:x%X\n"
"Remote:\n"
"\tLID..........:x%X\n"
"\tGlobalRoute..:%s\n",
AvInfo->PortGUID,
AvInfo->PathBits,
AvInfo->ServiceLevel,
AvInfo->StaticRate,
AvInfo->DestLID,
_DBG_PTR(AvInfo->GlobalRoute == TRUE ? "TRUE":"FALSE" )));
// Add Global Routing Info if present
if (AvInfo->GlobalRoute)
{
_DBG_PRINT(_DBG_LVL_DEVICE,(
"Global Route Info:\n"
"\tFlowLabel....:x%X\n"
"\tHopLimit.....:x%X\n"
"\tSrcGIDIndex..:x%X\n"
"\tTrafficClass.:x%X\n",
AvInfo->GlobalRouteInfo.FlowLabel,
AvInfo->GlobalRouteInfo.HopLimit,
AvInfo->GlobalRouteInfo.SrcGIDIndex,
AvInfo->GlobalRouteInfo.TrafficClass ));
}
status = iba_create_av( CaObj->CaHandle, CaObj->PdHandle, AvInfo, AvHandle);
_DBG_LEAVE_LVL(_DBG_LVL_DEVICE);
return status;
}
FSTATUS
PutAV(
IN SMA_CA_OBJ_PRIVATE *CaObj,
IN IB_HANDLE AvHandle
)
{
FSTATUS status = FSUCCESS;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, PutAV);
// Destroy AV or cache it
status = iba_destroy_av( AvHandle );
_DBG_LEAVE_LVL (_DBG_LVL_DEVICE);
return status;
}
void
NotifyIbtCallback (
IN void *Context
)
{
SMA_CA_OBJ_PRIVATE *pCaObj;
SMA_PORT_TABLE_PRIV *pPortTbl;
SMA_PORT_BLOCK_PRIV *pPortBlock;
uint32 j;
_DBG_ENTER_LVL(_DBG_LVL_DEVICE, NotifyIbtCallback);
// Scan through all CA's
SpinLockAcquire(&g_Sma->CaListLock);
for (pCaObj = g_Sma->CaObj; pCaObj != NULL; pCaObj = pCaObj->Next)
{
boolean exists;
pCaObj->UseCount++;
SpinLockRelease(&g_Sma->CaListLock);
exists = IbtNotifyUserEvent( Context,
pCaObj->CaPublic.CaGuid, // Port/Node GUID
IB_NOTIFY_CA_ADD );
if (! exists)
goto release;
// Now notify about port events too
pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl;
for ( j = 0; j< pCaObj->CaPublic.Ports ; j++ )
{
pPortBlock = &pPortTbl->PortBlock[j];
if ( IB_PORT_ACTIVE == pPortBlock->Public.State )
{
exists = IbtNotifyUserEvent( Context,
pPortBlock->Public.GUID,// Port/Node GUID
IB_NOTIFY_LID_EVENT );
if (! exists)
goto release;
}
}
SpinLockAcquire(&g_Sma->CaListLock);
pCaObj->UseCount--;
}
done:
SpinLockRelease(&g_Sma->CaListLock);
_DBG_LEAVE_LVL (_DBG_LVL_DEVICE);
return;
release:
SpinLockAcquire(&g_Sma->CaListLock);
pCaObj->UseCount--;
goto done;
}
void
SetClassMask (
IN uint8 Class,
IN boolean Enabled
)
{
switch (Class)
{
case MCLASS_COMM_MGT:
if ( TRUE == Enabled )
g_Sma->IsConnectionManagementSupported = 1;
else
g_Sma->IsConnectionManagementSupported = 0;
break;
#if 0
case MCLASS_SNMP:
if ( TRUE == Enabled )
g_Sma->IsSNMPTunnelingSupported = 1;
else
g_Sma->IsSNMPTunnelingSupported = 0;
break;
case MCLASS_DEV_MGT:
if ( TRUE == Enabled )
g_Sma->IsDeviceManagementSupported = 1;
else
g_Sma->IsDeviceManagementSupported = 0;
break;
#endif
//
// TBD:
// Must handle vendor Classes here
//case MCLASS_X:
//
default:
_DBG_PRINT(_DBG_LVL_DEVICE,(
"No capabilities for this Class [x%X]\n",
Class ));
}
}
void
SetPortCapabilities ( void )
{
SMA_CA_OBJ_PRIVATE *pCaObj;
FSTATUS status;
SMA_PORT_TABLE_PRIV *pPortTbl;
SMA_PORT_BLOCK_PRIV *pPortBlock;
STL_SMP *pSmp;
STL_PORT_INFO *pPortInfo;
uint32 j;
uint8 portNo;
uint32 smps;
POOL_DATA_BLOCK *pSmpBlock;
_DBG_ENTER_LVL (_DBG_LVL_DEVICE, SetPortCapabilities);
for ( ;; )
{
smps = 1;
pSmpBlock = NULL;
status = iba_smi_pool_get(
NULL,
&smps,
(SMP_BLOCK **)&pSmpBlock );
if ( (FSUCCESS != status) || (pSmpBlock == NULL) )
{
_DBG_ERROR ((
"Could not Grab from Pool!\n" ));
break;
}
pSmp = (STL_SMP*)pSmpBlock->Block.Smp;
pPortInfo = (STL_PORT_INFO*)pSmp->SmpExt.DirectedRoute.SMPData;
// Scan through all CA's
SpinLockAcquire(&g_Sma->CaListLock);
for (pCaObj = g_Sma->CaObj; pCaObj != NULL; pCaObj = pCaObj->Next)
{
uint32 capMaskUpdate=0;
uint32 MadQueryLength;
pCaObj->UseCount++;
SpinLockRelease(&g_Sma->CaListLock);
// Set each port
pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl;
for ( j = 0; j< pCaObj->CaPublic.Ports ; j++ )
{
pPortBlock = &pPortTbl->PortBlock[j];
portNo = (uint8)j; // switch port zero
// Format MAD get PortInfo
pSmp->common.BaseVersion = STL_BASE_VERSION;
pSmp->common.ClassVersion = STL_SM_CLASS_VERSION;
pSmp->common.mr.AsReg8 = 0;
pSmp->common.mr.s.Method = MMTHD_GET;
pSmp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE;
pSmp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE;
pSmp->common.u.DR.s.Status = 0;
pSmp->common.u.DR.s.D = 0;
pSmp->common.u.DR.HopCount = 0;
pSmp->common.u.DR.HopPointer = 0;
//pSmp->common.TransactionID = 0;
pSmp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE;
pSmp->common.AttributeID = STL_MCLASS_ATTRIB_ID_PORT_INFO;
pSmp->common.AttributeModifier = 0x01000000 | portNo;
STL_SMP_SET_LOCAL(pSmp); // local request
MadQueryLength = sizeof(*pSmp) - STL_MAX_PAYLOAD_SMP_DR;
status = iba_get_set_mad( pPortBlock->QpHandle, portNo,
0, // SLID ignored, local request
pSmp,
&MadQueryLength );
if ( FSUCCESS != status )
{
_DBG_ERROR ((
"Could not GET Port capabilities!\n" ));
break;
}
// SWAP THE GETPORTINFO response
BSWAP_STL_PORT_INFO(pPortInfo);
ZERO_RSVD_STL_PORT_INFO(pPortInfo);
// Set capability if necessary
if (g_Sma->IsConnectionManagementSupported && !pPortInfo->CapabilityMask.s.IsConnectionManagementSupported) {
pPortInfo->CapabilityMask.s.IsConnectionManagementSupported = \
g_Sma->IsConnectionManagementSupported;
capMaskUpdate = 1;
}
if (g_Sma->IsDeviceManagementSupported && !pPortInfo->CapabilityMask.s.IsDeviceManagementSupported) {
pPortInfo->CapabilityMask.s.IsDeviceManagementSupported = \
g_Sma->IsDeviceManagementSupported;
capMaskUpdate = 1;
}
if (!capMaskUpdate)
break; // nothing to change
// Do not change other fields
pPortInfo->LinkWidth.Enabled = STL_LINK_WIDTH_NOP;
pPortInfo->PortStates.s.PortState = IB_PORT_NOP;
pPortInfo->PortStates.s.PortPhysicalState = IB_PORT_PHYS_NOP;
pPortInfo->s4.OperationalVL = 0;
pPortInfo->LinkSpeed.Enabled = IB_LINK_SPEED_NOP;
// SWAP THE SET PORT INFO payload
BSWAP_STL_PORT_INFO(pPortInfo);
// Set base MAD info
pSmp->common.BaseVersion = STL_BASE_VERSION;
pSmp->common.ClassVersion = STL_SM_CLASS_VERSION;
pSmp->common.mr.AsReg8 = 0;
pSmp->common.mr.s.Method = MMTHD_SET;
pSmp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE;
pSmp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE;
pSmp->common.u.DR.s.Status = 0;
pSmp->common.u.DR.s.D = 0;
pSmp->common.u.DR.HopCount = 0;
pSmp->common.u.DR.HopPointer = 0;
//pSmp->common.TransactionID = 0;
pSmp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE;
pSmp->common.AttributeID = STL_MCLASS_ATTRIB_ID_PORT_INFO;
pSmp->common.AttributeModifier = 0x01000000 | portNo;
STL_SMP_SET_LOCAL(pSmp); // local request
MadQueryLength = sizeof(*pSmp) - STL_MAX_PAYLOAD_SMP_DR + sizeof(*pPortInfo);
status = iba_get_set_mad( pPortBlock->QpHandle, portNo,
0, // SLID ignored, local request
pSmp,
&MadQueryLength );
if ( FSUCCESS != status )
break;
} // loop j - ports
SpinLockAcquire(&g_Sma->CaListLock);
pCaObj->UseCount--;
if ( FSUCCESS != status )
break;
} // loop - CA's
SpinLockRelease(&g_Sma->CaListLock);
status = iba_smi_pool_put( NULL, (SMP_BLOCK *)pSmpBlock );
break;
}
_DBG_LEAVE_LVL (_DBG_LVL_DEVICE);
}
void
SetPortCapabilityMask (
IN uint8 Class,
IN boolean Enabled
)
{
_DBG_ENTER_LVL (_DBG_LVL_DEVICE, SetPortCapabilityMask );
// Check init state of drivers
SetClassMask ( Class, Enabled );
if ( g_Sma->NumCa )
{
SetPortCapabilities ();
} else {
_DBG_PRINT (_DBG_LVL_DEVICE, (
"No devices present. Caching capabilities for an Add Device\n" ));
}
_DBG_LEAVE_LVL (_DBG_LVL_DEVICE);
}