win-pvdrivers

changeset 232:0893bd5ff2cb

fix HWSendPacket code to get flags right in all cases
1st request should have total packet size. (Kinda weird, but whatever...)
check for if there are enough unused requests before doing anything
author Andy Grover <andy.grover@oracle.com>
date Thu Mar 27 16:36:27 2008 -0700 (2008-03-27)
parents 86394e366a71
children 098898889f00
files xennet/xennet_tx.c
line diff
     1.1 --- a/xennet/xennet_tx.c	Thu Mar 27 11:19:31 2008 -0700
     1.2 +++ b/xennet/xennet_tx.c	Thu Mar 27 16:36:27 2008 -0700
     1.3 @@ -28,6 +28,12 @@ Foundation, Inc., 51 Franklin Street, Fi
     1.4  #define PC_INC(var)
     1.5  #endif
     1.6  
     1.7 +static ULONG
     1.8 +free_requests(struct xennet_info *xi)
     1.9 +{
    1.10 +  return xi->tx_id_free;
    1.11 +}
    1.12 +
    1.13  static USHORT
    1.14  get_id_from_freelist(struct xennet_info *xi)
    1.15  {
    1.16 @@ -116,6 +122,34 @@ XenNet_SumHeader(
    1.17    ushorts[5] = SWAP_USHORT(~csum);
    1.18  }
    1.19  
    1.20 +/* How many requests on the TX ring will this packet take? */
    1.21 +static ULONG
    1.22 +XenNet_RequestsNeeded(PNDIS_PACKET packet)
    1.23 +{
    1.24 +  int count = 0;
    1.25 +  ULONG mss;
    1.26 +  ULONG sg_num;
    1.27 +  PSCATTER_GATHER_LIST sg_list;
    1.28 +
    1.29 +  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
    1.30 +  if (mss > 0)
    1.31 +  {
    1.32 +    count++; // extra_info
    1.33 +  }
    1.34 +
    1.35 +  sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
    1.36 +  ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(sg_list->Elements[0].Address.QuadPart,
    1.37 +    sg_list->Elements[0].Length) == 1);
    1.38 +  for (sg_num = 0; sg_num < sg_list->NumberOfElements; sg_num++)
    1.39 +  {
    1.40 +    count += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
    1.41 +      sg_list->Elements[sg_num].Address.QuadPart,
    1.42 +      sg_list->Elements[sg_num].Length);
    1.43 +  }
    1.44 +
    1.45 +  return count;
    1.46 +}
    1.47 +
    1.48  /* Place a buffer on tx ring. */
    1.49  static struct netif_tx_request*
    1.50  XenNet_PutOnTxRing(struct xennet_info *xi, ULONGLONG addr, size_t len, uint16_t flags)
    1.51 @@ -147,9 +181,7 @@ XenNet_PutOnTxRing(struct xennet_info *x
    1.52    return tx;
    1.53  }
    1.54  
    1.55 -
    1.56  /* Called at DISPATCH_LEVEL with tx_lock held */
    1.57 -
    1.58  /*
    1.59   * Send one NDIS_PACKET. This may involve multiple entries on TX ring.
    1.60   */
    1.61 @@ -161,7 +193,7 @@ XenNet_HWSendPacket(struct xennet_info *
    1.62    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    1.63    PSCATTER_GATHER_LIST sg_list;
    1.64    UINT total_packet_length;
    1.65 -  ULONG sg_num = 0;
    1.66 +  ULONG sg_num;
    1.67    ULONG mss; // 0 if not using large send
    1.68    PMDL first_buffer;
    1.69    int cycles = 0;
    1.70 @@ -170,7 +202,8 @@ XenNet_HWSendPacket(struct xennet_info *
    1.71    ULONG sg_elem_pages;
    1.72    ULONG sg_elem_page;
    1.73    ULONG chunk_len;
    1.74 -  uint16_t flags;
    1.75 +  uint16_t flags = NETTXF_more_data;
    1.76 +  uint16_t csum_flags = 0;
    1.77  #if defined(XEN_PROFILE)
    1.78    LARGE_INTEGER tsc, dummy;
    1.79  
    1.80 @@ -179,24 +212,37 @@ XenNet_HWSendPacket(struct xennet_info *
    1.81  
    1.82    NdisQueryPacket(packet, NULL, NULL, &first_buffer, &total_packet_length);
    1.83  
    1.84 -  flags = NETTXF_more_data;
    1.85 +  if (XenNet_RequestsNeeded(packet) > free_requests(xi))
    1.86 +  {
    1.87 +    return FALSE;
    1.88 +  }
    1.89 +
    1.90 +  csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
    1.91 +    packet, TcpIpChecksumPacketInfo);
    1.92 +  if (csum_info->Transmit.NdisPacketTcpChecksum
    1.93 +    || csum_info->Transmit.NdisPacketUdpChecksum)
    1.94 +  {
    1.95 +    csum_flags = NETTXF_csum_blank | NETTXF_data_validated;
    1.96 +    PC_INC(ProfCount_TxPacketsCsumOffload);
    1.97 +  }
    1.98 +
    1.99    mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
   1.100    if (mss > 0)
   1.101    {
   1.102 -    flags |= NETTXF_extra_info | NETTXF_csum_blank | NETTXF_data_validated;
   1.103 +    flags |= NETTXF_extra_info;
   1.104      XenNet_SumHeader(first_buffer);
   1.105      PC_INC(ProfCount_TxPacketsLargeOffload);
   1.106    }
   1.107  
   1.108 -  sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
   1.109 -
   1.110    /*
   1.111 -   * See io/netif.h. Must put (A) 1st packet, then (B) optional extra_info, then
   1.112 -   * (C) rest of packets on the ring.
   1.113 +   * See io/netif.h. Must put (A) 1st request, then (B) optional extra_info, then
   1.114 +   * (C) rest of requests on the ring.
   1.115     */
   1.116 +  sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
   1.117    /* (A) */
   1.118    tx = XenNet_PutOnTxRing(xi, sg_list->Elements[0].Address.QuadPart,
   1.119 -    sg_list->Elements[0].Length, flags);
   1.120 +    sg_list->Elements[0].Length, flags | csum_flags);
   1.121 +  tx->size = (uint16_t)total_packet_length; /* 1st req size always tot pkt len */
   1.122    xi->tx.req_prod_pvt++;
   1.123  
   1.124    /* (B) */
   1.125 @@ -227,17 +273,7 @@ XenNet_HWSendPacket(struct xennet_info *
   1.126      {
   1.127        chunk_len = min(sg_elem_len, PAGE_SIZE - BYTE_OFFSET(sg_elem_addr));
   1.128  
   1.129 -      flags = NETTXF_more_data;
   1.130 -      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   1.131 -        packet, TcpIpChecksumPacketInfo);
   1.132 -      if (csum_info->Transmit.NdisPacketTcpChecksum
   1.133 -        || csum_info->Transmit.NdisPacketUdpChecksum)
   1.134 -      {
   1.135 -        flags |= NETTXF_csum_blank | NETTXF_data_validated;
   1.136 -        PC_INC(ProfCount_TxPacketsCsumOffload);
   1.137 -      }
   1.138 -
   1.139 -      tx = XenNet_PutOnTxRing(xi, sg_elem_addr, chunk_len, flags);
   1.140 +      tx = XenNet_PutOnTxRing(xi, sg_elem_addr, chunk_len, NETTXF_more_data | csum_flags);
   1.141  
   1.142        sg_elem_addr += chunk_len;
   1.143        sg_elem_len -= chunk_len;