win-pvdrivers

changeset 103:a96426482216

xennet: actually do what I thought I was doing yesterday

Put all the code in Halt, not Shutdown.
Halt: Free TX and RX buffers, release refs.
Halt: Free all memory.
Rename "pkt" variables to "packet" for consistency.
Move Halt function down in file, to right after Shutdown.
Fix off-by-1 error with TX ref array. Yes, we want +1.
Rename RxBuffers functions to be consistent with TX function names
Tell Xen we do support csum offload
Remove unneeded & and report we support all ipv4 recv offloads (i.e. undo yesterday's mistakes :)
author Andy Grover <andy.grover@oracle.com>
date Tue Jan 08 17:49:08 2008 -0800 (2008-01-08)
parents a1db6a819d41
children 4ad735c07462
files xennet/xennet.c
line diff
     1.1 --- a/xennet/xennet.c	Mon Jan 07 19:31:14 2008 -0800
     1.2 +++ b/xennet/xennet.c	Tue Jan 08 17:49:08 2008 -0800
     1.3 @@ -80,7 +80,7 @@ struct xennet_info
     1.4    PNDIS_PACKET rx_pkts[NET_RX_RING_SIZE];
     1.5  
     1.6    grant_ref_t gref_tx_head;
     1.7 -  grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
     1.8 +  grant_ref_t grant_tx_ref[NET_TX_RING_SIZE+1];
     1.9    grant_ref_t gref_rx_head;
    1.10    grant_ref_t grant_rx_ref[NET_TX_RING_SIZE];
    1.11  
    1.12 @@ -231,9 +231,37 @@ XenNet_TxBufferGC(struct xennet_info *xi
    1.13    return NDIS_STATUS_SUCCESS;
    1.14  }
    1.15  
    1.16 +static void XenNet_TxBufferFree(struct xennet_info *xi)
    1.17 +{
    1.18 +  PNDIS_PACKET packet;
    1.19 +  PMDL pmdl;
    1.20 +  unsigned short id;
    1.21 +
    1.22 +  /* TODO: free packets in tx queue (once implemented) */
    1.23 +
    1.24 +  /* free sent-but-not-completed packets */
    1.25 +  for (id = 1; id < NET_TX_RING_SIZE+1; id++) {
    1.26 +    if (xi->grant_tx_ref[id] == GRANT_INVALID_REF)
    1.27 +      continue;
    1.28 +
    1.29 +    packet = xi->tx_pkts[id];
    1.30 +    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    1.31 +      xi->grant_tx_ref[id]);
    1.32 +    xi->grant_tx_ref[id] = GRANT_INVALID_REF;
    1.33 +    add_id_to_freelist(xi->tx_pkts, id);
    1.34 +
    1.35 +    /* free linearized data page */
    1.36 +    pmdl = *(PMDL *)packet->MiniportReservedEx;
    1.37 +    NdisFreeMemory(MmGetMdlVirtualAddress(pmdl), 0, 0); // <= DISPATCH_LEVEL
    1.38 +    IoFreeMdl(pmdl);
    1.39 +
    1.40 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
    1.41 +  }
    1.42 +}
    1.43 +
    1.44  // Called at DISPATCH_LEVEL with RxLock held
    1.45  static NDIS_STATUS
    1.46 -XenNet_AllocRXBuffers(struct xennet_info *xi)
    1.47 +XenNet_RxBufferAlloc(struct xennet_info *xi)
    1.48  {
    1.49    unsigned short id;
    1.50    PNDIS_PACKET packet;
    1.51 @@ -306,11 +334,11 @@ XenNet_AllocRXBuffers(struct xennet_info
    1.52    return NDIS_STATUS_SUCCESS;
    1.53  }
    1.54  
    1.55 -/* free rx buffers */
    1.56  static void
    1.57 -XenNet_FreeRXBuffers(struct xennet_info *xi)
    1.58 +XenNet_RxBufferFree(struct xennet_info *xi)
    1.59  {
    1.60    int i;
    1.61 +  grant_ref_t ref;
    1.62    PNDIS_PACKET packet;
    1.63    PNDIS_BUFFER buffer;
    1.64    PVOID buff_va;
    1.65 @@ -324,17 +352,22 @@ XenNet_FreeRXBuffers(struct xennet_info 
    1.66  
    1.67    for (i = 0; i < NET_RX_RING_SIZE; i++)
    1.68    {
    1.69 -    if (xi->rx_pkts[i])
    1.70 -    {
    1.71 -      packet = xi->rx_pkts[i];
    1.72 -      NdisGetFirstBufferFromPacketSafe(packet, &buffer, &buff_va, &buff_len,
    1.73 -        &tot_buff_len, NormalPagePriority);
    1.74 -      ASSERT(buff_len == tot_buff_len);
    1.75 +    if (!xi->rx_pkts[i])
    1.76 +      continue;
    1.77  
    1.78 -      NdisFreeMemory(buff_va, 0, 0);
    1.79 -      NdisFreeBuffer(buffer);
    1.80 -      NdisFreePacket(packet);
    1.81 -    }
    1.82 +    packet = xi->rx_pkts[i];
    1.83 +    ref = xi->grant_rx_ref[i];
    1.84 +
    1.85 +    /* don't check return, what can we do about it on failure? */
    1.86 +    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context, ref);
    1.87 +
    1.88 +    NdisGetFirstBufferFromPacketSafe(packet, &buffer, &buff_va, &buff_len,
    1.89 +      &tot_buff_len, NormalPagePriority);
    1.90 +    ASSERT(buff_len == tot_buff_len);
    1.91 +
    1.92 +    NdisFreeMemory(buff_va, 0, 0);
    1.93 +    NdisFreeBuffer(buffer);
    1.94 +    NdisFreePacket(packet);
    1.95    }
    1.96  
    1.97    KeReleaseSpinLock(&xi->RxLock, OldIrql);
    1.98 @@ -346,7 +379,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    1.99  {
   1.100    RING_IDX cons, prod;
   1.101  
   1.102 -  PNDIS_PACKET pkt;
   1.103 +  PNDIS_PACKET packet;
   1.104    PNDIS_BUFFER buffer;
   1.105    PVOID buff_va;
   1.106    UINT buff_len;
   1.107 @@ -374,13 +407,13 @@ XenNet_RxBufferCheck(struct xennet_info 
   1.108  
   1.109      //  KdPrint((__DRIVER_NAME "     Got a packet\n"));
   1.110  
   1.111 -      pkt = xi->rx_pkts[rxrsp->id];
   1.112 +      packet = xi->rx_pkts[rxrsp->id];
   1.113        xi->rx_pkts[rxrsp->id] = NULL;
   1.114        xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   1.115          xi->grant_rx_ref[rxrsp->id]);
   1.116        xi->grant_rx_ref[rxrsp->id] = GRANT_INVALID_REF;
   1.117  
   1.118 -      NdisGetFirstBufferFromPacketSafe(pkt, &buffer, &buff_va, &buff_len,
   1.119 +      NdisGetFirstBufferFromPacketSafe(packet, &buffer, &buff_va, &buff_len,
   1.120          &tot_buff_len, NormalPagePriority);
   1.121        ASSERT(rxrsp->offset == 0);
   1.122        ASSERT(rxrsp->status > 0);
   1.123 @@ -395,17 +428,17 @@ XenNet_RxBufferCheck(struct xennet_info 
   1.124  #endif
   1.125  // maybe use NDIS_GET_PACKET_PROTOCOL_TYPE(Packet) here and check for == NDIS_PROTOCOL_ID_TCP_IP etc
   1.126  
   1.127 -      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(pkt, TcpIpChecksumPacketInfo);
   1.128 +      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpIpChecksumPacketInfo);
   1.129        csum_info->Receive.NdisPacketTcpChecksumSucceeded = 1;
   1.130        csum_info->Receive.NdisPacketUdpChecksumSucceeded = 1;
   1.131        csum_info->Receive.NdisPacketIpChecksumSucceeded = 1;
   1.132  
   1.133        xi->stat_rx_ok++;
   1.134 -      NDIS_SET_PACKET_STATUS(pkt, NDIS_STATUS_SUCCESS);
   1.135 +      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   1.136  
   1.137        /* just indicate 1 packet for now */
   1.138      //  KdPrint((__DRIVER_NAME "     Indicating Received\n"));
   1.139 -      NdisMIndicateReceivePacket(xi->adapter_handle, &pkt, 1);
   1.140 +      NdisMIndicateReceivePacket(xi->adapter_handle, &packet, 1);
   1.141      //  KdPrint((__DRIVER_NAME "     Done Indicating Received\n"));
   1.142      }
   1.143  
   1.144 @@ -415,7 +448,7 @@ XenNet_RxBufferCheck(struct xennet_info 
   1.145    } while (moretodo);
   1.146  
   1.147    /* Give netback more buffers */
   1.148 -  XenNet_AllocRXBuffers(xi);
   1.149 +  XenNet_RxBufferAlloc(xi);
   1.150  
   1.151    KeReleaseSpinLock(&xi->RxLock, OldIrql);
   1.152  
   1.153 @@ -473,7 +506,7 @@ XenNet_BackEndStateHandler(char *Path, P
   1.154      {"event-channel", 0},
   1.155      {"request-rx-copy", 1},
   1.156      {"feature-rx-notify", 1},
   1.157 -    {"feature-no-csum-offload", 1},
   1.158 +    {"feature-no-csum-offload", 0},
   1.159      {"feature-sg", 1},
   1.160      {"feature-gso-tcpv4", 0},
   1.161      {NULL, 0},
   1.162 @@ -510,7 +543,7 @@ XenNet_BackEndStateHandler(char *Path, P
   1.163      KdPrint((__DRIVER_NAME "     Backend State Changed to InitWait\n"));  
   1.164  
   1.165      xi->event_channel = xi->XenInterface.EvtChn_AllocUnbound(
   1.166 -      xi->XenInterface.InterfaceHeader.Context, 0);  
   1.167 +      xi->XenInterface.InterfaceHeader.Context, 0);
   1.168      xi->XenInterface.EvtChn_BindDpc(xi->XenInterface.InterfaceHeader.Context,
   1.169        xi->event_channel, XenNet_Interrupt, xi);
   1.170  
   1.171 @@ -557,7 +590,7 @@ XenNet_BackEndStateHandler(char *Path, P
   1.172      xi->XenInterface.XenBus_EndTransaction(xi->XenInterface.InterfaceHeader.Context,
   1.173        xbt, 0, &retry);
   1.174  
   1.175 -    XenNet_AllocRXBuffers(xi);
   1.176 +    XenNet_RxBufferAlloc(xi);
   1.177  
   1.178      xi->state = XenbusStateConnected;
   1.179      KdPrint((__DRIVER_NAME "     Set Frontend state to Connected\n"));
   1.180 @@ -605,47 +638,6 @@ trouble:
   1.181    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   1.182  }
   1.183  
   1.184 -VOID
   1.185 -XenNet_Halt(
   1.186 -  IN NDIS_HANDLE MiniportAdapterContext
   1.187 -  )
   1.188 -{
   1.189 -  struct xennet_info *xi = MiniportAdapterContext;
   1.190 -  CHAR TmpPath[128];
   1.191 -
   1.192 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   1.193 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.194 -
   1.195 -  // set frontend state to 'closing'
   1.196 -  xi->state = XenbusStateClosing;
   1.197 -  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
   1.198 -  xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
   1.199 -    XBT_NIL, TmpPath, "%d", xi->state);
   1.200 -
   1.201 -  // wait for backend to set 'Closing' state
   1.202 -
   1.203 -  while (xi->backend_state != XenbusStateClosing)
   1.204 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
   1.205 -
   1.206 -  // set frontend state to 'closed'
   1.207 -  xi->state = XenbusStateClosed;
   1.208 -  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
   1.209 -  xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
   1.210 -    XBT_NIL, TmpPath, "%d", xi->state);
   1.211 -
   1.212 -  // wait for backend to set 'Closed' state
   1.213 -  while (xi->backend_state != XenbusStateClosed)
   1.214 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
   1.215 -
   1.216 -  // remove event channel xenbus entry
   1.217 -  // unbind event channel
   1.218 -  // remove tx/rx ring entries
   1.219 -  // clean up all grant table entries
   1.220 -  // free all memory
   1.221 -
   1.222 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   1.223 -}
   1.224 -
   1.225  static NDIS_STATUS
   1.226  XenNet_Init(
   1.227    OUT PNDIS_STATUS OpenErrorStatus,
   1.228 @@ -734,8 +726,6 @@ XenNet_Init(
   1.229    /* Initialize tx_pkts as a free chain containing every entry. */
   1.230    for (i = 0; i < NET_TX_RING_SIZE+1; i++) {
   1.231      xi->tx_pkts[i] = (void *)((unsigned long) i+1);
   1.232 -  }
   1.233 -  for (i = 0; i < NET_TX_RING_SIZE; i++) {
   1.234      xi->grant_tx_ref[i] = GRANT_INVALID_REF;
   1.235    }
   1.236  
   1.237 @@ -1070,16 +1060,16 @@ XenNet_QueryInformation(
   1.238        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   1.239  
   1.240        /* fill in checksum offload struct */
   1.241 -      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)&nto->TaskBuffer;
   1.242 +      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   1.243        nttic->V4Transmit.IpOptionsSupported = 0;
   1.244        nttic->V4Transmit.TcpOptionsSupported = 0;
   1.245        nttic->V4Transmit.TcpChecksum = 0;
   1.246        nttic->V4Transmit.UdpChecksum = 0;
   1.247        nttic->V4Transmit.IpChecksum = 0;
   1.248 -      nttic->V4Receive.IpOptionsSupported = 0;
   1.249 -      nttic->V4Receive.TcpOptionsSupported = 0;
   1.250 -      nttic->V4Receive.TcpChecksum = 0;
   1.251 -      nttic->V4Receive.UdpChecksum = 0;
   1.252 +      nttic->V4Receive.IpOptionsSupported = 1;
   1.253 +      nttic->V4Receive.TcpOptionsSupported = 1;
   1.254 +      nttic->V4Receive.TcpChecksum = 1;
   1.255 +      nttic->V4Receive.UdpChecksum = 1;
   1.256        nttic->V4Receive.IpChecksum = 1;
   1.257        nttic->V6Transmit.IpOptionsSupported = 0;
   1.258        nttic->V6Transmit.TcpOptionsSupported = 0;
   1.259 @@ -1102,7 +1092,7 @@ XenNet_QueryInformation(
   1.260        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   1.261  
   1.262        /* fill in large send struct */
   1.263 -      nttls = (PNDIS_TASK_TCP_LARGE_SEND)&nto->TaskBuffer;
   1.264 +      nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   1.265        nttls->Version = 0;
   1.266        nttls->MaxOffLoadSize = 1024*64; /* made up, fixme */
   1.267        nttls->MinSegmentCount = 4; /* also made up */
   1.268 @@ -1406,6 +1396,8 @@ XenNet_SendPackets(
   1.269  
   1.270      //KdPrint(("sending pkt, len %d\n", pkt_size));
   1.271  
   1.272 +    /* TODO: check if freelist is full */
   1.273 +
   1.274      pmdl = XenNet_Linearize(curr_packet);
   1.275      if (!pmdl)
   1.276      {
   1.277 @@ -1465,6 +1457,7 @@ XenNet_PnPEventNotify(
   1.278    KdPrint((__FUNCTION__ " called\n"));
   1.279  }
   1.280  
   1.281 +/* Called when machine is shutting down, so just quiesce the HW and be done fast. */
   1.282  VOID
   1.283  XenNet_Shutdown(
   1.284    IN NDIS_HANDLE MiniportAdapterContext
   1.285 @@ -1472,16 +1465,81 @@ XenNet_Shutdown(
   1.286  {
   1.287    struct xennet_info *xi = MiniportAdapterContext;
   1.288  
   1.289 +  /* turn off interrupt */
   1.290 +  xi->XenInterface.EvtChn_Unbind(xi->XenInterface.InterfaceHeader.Context,
   1.291 +    xi->event_channel);  
   1.292 +
   1.293 +  KdPrint((__FUNCTION__ " called\n"));
   1.294 +}
   1.295 +
   1.296 +/* Opposite of XenNet_Init */
   1.297 +XenNet_Halt(
   1.298 +  IN NDIS_HANDLE MiniportAdapterContext
   1.299 +  )
   1.300 +{
   1.301 +  struct xennet_info *xi = MiniportAdapterContext;
   1.302 +  CHAR TmpPath[128];
   1.303 +
   1.304 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   1.305 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.306 +
   1.307 +  XenNet_Shutdown(xi);
   1.308 +
   1.309 +  // set frontend state to 'closing'
   1.310 +  xi->state = XenbusStateClosing;
   1.311 +  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
   1.312 +  xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
   1.313 +    XBT_NIL, TmpPath, "%d", xi->state);
   1.314 +
   1.315 +  // wait for backend to set 'Closing' state
   1.316 +
   1.317 +  while (xi->backend_state != XenbusStateClosing)
   1.318 +    KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
   1.319 +
   1.320 +  // set frontend state to 'closed'
   1.321 +  xi->state = XenbusStateClosed;
   1.322 +  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
   1.323 +  xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
   1.324 +    XBT_NIL, TmpPath, "%d", xi->state);
   1.325 +
   1.326 +  // wait for backend to set 'Closed' state
   1.327 +  while (xi->backend_state != XenbusStateClosed)
   1.328 +    KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
   1.329 +
   1.330    xi->connected = FALSE;
   1.331  
   1.332 -  /* Free xen resources */
   1.333 -  /* TODO: disconnect from backend */
   1.334 +  // TODO: remove event channel xenbus entry (how?)
   1.335  
   1.336 -  /* Free ndis resources */
   1.337 -  XenNet_FreeRXBuffers(MiniportAdapterContext);
   1.338 -  /* TODO: clean TX ring */
   1.339 +  /* free TX resources */
   1.340 +  xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   1.341 +    xi->tx_ring_ref);
   1.342 +  xi->tx_ring_ref = GRANT_INVALID_REF;
   1.343 +  FreePages(xi->tx_mdl);
   1.344 +  xi->tx_pgs = NULL;
   1.345 +  XenNet_TxBufferFree(xi);
   1.346  
   1.347 -  KdPrint((__FUNCTION__ " called\n"));
   1.348 +  /* free RX resources */
   1.349 +  xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   1.350 +    xi->rx_ring_ref);
   1.351 +  xi->rx_ring_ref = GRANT_INVALID_REF;
   1.352 +  FreePages(xi->rx_mdl);
   1.353 +  xi->rx_pgs = NULL;
   1.354 +  XenNet_RxBufferFree(MiniportAdapterContext);
   1.355 +
   1.356 +  /* Remove watch on backend state */
   1.357 +  RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->BackendPath);
   1.358 +  xi->XenInterface.XenBus_RemWatch(xi->XenInterface.InterfaceHeader.Context,
   1.359 +      XBT_NIL, TmpPath, XenNet_BackEndStateHandler, xi);
   1.360 +
   1.361 +  xi->XenInterface.InterfaceHeader.InterfaceDereference(NULL);
   1.362 +
   1.363 +  WdfDriverMiniportUnload(WdfGetDriver());
   1.364 +
   1.365 +  NdisFreeBufferPool(xi->buffer_pool);
   1.366 +  NdisFreePacketPool(xi->packet_pool);
   1.367 +  NdisFreeMemory(xi, 0, 0); // <= DISPATCH_LEVEL
   1.368 +
   1.369 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   1.370  }
   1.371  
   1.372  NTSTATUS