#pragma warning( pop )\r
#include "nddebug.h"\r
\r
+extern uint32_t g_nd_max_inline_size;\r
+\r
#if defined(EVENT_TRACING)\r
#ifdef offsetof\r
#undef offsetof\r
__in SIZE_T nOutboundSge,\r
__in SIZE_T InboundReadLimit,\r
__in SIZE_T OutboundReadLimit,\r
- __out_opt SIZE_T* pMaxInlineData\r
+ __in_opt __out_opt SIZE_T* pMaxInlineData\r
)\r
{\r
ND_ENTER( ND_DBG_NDI );\r
m_pParent->m_Ifc.user_verbs.nd_get_qp_state != NULL ||\r
m_pParent->m_Ifc.user_verbs.pre_destroy_qp != NULL ||\r
m_pParent->m_Ifc.user_verbs.post_destroy_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_query_qp != NULL ||\r
m_pParent->m_Ifc.user_verbs.post_send != NULL ||\r
m_pParent->m_Ifc.user_verbs.post_recv != NULL /*||\r
m_pParent->m_Ifc.user_verbs.bind_mw != NULL*/ );\r
\r
+ UINT32 InlineSize;\r
+ if ( pMaxInlineData )\r
+ InlineSize = (UINT32)*pMaxInlineData;\r
+ else\r
+ InlineSize = g_nd_max_inline_size;\r
+ \r
HRESULT hr = CreateQp(\r
pInboundCq,\r
pOutboundCq,\r
nInboundSge,\r
nOutboundSge,\r
InboundReadLimit,\r
- OutboundReadLimit );\r
+ OutboundReadLimit,\r
+ InlineSize );\r
\r
if( FAILED( hr ) )\r
return hr;\r
\r
+ ib_qp_attr_t qp_attr;\r
+ hr = QueryQp(&qp_attr);\r
+ if( FAILED( hr ) ) {\r
+ DestroyQp();\r
+ return hr;\r
+ }\r
+ else\r
+ InlineSize = (UINT32)qp_attr.sq_max_inline;\r
+ \r
+ \r
m_Ird = (UINT8)InboundReadLimit;\r
m_Ord = (UINT8)OutboundReadLimit;\r
+ m_MaxInlineSize = InlineSize;\r
\r
// Move the QP to the INIT state so users can post receives.\r
hr = ModifyQp( IB_QPS_INIT );\r
DestroyQp();\r
\r
if( SUCCEEDED( hr ) && pMaxInlineData != NULL )\r
- {\r
- // Worst case.\r
- *pMaxInlineData = nOutboundSge * 12;\r
- }\r
+ *pMaxInlineData = InlineSize;\r
\r
return hr;\r
}\r
wr.p_next = NULL;\r
wr.wr_id = (ULONG_PTR)pResult;\r
wr.wr_type = WR_SEND;\r
- wr.send_opt = 0;\r
+ if ( pResult->BytesTransferred <= m_MaxInlineSize )\r
+ wr.send_opt = IB_SEND_OPT_INLINE; \r
+ else\r
+ wr.send_opt = 0;\r
+ \r
if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
if( Flags & ND_OP_FLAG_READ_FENCE )\r
wr.p_next = NULL;\r
wr.wr_id = (ULONG_PTR)pResult;\r
wr.wr_type = WR_SEND;\r
+ if ( pResult->BytesTransferred <= m_MaxInlineSize )\r
+ wr.send_opt = IB_SEND_OPT_INLINE; \r
+ else\r
+ wr.send_opt = 0;\r
// We simulate invalidate operations (since we simulate MW use). We\r
// put the RKey in the immediate data, the recipient will do the\r
// lookup of the MW based on that (as they would with a regular\r
// invalidate request).\r
- wr.send_opt = IB_SEND_OPT_IMMEDIATE;\r
+ wr.send_opt |= IB_SEND_OPT_IMMEDIATE;\r
if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
if( Flags & ND_OP_FLAG_READ_FENCE )\r
wr.p_next = NULL;\r
wr.wr_id = (ULONG_PTR)pResult;\r
wr.wr_type = Type;\r
- wr.send_opt = 0;\r
+ if ( pResult->BytesTransferred <= m_MaxInlineSize )\r
+ wr.send_opt = IB_SEND_OPT_INLINE; \r
+ else\r
+ wr.send_opt = 0;\r
if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
if( Flags & ND_OP_FLAG_READ_FENCE )\r
__in SIZE_T nInboundSge,\r
__in SIZE_T nOutboundSge,\r
__in SIZE_T InboundReadLimit,\r
- __in SIZE_T OutboundReadLimit\r
+ __in SIZE_T OutboundReadLimit,\r
+ __in SIZE_T MaxInlineData\r
)\r
{\r
ND_ENTER( ND_DBG_NDI );\r
\r
+ if( MaxInlineData > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_3;\r
if( nInboundEntries > UINT_MAX )\r
return ND_INVALID_PARAMETER_4;\r
if( nOutboundEntries > UINT_MAX )\r
qp_ioctl.in.qp_create.rq_depth = (uint32_t)nInboundEntries;\r
qp_ioctl.in.qp_create.sq_sge = (uint32_t)nOutboundSge;\r
qp_ioctl.in.qp_create.rq_sge = (uint32_t)nInboundSge;\r
+ qp_ioctl.in.qp_create.sq_max_inline = (uint32_t)MaxInlineData;\r
qp_ioctl.in.qp_create.h_srq = NULL;\r
qp_ioctl.in.qp_create.sq_signaled = FALSE;\r
\r
return S_OK;\r
}\r
\r
+HRESULT CEndpoint::QueryQp(\r
+ __out ib_qp_attr_t *qp_attr\r
+ )\r
+{\r
+ ib_api_status_t status;\r
+ \r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_query_qp_ioctl_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+ qp_ioctl.in.h_qp = m_hQp;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_pParent->m_Ifc.user_verbs.pre_query_qp )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_pParent->m_Ifc.user_verbs.pre_query_qp( m_uQp, &qp_ioctl.in.umv_buf );\r
+ if( status != IB_SUCCESS )\r
+ goto done;\r
+ }\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_QUERY_QP,\r
+ &qp_ioctl.in,\r
+ sizeof(qp_ioctl.in),\r
+ &qp_ioctl.out,\r
+ sizeof(qp_ioctl.out),\r
+ &bytes_ret,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || bytes_ret != sizeof(qp_ioctl.out) )\r
+ status = IB_ERROR;\r
+ else\r
+ status = qp_ioctl.out.status;\r
+\r
+ /* Call vendor's post_query_qp */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.post_query_qp );\r
+ if( m_pParent->m_Ifc.user_verbs.post_query_qp )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.post_query_qp( m_uQp, status,\r
+ &qp_ioctl.out.attr, &qp_ioctl.out.umv_buf );\r
+ }\r
+\r
+done:\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Queried QP %#I64x, QPn %#x, pd %#I64x, context %p, status %#x \n", \r
+ m_hQp, m_Qpn, m_pParent->m_hPd, this, status ) );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ *qp_attr = qp_ioctl.out.attr;\r
+ return S_OK;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ \r
+}\r
+\r
} // namespace\r