[ipoib] Add support for large send offload in ipoib. (mlnx 3044)
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 26 Aug 2008 17:37:19 +0000 (17:37 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 26 Aug 2008 17:37:19 +0000 (17:37 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1515 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

inc/kernel/ip_packet.h
ulp/ipoib/kernel/ipoib_adapter.h
ulp/ipoib/kernel/ipoib_driver.c
ulp/ipoib/kernel/ipoib_port.c
ulp/ipoib/kernel/ipoib_port.h
ulp/ipoib/kernel/offload.h [new file with mode: 0644]

index cb887b7..d8f08c8 100644 (file)
@@ -356,6 +356,15 @@ typedef struct _udp_hdr
 *********/\r
 #include <complib/cl_packoff.h>\r
 \r
+#define IP_HEADER_LENGTH(pIpHdr)   \\r
+        ( (ULONG)((pIpHdr->ver_hl & 0x0F) << 2) )\r
+\r
+#define TCP_HEADER_LENGTH(pTcpHdr) \\r
+               ((pTcpHdr->offset & 0xF0) >> 2)\r
+\r
+#define PROTOCOL_TCP         6\r
+\r
+\r
 #define IGMP_V2_MEMBERSHIP_QUERY       0x11\r
 #define IGMP_V2_MEMBERSHIP_REPORT      0x16\r
 #define IGMP_V1_MEMBERSHIP_REPORT      0x12    // for backward compatibility with IGMPv1\r
index c23a342..d59e958 100644 (file)
@@ -73,6 +73,7 @@ typedef struct _ipoib_params
        uint32_t        sa_retry_cnt;\r
        uint32_t        recv_pool_ratio;\r
        uint32_t        payload_mtu;\r
+       boolean_t       lso;\r
        uint32_t        xfer_block_size;\r
        mac_addr_t      conf_mac;\r
        uint32_t        mc_leave_rescan;\r
@@ -120,6 +121,15 @@ typedef struct _ipoib_params
 *              powers of 2, excluding 1.  When zero, grows only when the pool is\r
 *              exhausted.  Other values indicate fractional values\r
 *              (i.e. 2 indicates 1/2, 4 indicates 1/4, etc.)\r
+*\r
+*      payload_mtu\r
+*              The maximum available size of IPoIB transfer unit.\r
+*              It should be lower by size of IPoIB header (==4B)\r
+*              For example, if the HCA support 4K MTU, \r
+*              upper threshold for payload mtu is 4092B and not 4096B\r
+*      lso\r
+*      It indicates if there's a support for hardware large/giant send offload\r
+*              \r
 *********/\r
 \r
 \r
index 3d1056f..0cbf283 100644 (file)
@@ -50,6 +50,8 @@
 #include <iba/ipoib_ifc.h>\r
 #include "ntstrsafe.h"\r
 #include "strsafe.h"\r
+#include <offload.h>\r
+\r
 \r
 \r
 \r
@@ -154,6 +156,7 @@ IPOIB_REG_ENTRY HCARegTable[] = {
        {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
        {NDIS_STRING_CONST("PayloadMtu"),       1, IPOIB_OFFSET(payload_mtu),           IPOIB_SIZE(payload_mtu),        2044,       60,   4092},\r
+       {NDIS_STRING_CONST("lso"),              0, IPOIB_OFFSET(lso),                   IPOIB_SIZE(lso),                0,          0,      1},\r
        {NDIS_STRING_CONST("MCLeaveRescan"),    1, IPOIB_OFFSET(mc_leave_rescan),       IPOIB_SIZE(mc_leave_rescan),    260,        1,    3600}\r
 };  \r
 \r
@@ -848,6 +851,9 @@ ipoib_check_for_hang(
                IPOIB_EXIT( IPOIB_DBG_INIT );\r
                return FALSE;\r
        }\r
+       if (p_adapter->hung) {\r
+               ipoib_resume_oids(p_adapter);\r
+       }\r
 \r
        IPOIB_EXIT( IPOIB_DBG_INIT );\r
        return (p_adapter->hung? TRUE:FALSE);\r
@@ -1405,6 +1411,8 @@ __ipoib_get_tcp_task_offload(
        NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
        NDIS_TASK_OFFLOAD                       *p_offload_task;\r
        NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
+\r
+       NDIS_TASK_TCP_LARGE_SEND        *p_offload_lso;\r
        ULONG                                           buf_len;\r
 \r
        IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
@@ -1413,7 +1421,10 @@ __ipoib_get_tcp_task_offload(
 \r
        buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
                offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
-               sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
+               sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +\r
+               (p_adapter->params.lso  ? \r
+                       sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)\r
+                       : 0);\r
 \r
        *(p_oid_info->p_bytes_needed) = buf_len;\r
 \r
@@ -1472,6 +1483,33 @@ __ipoib_get_tcp_task_offload(
        p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
        p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
 \r
+\r
+       if (p_adapter->params.lso) {\r
+               // set the previous pointer to the correct place\r
+               p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +\r
+                                               p_offload_task->TaskBufferLength;\r
+               // set the LSO packet\r
+               p_offload_task = (PNDIS_TASK_OFFLOAD)\r
+                                               ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);\r
+\r
+               p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+               p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+               p_offload_task->Task = TcpLargeSendNdisTask;\r
+               p_offload_task->OffsetNextTask = 0;\r
+               p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);\r
+\r
+               p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;\r
+\r
+               p_offload_lso->Version = 0;\r
+               //TODO optimal size: 60000, 64000 or 65536\r
+               //TODO LSO_MIN_SEG_COUNT to be 1\r
+               p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; \r
+#define LSO_MIN_SEG_COUNT 2\r
+               p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+               p_offload_lso->TcpOptions = TRUE;\r
+               p_offload_lso->IpOptions = TRUE;\r
+       }\r
+\r
        *(p_oid_info->p_bytes_used) = buf_len;\r
 \r
        return NDIS_STATUS_SUCCESS;\r
@@ -1878,7 +1916,7 @@ ipoib_send_packets(
                for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
                {\r
                        ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
-                       NdisMSendComplete( p_adapter->h_adapter,\r
+                       NdisMSendCompleteX( p_adapter->h_adapter,\r
                                packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY );\r
                }\r
                IPOIB_EXIT( IPOIB_DBG_SEND );\r
index ad772ed..2799cb6 100644 (file)
@@ -42,6 +42,7 @@
 #endif\r
 #include "ipoib_port.tmh"\r
 #endif\r
+#include <offload.h>\r
 \r
 \r
 /* Amount of physical memory to register. */\r
@@ -281,7 +282,8 @@ __send_mgr_destroy(
 static NDIS_STATUS\r
 __send_gen(\r
        IN                              ipoib_port_t* const                     p_port,\r
-       IN                              ipoib_send_desc_t* const        p_desc );\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              INT                                             lso_data_index);\r
 \r
 static NDIS_STATUS\r
 __send_mgr_filter_ip(\r
@@ -334,6 +336,14 @@ __send_cb(
        IN              const   ib_cq_handle_t                          h_cq,\r
        IN                              void                                            *cq_context );\r
 \r
+static NDIS_STATUS GetLsoHeaderSize(\r
+       IN      ipoib_port_t* const pPort,\r
+       IN      PNDIS_BUFFER  CurrBuffer,\r
+       IN      LsoData *pLsoData,\r
+       OUT     uint16_t *pSize,\r
+       OUT     INT  *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr\r
+       );\r
 \r
 /******************************************************************************\r
 *\r
@@ -2679,7 +2689,7 @@ __pending_list_destroy(
                p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) )\r
        {\r
                p_packet = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
-               NdisMSendComplete( p_port->p_adapter->h_adapter, p_packet,\r
+               NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_packet,\r
                        NDIS_STATUS_RESET_IN_PROGRESS );\r
        }\r
        cl_spinlock_release( &p_port->send_lock );\r
@@ -2740,7 +2750,7 @@ __send_mgr_filter(
                 * Just send the payload and hope for the best.\r
                 */\r
                cl_perf_start( SendGen );\r
-               status = __send_gen( p_port, p_desc );\r
+               status = __send_gen( p_port, p_desc, 0 );\r
                cl_perf_stop( &p_port->p_adapter->perf, SendGen );\r
                break;\r
        }\r
@@ -2967,7 +2977,8 @@ __send_gen(
 static NDIS_STATUS\r
 __send_gen(\r
        IN                              ipoib_port_t* const                     p_port,\r
-       IN                              ipoib_send_desc_t* const        p_desc )\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              INT lso_data_index)\r
 {\r
        ib_api_status_t                 status;\r
        SCATTER_GATHER_LIST             *p_sgl;\r
@@ -3007,9 +3018,13 @@ __send_gen(
         * or part of it.\r
         */\r
        i = 0;\r
-       while( offset )\r
+       if (lso_data_index) { //we have an LSO packet\r
+               i = lso_data_index;\r
+               j = 0;\r
+       }\r
+       else while( offset )\r
        {\r
-               if( p_sgl->Elements[i].Length <= sizeof(eth_hdr_t) )\r
+               if( p_sgl->Elements[i].Length <= offset )\r
                {\r
                        offset -= p_sgl->Elements[i++].Length;\r
                }\r
@@ -3117,7 +3132,7 @@ __send_mgr_filter_ip(
                }\r
                /* Not a UDP packet. */\r
                cl_perf_start( SendTcp );\r
-               status = __send_gen( p_port, p_desc );\r
+               status = __send_gen( p_port, p_desc,0 );\r
                cl_perf_stop( &p_port->p_adapter->perf, SendTcp );\r
                IPOIB_EXIT( IPOIB_DBG_SEND );\r
                return status;\r
@@ -3316,7 +3331,7 @@ __send_mgr_filter_udp(
        {\r
                /* Not a DHCP packet. */\r
                cl_perf_start( SendUdp );\r
-               status = __send_gen( p_port, p_desc );\r
+               status = __send_gen( p_port, p_desc,0 );\r
                cl_perf_stop( &p_port->p_adapter->perf, SendUdp );\r
                IPOIB_EXIT( IPOIB_DBG_SEND );\r
                return status;\r
@@ -3758,6 +3773,14 @@ __build_send_desc(
        int32_t                         hdr_idx;\r
        PNDIS_PACKET_EXTENSION                          PktExt;\r
        PNDIS_TCP_IP_CHECKSUM_PACKET_INFO       pChecksumPktInfo; //NDIS 5.1\r
+       ULONG                                                           mss;\r
+       LsoData                                                         TheLsoData;\r
+       INT                                                                     IndexOfData = 0;\r
+       ULONG                                                           PhysBufCount;\r
+       ULONG                                                           PacketLength;\r
+       PNDIS_BUFFER                                            FirstBuffer;\r
+       uint16_t                                                        lso_header_size;\r
+\r
 \r
        PERF_DECLARE( SendMgrFilter );\r
 \r
@@ -3765,15 +3788,12 @@ __build_send_desc(
 \r
        /* Format the send descriptor. */\r
        cl_perf_start( SendMgrFilter );\r
-       status = __send_mgr_filter(\r
-               p_port, p_eth_hdr, p_buf, buf_len, p_desc );\r
-       cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
-       if( status != NDIS_STATUS_SUCCESS )\r
-       {\r
-               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
-                       ("__send_mgr_filter returned 0x%08X.\n", status) );\r
-               return status;\r
-       }\r
+\r
+       PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(p_desc->p_pkt);\r
+       pChecksumPktInfo = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&PktExt->NdisPacketInfo[TcpIpChecksumPacketInfo];\r
+       mss = PtrToUlong(PktExt->NdisPacketInfo[TcpLargeSendPacketInfo]);\r
+       //TODO: optimization: we already got total length from NdisGetFirstBufferFromPacketSafe before\r
+       NdisQueryPacket(p_desc->p_pkt, (PUINT)&PhysBufCount, NULL, &FirstBuffer,(PUINT)&PacketLength);\r
 \r
        /* Format the send descriptor. */\r
        hdr_idx = cl_atomic_inc( &p_port->hdr_idx );\r
@@ -3782,19 +3802,66 @@ __build_send_desc(
        p_port->hdr[hdr_idx].type = p_eth_hdr->type;\r
        p_port->hdr[hdr_idx].resv = 0;\r
 \r
-       /* Setup the first local data segment (used for the IPoIB header). */\r
-       p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
-       p_desc->local_ds[0].length = sizeof(ipoib_hdr_t);\r
-       p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       if (mss)\r
+       {\r
+               memset(&TheLsoData, 0, sizeof TheLsoData );\r
+               status = GetLsoHeaderSize(\r
+                       p_port,\r
+                       FirstBuffer, \r
+                       &TheLsoData, \r
+                       &lso_header_size,\r
+                       &IndexOfData,\r
+                       &p_port->hdr[hdr_idx]\r
+                       \r
+               );\r
+               if ((status != NDIS_STATUS_SUCCESS ) || \r
+                       (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) {\r
+                       ASSERT(FALSE);\r
+\r
+                       IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n"));\r
+\r
+                       //NdisReleaseSpinLock(&Port->SendLock);\r
+                       //MP_ASSERT_NDIS_PACKET_TYPE(Packet);\r
+                       //SendComplete(Port, Packet, NDIS_STATUS_INVALID_PACKET);\r
+                       //NdisAcquireSpinLock(&Port->SendLock);\r
+                       //IPOIB_PRINT_EXIT\r
+                       return status;\r
+               }\r
+               ASSERT(lso_header_size > 0);\r
+               p_desc->wr.dgrm.ud.mss = mss;\r
+               p_desc->wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData;\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
+               __send_gen(p_port, p_desc, IndexOfData);\r
+               p_desc->wr.wr_type = ( WR_LSO | IB_SEND_OPT_SIGNALED);\r
+       } else {\r
+\r
+               /* Setup the first local data segment (used for the IPoIB header). */\r
+               p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
+               p_desc->local_ds[0].length = sizeof(ipoib_hdr_t);\r
+               p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+\r
+               status = __send_mgr_filter(\r
+                       p_port, p_eth_hdr, p_buf, buf_len, p_desc);\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__send_mgr_filter returned 0x%08X.\n", status) );\r
+                       return status;\r
+               }\r
+               p_desc->wr.wr_type = WR_SEND;\r
+               p_desc->wr.send_opt = IB_SEND_OPT_SIGNALED;\r
+       }\r
+\r
+\r
 \r
        /* Setup the work request. */\r
        p_desc->wr.p_next = NULL;\r
        p_desc->wr.wr_id = (uintn_t)p_desc->p_pkt;\r
-       p_desc->wr.wr_type = WR_SEND;\r
-       p_desc->wr.send_opt = IB_SEND_OPT_SIGNALED;\r
-       \r
-       PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(p_desc->p_pkt);\r
-       pChecksumPktInfo = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&PktExt->NdisPacketInfo[TcpIpChecksumPacketInfo];\r
+\r
        if(p_port->p_adapter->params.send_chksum_offload & \r
                (pChecksumPktInfo->Transmit.NdisPacketChecksumV4 || pChecksumPktInfo->Transmit.NdisPacketChecksumV6))\r
        {\r
@@ -3836,7 +3903,7 @@ __process_failed_send(
        IPOIB_ENTER( IPOIB_DBG_SEND );\r
 \r
        /* Complete the packet. */\r
-       NdisMSendComplete( p_port->p_adapter->h_adapter,\r
+       NdisMSendCompleteX( p_port->p_adapter->h_adapter,\r
                p_desc->p_pkt, status );\r
        ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
        /* Deref the endpoint. */\r
@@ -3885,7 +3952,7 @@ ipoib_port_send(
                {\r
                        ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
                        /* Complete the packet. */\r
-                       NdisMSendComplete( p_port->p_adapter->h_adapter,\r
+                       NdisMSendCompleteX( p_port->p_adapter->h_adapter,\r
                                p_packet_array[i], NDIS_STATUS_ADAPTER_NOT_READY );\r
                        \r
                }\r
@@ -4203,7 +4270,9 @@ __send_cb(
                while( p_wc )\r
                {\r
                        cl_perf_start( SendComp );\r
-                       CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND );\r
+                       CL_ASSERT( p_wc->status != IB_WCS_SUCCESS \r
+                                                                       || p_wc->wc_type == IB_WC_SEND\r
+                                                                       || p_wc->wc_type == IB_WC_LSO);\r
                        p_packet = (NDIS_PACKET*)(uintn_t)p_wc->wr_id;\r
                        CL_ASSERT( p_packet );\r
                        CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_packet ) == p_port );\r
@@ -4241,7 +4310,7 @@ __send_cb(
                                IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
                                        ("Flushed send completion.\n") );\r
                                ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
-                               NdisMSendComplete( p_port->p_adapter->h_adapter,\r
+                               NdisMSendCompleteX( p_port->p_adapter->h_adapter,\r
                                        p_packet, NDIS_STATUS_RESET_IN_PROGRESS );\r
                                break;\r
 \r
@@ -4251,7 +4320,7 @@ __send_cb(
                                        p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
                                        (int)p_wc->vendor_specific) );\r
                                ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
-                               NdisMSendComplete( p_port->p_adapter->h_adapter,\r
+                               NdisMSendCompleteX( p_port->p_adapter->h_adapter,\r
                                        p_packet, NDIS_STATUS_FAILURE );\r
                                break;\r
                        }\r
@@ -5945,6 +6014,159 @@ __leave_error_mcast_cb(
        IPOIB_EXIT( IPOIB_DBG_MCAST );\r
 }\r
 \r
+\r
+NDIS_STATUS GetLsoHeaderSize(\r
+       IN      ipoib_port_t* const pPort,\r
+       IN      PNDIS_BUFFER  CurrBuffer,\r
+       IN      LsoData *pLsoData,\r
+       OUT     uint16_t *pSize,\r
+       OUT     INT  *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr\r
+       )\r
+       {\r
+       UINT    CurrLength;\r
+       PUCHAR  pSrc;\r
+       PUCHAR  pCopiedData = pLsoData->coppied_data;\r
+       ip_hdr_t UNALIGNED  *IpHdr;\r
+       tcp_hdr_t UNALIGNED *TcpHdr;\r
+       uint16_t                 TcpHeaderLen;\r
+       uint16_t                 IpHeaderLen;\r
+       uint16_t IpOffset;\r
+       INT                 FullBuffers = 0;\r
+       NDIS_STATUS         status = NDIS_STATUS_INVALID_PACKET;    \r
+       //\r
+       // This Flag indicates the way we gets the headers\r
+       // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer \r
+       // in sequence.\r
+       //\r
+#define IP_OFFSET 14;\r
+       boolean_t                       IsRegularFlow = TRUE;\r
+       const uint16_t ETH_OFFSET = IP_OFFSET; \r
+       *pSize = 0;\r
+       UNUSED_PARAM(pPort);\r
+       IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize;\r
+       *IndexOfData = 0;\r
+       NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );    \r
+       if (pSrc == NULL) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       // We start by looking for the ethernet and the IP\r
+       if (CurrLength < ETH_OFFSET) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       //*pSize = *pSize + ETH_OFFSET;\r
+       if (CurrLength == ETH_OFFSET) {        \r
+               ASSERT(FALSE);\r
+               IsRegularFlow = FALSE;        \r
+               memcpy(pCopiedData, pSrc, ETH_OFFSET);\r
+               pCopiedData += ETH_OFFSET;        \r
+               FullBuffers++;\r
+               // First buffer was only ethernet\r
+               NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
+               NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+           }\r
+       } else {\r
+               // This is ETH + IP together (at least)\r
+               pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t));\r
+               memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t));\r
+               CurrLength -= ETH_OFFSET;\r
+               pSrc = pSrc + ETH_OFFSET;\r
+               *pSize = *pSize + sizeof (ipoib_hdr_t);\r
+       }\r
+       // we should now be having at least the size of ethernet data\r
+       if (CurrLength < sizeof (ip_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       IpHdr = (ip_hdr_t UNALIGNED*)pSrc;\r
+       IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr);\r
+       ASSERT(IpHdr->prot == PROTOCOL_TCP);\r
+       if (CurrLength < IpHeaderLen) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       *pSize = *pSize + IpHeaderLen;\r
+       // We now start to find where the TCP header starts\r
+       if (CurrLength == IpHeaderLen) {\r
+               ASSERT(FALSE);\r
+               // two options : \r
+               // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers\r
+               // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer \r
+               // TCP will start at next buffer\r
+               if(IsRegularFlow){\r
+                       memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen);\r
+                       pCopiedData += (ETH_OFFSET + IpHeaderLen);\r
+               } else {\r
+                       memcpy(pCopiedData, pSrc,IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+           \r
+               FullBuffers++;\r
+               IsRegularFlow = FALSE;\r
+               NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
+               NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+               }\r
+       } else {\r
+               // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer       \r
+               // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer\r
+               if (IsRegularFlow) {            \r
+                       pLsoData->LsoBuffers[0].Len += IpHeaderLen;\r
+               } else {            \r
+                       memcpy(pCopiedData, pSrc, IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+\r
+               CurrLength -= IpHeaderLen;\r
+               pSrc = pSrc + IpHeaderLen;\r
+       }\r
+       if (CurrLength < sizeof (tcp_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       // We have finaly found the TCP header\r
+       TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc;\r
+       TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr);\r
+\r
+       ASSERT(TcpHeaderLen == 20);\r
+       \r
+       if (CurrLength < TcpHeaderLen) {\r
+               //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       *pSize =  *pSize + TcpHeaderLen;\r
+       if(IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].Len += TcpHeaderLen;            \r
+       }\r
+       else{\r
+               memcpy(pCopiedData, pSrc, TcpHeaderLen);                    \r
+               pCopiedData += TcpHeaderLen;                  \r
+       }         \r
+       if (CurrLength == TcpHeaderLen) {        \r
+               FullBuffers++;\r
+               pLsoData->UsedBuffers = FullBuffers;\r
+               *IndexOfData = FullBuffers ;\r
+       } else {\r
+               pLsoData->UsedBuffers = FullBuffers + 1;\r
+               *IndexOfData = FullBuffers - 1;\r
+       }\r
+       pLsoData->FullBuffers = FullBuffers; \r
+       if (!IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data;\r
+               pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen;\r
+               ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER);\r
+       }\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
 static void __port_do_mcast_garbage(ipoib_port_t* const        p_port)\r
 {\r
     const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01};\r
index bc29504..4c8d6a2 100644 (file)
@@ -53,7 +53,7 @@
 \r
 \r
 /* Max send data segment list size. */\r
-#define MAX_SEND_SGE   8\r
+#define MAX_SEND_SGE   30 //TODO optimize this value\r
 \r
 \r
 /* \r
@@ -626,5 +626,21 @@ inline void ipoib_port_deref(
        IN                              ipoib_port_t *                          p_port,\r
        IN                              int                                             type);\r
 \r
+#if DBG\r
+// This function is only used to monitor send failures\r
+static inline VOID NdisMSendCompleteX(\r
+       IN NDIS_HANDLE  MiniportAdapterHandle,\r
+       IN PNDIS_PACKET  Packet,\r
+       IN NDIS_STATUS  Status\r
+       ) {\r
+       if (Status != NDIS_STATUS_SUCCESS) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Sending status other than Success to NDIS\n"));\r
+       }\r
+       NdisMSendComplete(MiniportAdapterHandle,Packet,Status);\r
+}\r
+#else\r
+#define NdisMSendCompleteX NdisMSendComplete\r
+#endif\r
 \r
 #endif /* _IPOIB_PORT_H_ */\r
diff --git a/ulp/ipoib/kernel/offload.h b/ulp/ipoib/kernel/offload.h
new file mode 100644 (file)
index 0000000..de696c6
--- /dev/null
@@ -0,0 +1,47 @@
+/*++\r
\r
+Copyright (c) 2005-2008 Mellanox Technologies. All rights reserved.\r
+\r
+Module Name:\r
+    offload.h\r
+\r
+Abstract:\r
+    Task offloading header file\r
+\r
+Revision History:\r
+\r
+Notes:\r
+\r
+--*/\r
+\r
+//\r
+//  Define the maximum size of large TCP packets the driver can offload.\r
+//  This sample driver uses shared memory to map the large packets, \r
+//  LARGE_SEND_OFFLOAD_SIZE is useless in this case, so we just define \r
+//  it as NIC_MAX_PACKET_SIZE. But shipping drivers should define\r
+//  LARGE_SEND_OFFLOAD_SIZE if they support LSO, and use it as \r
+//  MaximumPhysicalMapping  when they call NdisMInitializeScatterGatherDma \r
+//  if they use ScatterGather method. If the drivers don't support\r
+//  LSO, then MaximumPhysicalMapping is NIC_MAX_PACKET_SIZE.\r
+//\r
+\r
+#define LSO_MAX_HEADER 136\r
+#define LARGE_SEND_OFFLOAD_SIZE 60000 \r
+\r
+// This struct is being used in order to pass data about the GSO buffers if they\r
+// are present\r
+typedef struct LsoBuffer_ {\r
+    PUCHAR pData;\r
+    UINT Len;\r
+} LsoBuffer;\r
+\r
+typedef struct LsoData_ {\r
+    LsoBuffer LsoBuffers[1];\r
+    UINT UsedBuffers;\r
+    UINT FullBuffers;\r
+    UINT LsoHeaderSize;\r
+    UINT IndexOfData;\r
+    UCHAR coppied_data[LSO_MAX_HEADER];\r
+} LsoData;\r
+\r
+\r