win-pvdrivers

changeset 250:532d7485ddf2

Looking for cause of crashing. Added periodic buffer reaper timer to clean up buffers not currently in use. Modified the tx code to use a freelist when getting buffers for merged headers.
This still crashes occasionally and I can't get bacula to compelete more than about 512Mb of data before failing with a connection error.
author James Harper <james.harper@bendigoit.com.au>
date Wed Apr 09 22:38:13 2008 +1000 (2008-04-09)
parents 1e47fb7bce04
children 3db181609094
files common.inc xennet/xennet.h xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Tue Apr 08 19:51:19 2008 +1000
     1.2 +++ b/common.inc	Wed Apr 09 22:38:13 2008 +1000
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.8.34
     1.5 +VERSION=0.8.8.38
     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	Tue Apr 08 19:51:19 2008 +1000
     2.2 +++ b/xennet/xennet.h	Wed Apr 09 22:38:13 2008 +1000
     2.3 @@ -110,7 +110,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  #define RX_DFL_MIN_TARGET 128
     2.5  #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
     2.6  
     2.7 -#define MAX_BUFFERS_PER_PACKET 32
     2.8 +#define MAX_BUFFERS_PER_PACKET 64
     2.9  
    2.10  
    2.11  typedef struct {
    2.12 @@ -177,11 +177,16 @@ struct xennet_info
    2.13    ULONG tx_id_free;
    2.14    ULONG tx_no_id_free;
    2.15    USHORT tx_id_list[NET_TX_RING_SIZE];
    2.16 -  ULONG tx_gref_free;
    2.17    grant_ref_t tx_gref_list[NET_TX_RING_SIZE];
    2.18    PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
    2.19    PNDIS_BUFFER tx_mdls[NET_TX_RING_SIZE];
    2.20    grant_ref_t tx_grefs[NET_TX_RING_SIZE];
    2.21 +  ULONG tx_gref_free;
    2.22 +  ULONG tx_gref_free_lowest;
    2.23 +  PMDL tx_page_list[NET_RX_RING_SIZE];
    2.24 +  ULONG tx_page_free;
    2.25 +  ULONG tx_page_free_lowest;
    2.26 +  NDIS_MINIPORT_TIMER tx_timer;
    2.27  
    2.28    /* rx_related - protected by rx_lock */
    2.29    struct netif_rx_front_ring rx;
    2.30 @@ -190,8 +195,10 @@ struct xennet_info
    2.31    PMDL rx_mdl;
    2.32    ULONG rx_id_free;
    2.33    PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    2.34 -  PMDL page_list[NET_RX_RING_SIZE];
    2.35 -  ULONG page_free;
    2.36 +  PMDL rx_page_list[NET_RX_RING_SIZE];
    2.37 +  ULONG rx_page_free;
    2.38 +  ULONG rx_page_free_lowest;
    2.39 +  NDIS_MINIPORT_TIMER rx_timer;
    2.40  
    2.41    packet_info_t rxpi;
    2.42  
     3.1 --- a/xennet/xennet_rx.c	Tue Apr 08 19:51:19 2008 +1000
     3.2 +++ b/xennet/xennet_rx.c	Wed Apr 09 22:38:13 2008 +1000
     3.3 @@ -27,7 +27,7 @@ get_page_from_freelist(struct xennet_inf
     3.4  
     3.5  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
     3.6  
     3.7 -  if (xi->page_free == 0)
     3.8 +  if (xi->rx_page_free == 0)
     3.9    {
    3.10      mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    3.11      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = xi->XenInterface.GntTbl_GrantAccess(
    3.12 @@ -38,8 +38,10 @@ get_page_from_freelist(struct xennet_inf
    3.13    }
    3.14    else
    3.15    {
    3.16 -    xi->page_free--;
    3.17 -    mdl = xi->page_list[xi->page_free];
    3.18 +    xi->rx_page_free--;
    3.19 +    if (xi->rx_page_free < xi->rx_page_free_lowest)
    3.20 +      xi->rx_page_free_lowest = xi->rx_page_free;
    3.21 +    mdl = xi->rx_page_list[xi->rx_page_free];
    3.22  //    KdPrint(("Old Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    3.23  //      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    3.24    }
    3.25 @@ -55,10 +57,10 @@ free_page_freelist(struct xennet_info *x
    3.26    PMDL mdl;
    3.27  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.28  
    3.29 -  while(xi->page_free != 0)
    3.30 +  while(xi->rx_page_free != 0)
    3.31    {
    3.32 -    xi->page_free--;
    3.33 -    mdl = xi->page_list[xi->page_free];
    3.34 +    xi->rx_page_free--;
    3.35 +    mdl = xi->rx_page_list[xi->rx_page_free];
    3.36      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    3.37        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    3.38      FreePages(mdl);
    3.39 @@ -72,8 +74,8 @@ put_page_on_freelist(struct xennet_info 
    3.40  
    3.41  //  KdPrint(("Mdl = %p\n",  mdl));
    3.42  
    3.43 -  xi->page_list[xi->page_free] = mdl;
    3.44 -  xi->page_free++;
    3.45 +  xi->rx_page_list[xi->rx_page_free] = mdl;
    3.46 +  xi->rx_page_free++;
    3.47  
    3.48  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.49  }
    3.50 @@ -415,6 +417,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    3.51      {
    3.52        ASSERT(cycles++ < 256);
    3.53        id = (USHORT)(cons & (NET_RX_RING_SIZE - 1));
    3.54 +      ASSERT(xi->rx_buffers[id]);
    3.55        mdl = xi->rx_buffers[id];
    3.56        xi->rx_buffers[id] = NULL;
    3.57        xi->rx_id_free++;
    3.58 @@ -450,6 +453,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    3.59          {
    3.60            KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
    3.61              rxrsp->offset, rxrsp->status));
    3.62 +          ASSERT(!xi->rxpi.extra_info);
    3.63            put_page_on_freelist(xi, mdl);
    3.64            continue;
    3.65          }
    3.66 @@ -458,14 +462,6 @@ XenNet_RxBufferCheck(struct xennet_info 
    3.67          {
    3.68            if (rxrsp->flags & NETRXF_csum_blank)
    3.69              xi->rxpi.csum_calc_required = TRUE;
    3.70 -#if 0
    3.71 -          if (rxrsp->flags & (NETRXF_csum_blank|NETRXF_data_validated) && xi->config_csum)
    3.72 -          {
    3.73 -            //KdPrint((__DRIVER_NAME "     RX csum blank = %d, validated = %d\n", !!(rxrsp->flags & NETRXF_csum_blank), !!(rxrsp->flags & NETRXF_data_validated)));
    3.74 -            if (rxrsp->flags & NETRXF_csum_blank)
    3.75 -              xi->rxpi.csum_calc_required = TRUE;
    3.76 -          }
    3.77 -#endif
    3.78          }
    3.79          NdisAdjustBufferLength(mdl, rxrsp->status);
    3.80          xi->rxpi.mdls[xi->rxpi.mdl_count++] = mdl;
    3.81 @@ -558,6 +554,44 @@ XenNet_ReturnPacket(
    3.82  #endif
    3.83  }
    3.84  
    3.85 +static VOID 
    3.86 +XenNet_RxTimer(
    3.87 +  PVOID SystemSpecific1,
    3.88 +  PVOID FunctionContext,
    3.89 +  PVOID SystemSpecific2,
    3.90 +  PVOID SystemSpecific3
    3.91 +)
    3.92 +{
    3.93 +  struct xennet_info *xi = (struct xennet_info *)FunctionContext;
    3.94 +  PMDL mdl;
    3.95 +  int i;
    3.96 +
    3.97 +  UNREFERENCED_PARAMETER(SystemSpecific1);
    3.98 +  UNREFERENCED_PARAMETER(SystemSpecific2);
    3.99 +  UNREFERENCED_PARAMETER(SystemSpecific3);
   3.100 +
   3.101 +  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   3.102 +
   3.103 +  KdPrint((__DRIVER_NAME " --- rx_timer - lowest = %d\n", xi->rx_page_free_lowest));
   3.104 +
   3.105 +  if (xi->rx_page_free_lowest > max(RX_DFL_MIN_TARGET / 4, 16)) // lots of potential for tuning here
   3.106 +  {
   3.107 +    for (i = 0; i < 16; i++)
   3.108 +    {
   3.109 +      mdl = get_page_from_freelist(xi);
   3.110 +      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.111 +        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
   3.112 +      FreePages(mdl);
   3.113 +    }
   3.114 +  }
   3.115 +
   3.116 +  xi->rx_page_free_lowest = xi->rx_page_free;
   3.117 +
   3.118 +  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   3.119 +
   3.120 +  return;
   3.121 +}
   3.122 +
   3.123  /*
   3.124     Free all Rx buffers (on halt, for example) 
   3.125     The ring must be stopped at this point.
   3.126 @@ -605,6 +639,9 @@ XenNet_RxInit(xennet_info_t *xi)
   3.127    xi->rx_outstanding = 0;
   3.128    XenNet_RxBufferAlloc(xi);
   3.129  
   3.130 +  NdisMInitializeTimer(&xi->rx_timer, xi->adapter_handle, XenNet_RxTimer, xi);
   3.131 +  NdisMSetPeriodicTimer(&xi->rx_timer, 1000);
   3.132 +
   3.133    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.134  
   3.135    return TRUE;
     4.1 --- a/xennet/xennet_tx.c	Tue Apr 08 19:51:19 2008 +1000
     4.2 +++ b/xennet/xennet_tx.c	Wed Apr 09 22:38:13 2008 +1000
     4.3 @@ -77,10 +77,65 @@ get_gref_from_freelist(struct xennet_inf
     4.4  static VOID
     4.5  put_gref_on_freelist(struct xennet_info *xi, grant_ref_t gref)
     4.6  {
     4.7 +  ASSERT(xi->tx_page_list[xi->tx_page_free] == NULL);
     4.8    xi->tx_gref_list[xi->tx_gref_free] = gref;
     4.9    xi->tx_gref_free++;
    4.10  }
    4.11  
    4.12 +static PMDL
    4.13 +get_page_from_freelist(struct xennet_info *xi)
    4.14 +{
    4.15 +  PMDL mdl;
    4.16 +
    4.17 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    4.18 +
    4.19 +  if (xi->tx_page_free == 0)
    4.20 +  {
    4.21 +    mdl = AllocatePage();
    4.22 +  }
    4.23 +  else
    4.24 +  {
    4.25 +    xi->tx_page_free--;
    4.26 +    if (xi->tx_page_free < xi->tx_page_free_lowest)
    4.27 +      xi->tx_page_free_lowest = xi->tx_page_free;
    4.28 +    mdl = xi->tx_page_list[xi->tx_page_free];
    4.29 +//    KdPrint(("Old Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    4.30 +//      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    4.31 +    xi->tx_page_list[xi->tx_page_free] = NULL;
    4.32 +  }
    4.33 +
    4.34 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    4.35 +
    4.36 +  return mdl;
    4.37 +}
    4.38 +
    4.39 +static VOID
    4.40 +free_page_freelist(struct xennet_info *xi)
    4.41 +{
    4.42 +  PMDL mdl;
    4.43 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    4.44 +
    4.45 +  while(xi->tx_page_free != 0)
    4.46 +  {
    4.47 +    xi->tx_page_free--;
    4.48 +    mdl = xi->tx_page_list[xi->tx_page_free];
    4.49 +    FreePages(mdl);
    4.50 +  }
    4.51 +}
    4.52 +
    4.53 +static VOID
    4.54 +put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
    4.55 +{
    4.56 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    4.57 +
    4.58 +//  KdPrint(("Mdl = %p\n",  mdl));
    4.59 +
    4.60 +  xi->tx_page_list[xi->tx_page_free] = mdl;
    4.61 +  xi->tx_page_free++;
    4.62 +
    4.63 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    4.64 +}
    4.65 +
    4.66  
    4.67  #define SWAP_USHORT(x) (USHORT)((((x & 0xFF) << 8)|((x >> 8) & 0xFF)))
    4.68  
    4.69 @@ -201,7 +256,7 @@ XenNet_HWSendPacket(struct xennet_info *
    4.70      || mss > 0)
    4.71      && XenNet_ParsePacketHeader(&pi) == PARSE_TOO_SMALL)
    4.72    {
    4.73 -    pi.mdls[0] = merged_buffer = AllocatePage();
    4.74 +    pi.mdls[0] = merged_buffer = get_page_from_freelist(xi);
    4.75      address = MmGetMdlVirtualAddress(pi.mdls[0]);
    4.76      memcpy(address, MmGetSystemAddressForMdlSafe(buffer, NormalPagePriority), MmGetMdlByteCount(buffer));
    4.77      length = MmGetMdlByteCount(buffer);
    4.78 @@ -215,9 +270,11 @@ XenNet_HWSendPacket(struct xennet_info *
    4.79        NdisAdjustBufferLength(pi.mdls[0], length); /* do this here so that ParsePacketHeader works */
    4.80      }
    4.81    }
    4.82 +  ASSERT(buffer != NULL);
    4.83    NdisGetNextBuffer(buffer, &buffer);
    4.84    while (buffer != NULL)
    4.85    {
    4.86 +    ASSERT(pi.mdl_count < MAX_BUFFERS_PER_PACKET);
    4.87      pi.mdls[pi.mdl_count++] = buffer;
    4.88      NdisGetNextBuffer(buffer, &buffer);
    4.89    }
    4.90 @@ -393,7 +450,7 @@ XenNet_TxBufferGC(struct xennet_info *xi
    4.91        }
    4.92        if (xi->tx_mdls[id])
    4.93        {
    4.94 -        FreePages(xi->tx_mdls[id]);
    4.95 +        put_page_on_freelist(xi, xi->tx_mdls[id]);
    4.96          xi->tx_mdls[id] = NULL;
    4.97        }
    4.98        put_gref_on_freelist(xi, xi->tx_grefs[id]);
    4.99 @@ -498,6 +555,46 @@ XenNet_SendPackets(
   4.100    //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.101  }
   4.102  
   4.103 +static VOID 
   4.104 +XenNet_TxTimer(
   4.105 +  PVOID SystemSpecific1,
   4.106 +  PVOID FunctionContext,
   4.107 +  PVOID SystemSpecific2,
   4.108 +  PVOID SystemSpecific3
   4.109 +)
   4.110 +{
   4.111 +  struct xennet_info *xi = (struct xennet_info *)FunctionContext;
   4.112 +//  PMDL mdl;
   4.113 +//  int i;
   4.114 +
   4.115 +  UNREFERENCED_PARAMETER(SystemSpecific1);
   4.116 +  UNREFERENCED_PARAMETER(SystemSpecific2);
   4.117 +  UNREFERENCED_PARAMETER(SystemSpecific3);
   4.118 +
   4.119 +  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   4.120 +
   4.121 +  KdPrint((__DRIVER_NAME " --- tx_timer - lowest = %d\n", xi->tx_page_free_lowest));
   4.122 +
   4.123 +#if 0
   4.124 +  if (xi->tx_page_free_lowest > max(RX_DFL_MIN_TARGET / 4, 16)) // lots of potential for tuning here
   4.125 +  {
   4.126 +    for (i = 0; i < 16; i++)
   4.127 +    {
   4.128 +      mdl = get_page_from_freelist(xi);
   4.129 +      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   4.130 +        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
   4.131 +      FreePages(mdl);
   4.132 +    }
   4.133 +  }
   4.134 +#endif
   4.135 +
   4.136 +  xi->tx_page_free_lowest = xi->tx_page_free;
   4.137 +
   4.138 +  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   4.139 +
   4.140 +  return;
   4.141 +}
   4.142 +
   4.143  static void
   4.144  XenNet_TxBufferFree(struct xennet_info *xi)
   4.145  {
   4.146 @@ -556,14 +653,23 @@ XenNet_TxInit(xennet_info_t *xi)
   4.147      put_gref_on_freelist(xi, xi->XenInterface.GntTbl_GetRef(
   4.148        xi->XenInterface.InterfaceHeader.Context));
   4.149    }
   4.150 +
   4.151 +  NdisMInitializeTimer(&xi->tx_timer, xi->adapter_handle, XenNet_TxTimer, xi);
   4.152 +  NdisMSetPeriodicTimer(&xi->tx_timer, 1000);
   4.153 +
   4.154    return TRUE;
   4.155  }
   4.156  
   4.157  BOOLEAN
   4.158  XenNet_TxShutdown(xennet_info_t *xi)
   4.159  {
   4.160 +  KIRQL OldIrql;
   4.161    ULONG i;
   4.162  
   4.163 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   4.164 +  NdisMSetPeriodicTimer(&xi->tx_timer, 1000);
   4.165 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   4.166 +
   4.167    XenNet_TxBufferFree(xi);
   4.168  
   4.169    /* free TX resources */
   4.170 @@ -577,6 +683,8 @@ XenNet_TxShutdown(xennet_info_t *xi)
   4.171       pages Dom0 still has access to */
   4.172    xi->tx_pgs = NULL;
   4.173  
   4.174 +  free_page_freelist(xi);
   4.175 +
   4.176    /* I think that NDIS takes care of this for us... */
   4.177    /* no it doesn't - this needs handling properly */
   4.178    ASSERT(xi->tx_outstanding == 0);