win-pvdrivers

changeset 237:bbfd6ac85128

Andy's tx updates were assuming that the first item in the SG list had exactly 1 page which was false. Also the flag setting wasn't correct. Fixed now.
author James Harper <james.harper@bendigoit.com.au>
date Sat Mar 29 23:46:42 2008 +1100 (2008-03-29)
parents 303c06237a1e
children 050947b66224
files common.inc xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Sat Mar 29 19:55:00 2008 +1100
     1.2 +++ b/common.inc	Sat Mar 29 23:46:42 2008 +1100
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.5.103
     1.5 +VERSION=0.8.5.104
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/xennet/xennet_tx.c	Sat Mar 29 19:55:00 2008 +1100
     2.2 +++ b/xennet/xennet_tx.c	Sat Mar 29 23:46:42 2008 +1100
     2.3 @@ -89,7 +89,7 @@ put_gref_on_freelist(struct xennet_info 
     2.4   * do IP header csum offload, so we have to fake it!
     2.5   */
     2.6  VOID
     2.7 -XenNet_SumHeader(
     2.8 +XenNet_SumIpHeader(
     2.9   PMDL mdl /* first buffer of the packet - containing the header */
    2.10  )
    2.11  {
    2.12 @@ -122,42 +122,58 @@ XenNet_SumHeader(
    2.13    ushorts[5] = SWAP_USHORT(~csum);
    2.14  }
    2.15  
    2.16 -/* How many requests on the TX ring will this packet take? */
    2.17 -static ULONG
    2.18 -XenNet_RequestsNeeded(PNDIS_PACKET packet)
    2.19 +typedef struct
    2.20  {
    2.21 -  int count = 0;
    2.22 -  ULONG mss;
    2.23 -  ULONG sg_num;
    2.24 -  PSCATTER_GATHER_LIST sg_list;
    2.25 +  PFN_NUMBER pfn;
    2.26 +  USHORT offset;
    2.27 +  USHORT length;
    2.28 +} page_element_t;
    2.29 +  
    2.30  
    2.31 -  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
    2.32 -  if (mss > 0)
    2.33 -  {
    2.34 -    count++; // extra_info
    2.35 -  }
    2.36 +static VOID
    2.37 +XenNet_BuildPageList(PNDIS_PACKET packet, page_element_t *elements, PUSHORT num_elements)
    2.38 +{
    2.39 +  PSCATTER_GATHER_LIST sg_list;
    2.40 +  USHORT sg_num;
    2.41 +  USHORT element_num;
    2.42 +  PFN_NUMBER pfn;
    2.43 +  USHORT offset;
    2.44 +  USHORT remaining;
    2.45 +  USHORT pages;
    2.46 +  USHORT page;
    2.47  
    2.48    sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
    2.49 -  ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_list->Elements[0].Address.QuadPart,
    2.50 -    sg_list->Elements[0].Length) == 1);
    2.51 -  for (sg_num = 0; sg_num < sg_list->NumberOfElements; sg_num++)
    2.52 +  for (sg_num = 0, element_num = 0; sg_num < sg_list->NumberOfElements; sg_num++)
    2.53    {
    2.54 -    count += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
    2.55 -      sg_list->Elements[sg_num].Address.QuadPart,
    2.56 -      sg_list->Elements[sg_num].Length);
    2.57 +    pfn = (PFN_NUMBER)(sg_list->Elements[sg_num].Address.QuadPart >> PAGE_SHIFT);
    2.58 +    remaining = (USHORT)sg_list->Elements[sg_num].Length;
    2.59 +    pages = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_list->Elements[sg_num].Address.QuadPart, remaining);
    2.60 +    offset = (USHORT)sg_list->Elements[sg_num].Address.LowPart & (PAGE_SIZE - 1);
    2.61 +    for (page = 0; page < pages; page++, element_num++)
    2.62 +    {
    2.63 +      ASSERT(element_num < *num_elements);
    2.64 +      elements[element_num].pfn = pfn + page;
    2.65 +      elements[element_num].offset = offset;
    2.66 +      elements[element_num].length = min(remaining, PAGE_SIZE - offset);
    2.67 +      offset = 0;
    2.68 +      remaining = remaining - (USHORT)elements[element_num].length;
    2.69 +    }
    2.70 +    ASSERT(remaining == 0);
    2.71    }
    2.72 -
    2.73 -  return count;
    2.74 +  *num_elements = element_num;
    2.75  }
    2.76  
    2.77  /* Place a buffer on tx ring. */
    2.78  static struct netif_tx_request*
    2.79 -XenNet_PutOnTxRing(struct xennet_info *xi, ULONGLONG addr, size_t len, uint16_t flags)
    2.80 +XenNet_PutOnTxRing(
    2.81 +  struct xennet_info *xi,
    2.82 +  PFN_NUMBER pfn,
    2.83 +  USHORT offset,
    2.84 +  USHORT len,
    2.85 +  uint16_t flags)
    2.86  {
    2.87    struct netif_tx_request *tx;
    2.88    unsigned short id;
    2.89 -  PFN_NUMBER pfn = (PFN_NUMBER)(addr >> PAGE_SHIFT);
    2.90 -  ULONG offset = BYTE_OFFSET(addr);
    2.91  
    2.92    id = get_id_from_freelist(xi);
    2.93    /* TODO: check id against FREELIST_ID_ERROR */
    2.94 @@ -191,19 +207,14 @@ XenNet_HWSendPacket(struct xennet_info *
    2.95    struct netif_tx_request *tx = NULL;
    2.96    struct netif_extra_info *ei;
    2.97    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    2.98 -  PSCATTER_GATHER_LIST sg_list;
    2.99    UINT total_packet_length;
   2.100 -  ULONG sg_num;
   2.101    ULONG mss; // 0 if not using large send
   2.102    PMDL first_buffer;
   2.103 -  int cycles = 0;
   2.104 -  ULONGLONG sg_elem_addr;
   2.105 -  ULONG sg_elem_len;
   2.106 -  ULONG sg_elem_pages;
   2.107 -  ULONG sg_elem_page;
   2.108 -  ULONG chunk_len;
   2.109    uint16_t flags = NETTXF_more_data;
   2.110 -  uint16_t csum_flags = 0;
   2.111 +  page_element_t elements[NET_TX_RING_SIZE];
   2.112 +  USHORT num_elements;
   2.113 +  USHORT element_num;
   2.114 +  
   2.115  #if defined(XEN_PROFILE)
   2.116    LARGE_INTEGER tsc, dummy;
   2.117  
   2.118 @@ -212,36 +223,35 @@ XenNet_HWSendPacket(struct xennet_info *
   2.119  
   2.120    NdisQueryPacket(packet, NULL, NULL, &first_buffer, &total_packet_length);
   2.121  
   2.122 -  if (XenNet_RequestsNeeded(packet) > free_requests(xi))
   2.123 -  {
   2.124 +  num_elements = NET_TX_RING_SIZE;
   2.125 +  XenNet_BuildPageList(packet, elements, &num_elements);
   2.126 +  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
   2.127 +
   2.128 +  if (num_elements + !!mss > (int)free_requests(xi))
   2.129      return FALSE;
   2.130 -  }
   2.131  
   2.132    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   2.133      packet, TcpIpChecksumPacketInfo);
   2.134    if (csum_info->Transmit.NdisPacketTcpChecksum
   2.135      || csum_info->Transmit.NdisPacketUdpChecksum)
   2.136    {
   2.137 -    csum_flags = NETTXF_csum_blank | NETTXF_data_validated;
   2.138 +    flags |= NETTXF_csum_blank | NETTXF_data_validated;
   2.139      PC_INC(ProfCount_TxPacketsCsumOffload);
   2.140    }
   2.141  
   2.142 -  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
   2.143    if (mss > 0)
   2.144    {
   2.145      flags |= NETTXF_extra_info;
   2.146 -    XenNet_SumHeader(first_buffer);
   2.147 +    XenNet_SumIpHeader(first_buffer);
   2.148      PC_INC(ProfCount_TxPacketsLargeOffload);
   2.149    }
   2.150  
   2.151    /*
   2.152     * See io/netif.h. Must put (A) 1st request, then (B) optional extra_info, then
   2.153 -   * (C) rest of requests on the ring.
   2.154 +   * (C) rest of requests on the ring. Only (A) has csum flags.
   2.155     */
   2.156 -  sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
   2.157    /* (A) */
   2.158 -  tx = XenNet_PutOnTxRing(xi, sg_list->Elements[0].Address.QuadPart,
   2.159 -    sg_list->Elements[0].Length, flags | csum_flags);
   2.160 +  tx = XenNet_PutOnTxRing(xi, elements[0].pfn, elements[0].offset, elements[0].length, flags);
   2.161    tx->size = (uint16_t)total_packet_length; /* 1st req size always tot pkt len */
   2.162    xi->tx.req_prod_pvt++;
   2.163  
   2.164 @@ -251,7 +261,7 @@ XenNet_HWSendPacket(struct xennet_info *
   2.165      get_no_id_from_freelist(xi);
   2.166      ei = (struct netif_extra_info *)RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   2.167      ei->type = XEN_NETIF_EXTRA_TYPE_GSO;
   2.168 -    ei->flags = NETTXF_more_data;
   2.169 +    ei->flags = 0;
   2.170      ei->u.gso.size = (USHORT) mss;
   2.171      ei->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
   2.172      ei->u.gso.pad = 0;
   2.173 @@ -261,25 +271,13 @@ XenNet_HWSendPacket(struct xennet_info *
   2.174    }
   2.175  
   2.176    /* (C) */
   2.177 -  for (sg_num = 1; sg_num < sg_list->NumberOfElements; sg_num++)
   2.178 +  for (element_num = 1; element_num < num_elements; element_num++)
   2.179    {
   2.180      //KdPrint((__DRIVER_NAME "     i = %d\n", i));
   2.181 -    ASSERT(cycles++ < 256);
   2.182 -
   2.183 -    sg_elem_addr = sg_list->Elements[sg_num].Address.QuadPart;
   2.184 -    sg_elem_len = sg_list->Elements[sg_num].Length;
   2.185 -    sg_elem_pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_elem_addr, sg_elem_len);
   2.186 -    for (sg_elem_page = 0; sg_elem_page < sg_elem_pages; sg_elem_page++)
   2.187 -    {
   2.188 -      chunk_len = min(sg_elem_len, PAGE_SIZE - BYTE_OFFSET(sg_elem_addr));
   2.189 -
   2.190 -      tx = XenNet_PutOnTxRing(xi, sg_elem_addr, chunk_len, NETTXF_more_data | csum_flags);
   2.191 -
   2.192 -      sg_elem_addr += chunk_len;
   2.193 -      sg_elem_len -= chunk_len;
   2.194 -
   2.195 -      xi->tx.req_prod_pvt++;
   2.196 -    }
   2.197 +    tx = XenNet_PutOnTxRing(xi, elements[element_num].pfn,
   2.198 +      elements[element_num].offset, elements[element_num].length,
   2.199 +      NETTXF_more_data);
   2.200 +    xi->tx.req_prod_pvt++;
   2.201    }
   2.202  
   2.203    /* only set the packet on the last buffer, clear more_data */