win-pvdrivers

changeset 921:dc37dfde7673

NDIS6 appears to be working properly now. good speed in both directions
author James Harper <james.harper@bendigoit.com.au>
date Sat May 14 15:15:18 2011 +1000 (2011-05-14)
parents a61e4e452f43
children 5604d7645acc
files xennet/xennet6.c xennet/xennet6.h xennet/xennet6_common.c xennet/xennet6_oid.c xennet/xennet6_rx.c xennet/xennet6_tx.c
line diff
     1.1 --- a/xennet/xennet6.c	Sat May 14 15:14:52 2011 +1000
     1.2 +++ b/xennet/xennet6.c	Sat May 14 15:15:18 2011 +1000
     1.3 @@ -135,13 +135,15 @@ XenNet_ConnectBackend(struct xennet_info
     1.4    UCHAR type;
     1.5    PCHAR setting, value, value2;
     1.6    UINT i;
     1.7 -  ULONG backend_sg = 0;
     1.8 -  ULONG backend_gso = 0;
     1.9  
    1.10    FUNCTION_ENTER();
    1.11    
    1.12    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
    1.13  
    1.14 +  xi->backend_csum_supported = TRUE; /* just assume this */
    1.15 +  xi->backend_gso_value = 0;
    1.16 +  xi->backend_sg_supported = FALSE;
    1.17 +  
    1.18    ptr = xi->config_page;
    1.19    while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
    1.20    {
    1.21 @@ -189,14 +191,14 @@ XenNet_ConnectBackend(struct xennet_info
    1.22        {
    1.23          if (atoi(value))
    1.24          {
    1.25 -          backend_sg = 1;
    1.26 +          xi->backend_sg_supported = TRUE;
    1.27          }
    1.28        }
    1.29        else if (strcmp(setting, "feature-gso-tcpv4") == 0)
    1.30        {
    1.31          if (atoi(value))
    1.32          {
    1.33 -          backend_gso = 1;
    1.34 +          xi->backend_gso_value = xi->frontend_gso_value;
    1.35          }
    1.36        }
    1.37        break;
    1.38 @@ -222,20 +224,19 @@ XenNet_ConnectBackend(struct xennet_info
    1.39        break;
    1.40      }
    1.41    }
    1.42 -  if (xi->config_sg && !backend_sg)
    1.43 -  {
    1.44 -    KdPrint((__DRIVER_NAME "     SG not supported by backend - disabling\n"));
    1.45 -    xi->config_sg = 0;
    1.46 -  }
    1.47 -  if (xi->config_gso && !backend_gso)
    1.48 -  {
    1.49 -    KdPrint((__DRIVER_NAME "     GSO not supported by backend - disabling\n"));
    1.50 -    xi->config_gso = 0;
    1.51 -  }
    1.52 +  if (!xi->backend_sg_supported)
    1.53 +    xi->backend_gso_value = min(xi->backend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
    1.54 +
    1.55 +  xi->current_sg_supported = xi->frontend_sg_supported && xi->backend_sg_supported;
    1.56 +  xi->current_csum_supported = xi->frontend_csum_supported && xi->backend_csum_supported;
    1.57 +  xi->current_gso_value = min(xi->backend_gso_value, xi->backend_gso_value);
    1.58 +  xi->current_mtu_value = xi->frontend_mtu_value;
    1.59 +  xi->current_gso_rx_split_type = xi->frontend_gso_rx_split_type;
    1.60 +    
    1.61    FUNCTION_EXIT();
    1.62    
    1.63    return NDIS_STATUS_SUCCESS;
    1.64 -}
    1.65 +} /* XenNet_ConnectBackend */
    1.66  
    1.67  static VOID
    1.68  XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context)
    1.69 @@ -344,7 +345,6 @@ XenNet_HandleEvent(PVOID context)
    1.70  {
    1.71    struct xennet_info *xi = context;
    1.72    ULONG suspend_resume_state_pdo;
    1.73 -  LARGE_INTEGER dpc_requeued;
    1.74    
    1.75    //FUNCTION_ENTER();
    1.76    suspend_resume_state_pdo = xi->device_state->suspend_resume_state_pdo;
    1.77 @@ -430,11 +430,11 @@ XenNet_D0Entry(struct xennet_info *xi)
    1.78    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-gso-tcpv4", NULL, NULL);
    1.79    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1", NULL);
    1.80    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1", NULL);
    1.81 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
    1.82 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->frontend_csum_supported);
    1.83    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf, NULL);
    1.84 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
    1.85 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->frontend_sg_supported);
    1.86    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf, NULL);
    1.87 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
    1.88 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->frontend_gso_value);
    1.89    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf, NULL);
    1.90    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
    1.91    __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
    1.92 @@ -471,12 +471,6 @@ XenNet_D0Entry(struct xennet_info *xi)
    1.93      return status;
    1.94    }
    1.95  
    1.96 -  if (!xi->config_sg)
    1.97 -  {
    1.98 -    /* without SG, GSO can be a maximum of PAGE_SIZE */
    1.99 -    xi->config_gso = min(xi->config_gso, PAGE_SIZE);
   1.100 -  }
   1.101 -
   1.102    XenNet_TxInit(xi);
   1.103    XenNet_RxInit(xi);
   1.104  
   1.105 @@ -593,12 +587,14 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.106    xi->current_lookahead = MIN_LOOKAHEAD_LENGTH;
   1.107  
   1.108    xi->event_channel = 0;
   1.109 +#if 0
   1.110    xi->config_csum = 1;
   1.111    xi->config_csum_rx_check = 1;
   1.112    xi->config_sg = 1;
   1.113    xi->config_gso = 61440;
   1.114    xi->config_page = NULL;
   1.115    xi->config_rx_interrupt_moderation = 0;
   1.116 +#endif
   1.117    
   1.118    nrl = init_parameters->AllocatedResources;
   1.119    for (i = 0; i < nrl->Count; i++)
   1.120 @@ -714,12 +710,12 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.121    if (!NT_SUCCESS(status))
   1.122    {
   1.123      KdPrint(("Could not read ScatterGather value (%08x)\n", status));
   1.124 -    xi->config_sg = 1;
   1.125 +    xi->frontend_sg_supported = TRUE;
   1.126    }
   1.127    else
   1.128    {
   1.129      KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
   1.130 -    xi->config_sg = config_param->ParameterData.IntegerData;
   1.131 +    xi->frontend_sg_supported = !!config_param->ParameterData.IntegerData;
   1.132    }
   1.133    
   1.134    NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
   1.135 @@ -727,16 +723,45 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.136    if (!NT_SUCCESS(status))
   1.137    {
   1.138      KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
   1.139 -    xi->config_gso = 0;
   1.140 +    xi->frontend_gso_value = 0;
   1.141    }
   1.142    else
   1.143    {
   1.144      KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
   1.145 -    xi->config_gso = config_param->ParameterData.IntegerData;
   1.146 -    if (xi->config_gso > 61440)
   1.147 +    xi->frontend_gso_value = config_param->ParameterData.IntegerData;
   1.148 +    if (xi->frontend_gso_value > 61440)
   1.149      {
   1.150 -      xi->config_gso = 61440;
   1.151 -      KdPrint(("(clipped to %d)\n", xi->config_gso));
   1.152 +      xi->frontend_gso_value = 61440;
   1.153 +      KdPrint(("(clipped to %d)\n", xi->frontend_gso_value));
   1.154 +    }
   1.155 +    if (!xi->frontend_sg_supported && xi->frontend_gso_value > PAGE_SIZE - MAX_PKT_HEADER_LENGTH)
   1.156 +    {
   1.157 +      /* without SG, GSO can be a maximum of PAGE_SIZE - MAX_PKT_HEADER_LENGTH */
   1.158 +      xi->frontend_gso_value = min(xi->frontend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
   1.159 +      KdPrint(("(clipped to %d with sg disabled)\n", xi->frontend_gso_value));
   1.160 +    }
   1.161 +  }
   1.162 +
   1.163 +  NdisInitUnicodeString(&config_param_name, L"LargeSendOffloadRxSplitMTU");
   1.164 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   1.165 +  if (!NT_SUCCESS(status))
   1.166 +  {
   1.167 +    KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
   1.168 +    xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
   1.169 +  }
   1.170 +  else
   1.171 +  {
   1.172 +    KdPrint(("LargeSendOffloadRxSplitMTU = %d\n", config_param->ParameterData.IntegerData));
   1.173 +    switch (config_param->ParameterData.IntegerData)
   1.174 +    {
   1.175 +    case RX_LSO_SPLIT_MSS:
   1.176 +    case RX_LSO_SPLIT_HALF:
   1.177 +    case RX_LSO_SPLIT_NONE:
   1.178 +      xi->frontend_gso_rx_split_type = config_param->ParameterData.IntegerData;
   1.179 +      break;
   1.180 +    default:
   1.181 +      xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
   1.182 +      break;
   1.183      }
   1.184    }
   1.185  
   1.186 @@ -745,64 +770,25 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.187    if (!NT_SUCCESS(status))
   1.188    {
   1.189      KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
   1.190 -    xi->config_csum = 1;
   1.191 +    xi->backend_csum_supported = TRUE;
   1.192    }
   1.193    else
   1.194    {
   1.195      KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
   1.196 -    xi->config_csum = !!config_param->ParameterData.IntegerData;
   1.197 +    xi->backend_csum_supported = !!config_param->ParameterData.IntegerData;
   1.198    }
   1.199  
   1.200 -  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadRxCheck");
   1.201 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   1.202 -  if (!NT_SUCCESS(status))
   1.203 -  {
   1.204 -    KdPrint(("Could not read ChecksumOffloadRxCheck value (%08x)\n", status));
   1.205 -    xi->config_csum_rx_check = 1;
   1.206 -  }
   1.207 -  else
   1.208 -  {
   1.209 -    KdPrint(("ChecksumOffloadRxCheck = %d\n", config_param->ParameterData.IntegerData));
   1.210 -    xi->config_csum_rx_check = !!config_param->ParameterData.IntegerData;
   1.211 -  }
   1.212 -
   1.213 -  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadDontFix");
   1.214 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   1.215 -  if (!NT_SUCCESS(status))
   1.216 -  {
   1.217 -    KdPrint(("Could not read ChecksumOffloadDontFix value (%08x)\n", status));
   1.218 -    xi->config_csum_rx_dont_fix = 0;
   1.219 -  }
   1.220 -  else
   1.221 -  {
   1.222 -    KdPrint(("ChecksumOffloadDontFix = %d\n", config_param->ParameterData.IntegerData));
   1.223 -    xi->config_csum_rx_dont_fix = !!config_param->ParameterData.IntegerData;
   1.224 -  }
   1.225 -  
   1.226    NdisInitUnicodeString(&config_param_name, L"MTU");
   1.227    NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   1.228    if (!NT_SUCCESS(status))
   1.229    {
   1.230      KdPrint(("Could not read MTU value (%08x)\n", status));
   1.231 -    xi->config_mtu = 1500;
   1.232 +    xi->frontend_mtu_value = 1500;
   1.233    }
   1.234    else
   1.235    {
   1.236      KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
   1.237 -    xi->config_mtu = config_param->ParameterData.IntegerData;
   1.238 -  }
   1.239 -
   1.240 -  NdisInitUnicodeString(&config_param_name, L"RxInterruptModeration");
   1.241 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   1.242 -  if (!NT_SUCCESS(status))
   1.243 -  {
   1.244 -    KdPrint(("Could not read RxInterruptModeration value (%08x)\n", status));
   1.245 -    xi->config_rx_interrupt_moderation = 1500;
   1.246 -  }
   1.247 -  else
   1.248 -  {
   1.249 -    KdPrint(("RxInterruptModeration = %d\n", config_param->ParameterData.IntegerData));
   1.250 -    xi->config_rx_interrupt_moderation = config_param->ParameterData.IntegerData;
   1.251 +    xi->frontend_mtu_value = config_param->ParameterData.IntegerData;
   1.252    }
   1.253    
   1.254    NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
   1.255 @@ -819,8 +805,6 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.256        xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]));
   1.257    }
   1.258  
   1.259 -  xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
   1.260 -  
   1.261    NdisCloseConfiguration(config_handle);
   1.262  
   1.263    status = XenNet_D0Entry(xi);
   1.264 @@ -829,10 +813,9 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.265      KdPrint(("Failed to go to D0 (%08x)\n", status));
   1.266      goto err;
   1.267    }
   1.268 -  
   1.269 -  xi->current_csum_ipv4 = xi->config_csum;
   1.270 -  xi->current_lso_ipv4 = xi->config_gso;
   1.271  
   1.272 +  xi->config_max_pkt_size = max(xi->current_mtu_value + XN_HDR_SIZE, xi->current_gso_value + XN_HDR_SIZE);
   1.273 +    
   1.274    registration_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
   1.275    registration_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
   1.276    registration_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
   1.277 @@ -841,7 +824,7 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.278    registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE;
   1.279    registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK;
   1.280    registration_attributes.CheckForHangTimeInSeconds = 0; /* use default */
   1.281 -  registration_attributes.InterfaceType = NdisInterfacePNPBus; /* or PnP??? */
   1.282 +  registration_attributes.InterfaceType = NdisInterfacePNPBus;
   1.283    status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registration_attributes);
   1.284    if (!NT_SUCCESS(status))
   1.285    {
   1.286 @@ -855,7 +838,7 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.287    general_attributes.Flags = 0;
   1.288    general_attributes.MediaType = NdisMedium802_3;
   1.289    general_attributes.PhysicalMediumType = NdisPhysicalMediumOther;
   1.290 -  general_attributes.MtuSize = xi->config_mtu;
   1.291 +  general_attributes.MtuSize = xi->current_mtu_value;
   1.292    general_attributes.MaxXmitLinkSpeed = MAX_LINK_SPEED;
   1.293    general_attributes.XmitLinkSpeed = MAX_LINK_SPEED;
   1.294    general_attributes.MaxRcvLinkSpeed = MAX_LINK_SPEED;
   1.295 @@ -923,64 +906,69 @@ XenNet_Initialize(NDIS_HANDLE adapter_ha
   1.296    df_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
   1.297    df_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
   1.298    df_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
   1.299 -  df_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.300 -  df_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.301 -  df_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.302 -  df_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SET_ON;
   1.303 -  df_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SET_ON;
   1.304 -  df_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SET_ON;
   1.305 -  df_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.306 -  df_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.307 -  df_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.308 -  df_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SET_ON;
   1.309 -  df_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SET_ON;
   1.310 -  df_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SET_ON;
   1.311 -  /* offload.Checksum.IPv6Transmit is not supported */
   1.312 -  /* offload.Checksum.IPv6Receive is not supported */
   1.313 -  df_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.314 -  df_offload.LsoV1.IPv4.MaxOffLoadSize = xi->config_gso;
   1.315 -  df_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.316 -  df_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.317 -  df_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.318 -  df_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.319 -  df_offload.LsoV2.IPv4.MaxOffLoadSize = xi->config_gso;
   1.320 -  df_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.321 -  /* df_offload.LsoV2.IPv6 is not supported */
   1.322 -  /* df_offload.IPsecV1 is not supported */
   1.323 -  df_offload.Flags = 0;
   1.324 -  /* df_offload.IPsecV2 is not supported */
   1.325 -
   1.326    /* this is the supported offload state */
   1.327    RtlZeroMemory(&hw_offload, sizeof(hw_offload));
   1.328    hw_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
   1.329    hw_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
   1.330    hw_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
   1.331 -  hw_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.332 -  hw_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.333 -  hw_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.334 -  hw_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.335 -  hw_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.336 -  hw_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.337 -  hw_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.338 -  hw_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.339 -  hw_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.340 -  hw_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.341 -  hw_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.342 -  hw_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.343 -  /* hw_offload.Checksum.IPv6Transmit is not supported */
   1.344 -  /* hw_offload.Checksum.IPv6Receive is not supported */
   1.345 -  hw_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.346 -  hw_offload.LsoV1.IPv4.MaxOffLoadSize = xi->config_gso;
   1.347 -  hw_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.348 -  hw_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.349 -  hw_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.350 -  hw_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.351 -  hw_offload.LsoV2.IPv4.MaxOffLoadSize = xi->config_gso;
   1.352 -  hw_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.353 -  /* hw_offload.LsoV2.IPv6 is not supported */
   1.354 +  if (xi->current_csum_supported)
   1.355 +  {
   1.356 +    df_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.357 +    df_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.358 +    df_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.359 +    df_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SET_ON;
   1.360 +    df_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SET_ON;
   1.361 +    df_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SET_ON;
   1.362 +    df_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.363 +    df_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.364 +    df_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
   1.365 +    df_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SET_ON;
   1.366 +    df_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SET_ON;
   1.367 +    df_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SET_ON;
   1.368 +    /* offload.Checksum.IPv6Transmit is not supported */
   1.369 +    /* offload.Checksum.IPv6Receive is not supported */
   1.370 +    hw_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.371 +    hw_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.372 +    hw_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.373 +    hw_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.374 +    hw_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.375 +    hw_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.376 +    hw_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.377 +    hw_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.378 +    hw_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
   1.379 +    hw_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.380 +    hw_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.381 +    hw_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
   1.382 +    /* hw_offload.Checksum.IPv6Transmit is not supported */
   1.383 +    /* hw_offload.Checksum.IPv6Receive is not supported */
   1.384 +  }
   1.385 +  if (xi->current_gso_value)
   1.386 +  {
   1.387 +    hw_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.388 +    hw_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
   1.389 +    hw_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.390 +    hw_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.391 +    hw_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.392 +    hw_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.393 +    hw_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
   1.394 +    hw_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.395 +    /* hw_offload.LsoV2.IPv6 is not supported */
   1.396 +    df_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.397 +    df_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
   1.398 +    df_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.399 +    df_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.400 +    df_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
   1.401 +    df_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
   1.402 +    df_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
   1.403 +    df_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   1.404 +    /* df_offload.LsoV2.IPv6 is not supported */
   1.405 +  }
   1.406    /* hw_offload.IPsecV1 is not supported */
   1.407 +  /* hw_offload.IPsecV2 is not supported */
   1.408 +  /* df_offload.IPsecV1 is not supported */
   1.409 +  /* df_offload.IPsecV2 is not supported */
   1.410    hw_offload.Flags = 0;
   1.411 -  /* hw_offload.IPsecV2 is not supported */
   1.412 +  df_offload.Flags = 0;
   1.413    
   1.414    RtlZeroMemory(&df_conn_offload, sizeof(df_conn_offload));
   1.415    df_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
   1.416 @@ -1015,7 +1003,6 @@ err:
   1.417    return status;
   1.418  }
   1.419  
   1.420 -#if 0
   1.421  NDIS_STATUS
   1.422  XenNet_D0Exit(struct xennet_info *xi)
   1.423  {
   1.424 @@ -1037,7 +1024,6 @@ XenNet_D0Exit(struct xennet_info *xi)
   1.425    
   1.426    return STATUS_SUCCESS;
   1.427  }
   1.428 -#endif
   1.429  
   1.430  static VOID
   1.431  XenNet_DevicePnPEventNotify(NDIS_HANDLE adapter_context, PNET_DEVICE_PNP_EVENT pnp_event)
   1.432 @@ -1090,7 +1076,7 @@ XenNet_Halt(NDIS_HANDLE adapter_context,
   1.433  
   1.434    FUNCTION_ENTER();
   1.435    
   1.436 -  //XenNet_D0Exit(xi);
   1.437 +  XenNet_D0Exit(xi);
   1.438  
   1.439    NdisFreeMemory(xi, 0, 0);
   1.440  
     2.1 --- a/xennet/xennet6.h	Sat May 14 15:14:52 2011 +1000
     2.2 +++ b/xennet/xennet6.h	Sat May 14 15:15:18 2011 +1000
     2.3 @@ -48,11 +48,11 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  #define NB_HEADER_BUF(_nb) (*(shared_buffer_t **)&(_nb)->NB_HEADER_BUF_FIELD)
     2.5  
     2.6  #define NBL_REF_FIELD MiniportReserved[0] // TX
     2.7 -#define NBL_PACKET_COUNT_FIELD MiniportReserved[0] // RX
     2.8 -#define NBL_LAST_NB_FIELD MiniportReserved[1] // RX
     2.9 +//#define NBL_PACKET_COUNT_FIELD MiniportReserved[0] // RX
    2.10 +//#define NBL_LAST_NB_FIELD MiniportReserved[1] // RX
    2.11  #define NBL_REF(_nbl) (*(ULONG_PTR *)&(_nbl)->NBL_REF_FIELD)
    2.12 -#define NBL_PACKET_COUNT(_nbl) (*(ULONG_PTR *)&(_nbl)->NBL_PACKET_COUNT_FIELD)
    2.13 -#define NBL_LAST_NB(_nbl) (*(PNET_BUFFER *)&(_nbl)->NBL_LAST_NB_FIELD)
    2.14 +//#define NBL_PACKET_COUNT(_nbl) (*(ULONG_PTR *)&(_nbl)->NBL_PACKET_COUNT_FIELD)
    2.15 +//#define NBL_LAST_NB(_nbl) (*(PNET_BUFFER *)&(_nbl)->NBL_LAST_NB_FIELD)
    2.16  
    2.17  #include <xen_windows.h>
    2.18  #include <memory.h>
    2.19 @@ -213,6 +213,7 @@ typedef struct
    2.20  } tx_shadow_t;
    2.21  
    2.22  typedef struct {
    2.23 +  ULONG parse_result;
    2.24    PMDL first_mdl;
    2.25    MDL first_mdl_storage;
    2.26    PPFN_NUMBER first_mdl_pfns[17]; /* maximum possible packet size */
    2.27 @@ -248,6 +249,13 @@ typedef struct {
    2.28  #define PAGE_LIST_SIZE (max(NET_RX_RING_SIZE, NET_TX_RING_SIZE) * 4)
    2.29  #define MULTICAST_LIST_MAX_SIZE 32
    2.30  
    2.31 +/* split incoming large packets into MSS sized chunks */
    2.32 +#define RX_LSO_SPLIT_MSS 0
    2.33 +/* split incoming large packets in half, to not invoke the delayed ack timer */
    2.34 +#define RX_LSO_SPLIT_HALF 1
    2.35 +/* don't split incoming large packets. not really useful */
    2.36 +#define RX_LSO_SPLIT_NONE 2
    2.37 +
    2.38  struct xennet_info
    2.39  {
    2.40    BOOLEAN inactive;
    2.41 @@ -310,9 +318,6 @@ struct xennet_info
    2.42    ULONG rx_id_free;
    2.43    packet_info_t *rxpi;
    2.44    KEVENT packet_returned_event;
    2.45 -  //NDIS_MINIPORT_TIMER rx_timer;
    2.46 -  KTIMER rx_timer;
    2.47 -  KDPC rx_timer_dpc;
    2.48    NDIS_HANDLE rx_nbl_pool;
    2.49    NDIS_HANDLE rx_nb_pool;
    2.50    volatile LONG rx_pb_free;
    2.51 @@ -333,16 +338,22 @@ struct xennet_info
    2.52    LONG rx_outstanding;
    2.53  
    2.54    /* config vars from registry */
    2.55 -  ULONG config_sg;
    2.56 -  ULONG config_csum;
    2.57 -  ULONG config_csum_rx_check;
    2.58 -  ULONG config_csum_rx_dont_fix;
    2.59 -  ULONG config_gso;
    2.60 -  ULONG config_mtu;
    2.61 -  ULONG config_rx_interrupt_moderation;
    2.62 +  /* the frontend_* indicate our willingness to support */
    2.63 +  BOOLEAN frontend_sg_supported;
    2.64 +  BOOLEAN frontend_csum_supported;
    2.65 +  ULONG frontend_gso_value;
    2.66 +  ULONG frontend_mtu_value;
    2.67 +  ULONG frontend_gso_rx_split_type; /* RX_LSO_SPLIT_* */
    2.68  
    2.69 -  BOOLEAN current_csum_ipv4;
    2.70 -  ULONG current_lso_ipv4;
    2.71 +  BOOLEAN backend_sg_supported;
    2.72 +  BOOLEAN backend_csum_supported;
    2.73 +  ULONG backend_gso_value;
    2.74 +  
    2.75 +  BOOLEAN current_sg_supported;
    2.76 +  BOOLEAN current_csum_supported;
    2.77 +  ULONG current_gso_value;
    2.78 +  ULONG current_mtu_value;
    2.79 +  ULONG current_gso_rx_split_type;
    2.80  
    2.81    /* config stuff calculated from the above */
    2.82    ULONG config_max_pkt_size;
    2.83 @@ -410,7 +421,7 @@ XenNet_SetPower;
    2.84  
    2.85  BOOLEAN
    2.86  XenNet_BuildHeader(packet_info_t *pi, PVOID header, ULONG new_header_size);
    2.87 -ULONG
    2.88 +VOID
    2.89  XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR buffer, ULONG min_header_size);
    2.90  BOOLEAN
    2.91  XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi);
     3.1 --- a/xennet/xennet6_common.c	Sat May 14 15:14:52 2011 +1000
     3.2 +++ b/xennet/xennet6_common.c	Sat May 14 15:15:18 2011 +1000
     3.3 @@ -112,7 +112,7 @@ XenNet_BuildHeader(packet_info_t *pi, PU
     3.4    return TRUE;
     3.5  }
     3.6  
     3.7 -ULONG
     3.8 +VOID
     3.9  XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR alt_buffer, ULONG min_header_size)
    3.10  {
    3.11    //FUNCTION_ENTER();
    3.12 @@ -134,7 +134,8 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.13    if (!XenNet_BuildHeader(pi, NULL, (ULONG)XN_HDR_SIZE))
    3.14    {
    3.15      //KdPrint((__DRIVER_NAME "     packet too small (Ethernet Header)\n"));
    3.16 -    return PARSE_TOO_SMALL;
    3.17 +    pi->parse_result = PARSE_TOO_SMALL;
    3.18 +    return;
    3.19    }
    3.20  
    3.21    switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
    3.22 @@ -146,14 +147,16 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.23        if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + 20)))
    3.24        {
    3.25          KdPrint((__DRIVER_NAME "     packet too small (IP Header)\n"));
    3.26 -        return PARSE_TOO_SMALL;
    3.27 +        pi->parse_result = PARSE_TOO_SMALL;
    3.28 +        return;
    3.29        }
    3.30      }
    3.31      pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
    3.32      if (pi->ip_version != 4)
    3.33      {
    3.34        //KdPrint((__DRIVER_NAME "     ip_version = %d\n", pi->ip_version));
    3.35 -      return PARSE_UNKNOWN_TYPE;
    3.36 +      pi->parse_result = PARSE_UNKNOWN_TYPE;
    3.37 +      return;
    3.38      }
    3.39      pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
    3.40      if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
    3.41 @@ -161,17 +164,20 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.42        if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)))
    3.43        {
    3.44          //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header)\n"));
    3.45 -        return PARSE_TOO_SMALL;
    3.46 +        pi->parse_result = PARSE_TOO_SMALL;
    3.47 +        return;
    3.48        }
    3.49      }
    3.50      break;
    3.51    case 0x86DD:  /* IPv6 */
    3.52      //KdPrint((__DRIVER_NAME "     IPv6\n"));
    3.53      //KdPrint((__DRIVER_NAME "     (not currently used)\n"));
    3.54 -    return PARSE_UNKNOWN_TYPE;
    3.55 +    pi->parse_result = PARSE_UNKNOWN_TYPE;
    3.56 +    return;
    3.57    default:
    3.58      //KdPrint((__DRIVER_NAME "     Not IP (%04x)\n", GET_NET_PUSHORT(&pi->header[12])));
    3.59 -    return PARSE_UNKNOWN_TYPE;
    3.60 +    pi->parse_result = PARSE_UNKNOWN_TYPE;
    3.61 +    return;
    3.62    }
    3.63    pi->ip_proto = pi->header[XN_HDR_SIZE + 9];
    3.64    switch (pi->ip_proto)
    3.65 @@ -181,7 +187,8 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.66      break;
    3.67    default:
    3.68      //KdPrint((__DRIVER_NAME "     Not TCP/UDP (%d)\n", pi->ip_proto));
    3.69 -    return PARSE_UNKNOWN_TYPE;
    3.70 +    pi->parse_result = PARSE_UNKNOWN_TYPE;
    3.71 +    return;
    3.72    }
    3.73    pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
    3.74    pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
    3.75 @@ -191,14 +198,16 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.76      if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)))
    3.77      {
    3.78        //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header + TCP Options)\n"));
    3.79 -      return PARSE_TOO_SMALL;
    3.80 +      pi->parse_result = PARSE_TOO_SMALL;
    3.81 +      return;
    3.82      }
    3.83    }
    3.84  
    3.85    if ((ULONG)XN_HDR_SIZE + pi->ip4_length > pi->total_length)
    3.86    {
    3.87      //KdPrint((__DRIVER_NAME "     XN_HDR_SIZE + ip4_length (%d) > total_length (%d)\n", XN_HDR_SIZE + pi->ip4_length, pi->total_length));
    3.88 -    return PARSE_UNKNOWN_TYPE;
    3.89 +    pi->parse_result = PARSE_UNKNOWN_TYPE;
    3.90 +    return;
    3.91    }
    3.92  
    3.93    pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
    3.94 @@ -212,7 +221,7 @@ XenNet_ParsePacketHeader(packet_info_t *
    3.95    //KdPrint((__DRIVER_NAME "     tcp_length = %d\n", pi->tcp_length));
    3.96    //FUNCTION_EXIT();
    3.97    
    3.98 -  return PARSE_OK;
    3.99 +  pi->parse_result = PARSE_OK;
   3.100  }
   3.101  
   3.102  VOID
     4.1 --- a/xennet/xennet6_oid.c	Sat May 14 15:14:52 2011 +1000
     4.2 +++ b/xennet/xennet6_oid.c	Sat May 14 15:15:18 2011 +1000
     4.3 @@ -86,10 +86,10 @@ XenNet_QueryInformation(
     4.4        temp_data = NdisMedium802_3;
     4.5        break;
     4.6      case OID_GEN_MAXIMUM_LOOKAHEAD:
     4.7 -      temp_data = MAX_LOOKAHEAD_LENGTH; //xi->config_mtu;
     4.8 +      temp_data = MAX_LOOKAHEAD_LENGTH; //xi->config_mtu_value;
     4.9        break;
    4.10      case OID_GEN_MAXIMUM_FRAME_SIZE:
    4.11 -      temp_data = xi->config_mtu;
    4.12 +      temp_data = xi->config_mtu_value;
    4.13        break;
    4.14      case OID_GEN_LINK_SPEED:
    4.15        temp_data = 10000000; /* 1Gb */
    4.16 @@ -302,7 +302,7 @@ XenNet_QueryInformation(
    4.17  
    4.18  #endif
    4.19      case OID_GEN_MAXIMUM_TOTAL_SIZE:
    4.20 -      temp_data = xi->config_mtu + XN_HDR_SIZE;
    4.21 +      temp_data = xi->current_mtu_value + XN_HDR_SIZE;
    4.22        break;
    4.23      case OID_GEN_INTERRUPT_MODERATION:
    4.24        SET_LEN_AND_BREAK_IF_SHORT(sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS));
    4.25 @@ -926,13 +926,13 @@ XenNet_SetInformation(
    4.26        {
    4.27        case NDIS_OFFLOAD_SET_ON:
    4.28          FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n");
    4.29 -        xi->current_csum_ipv4 = TRUE;
    4.30 -        xi->current_lso_ipv4 = TRUE;
    4.31 +        xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported;
    4.32 +        xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported);
    4.33          break;
    4.34        case NDIS_OFFLOAD_SET_OFF:
    4.35          FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n");
    4.36 -        xi->current_csum_ipv4 = FALSE;
    4.37 -        xi->current_lso_ipv4 = FALSE;
    4.38 +        xi->current_csum_supported = FALSE;
    4.39 +        xi->current_gso_value = 0;
    4.40          break;
    4.41        case NDIS_OFFLOAD_SET_NO_CHANGE:
    4.42          FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
     5.1 --- a/xennet/xennet6_rx.c	Sat May 14 15:14:52 2011 +1000
     5.2 +++ b/xennet/xennet6_rx.c	Sat May 14 15:15:18 2011 +1000
     5.3 @@ -184,23 +184,40 @@ XenNet_FillRing(struct xennet_info *xi)
     5.4    return NDIS_STATUS_SUCCESS;
     5.5  }
     5.6  
     5.7 +typedef struct {
     5.8 +  PNET_BUFFER_LIST first_nbl;
     5.9 +  PNET_BUFFER_LIST last_nbl;
    5.10 +  ULONG packet_count;
    5.11 +} rx_context_t;
    5.12 +
    5.13  static BOOLEAN
    5.14 -XenNet_MakePacket(struct xennet_info *xi, PNET_BUFFER_LIST nbl, packet_info_t *pi)
    5.15 +XenNet_MakePacket(struct xennet_info *xi, rx_context_t *rc, packet_info_t *pi)
    5.16  {
    5.17 +  PNET_BUFFER_LIST nbl;
    5.18    PNET_BUFFER nb;
    5.19    PMDL mdl_head, mdl_tail, curr_mdl;
    5.20    PUCHAR header_va;
    5.21    ULONG out_remaining;
    5.22    ULONG header_extra;
    5.23    shared_buffer_t *header_buf;
    5.24 +  NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csum_info;
    5.25  
    5.26    //FUNCTION_ENTER();
    5.27    
    5.28 +  nbl = NdisAllocateNetBufferList(xi->rx_nbl_pool, 0, 0);
    5.29 +  if (!nbl)
    5.30 +  {
    5.31 +    /* buffers will be freed in MakePackets */
    5.32 +    KdPrint((__DRIVER_NAME "     No free nbl's\n"));
    5.33 +    //FUNCTION_EXIT();
    5.34 +    return FALSE;
    5.35 +  }
    5.36 +
    5.37    nb = NdisAllocateNetBuffer(xi->rx_nb_pool, NULL, 0, 0);
    5.38    if (!nb)
    5.39    {
    5.40 -    /* buffers will be freed in MakePackets */
    5.41 -    KdPrint((__DRIVER_NAME "     No free packets\n"));
    5.42 +    KdPrint((__DRIVER_NAME "     No free nb's\n"));
    5.43 +    NdisFreeNetBufferList(nbl);
    5.44      //FUNCTION_EXIT();
    5.45      return FALSE;
    5.46    }
    5.47 @@ -209,6 +226,7 @@ XenNet_MakePacket(struct xennet_info *xi
    5.48    if (!header_buf)
    5.49    {
    5.50      KdPrint((__DRIVER_NAME "     No free header buffers\n"));
    5.51 +    NdisFreeNetBufferList(nbl);
    5.52      NdisFreeNetBuffer(nb);
    5.53      //FUNCTION_EXIT();
    5.54      return FALSE;
    5.55 @@ -310,17 +328,48 @@ XenNet_MakePacket(struct xennet_info *xi
    5.56      pi->header_length -= header_extra;
    5.57    //ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
    5.58    
    5.59 -  NBL_PACKET_COUNT(nbl)++;
    5.60 -  if (!NET_BUFFER_LIST_FIRST_NB(nbl))
    5.61 +  rc->packet_count++;
    5.62 +  NET_BUFFER_LIST_FIRST_NB(nbl) = nb;
    5.63 +  //NET_BUFFER_NEXT_NB(nb) = NULL; /*is this already done for me? */
    5.64 +
    5.65 +  if (pi->parse_result == PARSE_OK)
    5.66    {
    5.67 -    NET_BUFFER_LIST_FIRST_NB(nbl) = nb;
    5.68 +    BOOLEAN checksum_offload = FALSE;
    5.69 +    csum_info.Value = 0;
    5.70 +    if (pi->csum_blank || pi->data_validated || pi->mss)
    5.71 +    {
    5.72 +      if (pi->ip_proto == 6) // && xi->setting_csum.V4Receive.TcpChecksum)
    5.73 +      {
    5.74 +//          if (!pi->tcp_has_options || xi->setting_csum.V4Receive.TcpOptionsSupported)
    5.75 +//          {
    5.76 +          csum_info.Receive.IpChecksumSucceeded = TRUE;
    5.77 +          csum_info.Receive.TcpChecksumSucceeded = TRUE;
    5.78 +          checksum_offload = TRUE;
    5.79 +//          }
    5.80 +      }
    5.81 +      else if (pi->ip_proto == 17) // &&xi->setting_csum.V4Receive.UdpChecksum)
    5.82 +      {
    5.83 +        csum_info.Receive.IpChecksumSucceeded = TRUE;
    5.84 +        csum_info.Receive.UdpChecksumSucceeded = TRUE;
    5.85 +        checksum_offload = TRUE;
    5.86 +      }
    5.87 +    }
    5.88 +    NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo) = csum_info.Value;
    5.89 +  }
    5.90 +  
    5.91 +  //packet_count += NBL_PACKET_COUNT(nbl);
    5.92 +  if (!rc->first_nbl)
    5.93 +  {
    5.94 +    rc->first_nbl = nbl;
    5.95    }
    5.96    else
    5.97    {
    5.98 -    NET_BUFFER_NEXT_NB(NBL_LAST_NB(nbl)) = nb;
    5.99 +    NET_BUFFER_LIST_NEXT_NBL(rc->last_nbl) = nbl;
   5.100    }
   5.101 -  NBL_LAST_NB(nbl) = nb;
   5.102 -  NET_BUFFER_NEXT_NB(nb) = NULL; /*is this already done for me? */
   5.103 +  rc->last_nbl = nbl;
   5.104 +  NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
   5.105 +  InterlockedIncrement(&xi->rx_outstanding);
   5.106 +
   5.107    //FUNCTION_EXIT();
   5.108    return TRUE;
   5.109  }
   5.110 @@ -461,101 +510,52 @@ XenNet_SumPacketData(
   5.111  }
   5.112  #endif
   5.113  
   5.114 -static PNET_BUFFER_LIST
   5.115 -XenNet_MakePackets(struct xennet_info *xi, packet_info_t *pi)
   5.116 +static VOID
   5.117 +XenNet_MakePackets(struct xennet_info *xi, rx_context_t *rc, packet_info_t *pi)
   5.118  {
   5.119 -  PNET_BUFFER_LIST nbl = NULL;
   5.120    UCHAR psh;
   5.121 -  NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csum_info;
   5.122 -  ULONG parse_result;  
   5.123    //PNDIS_BUFFER buffer;
   5.124    shared_buffer_t *page_buf;
   5.125  
   5.126    //FUNCTION_ENTER();
   5.127  
   5.128 -  parse_result = XenNet_ParsePacketHeader(pi, NULL, 0);
   5.129 -  pi->split_required = FALSE;
   5.130 +  XenNet_ParsePacketHeader(pi, NULL, 0);
   5.131 +  //pi->split_required = FALSE;
   5.132  
   5.133    if (!XenNet_FilterAcceptPacket(xi, pi))
   5.134    {
   5.135      goto done;
   5.136    }
   5.137  
   5.138 -  nbl = NdisAllocateNetBufferList(xi->rx_nbl_pool, 0, 0);
   5.139 -  NBL_PACKET_COUNT(nbl) = 0;
   5.140 +  if (pi->split_required)
   5.141 +  {
   5.142 +    switch (xi->current_gso_rx_split_type)
   5.143 +    {
   5.144 +    case RX_LSO_SPLIT_HALF:
   5.145 +      pi->mss = (pi->tcp_length + 1) / 2;
   5.146 +      break;
   5.147 +    case RX_LSO_SPLIT_NONE:
   5.148 +      pi->mss = 65535;
   5.149 +      break;
   5.150 +    }
   5.151 +  }
   5.152  
   5.153    switch (pi->ip_proto)
   5.154    {
   5.155    case 6:  // TCP
   5.156      if (pi->split_required)
   5.157        break;
   5.158 -    // fallthrough
   5.159 +    /* fall through */
   5.160    case 17:  // UDP
   5.161 -    if (!XenNet_MakePacket(xi, nbl, pi))
   5.162 +    if (!XenNet_MakePacket(xi, rc, pi))
   5.163      {
   5.164        KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   5.165        xi->stat_rx_no_buffer++;
   5.166        goto done;
   5.167      }
   5.168 -    if (parse_result == PARSE_OK)
   5.169 -    {
   5.170 -      BOOLEAN checksum_offload = FALSE;
   5.171 -      csum_info.Value = 0;
   5.172 -      if (pi->csum_blank || pi->data_validated)
   5.173 -      {
   5.174 -        if (pi->ip_proto == 6) // && xi->setting_csum.V4Receive.TcpChecksum)
   5.175 -        {
   5.176 -//          if (!pi->tcp_has_options || xi->setting_csum.V4Receive.TcpOptionsSupported)
   5.177 -//          {
   5.178 -            csum_info.Receive.IpChecksumSucceeded = TRUE;
   5.179 -            csum_info.Receive.TcpChecksumSucceeded = TRUE;
   5.180 -            checksum_offload = TRUE;
   5.181 -//          }
   5.182 -        }
   5.183 -        else if (pi->ip_proto == 17) // &&xi->setting_csum.V4Receive.UdpChecksum)
   5.184 -        {
   5.185 -          csum_info.Receive.IpChecksumSucceeded = TRUE;
   5.186 -          csum_info.Receive.UdpChecksumSucceeded = TRUE;
   5.187 -          checksum_offload = TRUE;
   5.188 -        }
   5.189 -#if 0
   5.190 -        if (pi->csum_blank && (!xi->config_csum_rx_dont_fix || !checksum_offload))
   5.191 -        {
   5.192 -          XenNet_SumPacketData(pi, packet, TRUE);
   5.193 -        }
   5.194 -#endif
   5.195 -      }
   5.196 -#if 0
   5.197 -      else if (xi->config_csum_rx_check)
   5.198 -      {
   5.199 -        if (xi->setting_csum.V4Receive.TcpChecksum && pi->ip_proto == 6)
   5.200 -        {
   5.201 -          if (XenNet_SumPacketData(pi, packet, FALSE))
   5.202 -          {
   5.203 -            csum_info.Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.204 -          }
   5.205 -          else
   5.206 -          {
   5.207 -            csum_info.Receive.NdisPacketTcpChecksumFailed = TRUE;
   5.208 -          }
   5.209 -        } else if (xi->setting_csum.V4Receive.UdpChecksum && pi->ip_proto == 17)
   5.210 -        {
   5.211 -          if (XenNet_SumPacketData(pi, packet, FALSE))
   5.212 -          {
   5.213 -            csum_info.Receive.NdisPacketUdpChecksumSucceeded = TRUE;
   5.214 -          }
   5.215 -          else
   5.216 -          {
   5.217 -            csum_info.Receive.NdisPacketUdpChecksumFailed = TRUE;
   5.218 -          }
   5.219 -        }
   5.220 -      }
   5.221 -#endif
   5.222 -      NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo) = csum_info.Value;
   5.223 -    }
   5.224      goto done;
   5.225    default:
   5.226 -    if (!XenNet_MakePacket(xi, nbl, pi))
   5.227 +    if (!XenNet_MakePacket(xi, rc, pi))
   5.228      {
   5.229        KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   5.230        xi->stat_rx_no_buffer++;
   5.231 @@ -565,17 +565,13 @@ XenNet_MakePackets(struct xennet_info *x
   5.232    }
   5.233  
   5.234    /* this is the split_required code */
   5.235 -  csum_info.Value = 0;
   5.236 -  csum_info.Receive.IpChecksumSucceeded = TRUE;
   5.237 -  csum_info.Receive.TcpChecksumSucceeded = TRUE;
   5.238 -  //checksum_offload = TRUE;
   5.239    pi->tcp_remaining = pi->tcp_length;
   5.240  
   5.241    /* we can make certain assumptions here as the following code is only for tcp4 */
   5.242    psh = pi->header[XN_HDR_SIZE + pi->ip4_header_length + 13] & 8;
   5.243    while (pi->tcp_remaining)
   5.244    {
   5.245 -    if (!XenNet_MakePacket(xi, nbl, pi))
   5.246 +    if (!XenNet_MakePacket(xi, rc, pi))
   5.247      {
   5.248        KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   5.249        xi->stat_rx_no_buffer++;
   5.250 @@ -593,17 +589,7 @@ XenNet_MakePackets(struct xennet_info *x
   5.251      //entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   5.252      //InsertTailList(rx_packet_list, entry);
   5.253    }
   5.254 -  /* we want to be a bit flexible here if some form of offload has been disabled */
   5.255 -  csum_info.Value = 0;
   5.256 -  csum_info.Receive.IpChecksumSucceeded = TRUE;
   5.257 -  csum_info.Receive.TcpChecksumSucceeded = TRUE;
   5.258 -  NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo) = csum_info.Value;
   5.259  done:
   5.260 -  if (nbl && !NBL_PACKET_COUNT(nbl))
   5.261 -  {
   5.262 -    NdisFreeNetBufferList(nbl);
   5.263 -    nbl = NULL;
   5.264 -  }
   5.265    page_buf = pi->first_pb;
   5.266    while (page_buf)
   5.267    {
   5.268 @@ -613,7 +599,7 @@ done:
   5.269    }
   5.270    XenNet_ClearPacketInfo(pi);
   5.271    //FUNCTION_EXIT();
   5.272 -  return nbl;
   5.273 +  return;
   5.274  }
   5.275  
   5.276  /* called at <= DISPATCH_LEVEL */
   5.277 @@ -699,7 +685,6 @@ BOOLEAN
   5.278  XenNet_RxBufferCheck(struct xennet_info *xi)
   5.279  {
   5.280    RING_IDX cons, prod;
   5.281 -  LIST_ENTRY rx_packet_list;
   5.282    ULONG packet_count = 0;
   5.283    ULONG packet_data = 0;
   5.284    ULONG buffer_count = 0;
   5.285 @@ -708,11 +693,10 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.286    shared_buffer_t *page_buf;
   5.287    //LIST_ENTRY rx_header_only_packet_list;
   5.288    //PLIST_ENTRY entry;
   5.289 -  PNET_BUFFER_LIST nbl_head = NULL;
   5.290 -  PNET_BUFFER_LIST nbl_tail = NULL;
   5.291    ULONG nbl_count = 0;
   5.292    ULONG interim_packet_data = 0;
   5.293    struct netif_extra_info *ei;
   5.294 +  rx_context_t rc;
   5.295    packet_info_t *pi = &xi->rxpi[KeGetCurrentProcessorNumber() & 0xff];
   5.296    shared_buffer_t *head_buf = NULL;
   5.297    shared_buffer_t *tail_buf = NULL;
   5.298 @@ -720,18 +704,16 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.299    BOOLEAN extra_info_flag = FALSE;
   5.300    BOOLEAN more_data_flag = FALSE;
   5.301    BOOLEAN dont_set_event;
   5.302 -  int ring_packets1 = 0;
   5.303 -  int ring_packets2 = 0;
   5.304 -  int indicate_packets = 0;
   5.305    //FUNCTION_ENTER();
   5.306  
   5.307    if (!xi->connected)
   5.308      return FALSE; /* a delayed DPC could let this come through... just do nothing */
   5.309  
   5.310 -  InitializeListHead(&rx_packet_list);
   5.311 -
   5.312 +  rc.first_nbl = NULL;
   5.313 +  rc.last_nbl = NULL;
   5.314 +  rc.packet_count = 0;
   5.315 +  
   5.316    /* get all the buffers off the ring as quickly as possible so the lock is held for a minimum amount of time */
   5.317 -
   5.318    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   5.319    
   5.320    if (xi->rx_shutting_down)
   5.321 @@ -807,8 +789,7 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.322          packet_count++;
   5.323          packet_data += interim_packet_data;
   5.324          interim_packet_data = 0;
   5.325 -ring_packets1++;
   5.326 -      }
   5.327 +        }
   5.328        buffer_count++;
   5.329      }
   5.330      xi->rx.rsp_cons = cons;
   5.331 @@ -934,26 +915,9 @@ ring_packets1++;
   5.332      /* Packet done, add it to the list */
   5.333      if (!more_data_flag && !extra_info_flag)
   5.334      {
   5.335 -      PNET_BUFFER_LIST nbl;
   5.336        pi->curr_pb = pi->first_pb;
   5.337        pi->curr_mdl = pi->first_mdl;
   5.338 -      nbl = XenNet_MakePackets(xi, pi);
   5.339 -      if (nbl)
   5.340 -      {
   5.341 -        packet_count += NBL_PACKET_COUNT(nbl);
   5.342 -        nbl_count++;
   5.343 -        if (!nbl_head)
   5.344 -        {
   5.345 -          nbl_head = nbl;
   5.346 -        }
   5.347 -        else
   5.348 -        {
   5.349 -          NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
   5.350 -        }
   5.351 -        NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
   5.352 -        nbl_tail = nbl;
   5.353 -      }
   5.354 -ring_packets2++;
   5.355 +      XenNet_MakePackets(xi, &rc, pi);
   5.356      }
   5.357  
   5.358      page_buf = next_buf;
   5.359 @@ -962,19 +926,13 @@ ring_packets2++;
   5.360  
   5.361    xi->stat_rx_ok += packet_count;
   5.362  
   5.363 -  if (nbl_head)
   5.364 +  if (rc.first_nbl)
   5.365    {
   5.366 -    PNET_BUFFER_LIST nbl;
   5.367 -    for (nbl = nbl_head; nbl; nbl = NET_BUFFER_LIST_NEXT_NBL(nbl))
   5.368 -      indicate_packets++;
   5.369 -    if (indicate_packets != ring_packets1 || indicate_packets != ring_packets2)
   5.370 -      KdPrint((__DRIVER_NAME "     ring_packets1 = %d, ring_packets2 = %d, indicate_packets = %d\n", ring_packets1, ring_packets2, indicate_packets));
   5.371 -
   5.372 -    NdisMIndicateReceiveNetBufferLists(xi->adapter_handle, nbl_head, NDIS_DEFAULT_PORT_NUMBER, nbl_count,
   5.373 +    NdisMIndicateReceiveNetBufferLists(xi->adapter_handle, rc.first_nbl, NDIS_DEFAULT_PORT_NUMBER, nbl_count,
   5.374        NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL
   5.375        //| NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE 
   5.376        | NDIS_RECEIVE_FLAGS_PERFECT_FILTERED);
   5.377 -  };
   5.378 +  }
   5.379    //FUNCTION_EXIT();
   5.380    return dont_set_event;
   5.381  }
   5.382 @@ -985,7 +943,7 @@ ring_packets2++;
   5.383  */
   5.384  
   5.385  static VOID
   5.386 -XenNet_PurgeRing(struct xennet_info *xi)
   5.387 +XenNet_PurgeRing(xennet_info_t *xi)
   5.388  {
   5.389    int i;
   5.390    for (i = 0; i < NET_RX_RING_SIZE; i++)
   5.391 @@ -999,7 +957,7 @@ XenNet_PurgeRing(struct xennet_info *xi)
   5.392  }
   5.393  
   5.394  static VOID
   5.395 -XenNet_BufferFree(struct xennet_info *xi)
   5.396 +XenNet_BufferFree(xennet_info_t *xi)
   5.397  {
   5.398    shared_buffer_t *sb;
   5.399  
   5.400 @@ -1011,13 +969,13 @@ XenNet_BufferFree(struct xennet_info *xi
   5.401      xi->vectors.GntTbl_EndAccess(xi->vectors.context,
   5.402          sb->gref, FALSE, (ULONG)'XNRX');
   5.403      IoFreeMdl(sb->mdl);
   5.404 +    NdisFreeMemory(sb->virtual, sizeof(shared_buffer_t), 0);
   5.405      NdisFreeMemory(sb, PAGE_SIZE, 0);
   5.406 -    NdisFreeMemory(sb->virtual, sizeof(shared_buffer_t), 0);
   5.407    }
   5.408    while ((sb = get_hb_from_freelist(xi)) != NULL)
   5.409    {
   5.410      IoFreeMdl(sb->mdl);
   5.411 -    NdisFreeMemory(sb->virtual, sizeof(shared_buffer_t) + MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH, 0);
   5.412 +    NdisFreeMemory(sb, sizeof(shared_buffer_t) + MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH, 0);
   5.413    }
   5.414  }
   5.415  
   5.416 @@ -1077,7 +1035,6 @@ XenNet_RxInit(xennet_info_t *xi)
   5.417    xi->rx_shutting_down = FALSE;
   5.418    KeInitializeSpinLock(&xi->rx_lock);
   5.419    KeInitializeEvent(&xi->packet_returned_event, SynchronizationEvent, FALSE);
   5.420 -  KeInitializeTimer(&xi->rx_timer);
   5.421    xi->rxpi = NdisAllocateMemoryWithTagPriority(xi->adapter_handle, sizeof(packet_info_t) * NdisSystemProcessorCount(), XENNET_POOL_TAG, NormalPoolPriority);
   5.422    if (!xi->rxpi)
   5.423    {
   5.424 @@ -1130,22 +1087,16 @@ XenNet_RxInit(xennet_info_t *xi)
   5.425  BOOLEAN
   5.426  XenNet_RxShutdown(xennet_info_t *xi)
   5.427  {
   5.428 -  //KIRQL old_irql;
   5.429 +  KIRQL old_irql;
   5.430    //PNDIS_PACKET packet;
   5.431    UNREFERENCED_PARAMETER(xi);
   5.432  
   5.433    FUNCTION_ENTER();
   5.434  
   5.435 -#if 0
   5.436    KeAcquireSpinLock(&xi->rx_lock, &old_irql);
   5.437    xi->rx_shutting_down = TRUE;
   5.438    KeReleaseSpinLock(&xi->rx_lock, old_irql);
   5.439  
   5.440 -  if (xi->config_rx_interrupt_moderation)
   5.441 -  {
   5.442 -    KeCancelTimer(&xi->rx_timer);
   5.443 -  }
   5.444 -
   5.445    KeFlushQueuedDpcs();
   5.446  
   5.447    while (xi->rx_outstanding)
   5.448 @@ -1154,23 +1105,17 @@ XenNet_RxShutdown(xennet_info_t *xi)
   5.449      KeWaitForSingleObject(&xi->packet_returned_event, Executive, KernelMode, FALSE, NULL);
   5.450    }
   5.451  
   5.452 -  //KeAcquireSpinLock(&xi->rx_lock, &old_irql);
   5.453 -
   5.454    NdisFreeMemory(xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount(), 0);
   5.455  
   5.456    XenNet_BufferFree(xi);
   5.457  
   5.458 -  /* this works because get_packet_from_freelist won't allocate new packets when rx_shutting_down */
   5.459 -  while ((packet = get_packet_from_freelist(xi)) != NULL)
   5.460 -    NdisFreePacket(packet);
   5.461 -  //stack_delete(xi->rx_packet_stack, NULL, NULL);
   5.462 -  NdisFreePacketPool(xi->rx_packet_pool);
   5.463  
   5.464    stack_delete(xi->rx_pb_stack, NULL, NULL);
   5.465    stack_delete(xi->rx_hb_stack, NULL, NULL);
   5.466 -  //KeReleaseSpinLock(&xi->rx_lock, old_irql);
   5.467 +  
   5.468 +  NdisFreeNetBufferPool(xi->rx_nb_pool);
   5.469 +  NdisFreeNetBufferListPool(xi->rx_nbl_pool);
   5.470  
   5.471 -#endif
   5.472    FUNCTION_EXIT();
   5.473  
   5.474    return TRUE;
     6.1 --- a/xennet/xennet6_tx.c	Sat May 14 15:14:52 2011 +1000
     6.2 +++ b/xennet/xennet6_tx.c	Sat May 14 15:15:18 2011 +1000
     6.3 @@ -76,7 +76,6 @@ XenNet_HWSendPacket(struct xennet_info *
     6.4    BOOLEAN ndis_lso = FALSE;
     6.5    BOOLEAN xen_gso = FALSE;
     6.6    ULONG remaining;
     6.7 -  ULONG parse_result;
     6.8    ULONG frags = 0;
     6.9    BOOLEAN coalesce_required = FALSE;
    6.10    PVOID coalesce_buf;
    6.11 @@ -148,7 +147,7 @@ XenNet_HWSendPacket(struct xennet_info *
    6.12      //KdPrint((__DRIVER_NAME "     Full on send - ring full\n"));
    6.13      return FALSE;
    6.14    }
    6.15 -  parse_result = XenNet_ParsePacketHeader(&pi, coalesce_buf, PAGE_SIZE);
    6.16 +  XenNet_ParsePacketHeader(&pi, coalesce_buf, PAGE_SIZE);
    6.17    remaining = pi.total_length - pi.header_length;
    6.18    if (pi.ip_version == 4 && pi.ip_proto == 6 && pi.ip4_length == 0)
    6.19    {
    6.20 @@ -231,7 +230,7 @@ XenNet_HWSendPacket(struct xennet_info *
    6.21      /* should make use of TcpHeaderOffset too... maybe just assert if it's not what we expect */
    6.22      break;
    6.23    }
    6.24 -  if (mss && parse_result == PARSE_OK)
    6.25 +  if (mss && pi.parse_result == PARSE_OK)
    6.26    {
    6.27      //FUNCTION_MSG("lso mss = %d\n", mss);
    6.28      //if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) != NDIS_PROTOCOL_ID_TCP_IP)
    6.29 @@ -297,7 +296,7 @@ XenNet_HWSendPacket(struct xennet_info *
    6.30      ei->u.gso.features = 0;
    6.31    }
    6.32  
    6.33 -  ASSERT(xi->config_sg || !remaining);
    6.34 +  ASSERT(xi->current_sg_supported || !remaining);
    6.35    
    6.36    /* (C) - only if data is remaining */
    6.37    coalesce_buf = NULL;
    6.38 @@ -404,7 +403,7 @@ XenNet_HWSendPacket(struct xennet_info *
    6.39    switch (lso_info.Transmit.Type)
    6.40    {
    6.41    case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE:
    6.42 -    lso_info.LsoV1TransmitComplete.TcpPayload = UlongToPtr(tx_length - MAX_ETH_HEADER_LENGTH - pi.ip4_header_length - pi.tcp_header_length);
    6.43 +    lso_info.LsoV1TransmitComplete.TcpPayload = tx_length - MAX_ETH_HEADER_LENGTH - pi.ip4_header_length - pi.tcp_header_length;
    6.44      break;
    6.45    case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE:
    6.46      break;
    6.47 @@ -749,15 +748,16 @@ XenNet_TxShutdown(xennet_info_t *xi)
    6.48    //PNDIS_PACKET packet;
    6.49    ////PMDL mdl;
    6.50    ////ULONG i;
    6.51 -  //KIRQL OldIrql;
    6.52 -  UNREFERENCED_PARAMETER(xi);
    6.53 +  KIRQL old_irql;
    6.54 +  PNET_BUFFER nb;
    6.55 +  PNET_BUFFER_LIST nbl;
    6.56 +  PLIST_ENTRY nb_entry;
    6.57  
    6.58    FUNCTION_ENTER();
    6.59  
    6.60 -#if 0
    6.61 -  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
    6.62 +  KeAcquireSpinLock(&xi->tx_lock, &old_irql);
    6.63    xi->tx_shutting_down = TRUE;
    6.64 -  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
    6.65 +  KeReleaseSpinLock(&xi->tx_lock, old_irql);
    6.66  
    6.67    while (xi->tx_outstanding)
    6.68    {
    6.69 @@ -765,21 +765,24 @@ XenNet_TxShutdown(xennet_info_t *xi)
    6.70      KeWaitForSingleObject(&xi->tx_idle_event, Executive, KernelMode, FALSE, NULL);
    6.71    }
    6.72  
    6.73 -#if (NTDDI_VERSION >= NTDDI_WINXP)
    6.74    KeFlushQueuedDpcs();
    6.75 -#endif
    6.76  
    6.77    /* Free packets in tx queue */
    6.78    nb_entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
    6.79 +  /* if empty, the above returns head*, not NULL */
    6.80    while (nb_entry != &xi->tx_waiting_pkt_list)
    6.81    {
    6.82 -    packet = CONTAINING_RECORD(nb_entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
    6.83 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
    6.84 +    nb = CONTAINING_RECORD(nb_entry, NET_BUFFER, NB_LIST_ENTRY_FIELD);
    6.85 +    nbl = NB_NBL(nb);
    6.86 +    NBL_REF(nbl)--;
    6.87 +    if (!NBL_REF(nbl))
    6.88 +    {
    6.89 +      nbl->Status = NDIS_STATUS_FAILURE;
    6.90 +      NdisMSendNetBufferListsComplete(xi->adapter_handle, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
    6.91 +    }
    6.92      nb_entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
    6.93    }
    6.94 -
    6.95    NdisDeleteNPagedLookasideList(&xi->tx_lookaside_list);
    6.96 -#endif
    6.97  
    6.98    FUNCTION_EXIT();
    6.99