wc->recv.ud.path_bits = (u8)(cqe->g_mlpath_rqpn & 0x7f);\r
wc->recv.ud.recv_opt |= cqe->g_mlpath_rqpn & 0x080 ? IB_RECV_OPT_GRH_VALID : 0;\r
wc->recv.ud.pkey_index = (u16)(be32_to_cpu(cqe->immed_rss_invalid) & 0x7f);\r
- wc->csum_ok = mlx4_ib_ipoib_csum_ok(cqe->ipoib_status,cqe->checksum);\r
+ wc->recv.ud.csum_ok = mlx4_ib_ipoib_csum_ok(cqe->ipoib_status,cqe->checksum);\r
}\r
if (!is_send && cqe->rlid == 0){\r
MLX4_PRINT(TRACE_LEVEL_INFORMATION,MLX4_DBG_CQ,("found rlid == 0 \n "));\r
/*\r
* Macros\r
*/\r
-\r
+typedef enum {CSUM_DISABLED = 0, CSUM_ENABLED, CSUM_BYPASS} tCsumTypeEn;\r
\r
typedef struct _ipoib_params\r
{\r
int32_t rq_depth;\r
int32_t rq_low_watermark;\r
int32_t sq_depth;\r
- boolean_t send_chksum_offload;\r
- boolean_t recv_chksum_offload;\r
+ int32_t send_chksum_offload; //is actually of type tCsumTypeEn\r
+ int32_t recv_chksum_offload; //is actually of type tCsumTypeEn\r
uint32_t sa_timeout;\r
uint32_t sa_retry_cnt;\r
uint32_t recv_pool_ratio;\r
* Number of send WQEs to allocate.\r
*\r
* send_chksum_offload\r
-* Flag to indicate whether to offload send checksums. This will make it\r
-* so that IPoIB packets should never be forwarded out of the IB subnet\r
-* without recalculating the checksum.\r
-*\r
* recv_chksum_offload\r
-* Flag to indicate whether to offload recv checksums.\r
+* Flags to indicate whether to offload send/recv checksums.\r
+* 0 - No hardware cheksum\r
+* 1 - Try to offload if the device support it\r
+* 2 - Always report success (checksum bypass)\r
*\r
* wsdp_enabled\r
* Flag to indicate whether WSDP is enabled for an adapter adapter.\r
{NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024},\r
{NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8},\r
{NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024},\r
- {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),0, 0, 1},\r
- {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),0, 0, 1},\r
+ {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+ {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
{NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX},\r
{NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX},\r
{NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10},\r
p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
p_offload_chksum =\r
(NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
-\r
+ \r
p_offload_chksum->V4Transmit.IpOptionsSupported =\r
- p_adapter->params.send_chksum_offload;\r
p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
- p_adapter->params.send_chksum_offload;\r
p_offload_chksum->V4Transmit.TcpChecksum =\r
- p_adapter->params.send_chksum_offload;\r
p_offload_chksum->V4Transmit.UdpChecksum =\r
- p_adapter->params.send_chksum_offload;\r
p_offload_chksum->V4Transmit.IpChecksum =\r
- p_adapter->params.send_chksum_offload;\r
+ !!(p_adapter->params.send_chksum_offload);\r
\r
p_offload_chksum->V4Receive.IpOptionsSupported =\r
- p_adapter->params.recv_chksum_offload;\r
p_offload_chksum->V4Receive.TcpOptionsSupported =\r
- p_adapter->params.recv_chksum_offload;\r
p_offload_chksum->V4Receive.TcpChecksum =\r
- p_adapter->params.recv_chksum_offload;\r
p_offload_chksum->V4Receive.UdpChecksum =\r
- p_adapter->params.recv_chksum_offload;\r
p_offload_chksum->V4Receive.IpChecksum =\r
- p_adapter->params.recv_chksum_offload;\r
+ !!(p_adapter->params.recv_chksum_offload);\r
\r
p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
uint64_t vaddr;\r
net32_t rkey;\r
ib_qp_attr_t qp_attr;\r
+ ib_ca_attr_t * p_ca_attr;\r
+ uint32_t attr_size;\r
\r
IPOIB_ENTER( IPOIB_DBG_INIT );\r
\r
p_port->p_adapter->p_ifc->get_err_str( status )) );\r
return status;\r
}\r
-\r
+ \r
/* Allocate the QP. */\r
cl_memclr( &qp_create, sizeof(qp_create) );\r
qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
qp_create.rq_sge = 2; /* To support buffers spanning pages. */\r
qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
- //TODO: Figure out the right number of SGE entries for sends.\r
- qp_create.sq_sge = MAX_SEND_SGE;\r
+ \r
+ //Figure out the right number of SGE entries for sends.\r
+ /* Get the size of the CA attribute structure. */\r
+ status = p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL, &attr_size );\r
+ if( status != IB_INSUFFICIENT_MEMORY )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_ca failed with status %s.\n", p_port->p_adapter->p_ifc->get_err_str(status)) );\r
+ return status;\r
+ }\r
+\r
+ /* Allocate enough space to store the attribute structure. */\r
+ p_ca_attr = cl_malloc( attr_size );\r
+ if( !p_ca_attr )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_malloc failed to allocate p_ca_attr!\n") );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ /* Query the CA attributes. */\r
+ status = p_port->p_adapter->p_ifc->query_ca(p_port->ib_mgr.h_ca, p_ca_attr, &attr_size );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_free( p_ca_attr );\r
+\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_ca failed with status %s.\n", p_port->p_adapter->p_ifc->get_err_str(status)) );\r
+ return status;\r
+ }\r
+#define UD_QP_USED_SGE 3\r
+ qp_create.sq_sge = MAX_SEND_SGE < p_ca_attr->max_sges ? MAX_SEND_SGE : (p_ca_attr->max_sges - UD_QP_USED_SGE);\r
+ if (!p_ca_attr->ipoib_csum) { \r
+ //checksum is not supported by device\r
+ //user must specify BYPASS to explicitly cancel checksum calculation\r
+ if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
+ p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+ if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
+ p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
+ }\r
+ \r
qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
qp_create.sq_signaled = TRUE;\r
status = p_port->p_adapter->p_ifc->create_qp(\r
\r
}\r
/* Successful completion. Get the receive information. */\r
- p_desc->ndis_csum.Value = (ULONG) p_wc->csum_ok;\r
+ p_desc->ndis_csum.Value = (ULONG) p_wc->recv.ud.csum_ok;\r
cl_perf_start( GetRecvEndpts );\r
__recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
("__buf_mgr_get_ndis_pkt failed\n") );\r
return IB_INSUFFICIENT_RESOURCES;\r
}\r
-\r
+ if (p_port->p_adapter->params.recv_chksum_offload != CSUM_BYPASS) {\r
/* Get the checksums directly from packet information. */\r
- NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
- (PVOID) (uintn_t) (p_desc->ndis_csum.Value);\r
+ /* In this case, no one of cheksum's cat get false value */\r
+ /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */\r
+ NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
+ (PVOID) (uintn_t) (p_desc->ndis_csum.Value);\r
+ } else {\r
+ NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum;\r
+ /* Flag the checksums as having been calculated. */\r
+ chksum.Value = 0;\r
+ chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
+ chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
+ chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
+ NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+ (void*)(uintn_t)chksum.Value;\r
+ }\r
ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len );\r
\r
IPOIB_EXIT( IPOIB_DBG_RECV );\r
p_desc->wr.dgrm.ud.hlen = lso_header_size; \r
// Tell NDIS how much we will send.\r
PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength);\r
- p_desc->wr.send_opt |= (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM);\r
+ p_desc->wr.send_opt |= (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED;\r
__send_gen(p_port, p_desc, IndexOfData);\r
- p_desc->wr.wr_type = ( WR_LSO | IB_SEND_OPT_SIGNALED);\r
+ p_desc->wr.wr_type = WR_LSO;\r
} else {\r
\r
/* Setup the first local data segment (used for the IPoIB header). */\r
\r
HKR, Ndi\Params\SendChksum, ParamDesc, 0, "Send Checksum Offload"\r
HKR, Ndi\Params\SendChksum, Type, 0, "enum"\r
-HKR, Ndi\Params\SendChksum, Default, 0, "0"\r
+HKR, Ndi\Params\SendChksum, Default, 0, "1"\r
HKR, Ndi\Params\SendChksum, Optional, 0, "0"\r
HKR, Ndi\Params\SendChksum\enum, "0", 0, "Disabled"\r
-HKR, Ndi\Params\SendChksum\enum, "1", 0, "Enabled"\r
+HKR, Ndi\Params\SendChksum\enum, "1", 0, "Enabled (if supported by HW)"\r
+HKR, Ndi\Params\SendChksum\enum, "2", 0, "Bypass"\r
\r
HKR, Ndi\Params\RecvChksum, ParamDesc, 0, "Recv Checksum Offload"\r
HKR, Ndi\Params\RecvChksum, Type, 0, "enum"\r
-HKR, Ndi\Params\RecvChksum, Default, 0, "0"\r
+HKR, Ndi\Params\RecvChksum, Default, 0, "1"\r
HKR, Ndi\Params\RecvChksum, Optional, 0, "0"\r
HKR, Ndi\Params\RecvChksum\enum, "0", 0, "Disabled"\r
-HKR, Ndi\Params\RecvChksum\enum, "1", 0, "Enabled"\r
+HKR, Ndi\Params\RecvChksum\enum, "1", 0, "Enabled (if supported by HW)"\r
+HKR, Ndi\Params\RecvChksum\enum, "2", 0, "Bypass"\r
+\r
+HKR, Ndi\Params\lso, ParamDesc, 0, "Large Send Offload"\r
+HKR, Ndi\Params\lso, Type, 0, "enum"\r
+HKR, Ndi\Params\lso, Default, 0, "0"\r
+HKR, Ndi\Params\lso, Optional, 0, "0"\r
+HKR, Ndi\Params\lso\enum, "0", 0, "Disabled"\r
+HKR, Ndi\Params\lso\enum, "1", 0, "Enabled"\r
+\r
\r
HKR, Ndi\Params\SaTimeout, ParamDesc, 0, "SA Query Timeout (ms)"\r
HKR, Ndi\Params\SaTimeout, Type, 0, "dword"\r