win-pvdrivers

changeset 454:5e3e348cd101

Not-working-properly changes to add interrupt moderation and maximum work per interrupt
author James Harper <james.harper@bendigoit.com.au>
date Tue Nov 18 20:46:47 2008 +1100 (2008-11-18)
parents 2d4f85e453f3
children f9afef4ddf23
files xennet/xennet.c xennet/xennet.h xennet/xennet_common.c xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/xennet/xennet.c	Sat Nov 15 14:31:22 2008 +1100
     1.2 +++ b/xennet/xennet.c	Tue Nov 18 20:46:47 2008 +1100
     1.3 @@ -128,16 +128,24 @@ XenNet_InterruptIsr(
     1.4    struct xennet_info *xi = MiniportAdapterContext;
     1.5    
     1.6    //FUNCTION_ENTER();
     1.7 +  *InterruptRecognized = FALSE;
     1.8 +  *QueueMiniportHandleInterrupt = FALSE;
     1.9    if (!xi->vectors.EvtChn_AckEvent(xi->vectors.context, xi->event_channel))
    1.10    {
    1.11      /* interrupt was not for us */
    1.12 -    *InterruptRecognized = FALSE;
    1.13 -    *QueueMiniportHandleInterrupt = FALSE;
    1.14    }
    1.15    else
    1.16    {
    1.17 -    *QueueMiniportHandleInterrupt = (BOOLEAN)!!xi->connected;
    1.18 -    *InterruptRecognized = FALSE;
    1.19 +    //*QueueMiniportHandleInterrupt = (BOOLEAN)!!xi->connected;
    1.20 +    if (xi->connected)
    1.21 +    {
    1.22 +      KeInsertQueueDpc(&xi->tx_dpc, NULL, NULL);
    1.23 +      //KdPrint((__DRIVER_NAME "     Queueding Dpc (Isr)\n"));
    1.24 +      xi->last_dpc_isr = TRUE;
    1.25 +      KeQuerySystemTime(&xi->last_dpc_scheduled);
    1.26 +      KeInsertQueueDpc(&xi->rx_dpc, UlongToPtr(FALSE), NULL);
    1.27 +      //KdPrint((__DRIVER_NAME "     Dpc Queued (Isr)\n"));
    1.28 +    }
    1.29    }
    1.30  
    1.31    //FUNCTION_EXIT();
    1.32 @@ -236,6 +244,7 @@ XenNet_Resume(PDEVICE_OBJECT device_obje
    1.33    XenNet_TxResumeEnd(xi);
    1.34  }
    1.35  
    1.36 +#if 0
    1.37  static DDKAPI VOID
    1.38  XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
    1.39  {
    1.40 @@ -272,10 +281,11 @@ XenNet_InterruptDpc(NDIS_HANDLE Miniport
    1.41    if (xi->connected && !xi->inactive && xi->device_state->resume_state == RESUME_STATE_RUNNING)
    1.42    {
    1.43      XenNet_TxBufferGC(xi);
    1.44 -    XenNet_RxBufferCheck(xi);
    1.45 +    XenNet_RxBufferCheck(xi, FALSE);
    1.46    }
    1.47    //FUNCTION_EXIT();
    1.48  }
    1.49 +#endif
    1.50  
    1.51  // Called at <= DISPATCH_LEVEL
    1.52  static DDKAPI NDIS_STATUS
    1.53 @@ -752,7 +762,7 @@ DriverEntry(
    1.54    mini_chars.HaltHandler = XenNet_Halt;
    1.55    mini_chars.InitializeHandler = XenNet_Init;
    1.56    mini_chars.ISRHandler = XenNet_InterruptIsr;
    1.57 -  mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
    1.58 +  //mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
    1.59    mini_chars.QueryInformationHandler = XenNet_QueryInformation;
    1.60    mini_chars.ResetHandler = XenNet_Reset;
    1.61    mini_chars.SetInformationHandler = XenNet_SetInformation;
     2.1 --- a/xennet/xennet.h	Sat Nov 15 14:31:22 2008 +1100
     2.2 +++ b/xennet/xennet.h	Tue Nov 18 20:46:47 2008 +1100
     2.3 @@ -208,6 +208,8 @@ typedef struct
     2.4    ULONG page_free;
     2.5    ULONG page_free_lowest;
     2.6    ULONG page_free_target;
     2.7 +  ULONG page_limit;
     2.8 +  ULONG page_outstanding;
     2.9    NDIS_MINIPORT_TIMER timer;
    2.10    PKSPIN_LOCK lock;
    2.11    BOOLEAN grants_resumed;
    2.12 @@ -256,6 +258,7 @@ struct xennet_info
    2.13    //PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
    2.14    PNDIS_BUFFER tx_mdls[NET_TX_RING_SIZE];
    2.15    freelist_t tx_freelist;
    2.16 +  KDPC tx_dpc;
    2.17  
    2.18    /* rx_related - protected by rx_lock */
    2.19    KSPIN_LOCK rx_lock;
    2.20 @@ -268,7 +271,11 @@ struct xennet_info
    2.21    ULONG rx_packet_free;
    2.22    BOOLEAN rx_shutting_down;
    2.23    KEVENT packet_returned_event;
    2.24 -  NDIS_MINIPORT_TIMER rx_timer;
    2.25 +  //NDIS_MINIPORT_TIMER rx_timer;
    2.26 +  ULONG avg_page_count;
    2.27 +  KDPC rx_dpc;
    2.28 +  KTIMER rx_timer;
    2.29 +  KDPC rx_timer_dpc;
    2.30  
    2.31    /* Receive-ring batched refills. */
    2.32    ULONG rx_target;
    2.33 @@ -298,11 +305,16 @@ struct xennet_info
    2.34    ULONG64 stat_tx_error;
    2.35    ULONG64 stat_rx_error;
    2.36    ULONG64 stat_rx_no_buffer;
    2.37 +  
    2.38 +  BOOLEAN last_dpc_isr;
    2.39 +  LARGE_INTEGER last_dpc_scheduled;
    2.40  } typedef xennet_info_t;
    2.41  
    2.42  
    2.43 -NDIS_STATUS
    2.44 -XenNet_RxBufferCheck(struct xennet_info *xi);
    2.45 +//NDIS_STATUS
    2.46 +//XenNet_RxBufferCheck(struct xennet_info *xi, BOOLEAN is_timer);
    2.47 +//VOID
    2.48 +//XenNet_RxBufferCheck(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2);
    2.49  
    2.50  VOID DDKAPI
    2.51  XenNet_ReturnPacket(
    2.52 @@ -322,8 +334,10 @@ XenNet_RxResumeStart(xennet_info_t *xi);
    2.53  VOID
    2.54  XenNet_RxResumeEnd(xennet_info_t *xi);
    2.55  
    2.56 -NDIS_STATUS
    2.57 -XenNet_TxBufferGC(struct xennet_info *xi);
    2.58 +//NDIS_STATUS
    2.59 +//XenNet_TxBufferGC(struct xennet_info *xi);
    2.60 +VOID
    2.61 +XenNet_TxBufferGC(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2);
    2.62  
    2.63  VOID
    2.64  XenNet_TxResumeStart(xennet_info_t *xi);
     3.1 --- a/xennet/xennet_common.c	Sat Nov 15 14:31:22 2008 +1100
     3.2 +++ b/xennet/xennet_common.c	Tue Nov 18 20:46:47 2008 +1100
     3.3 @@ -172,6 +172,8 @@ XenFreelist_Init(struct xennet_info *xi,
     3.4    fl->page_free = 0;
     3.5    fl->page_free_lowest = 0;
     3.6    fl->page_free_target = 16; /* tune this */
     3.7 +  fl->page_limit = 512; /* 2MB */ /* tune this */
     3.8 +  fl->page_outstanding = 0;
     3.9    fl->grants_resumed = FALSE;
    3.10    NdisMInitializeTimer(&fl->timer, fl->xi->adapter_handle, XenFreelist_Timer, fl);
    3.11    NdisMSetPeriodicTimer(&fl->timer, 1000);
    3.12 @@ -188,6 +190,8 @@ XenFreelist_GetPage(freelist_t *fl)
    3.13  
    3.14    if (fl->page_free == 0)
    3.15    {
    3.16 +    if (fl->page_outstanding >= fl->page_limit)
    3.17 +      return NULL;
    3.18      mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    3.19      if (!mdl)
    3.20        return NULL;
    3.21 @@ -207,7 +211,7 @@ XenFreelist_GetPage(freelist_t *fl)
    3.22        fl->page_free_lowest = fl->page_free;
    3.23      mdl = fl->page_list[fl->page_free];
    3.24    }
    3.25 -
    3.26 +  fl->page_outstanding++;
    3.27    return mdl;
    3.28  }
    3.29  
    3.30 @@ -231,6 +235,7 @@ XenFreelist_PutPage(freelist_t *fl, PMDL
    3.31      fl->page_list[fl->page_free] = mdl;
    3.32      fl->page_free++;
    3.33    }
    3.34 +  fl->page_outstanding--;
    3.35  }
    3.36  
    3.37  VOID
     4.1 --- a/xennet/xennet_rx.c	Sat Nov 15 14:31:22 2008 +1100
     4.2 +++ b/xennet/xennet_rx.c	Tue Nov 18 20:46:47 2008 +1100
     4.3 @@ -35,8 +35,8 @@ XenNet_RxBufferAlloc(struct xennet_info 
     4.4  
     4.5    batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
     4.6  
     4.7 -  if (batch_target < (xi->rx_target >> 2))
     4.8 -    return NDIS_STATUS_SUCCESS; /* only refill if we are less than 3/4 full already */
     4.9 +  //if (batch_target < (xi->rx_target >> 2))
    4.10 +  //  return NDIS_STATUS_SUCCESS; /* only refill if we are less than 3/4 full already */
    4.11  
    4.12    for (i = 0; i < batch_target; i++)
    4.13    {
    4.14 @@ -62,7 +62,7 @@ XenNet_RxBufferAlloc(struct xennet_info 
    4.15      ASSERT(req->gref != INVALID_GRANT_REF);
    4.16      req->id = id;
    4.17    }
    4.18 -
    4.19 +  KeMemoryBarrier();
    4.20    xi->rx.req_prod_pvt = req_prod + i;
    4.21    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
    4.22    if (notify)
    4.23 @@ -87,7 +87,10 @@ get_packet_from_freelist(struct xennet_i
    4.24    {
    4.25      NdisAllocatePacket(&status, &packet, xi->packet_pool);
    4.26      if (status != NDIS_STATUS_SUCCESS)
    4.27 +    {
    4.28 +      KdPrint((__DRIVER_NAME "     cannot allocate packet\n"));
    4.29        return NULL;
    4.30 +    }
    4.31      NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
    4.32    }
    4.33    else
    4.34 @@ -110,10 +113,6 @@ put_packet_on_freelist(struct xennet_inf
    4.35      NdisFreePacket(packet);
    4.36      return;
    4.37    }
    4.38 -/*
    4.39 -  NdisReinitializePacket(packet);
    4.40 -  RtlZeroMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(packet), sizeof(NDIS_PACKET_EXTENSION));
    4.41 -*/
    4.42    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
    4.43      packet, TcpIpChecksumPacketInfo);
    4.44    csum_info->Value = 0;
    4.45 @@ -142,7 +141,6 @@ XenNet_MakePacket(struct xennet_info *xi
    4.46    USHORT out_remaining;
    4.47    USHORT length;
    4.48    USHORT new_ip4_length;
    4.49 -  //NDIS_STATUS status;
    4.50    USHORT i;
    4.51  
    4.52  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    4.53 @@ -159,8 +157,6 @@ XenNet_MakePacket(struct xennet_info *xi
    4.54      for (i = 0; i < xi->rxpi.mdl_count; i++)
    4.55        NdisChainBufferAtBack(packet, xi->rxpi.mdls[i]);
    4.56  
    4.57 -    //NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo) = UlongToPtr(xi->rxpi.mss);
    4.58 -
    4.59      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
    4.60    }
    4.61    else
    4.62 @@ -469,11 +465,56 @@ done:
    4.63  }
    4.64  
    4.65  #define MAXIMUM_PACKETS_PER_INDICATE 256
    4.66 +#define MAX_PACKETS_PER_INTERRUPT 64
    4.67 +
    4.68 +int log_flag = 0;
    4.69 +
    4.70 +typedef struct {
    4.71 +  struct xennet_info *xi;
    4.72 +  BOOLEAN is_timer;
    4.73 +} sync_context_t;
    4.74 +
    4.75 +static BOOLEAN
    4.76 +XenNet_RxQueueDpcSynchronized(PVOID context)
    4.77 +{
    4.78 +  sync_context_t *sc = context;
    4.79 +  BOOLEAN result;
    4.80 +  
    4.81 +  if (!sc->is_timer && sc->xi->config_rx_interrupt_moderation)
    4.82 +  {
    4.83 +    /* if an is_timer dpc is queued it will muck things up for us, so make sure we requeue a !is_timer dpc */
    4.84 +    KeRemoveQueueDpc(&sc->xi->rx_dpc);
    4.85 +  }
    4.86 +  sc->xi->last_dpc_isr = FALSE;
    4.87 +  KeQuerySystemTime(&sc->xi->last_dpc_scheduled);
    4.88 +  result = KeInsertQueueDpc(&sc->xi->rx_dpc, UlongToPtr(sc->is_timer), NULL);
    4.89 +  
    4.90 +  return TRUE;
    4.91 +}
    4.92 +
    4.93 +static VOID
    4.94 +XenNet_RxTimerDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
    4.95 +{
    4.96 +  struct xennet_info *xi = context;
    4.97 +  sync_context_t sc;
    4.98 +
    4.99 +  UNREFERENCED_PARAMETER(dpc);
   4.100 +  UNREFERENCED_PARAMETER(arg1);
   4.101 +  UNREFERENCED_PARAMETER(arg2);
   4.102 +  
   4.103 +  sc.xi = xi;
   4.104 +  sc.is_timer = TRUE;
   4.105 +#pragma warning(suppress:4054) /* no way around this... */
   4.106 +  NdisMSynchronizeWithInterrupt(&xi->interrupt, (PVOID)XenNet_RxQueueDpcSynchronized, &sc);
   4.107 +}
   4.108  
   4.109  // Called at DISPATCH_LEVEL
   4.110 -NDIS_STATUS
   4.111 -XenNet_RxBufferCheck(struct xennet_info *xi)
   4.112 +//NDIS_STATUS
   4.113 +//XenNet_RxBufferCheck(struct xennet_info *xi, BOOLEAN is_timer)
   4.114 +static VOID
   4.115 +XenNet_RxBufferCheck(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
   4.116  {
   4.117 +  struct xennet_info *xi = context;
   4.118    RING_IDX cons, prod;
   4.119    LIST_ENTRY rx_packet_list;
   4.120    PLIST_ENTRY entry;
   4.121 @@ -485,8 +526,24 @@ XenNet_RxBufferCheck(struct xennet_info 
   4.122    USHORT id;
   4.123    int more_to_do = FALSE;
   4.124    int page_count = 0;
   4.125 +  ULONG event = 1;
   4.126 +  BOOLEAN is_timer = (BOOLEAN)PtrToUlong(arg1);
   4.127 +  BOOLEAN set_timer = FALSE;
   4.128 +  LARGE_INTEGER current_time;
   4.129 +  ULONG delta;
   4.130 +
   4.131 +  UNREFERENCED_PARAMETER(dpc);
   4.132 +  UNREFERENCED_PARAMETER(arg1);
   4.133 +  UNREFERENCED_PARAMETER(arg2);
   4.134 +
   4.135 +  KeQuerySystemTime(&current_time);
   4.136    
   4.137 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.138 +  delta = (ULONG)((current_time.QuadPart - xi->last_dpc_scheduled.QuadPart) / 10);
   4.139 +  if (delta > 1000000) /* 1 second */
   4.140 +    KdPrint((__DRIVER_NAME "     Excessive Dpc Latency %d from %s\n", delta, xi->last_dpc_isr?"Isr":"Dpc"));
   4.141 +  if (is_timer) 
   4.142 +    KdPrint((__DRIVER_NAME "     RX Timer\n"));
   4.143 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.144  
   4.145    ASSERT(xi->connected);
   4.146  
   4.147 @@ -494,11 +551,14 @@ XenNet_RxBufferCheck(struct xennet_info 
   4.148  
   4.149    InitializeListHead(&rx_packet_list);
   4.150  
   4.151 +  if (xi->config_rx_interrupt_moderation)
   4.152 +    KeCancelTimer(&xi->rx_timer);
   4.153 +
   4.154    do {
   4.155      prod = xi->rx.sring->rsp_prod;
   4.156      KeMemoryBarrier(); /* Ensure we see responses up to 'prod'. */
   4.157  
   4.158 -    for (cons = xi->rx.rsp_cons; cons != prod; cons++)
   4.159 +    for (cons = xi->rx.rsp_cons; cons != prod && packet_count < MAX_PACKETS_PER_INTERRUPT; cons++)
   4.160      {
   4.161        id = (USHORT)(cons & (NET_RX_RING_SIZE - 1));
   4.162        ASSERT(xi->rx_mdls[id]);
   4.163 @@ -599,18 +659,28 @@ XenNet_RxBufferCheck(struct xennet_info 
   4.164        }
   4.165      }
   4.166      xi->rx.rsp_cons = cons;
   4.167 -    
   4.168 +
   4.169 +    if (!more_to_do)
   4.170 +    {
   4.171 +      /* if we were called on the timer then turn off moderation */
   4.172 +      if (is_timer)
   4.173 +        xi->avg_page_count = 0;
   4.174 +      else if (page_count != 0) /* if page_count == 0 then the interrupt wasn't really for us so it's not fair for it to affect the averages... */
   4.175 +        xi->avg_page_count = (xi->avg_page_count * 7 + page_count * 128) / 8;
   4.176 +    }
   4.177 +    if (packet_count >= MAX_PACKETS_PER_INTERRUPT)
   4.178 +      break;
   4.179      more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
   4.180      if (!more_to_do)
   4.181      {
   4.182        if (xi->config_rx_interrupt_moderation)
   4.183 -        xi->rx.sring->rsp_event = xi->rx.rsp_cons + min(max(1, page_count >> 1), 64);
   4.184 +        event = min(max(1, xi->avg_page_count * 3 / 4 / 128), 128);
   4.185        else
   4.186 -        xi->rx.sring->rsp_event = xi->rx.rsp_cons + 1;
   4.187 +        event = 1;
   4.188 +      xi->rx.sring->rsp_event = xi->rx.rsp_cons + event;
   4.189        mb();
   4.190        more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
   4.191      }
   4.192 -    //RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, more_to_do);
   4.193    } while (more_to_do);
   4.194  
   4.195    if (xi->rxpi.more_frags || xi->rxpi.extra_info)
   4.196 @@ -619,20 +689,26 @@ XenNet_RxBufferCheck(struct xennet_info 
   4.197    /* Give netback more buffers */
   4.198    XenNet_RxBufferAlloc(xi);
   4.199  
   4.200 +  //KdPrint((__DRIVER_NAME "     packet_count = %d, page_count = %d, avg_page_count = %d, event = %d\n", packet_count, page_count, xi->avg_page_count / 128, event));
   4.201 +
   4.202 +  if (packet_count >= MAX_PACKETS_PER_INTERRUPT)
   4.203 +  {
   4.204 +    /* fire again immediately */
   4.205 +    sync_context_t sc;
   4.206 +    sc.xi = xi;
   4.207 +    sc.is_timer = FALSE;
   4.208 +#pragma warning(suppress:4054) /* no way around this... */
   4.209 +    NdisMSynchronizeWithInterrupt(&xi->interrupt, (PVOID)XenNet_RxQueueDpcSynchronized, &sc);
   4.210 +  }
   4.211 +  else if (xi->config_rx_interrupt_moderation)
   4.212 +  {
   4.213 +    if (event > 1)
   4.214 +    {
   4.215 +      set_timer = TRUE;
   4.216 +    }
   4.217 +  }
   4.218    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   4.219  
   4.220 -  if (xi->config_rx_interrupt_moderation)
   4.221 -  {
   4.222 -    if (page_count >> 1)
   4.223 -    {
   4.224 -      NdisMSetTimer(&xi->rx_timer, 1);
   4.225 -    }
   4.226 -    else
   4.227 -    {
   4.228 -      BOOLEAN cancelled;
   4.229 -      NdisMCancelTimer(&xi->rx_timer, &cancelled);
   4.230 -    }
   4.231 -  }
   4.232    entry = RemoveHeadList(&rx_packet_list);
   4.233    packet_count = 0;
   4.234    while (entry != &rx_packet_list)
   4.235 @@ -651,7 +727,14 @@ XenNet_RxBufferCheck(struct xennet_info 
   4.236        packet_count = 0;
   4.237      }
   4.238    }
   4.239 -  return NDIS_STATUS_SUCCESS;
   4.240 +  /* set the timer after we have indicated the packets, as indicating can take a significant amount of time */
   4.241 +  if (set_timer)
   4.242 +  {
   4.243 +    LARGE_INTEGER due_time;
   4.244 +    due_time.QuadPart = -30 * 1000 * 10; /* 30ms */
   4.245 +    KeSetTimer(&xi->rx_timer, due_time, &xi->rx_timer_dpc);
   4.246 +  }
   4.247 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.248  }
   4.249  
   4.250  /* called at DISPATCH_LEVEL */
   4.251 @@ -681,7 +764,7 @@ XenNet_ReturnPacket(
   4.252      KeSetEvent(&xi->packet_returned_event, IO_NO_INCREMENT, FALSE);
   4.253  
   4.254    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   4.255 -  
   4.256 +
   4.257  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.258  }
   4.259  
   4.260 @@ -743,6 +826,7 @@ XenNet_RxResumeEnd(xennet_info_t *xi)
   4.261    KeReleaseSpinLock(&xi->rx_lock, old_irql);
   4.262  }
   4.263  
   4.264 +#if 0
   4.265  /* Called at DISPATCH LEVEL */
   4.266  static VOID DDKAPI
   4.267  XenNet_RxTimer(
   4.268 @@ -760,9 +844,11 @@ XenNet_RxTimer(
   4.269  
   4.270    if (xi->connected && !xi->inactive && xi->device_state->resume_state == RESUME_STATE_RUNNING)
   4.271    {
   4.272 -    XenNet_RxBufferCheck(xi);
   4.273 -  }  
   4.274 +    KdPrint((__DRIVER_NAME "     RX Timer\n"));
   4.275 +    XenNet_RxBufferCheck(xi, TRUE);
   4.276 +  }
   4.277  }
   4.278 +#endif
   4.279  
   4.280  BOOLEAN
   4.281  XenNet_RxInit(xennet_info_t *xi)
   4.282 @@ -772,7 +858,13 @@ XenNet_RxInit(xennet_info_t *xi)
   4.283    FUNCTION_ENTER();
   4.284  
   4.285    KeInitializeEvent(&xi->packet_returned_event, SynchronizationEvent, FALSE);
   4.286 -  NdisMInitializeTimer(&xi->rx_timer, xi->adapter_handle, XenNet_RxTimer, xi);
   4.287 +  KeInitializeTimer(&xi->rx_timer);
   4.288 +  KeInitializeDpc(&xi->rx_dpc, XenNet_RxBufferCheck, xi);
   4.289 +  KeSetTargetProcessorDpc(&xi->rx_dpc, 0);
   4.290 +  //KeSetImportanceDpc(&xi->rx_dpc, HighImportance);
   4.291 +  KeInitializeDpc(&xi->rx_timer_dpc, XenNet_RxTimerDpc, xi);
   4.292 +  //NdisMInitializeTimer(&xi->rx_timer, xi->adapter_handle, XenNet_RxTimer, xi);
   4.293 +  xi->avg_page_count = 0;
   4.294  
   4.295    xi->rx_shutting_down = FALSE;
   4.296    
   4.297 @@ -806,8 +898,7 @@ XenNet_RxShutdown(xennet_info_t *xi)
   4.298  
   4.299    if (xi->config_rx_interrupt_moderation)
   4.300    {
   4.301 -    BOOLEAN cancelled;
   4.302 -    NdisMCancelTimer(&xi->rx_timer, &cancelled);
   4.303 +    KeCancelTimer(&xi->rx_timer);
   4.304    }
   4.305  
   4.306    while (xi->rx_outstanding)
     5.1 --- a/xennet/xennet_tx.c	Sat Nov 15 14:31:22 2008 +1100
     5.2 +++ b/xennet/xennet_tx.c	Tue Nov 18 20:46:47 2008 +1100
     5.3 @@ -407,12 +407,19 @@ XenNet_ReturnSentPackets(struct xennet_i
     5.4  }
     5.5  
     5.6  // Called at DISPATCH_LEVEL
     5.7 -NDIS_STATUS
     5.8 -XenNet_TxBufferGC(struct xennet_info *xi)
     5.9 +//NDIS_STATUS
    5.10 +//XenNet_TxBufferGC(struct xennet_info *xi)
    5.11 +VOID
    5.12 +XenNet_TxBufferGC(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
    5.13  {
    5.14 +  struct xennet_info *xi = context;
    5.15    RING_IDX cons, prod;
    5.16    unsigned short id;
    5.17  
    5.18 +  UNREFERENCED_PARAMETER(dpc);
    5.19 +  UNREFERENCED_PARAMETER(arg1);
    5.20 +  UNREFERENCED_PARAMETER(arg2);
    5.21 +
    5.22    ASSERT(xi->connected);
    5.23    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
    5.24  
    5.25 @@ -457,8 +464,6 @@ XenNet_TxBufferGC(struct xennet_info *xi
    5.26    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
    5.27  
    5.28    XenNet_ReturnSentPackets(xi);
    5.29 -
    5.30 -  return NDIS_STATUS_SUCCESS;
    5.31  }
    5.32  
    5.33  // called at <= DISPATCH_LEVEL
    5.34 @@ -538,6 +543,9 @@ XenNet_TxInit(xennet_info_t *xi)
    5.35    USHORT i;
    5.36  
    5.37    KeInitializeSpinLock(&xi->tx_lock);
    5.38 +  KeInitializeDpc(&xi->tx_dpc, XenNet_TxBufferGC, xi);
    5.39 +  /* dpcs are only serialised to a single processor */
    5.40 +  KeSetTargetProcessorDpc(&xi->tx_dpc, 0);
    5.41  
    5.42    xi->tx_id_free = 0;
    5.43    xi->tx_no_id_used = 0;