win-pvdrivers

changeset 256:6c1ab34c1bda

Combined the rx and tx page management code - both now free pages that haven't been used recently. Performance seems to suck even more now though...
author James Harper <james.harper@bendigoit.com.au>
date Sun Apr 27 00:01:43 2008 +1000 (2008-04-27)
parents 77c9e91f543e
children 253ec5052cb4
files common.inc xennet/xennet.h xennet/xennet_common.c xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Sat Apr 26 16:50:40 2008 +1000
     1.2 +++ b/common.inc	Sun Apr 27 00:01:43 2008 +1000
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.9.1
     1.5 +VERSION=0.8.9.3
     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	Sat Apr 26 16:50:40 2008 +1000
     2.2 +++ b/xennet/xennet.h	Sun Apr 27 00:01:43 2008 +1000
     2.3 @@ -135,6 +135,17 @@ typedef struct {
     2.4    BOOLEAN more_frags;
     2.5  } packet_info_t;
     2.6  
     2.7 +typedef struct
     2.8 +{
     2.9 +  struct xennet_info *xi;
    2.10 +  PMDL page_list[NET_RX_RING_SIZE];
    2.11 +  ULONG page_free;
    2.12 +  ULONG page_free_lowest;
    2.13 +  ULONG page_free_target;
    2.14 +  NDIS_MINIPORT_TIMER timer;
    2.15 +  PKSPIN_LOCK lock;
    2.16 +} freelist_t;
    2.17 +
    2.18  struct xennet_info
    2.19  {
    2.20    /* Base device vars */
    2.21 @@ -178,10 +189,7 @@ struct xennet_info
    2.22    USHORT tx_id_list[NET_TX_RING_SIZE];
    2.23    PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
    2.24    PNDIS_BUFFER tx_mdls[NET_TX_RING_SIZE];
    2.25 -  PMDL tx_page_list[NET_RX_RING_SIZE];
    2.26 -  ULONG tx_page_free;
    2.27 -  ULONG tx_page_free_lowest;
    2.28 -  NDIS_MINIPORT_TIMER tx_timer;
    2.29 +  freelist_t tx_freelist;
    2.30  
    2.31    /* rx_related - protected by rx_lock */
    2.32    struct netif_rx_front_ring rx;
    2.33 @@ -190,11 +198,7 @@ struct xennet_info
    2.34    PMDL rx_mdl;
    2.35    ULONG rx_id_free;
    2.36    PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    2.37 -  PMDL rx_page_list[NET_RX_RING_SIZE];
    2.38 -  ULONG rx_page_free;
    2.39 -  ULONG rx_page_free_lowest;
    2.40 -  NDIS_MINIPORT_TIMER rx_timer;
    2.41 -
    2.42 +  freelist_t rx_freelist;
    2.43    packet_info_t rxpi;
    2.44  
    2.45    /* Receive-ring batched refills. */
    2.46 @@ -329,3 +333,18 @@ XenNet_SumIpHeader(
    2.47    PUCHAR header,
    2.48    USHORT ip4_header_length
    2.49  );
    2.50 +
    2.51 +static __inline grant_ref_t
    2.52 +get_grant_ref(PMDL mdl)
    2.53 +{
    2.54 +  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
    2.55 +}
    2.56 +
    2.57 +VOID
    2.58 +XenFreelist_Init(struct xennet_info *xi, freelist_t *fl, PKSPIN_LOCK lock);
    2.59 +PMDL
    2.60 +XenFreelist_GetPage(freelist_t *fl);
    2.61 +VOID
    2.62 +XenFreelist_PutPage(freelist_t *fl, PMDL mdl);
    2.63 +VOID
    2.64 +XenFreelist_Dispose(freelist_t *fl);
     3.1 --- a/xennet/xennet_common.c	Sat Apr 26 16:50:40 2008 +1000
     3.2 +++ b/xennet/xennet_common.c	Sun Apr 27 00:01:43 2008 +1000
     3.3 @@ -142,3 +142,104 @@ XenNet_GetData(
     3.4  
     3.5    return buffer;
     3.6  }
     3.7 +
     3.8 +
     3.9 +static VOID 
    3.10 +XenFreelist_Timer(
    3.11 +  PVOID SystemSpecific1,
    3.12 +  PVOID FunctionContext,
    3.13 +  PVOID SystemSpecific2,
    3.14 +  PVOID SystemSpecific3
    3.15 +)
    3.16 +{
    3.17 +  freelist_t *fl = (freelist_t *)FunctionContext;
    3.18 +  PMDL mdl;
    3.19 +  int i;
    3.20 +
    3.21 +  UNREFERENCED_PARAMETER(SystemSpecific1);
    3.22 +  UNREFERENCED_PARAMETER(SystemSpecific2);
    3.23 +  UNREFERENCED_PARAMETER(SystemSpecific3);
    3.24 +
    3.25 +  KeAcquireSpinLockAtDpcLevel(fl->lock);
    3.26 +
    3.27 +  KdPrint((__DRIVER_NAME " --- timer - page_free_lowest = %d\n", fl->page_free_lowest));
    3.28 +//  KdPrint((__DRIVER_NAME " --- rx_outstanding = %d, rx_id_free = %d\n", xi->rx_outstanding, xi->rx_id_free));
    3.29 +
    3.30 +  if (fl->page_free_lowest > fl->page_free_target) // lots of potential for tuning here
    3.31 +  {
    3.32 +    for (i = 0; i < (int)min(16, fl->page_free_lowest - fl->page_free_target); i++)
    3.33 +    {
    3.34 +      mdl = XenFreelist_GetPage(fl);
    3.35 +      fl->xi->XenInterface.GntTbl_EndAccess(fl->xi->XenInterface.InterfaceHeader.Context,
    3.36 +        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    3.37 +      FreePages(mdl);
    3.38 +    }
    3.39 +    KdPrint((__DRIVER_NAME " --- timer - freed %d pages\n", i));
    3.40 +  }
    3.41 +
    3.42 +  fl->page_free_lowest = fl->page_free;
    3.43 +
    3.44 +  KeReleaseSpinLockFromDpcLevel(fl->lock);
    3.45 +
    3.46 +  return;
    3.47 +}
    3.48 +
    3.49 +VOID
    3.50 +XenFreelist_Init(struct xennet_info *xi, freelist_t *fl, PKSPIN_LOCK lock)
    3.51 +{
    3.52 +  fl->xi = xi;
    3.53 +  fl->lock = lock;
    3.54 +  fl->page_free = 0;
    3.55 +  fl->page_free_lowest = 0;
    3.56 +  fl->page_free_target = 16; /* tune this */
    3.57 +  NdisMInitializeTimer(&fl->timer, fl->xi->adapter_handle, XenFreelist_Timer, fl);
    3.58 +  NdisMSetPeriodicTimer(&fl->timer, 1000);
    3.59 +}
    3.60 +
    3.61 +PMDL
    3.62 +XenFreelist_GetPage(freelist_t *fl)
    3.63 +{
    3.64 +  PMDL mdl;
    3.65 +
    3.66 +  if (fl->page_free == 0)
    3.67 +  {
    3.68 +    mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    3.69 +    *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = fl->xi->XenInterface.GntTbl_GrantAccess(
    3.70 +      fl->xi->XenInterface.InterfaceHeader.Context, 0,
    3.71 +      *MmGetMdlPfnArray(mdl), FALSE, 0);
    3.72 +  }
    3.73 +  else
    3.74 +  {
    3.75 +    fl->page_free--;
    3.76 +    if (fl->page_free < fl->page_free_lowest)
    3.77 +      fl->page_free_lowest = fl->page_free;
    3.78 +    mdl = fl->page_list[fl->page_free];
    3.79 +  }
    3.80 +
    3.81 +  return mdl;
    3.82 +}
    3.83 +
    3.84 +VOID
    3.85 +XenFreelist_PutPage(freelist_t *fl, PMDL mdl)
    3.86 +{
    3.87 +  fl->page_list[fl->page_free] = mdl;
    3.88 +  fl->page_free++;
    3.89 +}
    3.90 +
    3.91 +VOID
    3.92 +XenFreelist_Dispose(freelist_t *fl)
    3.93 +{
    3.94 +  PMDL mdl;
    3.95 +  BOOLEAN TimerCancelled;
    3.96 +
    3.97 +  NdisMCancelTimer(&fl->timer, &TimerCancelled);
    3.98 +
    3.99 +  while(fl->page_free != 0)
   3.100 +  {
   3.101 +    fl->page_free--;
   3.102 +    mdl = fl->page_list[fl->page_free];
   3.103 +    fl->xi->XenInterface.GntTbl_EndAccess(fl->xi->XenInterface.InterfaceHeader.Context,
   3.104 +      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
   3.105 +    FreePages(mdl);
   3.106 +  }
   3.107 +}
     4.1 --- a/xennet/xennet_rx.c	Sat Apr 26 16:50:40 2008 +1000
     4.2 +++ b/xennet/xennet_rx.c	Sun Apr 27 00:01:43 2008 +1000
     4.3 @@ -20,56 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fi
     4.4  
     4.5  #include "xennet.h"
     4.6  
     4.7 -static PMDL
     4.8 -get_page_from_freelist(struct xennet_info *xi)
     4.9 -{
    4.10 -  PMDL mdl;
    4.11 -
    4.12 -  if (xi->rx_page_free == 0)
    4.13 -  {
    4.14 -    mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    4.15 -    *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = xi->XenInterface.GntTbl_GrantAccess(
    4.16 -      xi->XenInterface.InterfaceHeader.Context, 0,
    4.17 -      *MmGetMdlPfnArray(mdl), FALSE, 0);
    4.18 -  }
    4.19 -  else
    4.20 -  {
    4.21 -    xi->rx_page_free--;
    4.22 -    if (xi->rx_page_free < xi->rx_page_free_lowest)
    4.23 -      xi->rx_page_free_lowest = xi->rx_page_free;
    4.24 -    mdl = xi->rx_page_list[xi->rx_page_free];
    4.25 -  }
    4.26 -
    4.27 -  return mdl;
    4.28 -}
    4.29 -
    4.30 -static VOID
    4.31 -put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
    4.32 -{
    4.33 -  xi->rx_page_list[xi->rx_page_free] = mdl;
    4.34 -  xi->rx_page_free++;
    4.35 -}
    4.36 -
    4.37 -static VOID
    4.38 -free_page_freelist(struct xennet_info *xi)
    4.39 -{
    4.40 -  PMDL mdl;
    4.41 -  while(xi->rx_page_free != 0)
    4.42 -  {
    4.43 -    xi->rx_page_free--;
    4.44 -    mdl = xi->rx_page_list[xi->rx_page_free];
    4.45 -    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    4.46 -      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    4.47 -    FreePages(mdl);
    4.48 -  }
    4.49 -}
    4.50 -
    4.51 -static __inline grant_ref_t
    4.52 -get_grant_ref(PMDL mdl)
    4.53 -{
    4.54 -  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
    4.55 -}
    4.56 -
    4.57  // Called at DISPATCH_LEVEL with rx lock held
    4.58  static NDIS_STATUS
    4.59  XenNet_RxBufferAlloc(struct xennet_info *xi)
    4.60 @@ -99,7 +49,7 @@ XenNet_RxBufferAlloc(struct xennet_info 
    4.61        KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring (ran out of id's)\n", i, batch_target));
    4.62        break;
    4.63      }
    4.64 -    mdl = get_page_from_freelist(xi);
    4.65 +    mdl = XenFreelist_GetPage(&xi->rx_freelist);
    4.66      if (mdl == NULL)
    4.67      {
    4.68        KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring (no free pages)\n", i, batch_target));
    4.69 @@ -277,7 +227,7 @@ XenNet_MakePacket(
    4.70    }
    4.71    else
    4.72    {
    4.73 -    out_mdl = get_page_from_freelist(xi);
    4.74 +    out_mdl = XenFreelist_GetPage(&xi->rx_freelist);
    4.75      out_buffer = MmGetMdlVirtualAddress(out_mdl);
    4.76      out_offset = XN_HDR_SIZE + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
    4.77      out_remaining = min(xi->rxpi.mss, xi->rxpi.tcp_remaining);
    4.78 @@ -353,7 +303,7 @@ XenNet_MakePackets(
    4.79    for (i = 0; i < xi->rxpi.mdl_count; i++)
    4.80    {
    4.81      NdisAdjustBufferLength(xi->rxpi.mdls[i], PAGE_SIZE);
    4.82 -    put_page_on_freelist(xi, xi->rxpi.mdls[i]);
    4.83 +    XenFreelist_PutPage(&xi->rx_freelist, xi->rxpi.mdls[i]);
    4.84    }
    4.85  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (split)\n"));
    4.86  }
    4.87 @@ -404,7 +354,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    4.88        xi->rx_id_free++;
    4.89        if (xi->rxpi.extra_info)
    4.90        {
    4.91 -        put_page_on_freelist(xi, mdl);
    4.92 +        XenFreelist_PutPage(&xi->rx_freelist, mdl);
    4.93          ei = (struct netif_extra_info *)RING_GET_RESPONSE(&xi->rx, cons);
    4.94          xi->rxpi.extra_info = (BOOLEAN)!!(ei->flags & XEN_NETIF_EXTRA_FLAG_MORE);
    4.95          switch (ei->type)
    4.96 @@ -435,7 +385,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    4.97            KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
    4.98              rxrsp->offset, rxrsp->status));
    4.99            ASSERT(!xi->rxpi.extra_info);
   4.100 -          put_page_on_freelist(xi, mdl);
   4.101 +          XenFreelist_PutPage(&xi->rx_freelist, mdl);
   4.102            continue;
   4.103          }
   4.104          ASSERT(rxrsp->id == id);
   4.105 @@ -522,7 +472,7 @@ XenNet_ReturnPacket(
   4.106    {
   4.107      ASSERT(cycles++ < 256);
   4.108      NdisAdjustBufferLength(mdl, PAGE_SIZE);
   4.109 -    put_page_on_freelist(xi, mdl);
   4.110 +    XenFreelist_PutPage(&xi->rx_freelist, mdl);
   4.111      NdisUnchainBufferAtBack(Packet, &mdl);
   4.112    }
   4.113  
   4.114 @@ -539,50 +489,11 @@ XenNet_ReturnPacket(
   4.115  #endif
   4.116  }
   4.117  
   4.118 -static VOID 
   4.119 -XenNet_RxTimer(
   4.120 -  PVOID SystemSpecific1,
   4.121 -  PVOID FunctionContext,
   4.122 -  PVOID SystemSpecific2,
   4.123 -  PVOID SystemSpecific3
   4.124 -)
   4.125 -{
   4.126 -  struct xennet_info *xi = (struct xennet_info *)FunctionContext;
   4.127 -  PMDL mdl;
   4.128 -  int i;
   4.129 -
   4.130 -  UNREFERENCED_PARAMETER(SystemSpecific1);
   4.131 -  UNREFERENCED_PARAMETER(SystemSpecific2);
   4.132 -  UNREFERENCED_PARAMETER(SystemSpecific3);
   4.133 -
   4.134 -  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   4.135 -
   4.136 -  KdPrint((__DRIVER_NAME " --- rx_timer - rx_page_free_lowest = %d\n", xi->rx_page_free_lowest));
   4.137 -//  KdPrint((__DRIVER_NAME " --- rx_outstanding = %d, rx_id_free = %d\n", xi->rx_outstanding, xi->rx_id_free));
   4.138 -
   4.139 -  if (xi->rx_page_free_lowest > max(RX_DFL_MIN_TARGET / 4, 16)) // lots of potential for tuning here
   4.140 -  {
   4.141 -    for (i = 0; i < 16; i++)
   4.142 -    {
   4.143 -      mdl = get_page_from_freelist(xi);
   4.144 -      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   4.145 -        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
   4.146 -      FreePages(mdl);
   4.147 -    }
   4.148 -    KdPrint((__DRIVER_NAME " --- rx_timer - freed %d pages\n", i));
   4.149 -  }
   4.150 -
   4.151 -  xi->rx_page_free_lowest = xi->rx_page_free;
   4.152 -
   4.153 -  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   4.154 -
   4.155 -  return;
   4.156 -}
   4.157 -
   4.158  /*
   4.159     Free all Rx buffers (on halt, for example) 
   4.160     The ring must be stopped at this point.
   4.161  */
   4.162 +
   4.163  static void
   4.164  XenNet_RxBufferFree(struct xennet_info *xi)
   4.165  {
   4.166 @@ -598,7 +509,7 @@ XenNet_RxBufferFree(struct xennet_info *
   4.167  
   4.168      mdl = xi->rx_buffers[i];
   4.169      NdisAdjustBufferLength(mdl, PAGE_SIZE);
   4.170 -    put_page_on_freelist(xi, mdl);
   4.171 +    XenFreelist_PutPage(&xi->rx_freelist, mdl);
   4.172    }
   4.173  }
   4.174  
   4.175 @@ -624,10 +535,10 @@ XenNet_RxInit(xennet_info_t *xi)
   4.176    }
   4.177  
   4.178    xi->rx_outstanding = 0;
   4.179 -  XenNet_RxBufferAlloc(xi);
   4.180  
   4.181 -  NdisMInitializeTimer(&xi->rx_timer, xi->adapter_handle, XenNet_RxTimer, xi);
   4.182 -  NdisMSetPeriodicTimer(&xi->rx_timer, 1000);
   4.183 +  XenFreelist_Init(xi, &xi->rx_freelist, &xi->rx_lock);
   4.184 +
   4.185 +  XenNet_RxBufferAlloc(xi);
   4.186  
   4.187    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.188  
   4.189 @@ -638,29 +549,25 @@ BOOLEAN
   4.190  XenNet_RxShutdown(xennet_info_t *xi)
   4.191  {
   4.192    KIRQL OldIrql;
   4.193 -  BOOLEAN TimerCancelled;
   4.194  
   4.195    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.196  
   4.197    KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
   4.198 -  NdisMCancelTimer(&xi->rx_timer, &TimerCancelled);
   4.199 -  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   4.200  
   4.201    XenNet_RxBufferFree(xi);
   4.202  
   4.203 -  free_page_freelist(xi);
   4.204 +  XenFreelist_Dispose(&xi->rx_freelist);
   4.205  
   4.206    /* free RX resources */
   4.207 -  if (xi->XenInterface.GntTbl_EndAccess(
   4.208 -    xi->XenInterface.InterfaceHeader.Context, xi->rx_ring_ref, 0))
   4.209 -  {
   4.210 -    xi->rx_ring_ref = GRANT_INVALID_REF;
   4.211 -    FreePages(xi->rx_mdl);
   4.212 -  }
   4.213 +  ASSERT(xi->XenInterface.GntTbl_EndAccess(
   4.214 +    xi->XenInterface.InterfaceHeader.Context, xi->rx_ring_ref, 0));
   4.215 +  FreePages(xi->rx_mdl);
   4.216    xi->rx_pgs = NULL;
   4.217  
   4.218    ASSERT(xi->rx_outstanding == 0);
   4.219  
   4.220 +  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   4.221 +
   4.222    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.223  
   4.224    return TRUE;
     5.1 --- a/xennet/xennet_tx.c	Sat Apr 26 16:50:40 2008 +1000
     5.2 +++ b/xennet/xennet_tx.c	Sun Apr 27 00:01:43 2008 +1000
     5.3 @@ -71,57 +71,6 @@ put_no_id_on_freelist(struct xennet_info
     5.4  {
     5.5    xi->tx_no_id_used--;
     5.6  }
     5.7 -
     5.8 -static PMDL
     5.9 -get_page_from_freelist(struct xennet_info *xi)
    5.10 -{
    5.11 -  PMDL mdl;
    5.12 -
    5.13 -  if (xi->tx_page_free == 0)
    5.14 -  {
    5.15 -    mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    5.16 -    *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = xi->XenInterface.GntTbl_GrantAccess(
    5.17 -      xi->XenInterface.InterfaceHeader.Context, 0,
    5.18 -      *MmGetMdlPfnArray(mdl), FALSE, 0);
    5.19 -  }
    5.20 -  else
    5.21 -  {
    5.22 -    xi->tx_page_free--;
    5.23 -    if (xi->tx_page_free < xi->tx_page_free_lowest)
    5.24 -      xi->tx_page_free_lowest = xi->tx_page_free;
    5.25 -    mdl = xi->tx_page_list[xi->tx_page_free];
    5.26 -  }
    5.27 -
    5.28 -  return mdl;
    5.29 -}
    5.30 -
    5.31 -static VOID
    5.32 -put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
    5.33 -{
    5.34 -  xi->tx_page_list[xi->tx_page_free] = mdl;
    5.35 -  xi->tx_page_free++;
    5.36 -}
    5.37 -
    5.38 -static VOID
    5.39 -free_page_freelist(struct xennet_info *xi)
    5.40 -{
    5.41 -  PMDL mdl;
    5.42 -  while(xi->tx_page_free != 0)
    5.43 -  {
    5.44 -    xi->tx_page_free--;
    5.45 -    mdl = xi->tx_page_list[xi->tx_page_free];
    5.46 -    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    5.47 -      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    5.48 -    FreePages(mdl);
    5.49 -  }
    5.50 -}
    5.51 -
    5.52 -static __inline grant_ref_t
    5.53 -get_grant_ref(PMDL mdl)
    5.54 -{
    5.55 -  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
    5.56 -}
    5.57 -
    5.58  #define SWAP_USHORT(x) (USHORT)((((x & 0xFF) << 8)|((x >> 8) & 0xFF)))
    5.59  
    5.60  /* Place a buffer on tx ring. */
    5.61 @@ -202,7 +151,7 @@ XenNet_HWSendPacket(struct xennet_info *
    5.62  
    5.63    for (page_num = 0, in_remaining = 0; page_num < pages_required; page_num++)
    5.64    {
    5.65 -    pi.mdls[page_num] = get_page_from_freelist(xi);
    5.66 +    pi.mdls[page_num] = XenFreelist_GetPage(&xi->tx_freelist);
    5.67      out_buffer = MmGetMdlVirtualAddress(pi.mdls[page_num]);
    5.68      out_remaining = (USHORT)min(PAGE_SIZE, total_packet_length - page_num * PAGE_SIZE);
    5.69      NdisAdjustBufferLength(pi.mdls[page_num], out_remaining);
    5.70 @@ -396,7 +345,7 @@ XenNet_TxBufferGC(struct xennet_info *xi
    5.71        if (xi->tx_mdls[id])
    5.72        {
    5.73          NdisAdjustBufferLength(xi->tx_mdls[id], PAGE_SIZE);
    5.74 -        put_page_on_freelist(xi, xi->tx_mdls[id]);
    5.75 +        XenFreelist_PutPage(&xi->tx_freelist, xi->tx_mdls[id]);
    5.76          xi->tx_mdls[id] = NULL;
    5.77        }
    5.78        put_id_on_freelist(xi, id);
    5.79 @@ -497,49 +446,6 @@ XenNet_SendPackets(
    5.80    //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    5.81  }
    5.82  
    5.83 -static VOID 
    5.84 -XenNet_TxTimer(
    5.85 -  PVOID SystemSpecific1,
    5.86 -  PVOID FunctionContext,
    5.87 -  PVOID SystemSpecific2,
    5.88 -  PVOID SystemSpecific3
    5.89 -)
    5.90 -{
    5.91 -  struct xennet_info *xi = (struct xennet_info *)FunctionContext;
    5.92 -//  PMDL mdl;
    5.93 -//  int i;
    5.94 -
    5.95 -  UNREFERENCED_PARAMETER(SystemSpecific1);
    5.96 -  UNREFERENCED_PARAMETER(SystemSpecific2);
    5.97 -  UNREFERENCED_PARAMETER(SystemSpecific3);
    5.98 -
    5.99 -  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
   5.100 -  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   5.101 -
   5.102 -  KdPrint((__DRIVER_NAME " --- tx_timer - tx_page_free_lowest = %d\n", xi->tx_page_free_lowest));
   5.103 -
   5.104 -//  KdPrint((__DRIVER_NAME " --- tx_id_free = %d, xi->tx_no_id_used = %d\n", xi->tx_id_free, xi->tx_no_id_used));
   5.105 -
   5.106 -#if 0
   5.107 -  if (xi->tx_page_free_lowest > max(RX_DFL_MIN_TARGET / 4, 16)) // lots of potential for tuning here
   5.108 -  {
   5.109 -    for (i = 0; i < 16; i++)
   5.110 -    {
   5.111 -      mdl = get_page_from_freelist(xi);
   5.112 -      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   5.113 -        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
   5.114 -      FreePages(mdl);
   5.115 -    }
   5.116 -  }
   5.117 -#endif
   5.118 -
   5.119 -  xi->tx_page_free_lowest = xi->tx_page_free;
   5.120 -
   5.121 -  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   5.122 -
   5.123 -  return;
   5.124 -}
   5.125 -
   5.126  BOOLEAN
   5.127  XenNet_TxInit(xennet_info_t *xi)
   5.128  {
   5.129 @@ -561,15 +467,15 @@ XenNet_TxInit(xennet_info_t *xi)
   5.130      put_id_on_freelist(xi, i);
   5.131    }
   5.132  
   5.133 -  NdisMInitializeTimer(&xi->tx_timer, xi->adapter_handle, XenNet_TxTimer, xi);
   5.134 -  NdisMSetPeriodicTimer(&xi->tx_timer, 1000);
   5.135 +  XenFreelist_Init(xi, &xi->tx_freelist, &xi->tx_lock);
   5.136  
   5.137    return TRUE;
   5.138  }
   5.139  
   5.140  /*
   5.141  The ring is completely closed down now. We just need to empty anything left
   5.142 -on our freelists and harvest anything left on the rings.
   5.143 +on our freelists and harvest anything left on the rings. The freelist timer
   5.144 +will still be running though.
   5.145  */
   5.146  
   5.147  BOOLEAN
   5.148 @@ -579,14 +485,13 @@ XenNet_TxShutdown(xennet_info_t *xi)
   5.149    PNDIS_PACKET packet;
   5.150    PMDL mdl;
   5.151    ULONG i;
   5.152 -  BOOLEAN TimerCancelled;
   5.153 +  KIRQL OldIrql;
   5.154  
   5.155    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.156  
   5.157 -  NdisMCancelTimer(&xi->tx_timer, &TimerCancelled);
   5.158 -
   5.159    ASSERT(!xi->connected);
   5.160  
   5.161 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   5.162    /* Free packets in tx queue */
   5.163    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   5.164    while (entry != &xi->tx_waiting_pkt_list)
   5.165 @@ -604,10 +509,10 @@ XenNet_TxShutdown(xennet_info_t *xi)
   5.166        NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   5.167      mdl = xi->tx_mdls[i];
   5.168      if (mdl)
   5.169 -      put_page_on_freelist(xi, xi->tx_mdls[i]);
   5.170 +      XenFreelist_PutPage(&xi->tx_freelist, xi->tx_mdls[i]);
   5.171    }
   5.172  
   5.173 -  free_page_freelist(xi);
   5.174 +  XenFreelist_Dispose(&xi->tx_freelist);
   5.175  
   5.176    /* free TX resources */
   5.177    ASSERT(xi->XenInterface.GntTbl_EndAccess(
   5.178 @@ -615,6 +520,8 @@ XenNet_TxShutdown(xennet_info_t *xi)
   5.179    FreePages(xi->tx_mdl);
   5.180    xi->tx_pgs = NULL;
   5.181  
   5.182 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   5.183 +
   5.184    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.185  
   5.186    return TRUE;