win-pvdrivers

changeset 422:9b7614f440b1

Updated save/restore code to work again after the change to IRQ routing.
Attempts at network rx performance improvements.
author James Harper <james.harper@bendigoit.com.au>
date Tue Aug 26 15:06:03 2008 +1000 (2008-08-26)
parents dcfc2f91a501
children 718d4567551d
files xennet/xennet.c xennet/xennet.h xennet/xennet_common.c xennet/xennet_rx.c xennet/xennet_tx.c xenpci/evtchn.c xenpci/xenpci.h xenpci/xenpci_pdo.c xenvbd/xenvbd.c
line diff
     1.1 --- a/xennet/xennet.c	Thu Aug 21 14:19:03 2008 +1000
     1.2 +++ b/xennet/xennet.c	Tue Aug 26 15:06:03 2008 +1000
     1.3 @@ -143,32 +143,6 @@ XenNet_InterruptIsr(
     1.4    //FUNCTION_EXIT();
     1.5  }
     1.6  
     1.7 -static DDKAPI VOID
     1.8 -XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
     1.9 -{
    1.10 -  struct xennet_info *xi = MiniportAdapterContext;
    1.11 -
    1.12 -  if (xi->device_state->resume_state != RESUME_STATE_RUNNING)
    1.13 -  {
    1.14 -    KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
    1.15 -    // there should be a better way to synchronise with rx and tx...
    1.16 -    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    1.17 -    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    1.18 -    KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
    1.19 -    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
    1.20 -    xi->device_state->resume_state_ack = xi->device_state->resume_state;
    1.21 -    return;
    1.22 -  }
    1.23 -
    1.24 -  //FUNCTION_ENTER();
    1.25 -  if (xi->connected)
    1.26 -  {
    1.27 -    XenNet_TxBufferGC(xi);
    1.28 -    XenNet_RxBufferCheck(xi);
    1.29 -  }
    1.30 -  //FUNCTION_EXIT();
    1.31 -}
    1.32 -
    1.33  static NDIS_STATUS
    1.34  XenNet_ConnectBackend(struct xennet_info *xi)
    1.35  {
    1.36 @@ -260,31 +234,47 @@ XenNet_Resume(PDEVICE_OBJECT device_obje
    1.37    xi->device_state->resume_state = RESUME_STATE_RUNNING;
    1.38    XenNet_RxResumeEnd(xi);
    1.39    XenNet_TxResumeEnd(xi);
    1.40 -  NdisMSetPeriodicTimer(&xi->resume_timer, 100);
    1.41  }
    1.42  
    1.43 -static DDKAPI VOID 
    1.44 -XenResumeCheck_Timer(
    1.45 - PVOID SystemSpecific1,
    1.46 - PVOID FunctionContext,
    1.47 - PVOID SystemSpecific2,
    1.48 - PVOID SystemSpecific3
    1.49 -)
    1.50 +static DDKAPI VOID
    1.51 +XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
    1.52  {
    1.53 -  struct xennet_info *xi = FunctionContext;
    1.54 +  struct xennet_info *xi = MiniportAdapterContext;
    1.55    PIO_WORKITEM work_item;
    1.56 -  BOOLEAN timer_cancelled;
    1.57 - 
    1.58 -  UNREFERENCED_PARAMETER(SystemSpecific1);
    1.59 -  UNREFERENCED_PARAMETER(SystemSpecific2);
    1.60 -  UNREFERENCED_PARAMETER(SystemSpecific3);
    1.61 - 
    1.62 -  if (xi->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
    1.63 +
    1.64 +  //FUNCTION_ENTER();
    1.65 +  if (xi->device_state->resume_state != xi->device_state->resume_state_ack)
    1.66    {
    1.67 -    NdisMCancelTimer(&xi->resume_timer, &timer_cancelled);
    1.68 -  	work_item = IoAllocateWorkItem(xi->fdo);
    1.69 -  	IoQueueWorkItem(work_item, XenNet_Resume, DelayedWorkQueue, xi);
    1.70 +    FUNCTION_ENTER();
    1.71 +    switch (xi->device_state->resume_state)
    1.72 +    {
    1.73 +    case RESUME_STATE_SUSPENDING:
    1.74 +      KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
    1.75 +      // there should be a better way to synchronise with rx and tx...
    1.76 +      KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    1.77 +      KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    1.78 +      KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
    1.79 +      KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
    1.80 +      break;
    1.81 +    case RESUME_STATE_FRONTEND_RESUME:
    1.82 +      KdPrint((__DRIVER_NAME "     New state RESUME_STATE_FRONTEND_RESUME\n"));
    1.83 +      work_item = IoAllocateWorkItem(xi->fdo);
    1.84 +      IoQueueWorkItem(work_item, XenNet_Resume, DelayedWorkQueue, xi);
    1.85 +      break;
    1.86 +    default:
    1.87 +      KdPrint((__DRIVER_NAME "     New state %d\n", xi->device_state->resume_state));
    1.88 +      break;
    1.89 +    }
    1.90 +    xi->device_state->resume_state_ack = xi->device_state->resume_state;
    1.91 +    KeMemoryBarrier();
    1.92 +    FUNCTION_EXIT();
    1.93    }
    1.94 +  if (xi->connected && xi->device_state->resume_state == RESUME_STATE_RUNNING)
    1.95 +  {
    1.96 +    XenNet_TxBufferGC(xi);
    1.97 +    XenNet_RxBufferCheck(xi);
    1.98 +  }
    1.99 +  //FUNCTION_EXIT();
   1.100  }
   1.101  
   1.102  // Called at <= DISPATCH_LEVEL
   1.103 @@ -599,9 +589,6 @@ XenNet_Init(
   1.104  
   1.105    /* send fake arp? */
   1.106  
   1.107 -  NdisMInitializeTimer(&xi->resume_timer, xi->adapter_handle, XenResumeCheck_Timer, xi);
   1.108 -  NdisMSetPeriodicTimer(&xi->resume_timer, 100);
   1.109 -
   1.110    FUNCTION_EXIT();
   1.111  
   1.112    return NDIS_STATUS_SUCCESS;
   1.113 @@ -648,7 +635,6 @@ XenNet_Halt(
   1.114    )
   1.115  {
   1.116    struct xennet_info *xi = MiniportAdapterContext;
   1.117 -  BOOLEAN timer_cancelled;
   1.118  
   1.119    FUNCTION_ENTER();
   1.120    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.121 @@ -663,8 +649,6 @@ XenNet_Halt(
   1.122  
   1.123    // TODO: remove event channel xenbus entry (how?)
   1.124  
   1.125 -  NdisMCancelTimer(&xi->resume_timer, &timer_cancelled);
   1.126 -
   1.127    XenNet_TxShutdown(xi);
   1.128    XenNet_RxShutdown(xi);
   1.129  
     2.1 --- a/xennet/xennet.h	Thu Aug 21 14:19:03 2008 +1000
     2.2 +++ b/xennet/xennet.h	Tue Aug 26 15:06:03 2008 +1000
     2.3 @@ -69,14 +69,59 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  
     2.5  #define ETH_ALEN 6
     2.6  
     2.7 +/*
     2.8  #define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
     2.9  #define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
    2.10  
    2.11  #define GET_NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    2.12  #define SET_NET_USHORT(y, x) *((USHORT *)&(y)) = ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    2.13 +*/
    2.14  
    2.15 +static FORCEINLINE USHORT
    2.16 +GET_NET_USHORT(USHORT data)
    2.17 +{
    2.18 +  return (data << 8) | (data >> 8);
    2.19 +}
    2.20 +
    2.21 +static FORCEINLINE USHORT
    2.22 +GET_NET_PUSHORT(PVOID pdata)
    2.23 +{
    2.24 +  return (*((PUSHORT)pdata) << 8) | (*((PUSHORT)pdata) >> 8);
    2.25 +}
    2.26 +
    2.27 +static FORCEINLINE VOID
    2.28 +SET_NET_USHORT(PVOID ptr, USHORT data)
    2.29 +{
    2.30 +  *((PUSHORT)ptr) = GET_NET_USHORT(data);
    2.31 +}
    2.32 +
    2.33 +static FORCEINLINE ULONG
    2.34 +GET_NET_ULONG(ULONG data)
    2.35 +{
    2.36 +  ULONG tmp;
    2.37 +  
    2.38 +  tmp = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
    2.39 +  return (tmp << 16) | (tmp >> 16);
    2.40 +}
    2.41 +
    2.42 +static FORCEINLINE ULONG
    2.43 +GET_NET_PULONG(PVOID pdata)
    2.44 +{
    2.45 +  ULONG tmp;
    2.46 +  
    2.47 +  tmp = ((*((PULONG)pdata) & 0x00ff00ff) << 8) | ((*((PULONG)pdata) & 0xff00ff00) >> 8);
    2.48 +  return (tmp << 16) | (tmp >> 16);
    2.49 +}
    2.50 +
    2.51 +static FORCEINLINE VOID
    2.52 +SET_NET_ULONG(PVOID ptr, ULONG data)
    2.53 +{
    2.54 +  *((PULONG)ptr) = GET_NET_ULONG(data);
    2.55 +}
    2.56 +/*
    2.57  #define GET_NET_ULONG(x) ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
    2.58  #define SET_NET_ULONG(y, x) *((ULONG *)&(y)) = ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
    2.59 +*/
    2.60  
    2.61  #define SUPPORTED_PACKET_FILTERS (\
    2.62    NDIS_PACKET_TYPE_DIRECTED | \
    2.63 @@ -232,7 +277,7 @@ struct xennet_info
    2.64    /* config stuff calculated from the above */
    2.65    ULONG config_max_pkt_size;
    2.66  
    2.67 -  NDIS_MINIPORT_TIMER resume_timer;
    2.68 +  //NDIS_MINIPORT_TIMER resume_timer;
    2.69  
    2.70    /* stats */
    2.71    ULONG64 stat_tx_ok;
     3.1 --- a/xennet/xennet_common.c	Thu Aug 21 14:19:03 2008 +1000
     3.2 +++ b/xennet/xennet_common.c	Tue Aug 26 15:06:03 2008 +1000
     3.3 @@ -43,7 +43,7 @@ XenNet_ParsePacketHeader(
     3.4      return PARSE_TOO_SMALL;
     3.5    }
     3.6    
     3.7 -  switch (GET_NET_USHORT(pi->header[12])) // L2 protocol field
     3.8 +  switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
     3.9    {
    3.10    case 0x0800:
    3.11      pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
    3.12 @@ -73,7 +73,7 @@ XenNet_ParsePacketHeader(
    3.13    default:
    3.14      return PARSE_UNKNOWN_TYPE;
    3.15    }
    3.16 -  pi->ip4_length = GET_NET_USHORT(pi->header[XN_HDR_SIZE + 2]);
    3.17 +  pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
    3.18    pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
    3.19  
    3.20    if (header_length < (ULONG)(pi->ip4_header_length + pi->tcp_header_length))
    3.21 @@ -84,7 +84,7 @@ XenNet_ParsePacketHeader(
    3.22  
    3.23    pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
    3.24    pi->tcp_remaining = pi->tcp_length;
    3.25 -  pi->tcp_seq = GET_NET_ULONG(pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
    3.26 +  pi->tcp_seq = GET_NET_PULONG(&pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
    3.27    if (pi->mss > 0 && pi->tcp_length > pi->mss)
    3.28      pi->split_required = TRUE;
    3.29  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.30 @@ -107,12 +107,12 @@ XenNet_SumIpHeader(
    3.31    header[XN_HDR_SIZE + 11] = 0;
    3.32    for (i = 0; i < ip4_header_length; i += 2)
    3.33    {
    3.34 -    csum += GET_NET_USHORT(header[XN_HDR_SIZE + i]);
    3.35 +    csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
    3.36    }
    3.37    while (csum & 0xFFFF0000)
    3.38      csum = (csum & 0xFFFF) + (csum >> 16);
    3.39    csum = ~csum;
    3.40 -  SET_NET_USHORT(header[XN_HDR_SIZE + 10], csum);
    3.41 +  SET_NET_USHORT(&header[XN_HDR_SIZE + 10], (USHORT)csum);
    3.42  }
    3.43  
    3.44  PUCHAR
     4.1 --- a/xennet/xennet_rx.c	Thu Aug 21 14:19:03 2008 +1000
     4.2 +++ b/xennet/xennet_rx.c	Tue Aug 26 15:06:03 2008 +1000
     4.3 @@ -174,8 +174,8 @@ XenNet_MakePacket(struct xennet_info *xi
     4.4      NdisAdjustBufferLength(out_mdl, out_offset + out_remaining);
     4.5      memcpy(out_buffer, xi->rxpi.header, out_offset);
     4.6      new_ip4_length = out_remaining + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
     4.7 -    SET_NET_USHORT(out_buffer[XN_HDR_SIZE + 2], new_ip4_length);
     4.8 -    SET_NET_ULONG(out_buffer[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 4], xi->rxpi.tcp_seq);
     4.9 +    SET_NET_USHORT(&out_buffer[XN_HDR_SIZE + 2], new_ip4_length);
    4.10 +    SET_NET_ULONG(&out_buffer[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 4], xi->rxpi.tcp_seq);
    4.11      xi->rxpi.tcp_seq += out_remaining;
    4.12      xi->rxpi.tcp_remaining = xi->rxpi.tcp_remaining - out_remaining;
    4.13      do 
    4.14 @@ -223,7 +223,7 @@ XenNet_SumPacketData(
    4.15    NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
    4.16    ASSERT(mdl);
    4.17  
    4.18 -  ip4_length = GET_NET_USHORT(buffer[XN_HDR_SIZE + 2]);
    4.19 +  ip4_length = GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 2]);
    4.20  
    4.21    if ((USHORT)(ip4_length + XN_HDR_SIZE) != total_length)
    4.22    {
    4.23 @@ -246,8 +246,8 @@ XenNet_SumPacketData(
    4.24    *csum_ptr = 0;
    4.25  
    4.26    csum = 0;
    4.27 -  csum += GET_NET_USHORT(buffer[XN_HDR_SIZE + 12]) + GET_NET_USHORT(buffer[XN_HDR_SIZE + 14]); // src
    4.28 -  csum += GET_NET_USHORT(buffer[XN_HDR_SIZE + 16]) + GET_NET_USHORT(buffer[XN_HDR_SIZE + 18]); // dst
    4.29 +  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 12]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 14]); // src
    4.30 +  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 16]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 18]); // dst
    4.31    csum += ((USHORT)buffer[XN_HDR_SIZE + 9]);
    4.32  
    4.33    remaining = ip4_length - pi->ip4_header_length;
    4.34 @@ -283,7 +283,7 @@ XenNet_SumPacketData(
    4.35          NdisQueryBufferSafe(mdl, (PVOID) &buffer, &buffer_length, NormalPagePriority);
    4.36          buffer_offset = 0;
    4.37        }
    4.38 -      csum += GET_NET_USHORT(buffer[buffer_offset]);
    4.39 +      csum += GET_NET_PUSHORT(&buffer[buffer_offset]);
    4.40      }
    4.41    }
    4.42    if (i != total_length) // last odd byte
    4.43 @@ -292,7 +292,7 @@ XenNet_SumPacketData(
    4.44    }
    4.45    while (csum & 0xFFFF0000)
    4.46      csum = (csum & 0xFFFF) + (csum >> 16);
    4.47 -  *csum_ptr = (USHORT)~GET_NET_USHORT(csum);
    4.48 +  *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
    4.49  
    4.50  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    4.51  }
    4.52 @@ -404,7 +404,7 @@ done:
    4.53    return packet_count;
    4.54  }
    4.55  
    4.56 -#define MAXIMUM_PACKETS_PER_INDICATE 32
    4.57 +#define MAXIMUM_PACKETS_PER_INDICATE 256
    4.58  
    4.59  // Called at DISPATCH_LEVEL
    4.60  NDIS_STATUS
    4.61 @@ -427,11 +427,10 @@ XenNet_RxBufferCheck(struct xennet_info 
    4.62    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    4.63  
    4.64    InitializeListHead(&rx_packet_list);
    4.65 -  //KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " xi->rx.sring->rsp_prod = %d, xi->rx.rsp_cons = %d\n", xi->rx.sring->rsp_prod, xi->rx.rsp_cons));
    4.66  
    4.67    do {
    4.68      prod = xi->rx.sring->rsp_prod;
    4.69 -    KeMemoryBarrier(); /* Ensure we see responses up to 'prop'. */
    4.70 +    KeMemoryBarrier(); /* Ensure we see responses up to 'prod'. */
    4.71  
    4.72      for (cons = xi->rx.rsp_cons; cons != prod; cons++)
    4.73      {
    4.74 @@ -500,7 +499,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    4.75      xi->rx.rsp_cons = cons;
    4.76      if (!RING_HAS_UNCONSUMED_RESPONSES(&xi->rx))
    4.77      {
    4.78 -      xi->rx.sring->rsp_event = cons + 1; //new_ring_buffer_size + 1;
    4.79 +      xi->rx.sring->rsp_event = cons + 1;
    4.80        KeMemoryBarrier();
    4.81      }
    4.82    } while (RING_HAS_UNCONSUMED_RESPONSES(&xi->rx));
     5.1 --- a/xennet/xennet_tx.c	Thu Aug 21 14:19:03 2008 +1000
     5.2 +++ b/xennet/xennet_tx.c	Tue Aug 26 15:06:03 2008 +1000
     5.3 @@ -402,7 +402,6 @@ XenNet_TxResumeStart(xennet_info_t *xi)
     5.4  {
     5.5    int i;
     5.6    KIRQL old_irql;
     5.7 -//  PLIST_ENTRY entry;
     5.8  
     5.9    KeAcquireSpinLock(&xi->tx_lock, &old_irql);
    5.10    for (i = 0; i < NET_TX_RING_SIZE; i++)
    5.11 @@ -413,16 +412,6 @@ XenNet_TxResumeStart(xennet_info_t *xi)
    5.12        XenFreelist_PutPage(&xi->tx_freelist, xi->tx_mdls[i]);
    5.13        xi->tx_mdls[i] = NULL;
    5.14      }
    5.15 -#if 0
    5.16 -    /* this may result in packets being sent out of order... I don't think it matters though */
    5.17 -    if (xi->tx_pkts[i])
    5.18 -    {
    5.19 -      *(ULONG *)&xi->tx_pkts[i]->MiniportReservedEx = 0;
    5.20 -      entry = (PLIST_ENTRY)&xi->tx_pkts[i]->MiniportReservedEx[sizeof(PVOID)];
    5.21 -      InsertTailList(&xi->tx_waiting_pkt_list, entry);
    5.22 -      xi->tx_pkts[i] = 0;
    5.23 -    }
    5.24 -#endif
    5.25    }
    5.26    XenFreelist_ResumeStart(&xi->tx_freelist);
    5.27    xi->tx_id_free = 0;
    5.28 @@ -496,11 +485,6 @@ XenNet_TxShutdown(xennet_info_t *xi)
    5.29    /* free sent-but-not-completed packets */
    5.30    for (i = 0; i < NET_TX_RING_SIZE; i++)
    5.31    {
    5.32 -/*  
    5.33 -    packet = xi->tx_pkts[i];
    5.34 -    if (packet)
    5.35 -      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
    5.36 -*/
    5.37      mdl = xi->tx_mdls[i];
    5.38      if (mdl)
    5.39      {
     6.1 --- a/xenpci/evtchn.c	Thu Aug 21 14:19:03 2008 +1000
     6.2 +++ b/xenpci/evtchn.c	Tue Aug 26 15:06:03 2008 +1000
     6.3 @@ -45,12 +45,7 @@ EvtChn_DpcBounce(PRKDPC Dpc, PVOID Conte
     6.4  
     6.5    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
     6.6  
     6.7 -  if (action->type == EVT_ACTION_TYPE_IRQ)
     6.8 -  {
     6.9 -    //KdPrint((__DRIVER_NAME "     Calling interrupt vector %02x\n", action->vector));
    6.10 -    sw_interrupt((UCHAR)action->vector);
    6.11 -  }
    6.12 -  else
    6.13 +  if (action->type == EVT_ACTION_TYPE_DPC)
    6.14    {
    6.15      action->ServiceRoutine(NULL, action->ServiceContext);
    6.16    }
    6.17 @@ -97,6 +92,7 @@ to CPU != 0, but we should always use vc
    6.18    ev_action_t *ev_action;
    6.19    BOOLEAN handled = FALSE;
    6.20    BOOLEAN deferred = FALSE;
    6.21 +  int i;
    6.22  
    6.23    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (cpu = %d)\n", cpu));
    6.24  
    6.25 @@ -136,15 +132,26 @@ to CPU != 0, but we should always use vc
    6.26        case EVT_ACTION_TYPE_IRQ:
    6.27          synch_clear_bit(evt_bit, (volatile xen_long_t *)&shared_info_area->evtchn_pending[evt_word]);
    6.28          synch_set_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[evt_word]);
    6.29 -        //KdPrint((__DRIVER_NAME "     deferred %d\n", port));
    6.30 -        /* this is now handled by one of the next Isr's */
    6.31 -        //sw_interrupt((UCHAR)ev_action->vector);
    6.32          deferred = TRUE;
    6.33          break;
    6.34        case EVT_ACTION_TYPE_DPC:
    6.35          synch_clear_bit(evt_bit, (volatile xen_long_t *)&shared_info_area->evtchn_pending[evt_word]);
    6.36          KeInsertQueueDpc(&ev_action->Dpc, NULL, NULL);
    6.37          break;
    6.38 +      case EVT_ACTION_TYPE_SUSPEND:
    6.39 +        synch_clear_bit(evt_bit, (volatile xen_long_t *)&shared_info_area->evtchn_pending[evt_word]);
    6.40 +        KdPrint((__DRIVER_NAME "     EVT_ACTION_TYPE_SUSPEND\n"));
    6.41 +        for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt); i++)
    6.42 +        {
    6.43 +          if (xpdd->ev_actions[i].type == EVT_ACTION_TYPE_IRQ)
    6.44 +          {
    6.45 +            int suspend_bit = i & ((sizeof(xen_ulong_t) * 8) - 1);
    6.46 +            int suspend_word = i >> (5 + (sizeof(xen_ulong_t) >> 3));
    6.47 +            synch_set_bit(suspend_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[suspend_word]);
    6.48 +          }
    6.49 +        }
    6.50 +        deferred = TRUE;
    6.51 +        break;
    6.52        default:
    6.53          synch_clear_bit(evt_bit, (volatile xen_long_t *)&shared_info_area->evtchn_pending[evt_word]);
    6.54          KdPrint((__DRIVER_NAME "     Unhandled Event!!!\n"));
    6.55 @@ -289,6 +296,20 @@ EvtChn_Notify(PVOID Context, evtchn_port
    6.56  }
    6.57  
    6.58  evtchn_port_t
    6.59 +EvtChn_BindIpi(PVOID context, ULONG vcpu)
    6.60 +{
    6.61 +  PXENPCI_DEVICE_DATA xpdd = context;
    6.62 +  evtchn_bind_ipi_t op;
    6.63 +  
    6.64 +  FUNCTION_ENTER();
    6.65 +  op.vcpu = vcpu;
    6.66 +  op.port = 0;
    6.67 +  HYPERVISOR_event_channel_op(xpdd, EVTCHNOP_bind_ipi, &op);
    6.68 +  FUNCTION_EXIT();
    6.69 +  return op.port;
    6.70 +}
    6.71 +
    6.72 +evtchn_port_t
    6.73  EvtChn_AllocUnbound(PVOID Context, domid_t Domain)
    6.74  {
    6.75    PXENPCI_DEVICE_DATA xpdd = Context;
    6.76 @@ -344,7 +365,12 @@ EvtChn_Init(PXENPCI_DEVICE_DATA xpdd)
    6.77    xpdd->interrupts_masked = FALSE;
    6.78    KeMemoryBarrier();
    6.79  
    6.80 +  xpdd->suspend_evtchn = EvtChn_BindIpi(xpdd, 0);
    6.81 +  xpdd->ev_actions[xpdd->suspend_evtchn].type = EVT_ACTION_TYPE_SUSPEND;
    6.82 +  EvtChn_Unmask(xpdd, xpdd->suspend_evtchn);
    6.83    
    6.84 +  KdPrint((__DRIVER_NAME "     suspend_evtchn = %d\n", xpdd->suspend_evtchn));
    6.85 +
    6.86    FUNCTION_EXIT();
    6.87    
    6.88    return STATUS_SUCCESS;
     7.1 --- a/xenpci/xenpci.h	Thu Aug 21 14:19:03 2008 +1000
     7.2 +++ b/xenpci/xenpci.h	Tue Aug 26 15:06:03 2008 +1000
     7.3 @@ -62,10 +62,11 @@ DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC82
     7.4  
     7.5  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
     7.6  
     7.7 -#define EVT_ACTION_TYPE_EMPTY  0
     7.8 -#define EVT_ACTION_TYPE_NORMAL 1
     7.9 -#define EVT_ACTION_TYPE_DPC    2
    7.10 -#define EVT_ACTION_TYPE_IRQ    3
    7.11 +#define EVT_ACTION_TYPE_EMPTY   0
    7.12 +#define EVT_ACTION_TYPE_NORMAL  1
    7.13 +#define EVT_ACTION_TYPE_DPC     2
    7.14 +#define EVT_ACTION_TYPE_IRQ     3
    7.15 +#define EVT_ACTION_TYPE_SUSPEND 4
    7.16  
    7.17  typedef struct _ev_action_t {
    7.18    PKSERVICE_ROUTINE ServiceRoutine;
    7.19 @@ -178,6 +179,8 @@ typedef struct {
    7.20    PHYSICAL_ADDRESS shared_info_area_unmapped;
    7.21    shared_info_t *shared_info_area;
    7.22    xen_ulong_t evtchn_pending_pvt[sizeof(xen_ulong_t) * 8];
    7.23 +  xen_ulong_t evtchn_pending_suspend[sizeof(xen_ulong_t) * 8];
    7.24 +  evtchn_port_t suspend_evtchn;
    7.25    BOOLEAN interrupts_masked;
    7.26  
    7.27    PHYSICAL_ADDRESS platform_mmio_addr;
    7.28 @@ -278,6 +281,7 @@ typedef struct
    7.29  #define SWINT(x) if (intno == x) { __asm { int x } return; }
    7.30  #endif
    7.31  
    7.32 +#if 0
    7.33  #if defined(_X86_)
    7.34  static __inline VOID
    7.35  sw_interrupt(UCHAR intno)
    7.36 @@ -327,7 +331,7 @@ sw_interrupt(UCHAR intno)
    7.37    _sw_interrupt(intno);
    7.38  }
    7.39  #endif
    7.40 -
    7.41 +#endif
    7.42    
    7.43  #include "hypercall.h"
    7.44  
    7.45 @@ -439,6 +443,8 @@ NTSTATUS
    7.46  EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext);
    7.47  NTSTATUS
    7.48  EvtChn_BindIrq(PVOID Context, evtchn_port_t Port, ULONG vector, PCHAR description);
    7.49 +evtchn_port_t
    7.50 +EvtChn_BindIpi(PVOID context, ULONG vcpu);
    7.51  NTSTATUS
    7.52  EvtChn_Unbind(PVOID Context, evtchn_port_t Port);
    7.53  NTSTATUS
     8.1 --- a/xenpci/xenpci_pdo.c	Thu Aug 21 14:19:03 2008 +1000
     8.2 +++ b/xenpci/xenpci_pdo.c	Tue Aug 26 15:06:03 2008 +1000
     8.3 @@ -697,13 +697,7 @@ XenPci_Pdo_Resume(PDEVICE_OBJECT device_
     8.4  {
     8.5    NTSTATUS status;
     8.6    PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
     8.7 -  //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
     8.8 -  //PUCHAR in_ptr;
     8.9 -  //UCHAR type;
    8.10 -  //PVOID setting;
    8.11 -  //PVOID value;
    8.12 -  //CHAR path[256];
    8.13 -  //PVOID address;
    8.14 +  PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
    8.15    ULONG old_backend_state;
    8.16    PUCHAR src, dst;
    8.17  
    8.18 @@ -711,7 +705,6 @@ XenPci_Pdo_Resume(PDEVICE_OBJECT device_
    8.19  
    8.20    old_backend_state = xppdd->backend_state;
    8.21  
    8.22 -  //if (xppdd->common.current_pnp_state == Started && old_backend_state == XenbusStateClosed)
    8.23    if (xppdd->restart_on_resume)
    8.24    {  
    8.25      status = XenPci_GetBackendAndAddWatch(device_object);
    8.26 @@ -752,6 +745,8 @@ XenPci_Pdo_Resume(PDEVICE_OBJECT device_
    8.27    }
    8.28    KeMemoryBarrier();
    8.29    xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
    8.30 +  KeMemoryBarrier();
    8.31 +  EvtChn_Notify(xpdd, xpdd->suspend_evtchn);  
    8.32  
    8.33    FUNCTION_EXIT();
    8.34  
    8.35 @@ -781,9 +776,7 @@ XenPci_Pdo_Suspend(PDEVICE_OBJECT device
    8.36      KeMemoryBarrier();
    8.37      xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
    8.38      KeMemoryBarrier();
    8.39 -    KdPrint((__DRIVER_NAME "     Calling interrupt\n"));
    8.40 -    sw_interrupt((UCHAR)xppdd->irq_vector);
    8.41 -    KdPrint((__DRIVER_NAME "     Back from interrupt call\n"));
    8.42 +    EvtChn_Notify(xpdd, xpdd->suspend_evtchn);    
    8.43      while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
    8.44      {
    8.45        KdPrint((__DRIVER_NAME "     Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
     9.1 --- a/xenvbd/xenvbd.c	Thu Aug 21 14:19:03 2008 +1000
     9.2 +++ b/xenvbd/xenvbd.c	Tue Aug 26 15:06:03 2008 +1000
     9.3 @@ -384,10 +384,8 @@ XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA 
     9.4    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
     9.5  }
     9.6  
     9.7 -#define RESUME_CHECK_TIMER_INTERVAL (100 * 1000)
     9.8 -
     9.9  static VOID
    9.10 -XenVbd_HwScsiTimer(PVOID DeviceExtension)
    9.11 +XenVbd_Resume(PVOID DeviceExtension)
    9.12  {
    9.13    PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
    9.14    ULONG i;
    9.15 @@ -395,41 +393,38 @@ XenVbd_HwScsiTimer(PVOID DeviceExtension
    9.16    ULONG shadow_entries;
    9.17    blkif_shadow_t *shadow;  
    9.18  
    9.19 -  if (xvdd->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
    9.20 +  FUNCTION_ENTER();
    9.21 +  KdPrint((__DRIVER_NAME "     found device in resume state\n"));
    9.22 +  FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
    9.23 +  // re-submit srb's
    9.24 +  
    9.25 +  shadow_entries = 0;
    9.26 +  for (i = 0; i < SHADOW_ENTRIES; i++)
    9.27    {
    9.28 -    KdPrint((__DRIVER_NAME "     found device in resume state\n"));
    9.29 -    FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
    9.30 -    // re-submit srb's
    9.31 -    
    9.32 -    shadow_entries = 0;
    9.33 -    for (i = 0; i < SHADOW_ENTRIES; i++)
    9.34 +    shadow = &xvdd->shadows[i];
    9.35 +    if (shadow->srb)
    9.36      {
    9.37 -      shadow = &xvdd->shadows[i];
    9.38 -      if (shadow->srb)
    9.39 -      {
    9.40 -        shadows[shadow_entries++] = xvdd->shadows[i];
    9.41 -        shadow->srb = NULL;
    9.42 -      }
    9.43 -    }
    9.44 -
    9.45 -    XenVbd_InitFromConfig(xvdd);
    9.46 -    
    9.47 -    for (i = 0; i < shadow_entries; i++)
    9.48 -    {
    9.49 -      shadow = &shadows[i];
    9.50 -      XenVbd_PutSrbOnRing(xvdd, shadow->srb, shadow->offset);
    9.51 -    }
    9.52 -    
    9.53 -    xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
    9.54 -    
    9.55 -    if (i == 0)
    9.56 -    {
    9.57 -      /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
    9.58 -      ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
    9.59 +      shadows[shadow_entries++] = xvdd->shadows[i];
    9.60 +      shadow->srb = NULL;
    9.61      }
    9.62    }
    9.63 +
    9.64 +  XenVbd_InitFromConfig(xvdd);
    9.65    
    9.66 -  ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
    9.67 +  for (i = 0; i < shadow_entries; i++)
    9.68 +  {
    9.69 +    shadow = &shadows[i];
    9.70 +    XenVbd_PutSrbOnRing(xvdd, shadow->srb, shadow->offset);
    9.71 +  }
    9.72 +  
    9.73 +  xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
    9.74 +  
    9.75 +  if (i == 0)
    9.76 +  {
    9.77 +    /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
    9.78 +    ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
    9.79 +  }
    9.80 +  FUNCTION_EXIT();
    9.81  }
    9.82  
    9.83  static ULONG DDKAPI
    9.84 @@ -547,8 +542,6 @@ XenVbd_HwScsiInitialize(PVOID DeviceExte
    9.85    if (notify)
    9.86      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
    9.87  
    9.88 -  ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
    9.89 -
    9.90    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    9.91  
    9.92    return TRUE;
    9.93 @@ -688,16 +681,35 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
    9.94    blkif_shadow_t *shadow;
    9.95    ULONG offset;
    9.96  
    9.97 -  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    9.98 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ bac"\n"));
    9.99  
   9.100    /* in dump mode I think we get called on a timer, not by an actual IRQ */
   9.101    if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
   9.102      return FALSE; /* interrupt was not for us */
   9.103 +
   9.104 +  if (xvdd->device_state->resume_state != xvdd->device_state->resume_state_ack)
   9.105 +  {
   9.106 +    FUNCTION_ENTER();
   9.107 +    switch (xvdd->device_state->resume_state)
   9.108 +    {
   9.109 +      case RESUME_STATE_SUSPENDING:
   9.110 +        KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
   9.111 +        break;
   9.112 +      case RESUME_STATE_FRONTEND_RESUME:
   9.113 +        KdPrint((__DRIVER_NAME "     New state RESUME_STATE_FRONTEND_RESUME\n"));
   9.114 +        XenVbd_Resume(xvdd);
   9.115 +        break;
   9.116 +      default:
   9.117 +        KdPrint((__DRIVER_NAME "     New state %d\n", xvdd->device_state->resume_state));
   9.118 +        break;
   9.119 +    }
   9.120 +    xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
   9.121 +    KeMemoryBarrier();
   9.122 +    FUNCTION_EXIT();
   9.123 +  }
   9.124 +
   9.125    if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
   9.126    {
   9.127 -    //KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
   9.128 -    xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
   9.129 -    KeMemoryBarrier();
   9.130      return FALSE;
   9.131    }
   9.132