win-pvdrivers

changeset 208:e2939422de10

Fixed deadlocks caused by calling NdisMIndicateReceivePacket and NdisMSendComplete with a spinlock held. The DDK docs say you shouldn't do this!
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 06 23:20:12 2008 +1100 (2008-03-06)
parents 2b9e77dc2071
children 45fdf0d55f31
files common.inc xennet/xennet.h xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Wed Mar 05 23:41:32 2008 +1100
     1.2 +++ b/common.inc	Thu Mar 06 23:20:12 2008 +1100
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.4.80
     1.5 +VERSION=0.8.4.82
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/xennet/xennet.h	Wed Mar 05 23:41:32 2008 +1100
     2.2 +++ b/xennet/xennet.h	Thu Mar 06 23:20:12 2008 +1100
     2.3 @@ -72,7 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  
     2.5  #pragma warning(disable: 4127) // conditional expression is constant
     2.6  
     2.7 -#define XEN_PROFILE
     2.8 +//#define XEN_PROFILE
     2.9  
    2.10  /* TODO: crank this up if we support higher mtus? */
    2.11  #define XN_DATA_SIZE 1500
     3.1 --- a/xennet/xennet_rx.c	Wed Mar 05 23:41:32 2008 +1100
     3.2 +++ b/xennet/xennet_rx.c	Thu Mar 06 23:20:12 2008 +1100
     3.3 @@ -109,6 +109,7 @@ XenNet_RxBufferAlloc(struct xennet_info 
     3.4    int i, batch_target, notify;
     3.5    RING_IDX req_prod = xi->rx.req_prod_pvt;
     3.6    netif_rx_request_t *req;
     3.7 +  int cycles = 0;
     3.8  #if defined(XEN_PROFILE)
     3.9    LARGE_INTEGER tsc, dummy;
    3.10  #endif
    3.11 @@ -122,6 +123,7 @@ XenNet_RxBufferAlloc(struct xennet_info 
    3.12  
    3.13    for (i = 0; i < batch_target; i++)
    3.14    {
    3.15 +    ASSERT(cycles++ < 256);
    3.16      mdl = get_page_from_freelist(xi);
    3.17      if (mdl == NULL)
    3.18        break;
    3.19 @@ -195,6 +197,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    3.20      KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
    3.21  
    3.22      for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
    3.23 +      ASSERT(cycles++ < 256);
    3.24  
    3.25        rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
    3.26        id = rxrsp->id;
    3.27 @@ -254,13 +257,14 @@ XenNet_RxBufferCheck(struct xennet_info 
    3.28    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    3.29  
    3.30    ASSERT(!more_frags);
    3.31 -/*
    3.32 +#if 0
    3.33 +  /* this must be called at DESPATCH_LEVEL */
    3.34    if (more_frags)
    3.35    {
    3.36      KdPrint((__DRIVER_NAME "     Missing fragments\n"));
    3.37      XenNet_ReturnPacket(xi, packets[packet_count]);
    3.38    }
    3.39 -*/
    3.40 +#endif
    3.41    if (packet_count != 0)
    3.42    {
    3.43      NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
     4.1 --- a/xennet/xennet_tx.c	Wed Mar 05 23:41:32 2008 +1100
     4.2 +++ b/xennet/xennet_tx.c	Thu Mar 06 23:20:12 2008 +1100
     4.3 @@ -85,8 +85,7 @@ XenNet_SendQueuedPackets(struct xennet_i
     4.4    /* if empty, the above returns head*, not NULL */
     4.5    while (entry != &xi->tx_waiting_pkt_list)
     4.6    {
     4.7 -    cycles++;
     4.8 -    ASSERT(cycles < 256);
     4.9 +    ASSERT(cycles++ < 256);
    4.10  //KdPrint((__DRIVER_NAME "     Packet ready to send\n"));
    4.11      packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
    4.12      sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
    4.13 @@ -98,8 +97,7 @@ XenNet_SendQueuedPackets(struct xennet_i
    4.14      id = 0;
    4.15      while (sg_num < sg_list->NumberOfElements || remaining > 0)
    4.16      {
    4.17 -      cycles++;
    4.18 -      ASSERT(cycles < 256);
    4.19 +      ASSERT(cycles++ < 256);
    4.20        if (remaining == 0)
    4.21        {
    4.22  //KdPrint((__DRIVER_NAME "     First Frag in sg...\n"));
    4.23 @@ -199,8 +197,10 @@ XenNet_TxBufferGC(struct xennet_info *xi
    4.24  {
    4.25    RING_IDX cons, prod;
    4.26    unsigned short id;
    4.27 -  PNDIS_PACKET packet;
    4.28 +  PNDIS_PACKET packets[NET_TX_RING_SIZE];
    4.29 +  ULONG packet_count = 0;
    4.30    int moretodo;
    4.31 +  ULONG i;
    4.32    int cycles = 0;
    4.33  #if defined(XEN_PROFILE)
    4.34    LARGE_INTEGER tsc, dummy;
    4.35 @@ -226,16 +226,17 @@ XenNet_TxBufferGC(struct xennet_info *xi
    4.36      {
    4.37        struct netif_tx_response *txrsp;
    4.38  
    4.39 +      ASSERT(cycles++ < 256);
    4.40 +
    4.41        txrsp = RING_GET_RESPONSE(&xi->tx, cons);
    4.42        if (txrsp->status == NETIF_RSP_NULL)
    4.43          continue; // should this happen? what about the page?
    4.44        id  = txrsp->id;
    4.45 -      packet = xi->tx_pkts[id];
    4.46 -      if (packet)
    4.47 +      packets[packet_count] = xi->tx_pkts[id];
    4.48 +      if (packets[packet_count])
    4.49        {
    4.50          xi->tx_pkts[id] = NULL;
    4.51 -        /* TODO: check status and indicate appropriately */
    4.52 -        NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
    4.53 +        packet_count++;
    4.54        }
    4.55        put_gref_on_freelist(xi, xi->tx_grefs[id]);
    4.56        xi->tx_grefs[id] = 0;
    4.57 @@ -255,6 +256,13 @@ XenNet_TxBufferGC(struct xennet_info *xi
    4.58  
    4.59    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
    4.60  
    4.61 +  for (i = 0; i < packet_count; i++)
    4.62 +  {
    4.63 +    /* A miniport driver must release any spin lock that it is holding before
    4.64 +       calling NdisMSendComplete. */
    4.65 +    NdisMSendComplete(xi->adapter_handle, packets[i], NDIS_STATUS_SUCCESS);
    4.66 +  }
    4.67 +
    4.68  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    4.69  
    4.70  #if defined(XEN_PROFILE)