win-pvdrivers

changeset 216:90fcd61a9cbb

xennet: give code to send one packet to HW its own function
author Andy Grover <andy.grover@oracle.com>
date Thu Mar 20 17:51:37 2008 -0700 (2008-03-20)
parents e12cad680f3c
children c33404027885 a9a5b54bee92
files xennet/xennet_tx.c
line diff
     1.1 --- a/xennet/xennet_tx.c	Thu Mar 20 16:58:34 2008 -0700
     1.2 +++ b/xennet/xennet_tx.c	Thu Mar 20 17:51:37 2008 -0700
     1.3 @@ -110,32 +110,197 @@ XenNet_SumHeader(
     1.4  
     1.5  /* Called at DISPATCH_LEVEL with tx_lock held */
     1.6  
     1.7 +static BOOLEAN
     1.8 +XenNet_HWSendPacket(struct xennet_info *xi, PNDIS_PACKET packet)
     1.9 +{
    1.10 +  struct netif_tx_request *tx;
    1.11 +  struct netif_extra_info *ei;
    1.12 +  unsigned short id;
    1.13 +#if defined(XEN_PROFILE)
    1.14 +  LARGE_INTEGER tsc, dummy;
    1.15 +#endif
    1.16 +  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    1.17 +  
    1.18 +  ULONG i = 0;
    1.19 +  PSCATTER_GATHER_LIST sg_list;
    1.20 +  UINT total_packet_length;
    1.21 +  USHORT remaining = 0;
    1.22 +  USHORT offset = 0;
    1.23 +  USHORT length;
    1.24 +  ULONGLONG curr_addr = 0;
    1.25 +  ULONG sg_num = 0;
    1.26 +  ULONG pfn;
    1.27 +  ULONG mss = 0;
    1.28 +  PMDL first_buffer;
    1.29 +  int cycles = 0;
    1.30 +
    1.31 +#if defined(XEN_PROFILE)
    1.32 +  tsc = KeQueryPerformanceCounter(&dummy);
    1.33 +#endif
    1.34 +
    1.35 +  NdisQueryPacket(packet, NULL, NULL, &first_buffer, &total_packet_length);
    1.36 +  sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
    1.37 +
    1.38 +  while (sg_num < sg_list->NumberOfElements || remaining || (i == 1 && mss))
    1.39 +  {
    1.40 +    //KdPrint((__DRIVER_NAME "     i = %d\n", i));
    1.41 +    ASSERT(cycles++ < 256);
    1.42 +    if (i == 1 && mss)
    1.43 +    {
    1.44 +      //KdPrint((__DRIVER_NAME "     Start of loop - Large Send...\n"));
    1.45 +      length = 0;
    1.46 +    }
    1.47 +    else if (remaining == 0)
    1.48 +    {
    1.49 +      mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
    1.50 +      if (total_packet_length <= mss)
    1.51 +      {
    1.52 +        mss = 0;
    1.53 +      }
    1.54 +      //if (mss)
    1.55 +      //KdPrint((__DRIVER_NAME "     Start of loop - First Frag in sg...\n"));
    1.56 +      curr_addr = sg_list->Elements[sg_num].Address.QuadPart;
    1.57 +      offset = (USHORT)(sg_list->Elements[sg_num].Address.QuadPart & (PAGE_SIZE - 1));
    1.58 +      remaining = (USHORT)sg_list->Elements[sg_num].Length;
    1.59 +      length = min(remaining, PAGE_SIZE - offset);
    1.60 +      //if (mss)
    1.61 +      //KdPrint((__DRIVER_NAME "     sg entry %d - start = %08x, length = %d\n", sg_num, (ULONG)curr_addr, length));
    1.62 +      sg_num++;
    1.63 +    }
    1.64 +    else
    1.65 +    {
    1.66 +      //if (mss)
    1.67 +      //KdPrint((__DRIVER_NAME "     Start of loop - Subsequent Frag in sg...\n"));
    1.68 +      offset = 0;
    1.69 +      length = min(remaining, PAGE_SIZE);
    1.70 +      //if (mss)
    1.71 +      //KdPrint((__DRIVER_NAME "     sg entry %d - start = %08x, length = %d\n", sg_num, (ULONG)curr_addr, length));
    1.72 +    }
    1.73 +    remaining = remaining - length;
    1.74 +    pfn = (ULONG)(curr_addr >> PAGE_SHIFT);
    1.75 +    curr_addr += length;
    1.76 +
    1.77 +    if (i++ < *(ULONG *)&packet->MiniportReservedEx)
    1.78 +      continue;
    1.79 +    if (length > 0)
    1.80 +    {
    1.81 +      id = get_id_from_freelist(xi);
    1.82 +      if (id == 0xFFFF)
    1.83 +      {
    1.84 +        KdPrint((__DRIVER_NAME "     Out of space...\n"));
    1.85 +        /* whups, out of space on the ring. requeue and get out */
    1.86 +        /* TODO: preallocate all ids so we can exit cleanly here? */
    1.87 +        return FALSE;
    1.88 +        //InsertHeadList(&xi->tx_waiting_pkt_list, entry);
    1.89 +        //break;
    1.90 +      }
    1.91 +      ASSERT(xi->tx_pkts[id] == NULL);
    1.92 +      (*(ULONG *)&packet->MiniportReservedEx)++;
    1.93 +      tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
    1.94 +
    1.95 +      tx->gref = get_gref_from_freelist(xi);
    1.96 +      ASSERT(tx->gref != 0);
    1.97 +      ASSERT(xi->tx_grefs[id] == 0);
    1.98 +      xi->tx_grefs[id] = tx->gref;
    1.99 +
   1.100 +      xi->XenInterface.GntTbl_GrantAccess(
   1.101 +        xi->XenInterface.InterfaceHeader.Context, 0,
   1.102 +        pfn, FALSE, tx->gref);
   1.103 +      tx->id = id;
   1.104 +      tx->offset = offset;
   1.105 +      tx->flags = 0;
   1.106 +      if (i != 1)
   1.107 +      {
   1.108 +        //if (mss)
   1.109 +        //KdPrint((__DRIVER_NAME "     Subsequent Frag in packet...\n"));
   1.110 +        tx->size = length;
   1.111 +      }
   1.112 +      else // we have already incremented i!!!
   1.113 +      {
   1.114 +        //if (mss)
   1.115 +        //KdPrint((__DRIVER_NAME "     First Frag in packet...\n"));
   1.116 +        tx->size = (USHORT)total_packet_length;
   1.117 +#if defined(XEN_PROFILE)
   1.118 +        ProfCount_TxPacketsTotal++;
   1.119 +#endif
   1.120 +        csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   1.121 +          packet, TcpIpChecksumPacketInfo);
   1.122 +        if (csum_info->Transmit.NdisPacketTcpChecksum
   1.123 +          || csum_info->Transmit.NdisPacketUdpChecksum)
   1.124 +        {
   1.125 +          tx->flags |= NETTXF_csum_blank|NETTXF_data_validated;
   1.126 +#if defined(XEN_PROFILE)
   1.127 +          ProfCount_TxPacketsCsumOffload++;
   1.128 +#endif
   1.129 +        }
   1.130 +
   1.131 +        if (mss)
   1.132 +        {
   1.133 +          XenNet_SumHeader(first_buffer);
   1.134 +          //KdPrint((__DRIVER_NAME "     Large Send Offload - mss = %d, length = %d\n", mss, total_packet_length));
   1.135 +          tx->flags |= NETTXF_extra_info|NETTXF_csum_blank|NETTXF_data_validated;
   1.136 +#if defined(XEN_PROFILE)
   1.137 +          ProfCount_TxPacketsLargeOffload++;
   1.138 +#endif
   1.139 +        }
   1.140 +      }
   1.141 +
   1.142 +      if (sg_num == sg_list->NumberOfElements && remaining == 0)
   1.143 +      {
   1.144 +        //if (mss)
   1.145 +        //KdPrint((__DRIVER_NAME "     No more frags\n"));
   1.146 +        xi->tx_pkts[id] = packet; /* only set the packet on the last buffer */
   1.147 +      }
   1.148 +      else
   1.149 +      {
   1.150 +        //if (mss)
   1.151 +        //KdPrint((__DRIVER_NAME "     More frags\n"));
   1.152 +        tx->flags |= NETTXF_more_data;
   1.153 +      }
   1.154 +    }
   1.155 +    else
   1.156 +    {
   1.157 +      id = get_no_id_from_freelist(xi);
   1.158 +      if (id == 0xFFFF)
   1.159 +      {
   1.160 +        KdPrint((__DRIVER_NAME "     Out of space...\n"));
   1.161 +        /* whups, out of space on the ring. requeue and get out */
   1.162 +        /* TODO: preallocate all ids so we can exit cleanly here? */
   1.163 +        return FALSE;
   1.164 +        //InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   1.165 +        //break;
   1.166 +      }
   1.167 +      //if (mss)
   1.168 +      //KdPrint((__DRIVER_NAME "     Extra Info...\n"));
   1.169 +      (*(ULONG *)&packet->MiniportReservedEx)++;
   1.170 +      ei = (struct netif_extra_info *)RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   1.171 +      ei->type = XEN_NETIF_EXTRA_TYPE_GSO;
   1.172 +      ei->flags = 0;
   1.173 +      ei->u.gso.size = (USHORT)mss;
   1.174 +      ei->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
   1.175 +      ei->u.gso.pad = 0;
   1.176 +      ei->u.gso.features = 0;
   1.177 +    }
   1.178 +    xi->tx.req_prod_pvt++;
   1.179 +  }
   1.180 +
   1.181 +  return TRUE;
   1.182 +}
   1.183 +
   1.184 +/* Called at DISPATCH_LEVEL with tx_lock held */
   1.185 +
   1.186  static VOID
   1.187  XenNet_SendQueuedPackets(struct xennet_info *xi)
   1.188  {
   1.189    PLIST_ENTRY entry;
   1.190    PNDIS_PACKET packet;
   1.191 -  struct netif_tx_request *tx;
   1.192 -  struct netif_extra_info *ei;
   1.193 -  unsigned short id;
   1.194    int notify;
   1.195  #if defined(XEN_PROFILE)
   1.196    LARGE_INTEGER tsc, dummy;
   1.197  #endif
   1.198 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   1.199    
   1.200 -  ULONG i;
   1.201 -  PSCATTER_GATHER_LIST sg_list;
   1.202 -  UINT total_packet_length;
   1.203 -  USHORT remaining;
   1.204 -  USHORT offset;
   1.205 -  USHORT length;
   1.206 -  ULONGLONG curr_addr;
   1.207 -  ULONG sg_num;
   1.208 -  ULONG pfn;
   1.209 -  ULONG mss;
   1.210 -  PMDL first_buffer;
   1.211    int cycles = 0;
   1.212 +  BOOLEAN success;
   1.213  
   1.214  #if defined(XEN_PROFILE)
   1.215    tsc = KeQueryPerformanceCounter(&dummy);
   1.216 @@ -148,151 +313,8 @@ XenNet_SendQueuedPackets(struct xennet_i
   1.217      ASSERT(cycles++ < 256);
   1.218      //KdPrint((__DRIVER_NAME "     Packet ready to send\n"));
   1.219      packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   1.220 -    NdisQueryPacket(packet, NULL, NULL, &first_buffer, &total_packet_length);
   1.221 -    sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
   1.222 -
   1.223 -    i = 0;
   1.224 -    sg_num = 0;
   1.225 -    remaining = 0;
   1.226 -    curr_addr = 0;
   1.227 -    id = 0;
   1.228 -    mss = 0;
   1.229 -    offset = 0;
   1.230 -    while (sg_num < sg_list->NumberOfElements || remaining || (i == 1 && mss))
   1.231 -    {
   1.232 -      //KdPrint((__DRIVER_NAME "     i = %d\n", i));
   1.233 -      ASSERT(cycles++ < 256);
   1.234 -      if (i == 1 && mss)
   1.235 -      {
   1.236 -        //KdPrint((__DRIVER_NAME "     Start of loop - Large Send...\n"));
   1.237 -        length = 0;
   1.238 -      }
   1.239 -      else if (remaining == 0)
   1.240 -      {
   1.241 -        mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
   1.242 -        if (total_packet_length <= mss)
   1.243 -        {
   1.244 -          mss = 0;
   1.245 -        }
   1.246 -        //if (mss)
   1.247 -        //KdPrint((__DRIVER_NAME "     Start of loop - First Frag in sg...\n"));
   1.248 -        curr_addr = sg_list->Elements[sg_num].Address.QuadPart;
   1.249 -        offset = (USHORT)(sg_list->Elements[sg_num].Address.QuadPart & (PAGE_SIZE - 1));
   1.250 -        remaining = (USHORT)sg_list->Elements[sg_num].Length;
   1.251 -        length = min(remaining, PAGE_SIZE - offset);
   1.252 -        //if (mss)
   1.253 -        //KdPrint((__DRIVER_NAME "     sg entry %d - start = %08x, length = %d\n", sg_num, (ULONG)curr_addr, length));
   1.254 -        sg_num++;
   1.255 -      }
   1.256 -      else
   1.257 -      {
   1.258 -        //if (mss)
   1.259 -        //KdPrint((__DRIVER_NAME "     Start of loop - Subsequent Frag in sg...\n"));
   1.260 -        offset = 0;
   1.261 -        length = min(remaining, PAGE_SIZE);
   1.262 -        //if (mss)
   1.263 -        //KdPrint((__DRIVER_NAME "     sg entry %d - start = %08x, length = %d\n", sg_num, (ULONG)curr_addr, length));
   1.264 -      }
   1.265 -      remaining = remaining - length;
   1.266 -      pfn = (ULONG)(curr_addr >> PAGE_SHIFT);
   1.267 -      curr_addr += length;
   1.268 -
   1.269 -      if (i++ < *(ULONG *)&packet->MiniportReservedEx)
   1.270 -        continue;
   1.271 -      if (length > 0)
   1.272 -      {
   1.273 -        id = get_id_from_freelist(xi);
   1.274 -        if (id == 0xFFFF)
   1.275 -        {
   1.276 -          KdPrint((__DRIVER_NAME "     Out of space...\n"));
   1.277 -          /* whups, out of space on the ring. requeue and get out */
   1.278 -          InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   1.279 -          break;
   1.280 -        }
   1.281 -        ASSERT(xi->tx_pkts[id] == NULL);
   1.282 -        (*(ULONG *)&packet->MiniportReservedEx)++;
   1.283 -        tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   1.284 -
   1.285 -        tx->gref = get_gref_from_freelist(xi);
   1.286 -        ASSERT(tx->gref != 0);
   1.287 -        ASSERT(xi->tx_grefs[id] == 0);
   1.288 -        xi->tx_grefs[id] = tx->gref;
   1.289 -  
   1.290 -        xi->XenInterface.GntTbl_GrantAccess(
   1.291 -          xi->XenInterface.InterfaceHeader.Context, 0,
   1.292 -          pfn, FALSE, tx->gref);
   1.293 -        tx->id = id;
   1.294 -        tx->offset = offset;
   1.295 -        tx->flags = 0;
   1.296 -        if (i == 1) // we have already incremented i!!!
   1.297 -        {
   1.298 -          //if (mss)
   1.299 -          //KdPrint((__DRIVER_NAME "     First Frag in packet...\n"));
   1.300 -          tx->size = (USHORT)total_packet_length;
   1.301 -#if defined(XEN_PROFILE)
   1.302 -          ProfCount_TxPacketsTotal++;
   1.303 -#endif
   1.304 -          csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpIpChecksumPacketInfo);
   1.305 -          if (csum_info->Transmit.NdisPacketTcpChecksum || csum_info->Transmit.NdisPacketUdpChecksum)
   1.306 -          {
   1.307 -            tx->flags |= NETTXF_csum_blank|NETTXF_data_validated;
   1.308 -#if defined(XEN_PROFILE)
   1.309 -            ProfCount_TxPacketsCsumOffload++;
   1.310 -#endif
   1.311 -          }
   1.312 -          if (mss)
   1.313 -          {
   1.314 -            XenNet_SumHeader(first_buffer);
   1.315 -            //KdPrint((__DRIVER_NAME "     Large Send Offload - mss = %d, length = %d\n", mss, total_packet_length));
   1.316 -            tx->flags |= NETTXF_extra_info|NETTXF_csum_blank|NETTXF_data_validated;
   1.317 -#if defined(XEN_PROFILE)
   1.318 -            ProfCount_TxPacketsLargeOffload++;
   1.319 -#endif
   1.320 -          }
   1.321 -        }
   1.322 -        else
   1.323 -        {
   1.324 -          //if (mss)
   1.325 -          //KdPrint((__DRIVER_NAME "     Subsequent Frag in packet...\n"));
   1.326 -          tx->size = length;
   1.327 -        }
   1.328 -        if (sg_num == sg_list->NumberOfElements && remaining == 0)
   1.329 -        {
   1.330 -          //if (mss)
   1.331 -          //KdPrint((__DRIVER_NAME "     No more frags\n"));
   1.332 -          xi->tx_pkts[id] = packet; /* only set the packet on the last buffer */
   1.333 -        }
   1.334 -        else
   1.335 -        {
   1.336 -          //if (mss)
   1.337 -          //KdPrint((__DRIVER_NAME "     More frags\n"));
   1.338 -          tx->flags |= NETTXF_more_data;
   1.339 -        }
   1.340 -      }
   1.341 -      else
   1.342 -      {
   1.343 -        id = get_no_id_from_freelist(xi);
   1.344 -        if (id == 0xFFFF)
   1.345 -        {
   1.346 -          KdPrint((__DRIVER_NAME "     Out of space...\n"));
   1.347 -          /* whups, out of space on the ring. requeue and get out */
   1.348 -          InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   1.349 -          break;
   1.350 -        }
   1.351 -        //if (mss)
   1.352 -        //KdPrint((__DRIVER_NAME "     Extra Info...\n"));
   1.353 -        (*(ULONG *)&packet->MiniportReservedEx)++;
   1.354 -        ei = (struct netif_extra_info *)RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   1.355 -        ei->type = XEN_NETIF_EXTRA_TYPE_GSO;
   1.356 -        ei->flags = 0;
   1.357 -        ei->u.gso.size = (USHORT)mss;
   1.358 -        ei->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
   1.359 -        ei->u.gso.pad = 0;
   1.360 -        ei->u.gso.features = 0;
   1.361 -      }
   1.362 -      xi->tx.req_prod_pvt++;
   1.363 -    }
   1.364 -    if (id == 0xFFFF)
   1.365 +    success = XenNet_HWSendPacket(xi, packet);
   1.366 +    if (!success)
   1.367        break;
   1.368      entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   1.369    }