win-pvdrivers

changeset 102:a1db6a819d41

xennet: fix off by 1 bug; start implementing shutdown code; redo task offload code in QueryInformation
author Andy Grover <andy.grover@oracle.com>
date Mon Jan 07 19:31:14 2008 -0800 (2008-01-07)
parents bbc88927c82b
children a96426482216
files xennet/xennet.c
line diff
     1.1 --- a/xennet/xennet.c	Mon Jan 07 19:29:28 2008 -0800
     1.2 +++ b/xennet/xennet.c	Mon Jan 07 19:31:14 2008 -0800
     1.3 @@ -76,7 +76,7 @@ struct xennet_info
     1.4  
     1.5    /* Outstanding packets. The first entry in tx_pkts
     1.6     * is an index into a chain of free entries. */
     1.7 -  PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
     1.8 +  PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE+1];
     1.9    PNDIS_PACKET rx_pkts[NET_RX_RING_SIZE];
    1.10  
    1.11    grant_ref_t gref_tx_head;
    1.12 @@ -306,6 +306,40 @@ XenNet_AllocRXBuffers(struct xennet_info
    1.13    return NDIS_STATUS_SUCCESS;
    1.14  }
    1.15  
    1.16 +/* free rx buffers */
    1.17 +static void
    1.18 +XenNet_FreeRXBuffers(struct xennet_info *xi)
    1.19 +{
    1.20 +  int i;
    1.21 +  PNDIS_PACKET packet;
    1.22 +  PNDIS_BUFFER buffer;
    1.23 +  PVOID buff_va;
    1.24 +  UINT buff_len;
    1.25 +  UINT tot_buff_len;
    1.26 +  KIRQL OldIrql;
    1.27 +
    1.28 +  ASSERT(!xi->connected);
    1.29 +
    1.30 +  KeAcquireSpinLock(&xi->RxLock, &OldIrql);
    1.31 +
    1.32 +  for (i = 0; i < NET_RX_RING_SIZE; i++)
    1.33 +  {
    1.34 +    if (xi->rx_pkts[i])
    1.35 +    {
    1.36 +      packet = xi->rx_pkts[i];
    1.37 +      NdisGetFirstBufferFromPacketSafe(packet, &buffer, &buff_va, &buff_len,
    1.38 +        &tot_buff_len, NormalPagePriority);
    1.39 +      ASSERT(buff_len == tot_buff_len);
    1.40 +
    1.41 +      NdisFreeMemory(buff_va, 0, 0);
    1.42 +      NdisFreeBuffer(buffer);
    1.43 +      NdisFreePacket(packet);
    1.44 +    }
    1.45 +  }
    1.46 +
    1.47 +  KeReleaseSpinLock(&xi->RxLock, OldIrql);
    1.48 +}
    1.49 +
    1.50  // Called at DISPATCH_LEVEL
    1.51  static NDIS_STATUS
    1.52  XenNet_RxBufferCheck(struct xennet_info *xi)
    1.53 @@ -698,8 +732,10 @@ XenNet_Init(
    1.54    xi->pdoData = (PXENPCI_XEN_DEVICE_DATA)xi->pdo->DeviceExtension;
    1.55  
    1.56    /* Initialize tx_pkts as a free chain containing every entry. */
    1.57 -  for (i = 0; i <= NET_TX_RING_SIZE; i++) {
    1.58 +  for (i = 0; i < NET_TX_RING_SIZE+1; i++) {
    1.59      xi->tx_pkts[i] = (void *)((unsigned long) i+1);
    1.60 +  }
    1.61 +  for (i = 0; i < NET_TX_RING_SIZE; i++) {
    1.62      xi->grant_tx_ref[i] = GRANT_INVALID_REF;
    1.63    }
    1.64  
    1.65 @@ -760,17 +796,6 @@ XenNet_Init(
    1.66    RtlStringCbCopyA(xi->BackendPath, ARRAY_SIZE(xi->BackendPath), Value);
    1.67    KdPrint((__DRIVER_NAME "backend path = %s\n", xi->BackendPath));
    1.68  
    1.69 -  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/type", xi->BackendPath);
    1.70 -  res = xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
    1.71 -      XBT_NIL, TmpPath, &Value);
    1.72 -  if (res || strcmp(Value, "netfront") != 0)
    1.73 -  {
    1.74 -    KdPrint((__DRIVER_NAME "    Backend type is not 'netfront'\n"));
    1.75 -    status = NDIS_STATUS_FAILURE;
    1.76 -    goto err;
    1.77 -  }
    1.78 -
    1.79 -
    1.80    KeInitializeEvent(&xi->backend_state_change_event, SynchronizationEvent, FALSE);  
    1.81  
    1.82    /* Add watch on backend state */
    1.83 @@ -802,7 +827,6 @@ XenNet_Init(
    1.84    else
    1.85    {
    1.86      char *s, *e;
    1.87 -    int i;
    1.88      s = Value;
    1.89      for (i = 0; i < ETH_ALEN; i++) {
    1.90        xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
    1.91 @@ -868,6 +892,16 @@ NDIS_OID supported_oids[] =
    1.92    OID_TCP_TASK_OFFLOAD,
    1.93  };
    1.94  
    1.95 +/* return 4 or 8 depending on size of buffer */
    1.96 +#define HANDLE_STAT_RETURN \
    1.97 +  {if (InformationBufferLength == 4) { \
    1.98 +    len = 4; *BytesNeeded = 8; \
    1.99 +    } else { \
   1.100 +    len = 8; \
   1.101 +    } }
   1.102 +
   1.103 +//#define LARGE_SEND
   1.104 +
   1.105  NDIS_STATUS 
   1.106  XenNet_QueryInformation(
   1.107    IN NDIS_HANDLE MiniportAdapterContext,
   1.108 @@ -883,10 +917,14 @@ XenNet_QueryInformation(
   1.109    PVOID data = &temp_data;
   1.110    ULONG offset = 0;
   1.111    UINT len = 4;
   1.112 +  BOOLEAN used_temp_buffer = TRUE;
   1.113    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
   1.114    PNDIS_TASK_OFFLOAD_HEADER ntoh;
   1.115    PNDIS_TASK_OFFLOAD nto;
   1.116    PNDIS_TASK_TCP_IP_CHECKSUM nttic;
   1.117 +#ifdef LARGE_SEND
   1.118 +  PNDIS_TASK_TCP_LARGE_SEND nttls;
   1.119 +#endif
   1.120  
   1.121  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   1.122  
   1.123 @@ -970,23 +1008,23 @@ XenNet_QueryInformation(
   1.124        break;
   1.125      case OID_GEN_XMIT_OK:
   1.126        temp_data = xi->stat_tx_ok;
   1.127 -      len = sizeof(ULONG64);
   1.128 +      HANDLE_STAT_RETURN;
   1.129        break;
   1.130      case OID_GEN_RCV_OK:
   1.131        temp_data = xi->stat_rx_ok;
   1.132 -      len = sizeof(ULONG64);
   1.133 +      HANDLE_STAT_RETURN;
   1.134        break;
   1.135      case OID_GEN_XMIT_ERROR:
   1.136        temp_data = xi->stat_tx_error;
   1.137 -      len = sizeof(ULONG64);
   1.138 +      HANDLE_STAT_RETURN;
   1.139        break;
   1.140      case OID_GEN_RCV_ERROR:
   1.141        temp_data = xi->stat_rx_error;
   1.142 -      len = sizeof(ULONG64);
   1.143 +      HANDLE_STAT_RETURN;
   1.144        break;
   1.145      case OID_GEN_RCV_NO_BUFFER:
   1.146        temp_data = xi->stat_rx_no_buffer;
   1.147 -      len = sizeof(ULONG64);
   1.148 +      HANDLE_STAT_RETURN;
   1.149        break;
   1.150      case OID_802_3_PERMANENT_ADDRESS:
   1.151        data = xi->perm_mac_addr;
   1.152 @@ -1004,37 +1042,44 @@ XenNet_QueryInformation(
   1.153        break;
   1.154      case OID_TCP_TASK_OFFLOAD:
   1.155        KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
   1.156 -      len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + sizeof(NDIS_TASK_OFFLOAD) - 1 + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   1.157 -      offset = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   1.158 -      NdisAllocateMemoryWithTag(&data, len - offset, XENNET_POOL_TAG);
   1.159 +      /* it's times like this that C really sucks */
   1.160 +      len = sizeof(NDIS_TASK_OFFLOAD_HEADER)
   1.161 +        + FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   1.162 +        + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   1.163 +#ifdef LARGE_SEND
   1.164 +      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   1.165 +        + sizeof(NDIS_TASK_TCP_LARGE_SEND);
   1.166 +#endif
   1.167 +
   1.168 +      if (len > InformationBufferLength)
   1.169 +      {
   1.170 +          break;
   1.171 +      }
   1.172  
   1.173        ntoh = InformationBuffer;
   1.174 -
   1.175 +      ASSERT(ntoh->Version == NDIS_TASK_OFFLOAD_VERSION);
   1.176 +      ASSERT(ntoh->Size == sizeof(*ntoh));
   1.177 +      ASSERT(ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation);
   1.178 +      ntoh->OffsetFirstTask = ntoh->Size;
   1.179  
   1.180 -      // check that ntoh->Version == NDIS_TASK_OFFLOAD_VERSION
   1.181 -      // check that ntoh->Size == sizeof(NDIS_TASK_OFFLOAD_HEADER) (maybe)
   1.182 -      // check that ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
   1.183 -
   1.184 -      ntoh->OffsetFirstTask = offset;
   1.185 -
   1.186 -      nto = data; //((char *)ntoh) + ntoh->OffsetFirstTask;
   1.187 -
   1.188 +      /* fill in first nto */
   1.189 +      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   1.190        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   1.191        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   1.192        nto->Task = TcpIpChecksumNdisTask;
   1.193 -      nto->OffsetNextTask = 0;
   1.194        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   1.195  
   1.196 -      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   1.197 +      /* fill in checksum offload struct */
   1.198 +      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)&nto->TaskBuffer;
   1.199        nttic->V4Transmit.IpOptionsSupported = 0;
   1.200        nttic->V4Transmit.TcpOptionsSupported = 0;
   1.201        nttic->V4Transmit.TcpChecksum = 0;
   1.202        nttic->V4Transmit.UdpChecksum = 0;
   1.203        nttic->V4Transmit.IpChecksum = 0;
   1.204 -      nttic->V4Receive.IpOptionsSupported = 1;
   1.205 -      nttic->V4Receive.TcpOptionsSupported = 1;
   1.206 -      nttic->V4Receive.TcpChecksum = 1;
   1.207 -      nttic->V4Receive.UdpChecksum = 1;
   1.208 +      nttic->V4Receive.IpOptionsSupported = 0;
   1.209 +      nttic->V4Receive.TcpOptionsSupported = 0;
   1.210 +      nttic->V4Receive.TcpChecksum = 0;
   1.211 +      nttic->V4Receive.UdpChecksum = 0;
   1.212        nttic->V4Receive.IpChecksum = 1;
   1.213        nttic->V6Transmit.IpOptionsSupported = 0;
   1.214        nttic->V6Transmit.TcpOptionsSupported = 0;
   1.215 @@ -1044,6 +1089,29 @@ XenNet_QueryInformation(
   1.216        nttic->V6Receive.TcpOptionsSupported = 0;
   1.217        nttic->V6Receive.TcpChecksum = 0;
   1.218        nttic->V6Receive.UdpChecksum = 0;
   1.219 +#ifdef LARGE_SEND
   1.220 +      nto->OffsetNextTask = sizeof(NDIS_TASK_OFFLOAD_HEADER)
   1.221 +        + FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   1.222 +        + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   1.223 +
   1.224 +      /* fill in second nto */
   1.225 +      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + nto->OffsetNextTask);
   1.226 +      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   1.227 +      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   1.228 +      nto->Task = TcpLargeSendNdisTask;
   1.229 +      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   1.230 +
   1.231 +      /* fill in large send struct */
   1.232 +      nttls = (PNDIS_TASK_TCP_LARGE_SEND)&nto->TaskBuffer;
   1.233 +      nttls->Version = 0;
   1.234 +      nttls->MaxOffLoadSize = 1024*64; /* made up, fixme */
   1.235 +      nttls->MinSegmentCount = 4; /* also made up */
   1.236 +      nttls->TcpOptions = FALSE;
   1.237 +      nttls->IpOptions = FALSE;
   1.238 +#endif
   1.239 +      nto->OffsetNextTask = 0; /* last one */
   1.240 +
   1.241 +      used_temp_buffer = FALSE;
   1.242        break;
   1.243      default:
   1.244        KdPrint(("Get Unknown OID 0x%x\n", Oid));
   1.245 @@ -1064,7 +1132,7 @@ XenNet_QueryInformation(
   1.246    }
   1.247  
   1.248    *BytesWritten = len;
   1.249 -  if (len)
   1.250 +  if (len && used_temp_buffer)
   1.251    {
   1.252      NdisMoveMemory(((PUCHAR)InformationBuffer) + offset, data, len - offset);
   1.253    }
   1.254 @@ -1254,6 +1322,8 @@ XenNet_ReturnPacket(
   1.255      &tot_buff_len, NormalPagePriority);
   1.256    ASSERT(buff_len == tot_buff_len);
   1.257  
   1.258 +  /* TODO: reuse returned packets */
   1.259 +
   1.260    NdisFreeMemory(buff_va, 0, 0);
   1.261    NdisFreeBuffer(buffer);
   1.262    NdisFreePacket(Packet);
   1.263 @@ -1400,10 +1470,16 @@ XenNet_Shutdown(
   1.264    IN NDIS_HANDLE MiniportAdapterContext
   1.265    )
   1.266  {
   1.267 -  //struct xennet_info *xi = MiniportAdapterContext;
   1.268 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   1.269 +  struct xennet_info *xi = MiniportAdapterContext;
   1.270  
   1.271 -  // I think all we are supposed to do here is reset the adapter, which for us might be nothing...
   1.272 +  xi->connected = FALSE;
   1.273 +
   1.274 +  /* Free xen resources */
   1.275 +  /* TODO: disconnect from backend */
   1.276 +
   1.277 +  /* Free ndis resources */
   1.278 +  XenNet_FreeRXBuffers(MiniportAdapterContext);
   1.279 +  /* TODO: clean TX ring */
   1.280  
   1.281    KdPrint((__FUNCTION__ " called\n"));
   1.282  }