win-pvdrivers

changeset 409:a7cf863172cf

More attempts at removing races and deadlocks in save/restore
author James Harper <james.harper@bendigoit.com.au>
date Thu Jul 31 09:24:12 2008 +1000 (2008-07-31)
parents 853fa6745f58
children a25065ea9cca
files xennet/xennet.c xenpci/gnttbl.c xenpci/xenbus.c xenpci/xenpci.h xenpci/xenpci_fdo.c xenpci/xenpci_pdo.c
line diff
     1.1 --- a/xennet/xennet.c	Mon Jul 28 13:31:56 2008 +1000
     1.2 +++ b/xennet/xennet.c	Thu Jul 31 09:24:12 2008 +1000
     1.3 @@ -177,7 +177,7 @@ XenNet_ConnectBackend(struct xennet_info
     1.4      switch(type)
     1.5      {
     1.6      case XEN_INIT_TYPE_RING: /* frontend ring */
     1.7 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
     1.8 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
     1.9        if (strcmp(setting, "tx-ring-ref") == 0)
    1.10        {
    1.11          FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
    1.12 @@ -187,7 +187,7 @@ XenNet_ConnectBackend(struct xennet_info
    1.13        }
    1.14        break;
    1.15      case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
    1.16 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
    1.17 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
    1.18        if (strcmp(setting, "event-channel") == 0)
    1.19        {
    1.20          xi->event_channel = PtrToUlong(value);
    1.21 @@ -195,7 +195,7 @@ XenNet_ConnectBackend(struct xennet_info
    1.22        break;
    1.23      case XEN_INIT_TYPE_READ_STRING_BACK:
    1.24      case XEN_INIT_TYPE_READ_STRING_FRONT:
    1.25 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
    1.26 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
    1.27        if (strcmp(setting, "mac") == 0)
    1.28        {
    1.29          char *s, *e;
    1.30 @@ -211,7 +211,7 @@ XenNet_ConnectBackend(struct xennet_info
    1.31        }
    1.32        break;
    1.33      case XEN_INIT_TYPE_VECTORS:
    1.34 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
    1.35 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
    1.36        if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
    1.37          ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
    1.38        {
    1.39 @@ -224,7 +224,7 @@ XenNet_ConnectBackend(struct xennet_info
    1.40          memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
    1.41        break;
    1.42      case XEN_INIT_TYPE_STATE_PTR:
    1.43 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
    1.44 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
    1.45        xi->device_state = (PXENPCI_DEVICE_STATE)value;
    1.46        break;
    1.47      default:
     2.1 --- a/xenpci/gnttbl.c	Mon Jul 28 13:31:56 2008 +1000
     2.2 +++ b/xenpci/gnttbl.c	Thu Jul 31 09:24:12 2008 +1000
     2.3 @@ -225,6 +225,7 @@ GntTbl_InitMap(PXENPCI_DEVICE_DATA xpdd)
     2.4      GntTbl_PutRef(xpdd, i);
     2.5    
     2.6    GntTbl_Map(xpdd, 0, grant_frames - 1);
     2.7 +  RtlZeroMemory(xpdd->gnttab_table, PAGE_SIZE * grant_frames);
     2.8  }
     2.9  
    2.10  VOID
     3.1 --- a/xenpci/xenbus.c	Mon Jul 28 13:31:56 2008 +1000
     3.2 +++ b/xenpci/xenbus.c	Thu Jul 31 09:24:12 2008 +1000
     3.3 @@ -305,7 +305,6 @@ XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
     3.4  {
     3.5    PHYSICAL_ADDRESS pa_xen_store_interface;
     3.6    xen_ulong_t xen_store_mfn;
     3.7 -  NTSTATUS status;
     3.8  
     3.9    xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
    3.10    xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
    3.11 @@ -316,20 +315,6 @@ XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
    3.12  
    3.13    xpdd->XenBus_ShuttingDown = FALSE;
    3.14    KeMemoryBarrier();
    3.15 -
    3.16 -  status = PsCreateSystemThread(&xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, xpdd);
    3.17 -  if (!NT_SUCCESS(status))
    3.18 -  {
    3.19 -    KdPrint((__DRIVER_NAME " Could not start read thread\n"));
    3.20 -    return status;
    3.21 -  }
    3.22 -
    3.23 -  status = PsCreateSystemThread(&xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, xpdd);
    3.24 -  if (!NT_SUCCESS(status))
    3.25 -  {
    3.26 -    KdPrint((__DRIVER_NAME " Could not start watch thread\n"));
    3.27 -    return status;
    3.28 -  }
    3.29    
    3.30    return STATUS_SUCCESS;
    3.31  }
    3.32 @@ -338,9 +323,10 @@ NTSTATUS
    3.33  XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
    3.34  {
    3.35    NTSTATUS status;
    3.36 +  HANDLE thread_handle;
    3.37    int i;
    3.38      
    3.39 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.40 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.41  
    3.42    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
    3.43  
    3.44 @@ -363,8 +349,38 @@ XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
    3.45    {
    3.46      return status;
    3.47    }
    3.48 +
    3.49 +  status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, xpdd);
    3.50 +  if (!NT_SUCCESS(status))
    3.51 +  {
    3.52 +    KdPrint((__DRIVER_NAME "     Could not start read thread\n"));
    3.53 +    return status;
    3.54 +  }
    3.55 +  KdPrint((__DRIVER_NAME "    Started ReadThread\n"));
    3.56    
    3.57 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.58 +  status = ObReferenceObjectByHandle(thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &xpdd->XenBus_ReadThread, NULL);
    3.59 +  ZwClose(thread_handle);
    3.60 +  if (!NT_SUCCESS(status))
    3.61 +  {
    3.62 +    KdPrint((__DRIVER_NAME "     ObReferenceObjectByHandle(XenBus_ReadThread) = %08x\n", status));
    3.63 +    return status;
    3.64 +  }
    3.65 +
    3.66 +  status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, xpdd);
    3.67 +  if (!NT_SUCCESS(status))
    3.68 +  {
    3.69 +    KdPrint((__DRIVER_NAME " Could not start watch thread\n"));
    3.70 +    return status;
    3.71 +  }
    3.72 +  KdPrint((__DRIVER_NAME "    Started WatchThread\n"));
    3.73 +  status = ObReferenceObjectByHandle(thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &xpdd->XenBus_WatchThread, NULL);
    3.74 +  ZwClose(thread_handle);
    3.75 +  if (!NT_SUCCESS(status))
    3.76 +  {
    3.77 +    KdPrint((__DRIVER_NAME "     ObReferenceObjectByHandle(XenBus_WatchThread) = %08x\n", status));
    3.78 +  }
    3.79 +  
    3.80 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.81  
    3.82    return STATUS_SUCCESS;
    3.83  }
    3.84 @@ -426,9 +442,10 @@ XenBus_SendRemWatch(
    3.85  NTSTATUS
    3.86  XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd)
    3.87  {
    3.88 +  NTSTATUS status;
    3.89    //KWAIT_BLOCK WaitBlockArray[2];
    3.90    int i;
    3.91 -  PVOID WaitArray[2];
    3.92 +  LARGE_INTEGER timeout;
    3.93  
    3.94    FUNCTION_ENTER();
    3.95    
    3.96 @@ -449,19 +466,27 @@ KdPrint((__DRIVER_NAME "     Setting Rea
    3.97    KeSetEvent(&xpdd->XenBus_ReadThreadEvent, IO_NO_INCREMENT, FALSE);
    3.98  KdPrint((__DRIVER_NAME "     Setting WatchThreadEvent\n"));
    3.99    KeSetEvent(&xpdd->XenBus_WatchThreadEvent, IO_NO_INCREMENT, FALSE);
   3.100 -  ObReferenceObjectByHandle(xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[0], NULL);
   3.101 -  ObReferenceObjectByHandle(xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &WaitArray[1], NULL);
   3.102 +  
   3.103  KdPrint((__DRIVER_NAME "     Waiting for ReadThread\n"));
   3.104 -  KeWaitForSingleObject(WaitArray[0], Executive, KernelMode, FALSE, NULL);
   3.105 +  timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
   3.106 +  while ((status = KeWaitForSingleObject(xpdd->XenBus_ReadThread, Executive, KernelMode, FALSE, &timeout)) != STATUS_SUCCESS)
   3.107 +  {
   3.108 +KdPrint((__DRIVER_NAME "     Still waiting for ReadThread (status = %08x)\n", status));
   3.109 +    timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
   3.110 +  }
   3.111 +  ObDereferenceObject(xpdd->XenBus_ReadThread);
   3.112  KdPrint((__DRIVER_NAME "     Waiting for WatchThread\n"));
   3.113 -  KeWaitForSingleObject(WaitArray[1], Executive, KernelMode, FALSE, NULL);
   3.114 +  timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
   3.115 +  while ((status = KeWaitForSingleObject(xpdd->XenBus_WatchThread, Executive, KernelMode, FALSE, &timeout)) != STATUS_SUCCESS)
   3.116 +  {
   3.117 +KdPrint((__DRIVER_NAME "     Still waiting for WatchThread (status = %08x)\n", status));
   3.118 +    timeout.QuadPart = (LONGLONG)-1 * 1000 * 1000 * 10;
   3.119 +  }
   3.120 +  ObDereferenceObject(xpdd->XenBus_WatchThread);
   3.121  KdPrint((__DRIVER_NAME "     Done\n"));
   3.122    
   3.123    xpdd->XenBus_ShuttingDown = FALSE;
   3.124  
   3.125 -  ZwClose(xpdd->XenBus_WatchThreadHandle);
   3.126 -  ZwClose(xpdd->XenBus_ReadThreadHandle);
   3.127 -
   3.128    FUNCTION_EXIT();
   3.129  
   3.130    return STATUS_SUCCESS;
   3.131 @@ -530,6 +555,7 @@ XenBus_ReadThreadProc(PVOID StartContext
   3.132      {
   3.133        KdPrint((__DRIVER_NAME "     Shutdown detected in ReadThreadProc\n"));
   3.134        PsTerminateSystemThread(0);
   3.135 +      KdPrint((__DRIVER_NAME "     ReadThreadProc still running... wtf?\n"));
   3.136      }
   3.137      while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
   3.138      {
   3.139 @@ -598,12 +624,13 @@ XenBus_WatchThreadProc(PVOID StartContex
   3.140    for(;;)
   3.141    {
   3.142      KeWaitForSingleObject(&xpdd->XenBus_WatchThreadEvent, Executive, KernelMode, FALSE, NULL);
   3.143 -      ExAcquireFastMutex(&xpdd->watch_mutex);
   3.144 +    ExAcquireFastMutex(&xpdd->watch_mutex);
   3.145      if (xpdd->XenBus_ShuttingDown)
   3.146      {
   3.147        KdPrint((__DRIVER_NAME "     Shutdown detected in WatchThreadProc\n"));
   3.148        ExReleaseFastMutex(&xpdd->watch_mutex);
   3.149        PsTerminateSystemThread(0);
   3.150 +      KdPrint((__DRIVER_NAME "     WatchThreadProc still running... wtf?\n"));
   3.151      }
   3.152      while (xpdd->XenBus_WatchRingReadIndex != xpdd->XenBus_WatchRingWriteIndex)
   3.153      {
   3.154 @@ -661,6 +688,25 @@ XenBus_SendAddWatch(
   3.155  
   3.156  /* called at PASSIVE_LEVEL */
   3.157  NTSTATUS
   3.158 +XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd)
   3.159 +{
   3.160 +  int i;
   3.161 +  
   3.162 +  /* we need to remove the watches as a watch firing could lead to a XenBus_Read/Write/Printf */
   3.163 +  ExAcquireFastMutex(&xpdd->watch_mutex);
   3.164 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
   3.165 +    if (xpdd->XenBus_WatchEntries[i].Active)
   3.166 +      XenBus_SendRemWatch(xpdd, XBT_NIL, xpdd->XenBus_WatchEntries[i].Path, i);
   3.167 +  }
   3.168 +  ExReleaseFastMutex(&xpdd->watch_mutex);
   3.169 +
   3.170 +  // need to synchronise with readthread here too to ensure that it won't do anything silly
   3.171 +  
   3.172 +  return STATUS_SUCCESS;
   3.173 +}
   3.174 +
   3.175 +/* called at PASSIVE_LEVEL */
   3.176 +NTSTATUS
   3.177  XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
   3.178  {
   3.179    NTSTATUS status;
   3.180 @@ -763,12 +809,27 @@ XenBus_RemWatch(
   3.181  
   3.182    // check that Path < 128 chars
   3.183  
   3.184 -  for (i = 0; i < MAX_WATCH_ENTRIES; i++) {
   3.185 +  for (i = 0; i < MAX_WATCH_ENTRIES; i++)
   3.186 +  {
   3.187 +#if 0
   3.188 +    if (xpdd->XenBus_WatchEntries[i].Active)
   3.189 +    {
   3.190 +    KdPrint((__DRIVER_NAME "     (%d == 1) = %d\n", xpdd->XenBus_WatchEntries[i].Active, xpdd->XenBus_WatchEntries[i].Active == 1));
   3.191 +    KdPrint((__DRIVER_NAME "     strcmp(%s, %s) = %d\n", xpdd->XenBus_WatchEntries[i].Path, Path, strcmp(xpdd->XenBus_WatchEntries[i].Path, Path)));
   3.192 +    KdPrint((__DRIVER_NAME "     (%p == %p) = %d\n", xpdd->XenBus_WatchEntries[i].ServiceRoutine, ServiceRoutine, xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine));
   3.193 +    KdPrint((__DRIVER_NAME "     (%p == %p) = %d\n", xpdd->XenBus_WatchEntries[i].ServiceContext, ServiceContext, xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext));
   3.194 +#endif
   3.195      if (xpdd->XenBus_WatchEntries[i].Active == 1
   3.196        && strcmp(xpdd->XenBus_WatchEntries[i].Path, Path) == 0
   3.197        && xpdd->XenBus_WatchEntries[i].ServiceRoutine == ServiceRoutine
   3.198        && xpdd->XenBus_WatchEntries[i].ServiceContext == ServiceContext)
   3.199 +    {
   3.200 +      KdPrint((__DRIVER_NAME "     Match\n"));
   3.201        break;
   3.202 +    }
   3.203 +#if 0
   3.204 +    }
   3.205 +#endif
   3.206    }
   3.207  
   3.208    if (i == MAX_WATCH_ENTRIES)
     4.1 --- a/xenpci/xenpci.h	Mon Jul 28 13:31:56 2008 +1000
     4.2 +++ b/xenpci/xenpci.h	Thu Jul 31 09:24:12 2008 +1000
     4.3 @@ -198,9 +198,9 @@ typedef struct {
     4.4    ev_action_t ev_actions[NR_EVENTS];
     4.5  //  unsigned long bound_ports[NR_EVENTS/(8*sizeof(unsigned long))];
     4.6  
     4.7 -  HANDLE XenBus_ReadThreadHandle;
     4.8 +  PKTHREAD XenBus_ReadThread;
     4.9    KEVENT XenBus_ReadThreadEvent;
    4.10 -  HANDLE XenBus_WatchThreadHandle;
    4.11 +  PKTHREAD XenBus_WatchThread;
    4.12    KEVENT XenBus_WatchThreadEvent;
    4.13  
    4.14    KSPIN_LOCK xenbus_id_lock;
    4.15 @@ -259,6 +259,7 @@ typedef struct {
    4.16    PUCHAR assigned_resources_start;
    4.17    PUCHAR assigned_resources_ptr;
    4.18    XENPCI_DEVICE_STATE device_state;
    4.19 +  BOOLEAN restart_on_resume;
    4.20  } XENPCI_PDO_DEVICE_DATA, *PXENPCI_PDO_DEVICE_DATA;
    4.21  
    4.22  typedef struct
    4.23 @@ -402,6 +403,8 @@ XenBus_Start(PXENPCI_DEVICE_DATA xpdd);
    4.24  NTSTATUS
    4.25  XenBus_Stop(PXENPCI_DEVICE_DATA xpdd);
    4.26  NTSTATUS
    4.27 +XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd);
    4.28 +NTSTATUS
    4.29  XenBus_Resume(PXENPCI_DEVICE_DATA xpdd);
    4.30  NTSTATUS
    4.31  XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd);
    4.32 @@ -430,6 +433,8 @@ NTSTATUS
    4.33  EvtChn_Unbind(PVOID Context, evtchn_port_t Port);
    4.34  NTSTATUS
    4.35  EvtChn_Notify(PVOID Context, evtchn_port_t Port);
    4.36 +VOID
    4.37 +EvtChn_Close(PVOID Context, evtchn_port_t Port);
    4.38  evtchn_port_t
    4.39  EvtChn_AllocUnbound(PVOID Context, domid_t Domain);
    4.40  
     5.1 --- a/xenpci/xenpci_fdo.c	Mon Jul 28 13:31:56 2008 +1000
     5.2 +++ b/xenpci/xenpci_fdo.c	Thu Jul 31 09:24:12 2008 +1000
     5.3 @@ -144,7 +144,7 @@ XenPci_Init(PXENPCI_DEVICE_DATA xpdd)
     5.4    xatp.idx = 0;
     5.5    xatp.space = XENMAPSPACE_shared_info;
     5.6    xatp.gpfn = (xen_pfn_t)(xpdd->shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
     5.7 -  KdPrint((__DRIVER_NAME " gpfn = %d\n", xatp.gpfn));
     5.8 +  KdPrint((__DRIVER_NAME " gpfn = %x\n", xatp.gpfn));
     5.9    ret = HYPERVISOR_memory_op(xpdd, XENMEM_add_to_physmap, &xatp);
    5.10    KdPrint((__DRIVER_NAME " hypervisor memory op ret = %d\n", ret));
    5.11  
    5.12 @@ -297,18 +297,13 @@ XenBus_ShutdownIoCancel(PDEVICE_OBJECT d
    5.13    FUNCTION_EXIT();
    5.14  }
    5.15  
    5.16 -#define SPIN_STATE_NONE 0
    5.17 -#define SPIN_STATE_DPC1 1
    5.18 -#define SPIN_STATE_HIGH 2
    5.19 -#define SPIN_STATE_DPC2 3
    5.20 -
    5.21  struct {
    5.22 -  volatile ULONG spin_state;
    5.23 +  volatile ULONG do_spin;
    5.24    volatile ULONG abort_spin;
    5.25 -  volatile LONG nr_spinning_dpc1;
    5.26 -  volatile LONG nr_spinning_high;
    5.27 -  volatile LONG nr_spinning_dpc2;
    5.28 +  volatile LONG nr_spinning;
    5.29 +  KDPC dpcs[MAX_VIRT_CPUS];
    5.30    KEVENT spin_event;
    5.31 +  KEVENT resume_event;
    5.32  } typedef SUSPEND_INFO, *PSUSPEND_INFO;
    5.33  
    5.34  /* runs at PASSIVE_LEVEL */
    5.35 @@ -324,15 +319,12 @@ XenPci_CompleteResume(PDEVICE_OBJECT dev
    5.36  
    5.37    xpdd = (PXENPCI_DEVICE_DATA)device_object->DeviceExtension;
    5.38  
    5.39 -  while (suspend_info->nr_spinning_dpc2 != 0)
    5.40 +  while (suspend_info->nr_spinning)
    5.41    {
    5.42 -    KdPrint((__DRIVER_NAME "     %d processors are still spinning at dpc2\n", suspend_info->nr_spinning_dpc2));
    5.43 +    KdPrint((__DRIVER_NAME "     %d processors are still spinning\n", suspend_info->nr_spinning));
    5.44      KeWaitForSingleObject(&suspend_info->spin_event, Executive, KernelMode, FALSE, NULL);
    5.45    }
    5.46 -  KdPrint((__DRIVER_NAME "     all other processors have stopped spinning at dpc2\n"));
    5.47 -
    5.48 -  /* this has to be done at PASSIVE_LEVEL */
    5.49 -  //EvtChn_ConnectInterrupt(xpdd);
    5.50 +  KdPrint((__DRIVER_NAME "     all other processors have stopped spinning\n"));
    5.51  
    5.52    XenBus_Resume(xpdd);
    5.53  
    5.54 @@ -360,8 +352,7 @@ XenPci_Suspend(
    5.55    PSUSPEND_INFO suspend_info = SystemArgument1;
    5.56    ULONG ActiveProcessorCount;
    5.57    KIRQL old_irql;
    5.58 -  int cancelled;
    5.59 -  PIO_WORKITEM work_item;
    5.60 +  int cancelled = 0;
    5.61    PXEN_CHILD child;
    5.62    LARGE_INTEGER spin_abort_time;
    5.63    LARGE_INTEGER current_time;
    5.64 @@ -376,11 +367,12 @@ XenPci_Suspend(
    5.65  
    5.66    if (KeGetCurrentProcessorNumber() != 0)
    5.67    {
    5.68 -    KdPrint((__DRIVER_NAME "     CPU %d spinning at dpc1...\n", KeGetCurrentProcessorNumber()));
    5.69 +    KdPrint((__DRIVER_NAME "     CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
    5.70      KeQuerySystemTime(&spin_abort_time);
    5.71 -    spin_abort_time.QuadPart += 10 * 1000 * 5000;
    5.72 -    InterlockedIncrement(&suspend_info->nr_spinning_dpc1);
    5.73 -    while(suspend_info->spin_state == SPIN_STATE_DPC1 && !suspend_info->abort_spin)
    5.74 +    spin_abort_time.QuadPart += 10 * 1000 * 10000;
    5.75 +    KeRaiseIrql(HIGH_LEVEL, &old_irql);
    5.76 +    InterlockedIncrement(&suspend_info->nr_spinning);
    5.77 +    while(suspend_info->do_spin && !suspend_info->abort_spin)
    5.78      {
    5.79        KeStallExecutionProcessor(1);
    5.80        KeMemoryBarrier();
    5.81 @@ -389,8 +381,9 @@ XenPci_Suspend(
    5.82        {
    5.83          suspend_info->abort_spin = TRUE;
    5.84          KeMemoryBarrier();
    5.85 -        InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
    5.86 +        InterlockedDecrement(&suspend_info->nr_spinning);
    5.87          KdPrint((__DRIVER_NAME "     CPU %d waited long enough - aborting\n", KeGetCurrentProcessorNumber()));
    5.88 +KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000000, 0x00000000, 0x00000000);
    5.89          return;
    5.90        }
    5.91        /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
    5.92 @@ -398,76 +391,46 @@ XenPci_Suspend(
    5.93      if (suspend_info->abort_spin)
    5.94      {
    5.95        KdPrint((__DRIVER_NAME "     CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
    5.96 +KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000001, 0x00000000, 0x00000000);
    5.97        return;
    5.98      }
    5.99 -    InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
   5.100 -    KdPrint((__DRIVER_NAME "     CPU %d done spinning at dpc1\n", KeGetCurrentProcessorNumber()));
   5.101 -    KeRaiseIrql(HIGH_LEVEL, &old_irql);
   5.102 -    KdPrint((__DRIVER_NAME "     CPU %d spinning at high...\n", KeGetCurrentProcessorNumber()));
   5.103 -    InterlockedIncrement(&suspend_info->nr_spinning_high);
   5.104 -    while(suspend_info->spin_state == SPIN_STATE_HIGH)
   5.105 -    {
   5.106 -      KeStallExecutionProcessor(1);
   5.107 -      KeMemoryBarrier();
   5.108 -      /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
   5.109 -    }
   5.110 -    InterlockedDecrement(&suspend_info->nr_spinning_high);    
   5.111 -    KdPrint((__DRIVER_NAME "     CPU %d done spinning at high\n", KeGetCurrentProcessorNumber()));
   5.112      KeLowerIrql(old_irql);
   5.113 -
   5.114 -    KdPrint((__DRIVER_NAME "     CPU %d spinning at dpc2...\n", KeGetCurrentProcessorNumber()));
   5.115 -    InterlockedIncrement(&suspend_info->nr_spinning_dpc2);
   5.116 -    while(suspend_info->spin_state == SPIN_STATE_DPC2)
   5.117 -    {
   5.118 -      KeStallExecutionProcessor(1);
   5.119 -      KeMemoryBarrier();
   5.120 -      /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
   5.121 -    }
   5.122 -    InterlockedDecrement(&suspend_info->nr_spinning_dpc2);
   5.123 -    KdPrint((__DRIVER_NAME "     CPU %d done spinning at dpc2\n", KeGetCurrentProcessorNumber()));
   5.124 +    InterlockedDecrement(&suspend_info->nr_spinning);
   5.125 +    KdPrint((__DRIVER_NAME "     CPU %d done spinning\n", KeGetCurrentProcessorNumber()));
   5.126      KeSetEvent(&suspend_info->spin_event, IO_NO_INCREMENT, FALSE);
   5.127      FUNCTION_EXIT();
   5.128      return;
   5.129    }
   5.130    ActiveProcessorCount = (ULONG)KeNumberProcessors;
   5.131  
   5.132 -  KdPrint((__DRIVER_NAME "     waiting for all other processors to spin at dpc1\n"));
   5.133 +  KdPrint((__DRIVER_NAME "     waiting for all other processors to spin\n"));
   5.134    KeQuerySystemTime(&spin_abort_time);
   5.135 -  spin_abort_time.QuadPart += 10 * 1000 * 5000;
   5.136 -  while (suspend_info->nr_spinning_dpc1 < (LONG)ActiveProcessorCount - 1 && !suspend_info->abort_spin)
   5.137 +  spin_abort_time.QuadPart += 10 * 1000 * 10000;
   5.138 +  KeRaiseIrql(HIGH_LEVEL, &old_irql);
   5.139 +  xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
   5.140 +  while (suspend_info->nr_spinning < (LONG)ActiveProcessorCount - 1 && !suspend_info->abort_spin)
   5.141    {
   5.142      KeStallExecutionProcessor(1);
   5.143      //HYPERVISOR_yield(xpdd);
   5.144      KeMemoryBarrier();
   5.145 +
   5.146      KeQuerySystemTime(&current_time);
   5.147      if (current_time.QuadPart > spin_abort_time.QuadPart)
   5.148      {
   5.149        suspend_info->abort_spin = TRUE;
   5.150        KeMemoryBarrier();
   5.151 -      InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
   5.152        KdPrint((__DRIVER_NAME "     CPU %d waited long enough - aborting\n", KeGetCurrentProcessorNumber()));
   5.153 +KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000002, 0x00000000, 0x00000000);
   5.154        return;
   5.155      }
   5.156    }
   5.157    if (suspend_info->abort_spin)
   5.158    {
   5.159      KdPrint((__DRIVER_NAME "     CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
   5.160 +KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000003, 0x00000000, 0x00000000);
   5.161      return;
   5.162    }
   5.163 -  KdPrint((__DRIVER_NAME "     all other processors are spinning at dpc1\n"));
   5.164 -  KeRaiseIrql(HIGH_LEVEL, &old_irql);
   5.165 -  
   5.166 -  suspend_info->spin_state = SPIN_STATE_HIGH;
   5.167 -  xpdd->suspend_state = SUSPEND_STATE_HIGH_IRQL;
   5.168 -  KeMemoryBarrier();
   5.169 -
   5.170 -  KdPrint((__DRIVER_NAME "     waiting for all other processors to spin at high\n"));
   5.171 -  while (suspend_info->nr_spinning_high < (LONG)ActiveProcessorCount - 1)
   5.172 -  {
   5.173 -      HYPERVISOR_yield(xpdd);
   5.174 -      KeMemoryBarrier();
   5.175 -  }
   5.176 -  KdPrint((__DRIVER_NAME "     all other processors are spinning at high\n"));
   5.177 +  KdPrint((__DRIVER_NAME "     all other processors are spinning\n"));
   5.178    KdPrint((__DRIVER_NAME "     calling suspend\n"));
   5.179    cancelled = hvm_shutdown(Context, SHUTDOWN_suspend);
   5.180    KdPrint((__DRIVER_NAME "     back from suspend, cancelled = %d\n", cancelled));
   5.181 @@ -485,23 +448,15 @@ XenPci_Suspend(
   5.182    }
   5.183    KeLowerIrql(old_irql);
   5.184    xpdd->suspend_state = SUSPEND_STATE_RESUMING;
   5.185 -  suspend_info->spin_state = SPIN_STATE_DPC2;
   5.186 -  KeMemoryBarrier();
   5.187 -  
   5.188 -  KdPrint((__DRIVER_NAME "     waiting for all other processors to spin at dpc2\n"));
   5.189 -  while (suspend_info->nr_spinning_dpc2 < (LONG)ActiveProcessorCount - 1)
   5.190 -  {
   5.191 -      HYPERVISOR_yield(xpdd);
   5.192 -      KeMemoryBarrier();
   5.193 -  }
   5.194 -  KdPrint((__DRIVER_NAME "     all other processors are spinning at dpc2\n"));
   5.195 -  KdPrint((__DRIVER_NAME "     waiting for all other processors to stop spinning\n"));
   5.196 -  suspend_info->spin_state = SPIN_STATE_NONE;
   5.197 -  KeMemoryBarrier();
   5.198 +  suspend_info->do_spin = FALSE;
   5.199 +  KeMemoryBarrier();  
   5.200 +  KeSetEvent(&suspend_info->resume_event, IO_NO_INCREMENT, FALSE);
   5.201  
   5.202 +/*
   5.203  	work_item = IoAllocateWorkItem(xpdd->common.fdo);
   5.204 +  KdPrint((__DRIVER_NAME "     work_item = %x\n", work_item));
   5.205  	IoQueueWorkItem(work_item, XenPci_CompleteResume, DelayedWorkQueue, suspend_info);
   5.206 -  
   5.207 +*/  
   5.208    FUNCTION_EXIT();
   5.209  }
   5.210  
   5.211 @@ -514,7 +469,7 @@ XenPci_BeginSuspend(PDEVICE_OBJECT devic
   5.212    ULONG ActiveProcessorCount;
   5.213    ULONG i;
   5.214    PSUSPEND_INFO suspend_info;
   5.215 -  PKDPC Dpc;
   5.216 +  //PKDPC Dpc;
   5.217    KIRQL OldIrql;
   5.218    PXEN_CHILD child;
   5.219  
   5.220 @@ -525,35 +480,40 @@ XenPci_BeginSuspend(PDEVICE_OBJECT devic
   5.221    {
   5.222      xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
   5.223      KeMemoryBarrier();
   5.224 +
   5.225 +    suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
   5.226 +    RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
   5.227 +    KeInitializeEvent(&suspend_info->spin_event, SynchronizationEvent, FALSE);
   5.228 +    KeInitializeEvent(&suspend_info->resume_event, SynchronizationEvent, FALSE);
   5.229      
   5.230      for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
   5.231      {
   5.232        XenPci_Pdo_Suspend(child->context->common.pdo);
   5.233      }
   5.234  
   5.235 -    XenBus_StopThreads(xpdd);
   5.236 -
   5.237 -    suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
   5.238 -    RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
   5.239 -    KeInitializeEvent(&suspend_info->spin_event, SynchronizationEvent, FALSE);
   5.240 +    XenBus_Suspend(xpdd);
   5.241  
   5.242      EvtChn_Shutdown(xpdd);
   5.243  
   5.244      //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask); // this is for Vista+
   5.245      ActiveProcessorCount = (ULONG)KeNumberProcessors;
   5.246 -    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
   5.247 -    suspend_info->spin_state = SPIN_STATE_DPC1;
   5.248 +    /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
   5.249 +    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
   5.250 +    suspend_info->do_spin = TRUE;
   5.251      for (i = 0; i < ActiveProcessorCount; i++)
   5.252      {
   5.253 -      Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
   5.254 -      KeInitializeDpc(Dpc, XenPci_Suspend, xpdd);
   5.255 -      KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
   5.256 +      //Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
   5.257 +      KeInitializeDpc(&suspend_info->dpcs[i], XenPci_Suspend, xpdd);
   5.258 +      KeSetTargetProcessorDpc(&suspend_info->dpcs[i], (CCHAR)i);
   5.259 +      KeSetImportanceDpc(&suspend_info->dpcs[i], HighImportance);
   5.260        KdPrint((__DRIVER_NAME "     queuing Dpc for CPU %d\n", i));
   5.261 -      KeInsertQueueDpc(Dpc, suspend_info, NULL);
   5.262 +      KeInsertQueueDpc(&suspend_info->dpcs[i], suspend_info, NULL);
   5.263      }
   5.264      KdPrint((__DRIVER_NAME "     All Dpc's queued\n"));
   5.265      KeMemoryBarrier();
   5.266      KeLowerIrql(OldIrql);
   5.267 +    KeWaitForSingleObject(&suspend_info->resume_event, Executive, KernelMode, FALSE, NULL);
   5.268 +    XenPci_CompleteResume(device_object, suspend_info);
   5.269    }
   5.270    FUNCTION_EXIT();
   5.271  }
   5.272 @@ -662,6 +622,7 @@ XenPci_SysrqHandler(char *path, PVOID co
   5.273    PXENPCI_DEVICE_DATA xpdd = context;
   5.274    NTSTATUS status;
   5.275    HANDLE thread_handle;
   5.276 +  PIO_WORKITEM work_item;
   5.277    char *value;
   5.278    char letter;
   5.279    char *res;
   5.280 @@ -703,6 +664,11 @@ XenPci_SysrqHandler(char *path, PVOID co
   5.281    case 'X':
   5.282      status = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_DummyXenbusThreadProc, xpdd);
   5.283      break;
   5.284 +  case 'S':
   5.285 +    /* call shutdown from here for testing */
   5.286 +  	work_item = IoAllocateWorkItem(xpdd->common.fdo);
   5.287 +    IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
   5.288 +    break;
   5.289    default:
   5.290      KdPrint(("     Unhandled sysrq letter %c\n", letter));
   5.291      break;
     6.1 --- a/xenpci/xenpci_pdo.c	Mon Jul 28 13:31:56 2008 +1000
     6.2 +++ b/xenpci/xenpci_pdo.c	Thu Jul 31 09:24:12 2008 +1000
     6.3 @@ -428,6 +428,7 @@ XenPci_XenShutdownDevice(PVOID Context)
     6.4          break;
     6.5        case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
     6.6          EvtChn_Unbind(xpdd, PtrToUlong(value));
     6.7 +        EvtChn_Close(xpdd, PtrToUlong(value));
     6.8          break;
     6.9        case XEN_INIT_TYPE_GRANT_ENTRIES:
    6.10          for (i = 0; i < PtrToUlong(setting); i++)
    6.11 @@ -513,7 +514,7 @@ XenPci_XenConfigDeviceSpecifyBuffers(PVO
    6.12      case XEN_INIT_TYPE_RUN:
    6.13        run = TRUE;
    6.14      case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
    6.15 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
    6.16 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
    6.17        RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
    6.18        XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
    6.19        break;
    6.20 @@ -522,7 +523,7 @@ XenPci_XenConfigDeviceSpecifyBuffers(PVO
    6.21        if ((ring = AllocatePage()) != 0)
    6.22        {
    6.23          address = MmGetMdlVirtualAddress(ring);
    6.24 -        KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
    6.25 +        //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
    6.26          SHARED_RING_INIT((struct dummy_sring *)address);
    6.27          if ((gref = GntTbl_GrantAccess(
    6.28            xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, 0)) != 0)
    6.29 @@ -553,7 +554,7 @@ XenPci_XenConfigDeviceSpecifyBuffers(PVO
    6.30      case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
    6.31        if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
    6.32        {
    6.33 -        KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
    6.34 +        //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
    6.35          RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
    6.36          XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
    6.37          ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel));
    6.38 @@ -597,13 +598,13 @@ XenPci_XenConfigDeviceSpecifyBuffers(PVO
    6.39        res = XenBus_Read(xpdd, XBT_NIL, path, &value);
    6.40        if (res)
    6.41        {
    6.42 -        KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
    6.43 +        //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
    6.44          XenPci_FreeMem(res);
    6.45          ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL);
    6.46        }
    6.47        else
    6.48        {
    6.49 -        KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
    6.50 +        //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
    6.51          ADD_XEN_INIT_RSP(&out_ptr, type, setting, value);
    6.52          XenPci_FreeMem(value);
    6.53        }
    6.54 @@ -612,7 +613,7 @@ XenPci_XenConfigDeviceSpecifyBuffers(PVO
    6.55        // this is always done so ignore the request
    6.56        break;
    6.57      case XEN_INIT_TYPE_GRANT_ENTRIES:
    6.58 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
    6.59 +      //KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
    6.60        __ADD_XEN_INIT_UCHAR(&out_ptr, type);
    6.61        __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
    6.62        __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
    6.63 @@ -661,14 +662,6 @@ XenPci_GetBackendAndAddWatch(PDEVICE_OBJ
    6.64    PCHAR res;
    6.65    PCHAR value;
    6.66  
    6.67 -  if (strlen(xppdd->backend_path) != 0)
    6.68 -  {
    6.69 -    // this must be the restore path - remove the existing watch
    6.70 -    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
    6.71 -    KdPrint((__DRIVER_NAME "    Removing old watch on %s\n", path));
    6.72 -    XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
    6.73 -  }
    6.74 -  
    6.75    /* Get backend path */
    6.76    RtlStringCbPrintfA(path, ARRAY_SIZE(path),
    6.77      "%s/backend", xppdd->path);
    6.78 @@ -707,15 +700,12 @@ XenPci_Pdo_Resume(PDEVICE_OBJECT device_
    6.79    FUNCTION_ENTER();
    6.80  
    6.81    old_backend_state = xppdd->backend_state;
    6.82 -  status = XenPci_GetBackendAndAddWatch(device_object);
    6.83 -  if (!NT_SUCCESS(status)) {
    6.84 -    KdPrint((__DRIVER_NAME "     Failed to remove old watch\n"));
    6.85 -    FUNCTION_ERROR_EXIT();
    6.86 -    return status;
    6.87 -  }
    6.88 +
    6.89 +  //if (xppdd->common.current_pnp_state == Started && old_backend_state == XenbusStateClosed)
    6.90 +  if (xppdd->restart_on_resume)
    6.91 +  {  
    6.92 +    status = XenPci_GetBackendAndAddWatch(device_object);
    6.93    
    6.94 -  if (xppdd->common.current_pnp_state == Started && old_backend_state == XenbusStateClosed)
    6.95 -  {  
    6.96      if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
    6.97      {
    6.98        KdPrint((__DRIVER_NAME "     Failed to change frontend state to Initialising\n"));
    6.99 @@ -764,12 +754,19 @@ XenPci_Pdo_Suspend(PDEVICE_OBJECT device
   6.100  {
   6.101    NTSTATUS status = STATUS_SUCCESS;
   6.102    PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
   6.103 +  PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
   6.104    LARGE_INTEGER wait_time;
   6.105 +  char path[128];
   6.106 +  PUCHAR in_ptr;
   6.107 +  UCHAR type;
   6.108 +  PVOID setting;
   6.109 +  PVOID value;
   6.110  
   6.111 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s | %s)\n", xppdd->path, xppdd->device));
   6.112 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
   6.113  
   6.114    if (xppdd->backend_state == XenbusStateConnected)
   6.115    {
   6.116 +    xppdd->restart_on_resume = TRUE;
   6.117      xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
   6.118      KeMemoryBarrier();
   6.119      xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
   6.120 @@ -788,8 +785,33 @@ XenPci_Pdo_Suspend(PDEVICE_OBJECT device
   6.121  
   6.122      XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
   6.123      XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
   6.124 +    XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
   6.125 +
   6.126 +    if (xppdd->assigned_resources_start != NULL)
   6.127 +    {
   6.128 +      in_ptr = xppdd->assigned_resources_ptr;
   6.129 +      ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
   6.130 +      in_ptr = xppdd->assigned_resources_start;
   6.131 +      while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
   6.132 +      {
   6.133 +        switch (type)
   6.134 +        {
   6.135 +        case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   6.136 +        case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
   6.137 +          EvtChn_Close(xpdd, PtrToUlong(value));
   6.138 +          break;
   6.139 +        }
   6.140 +      }
   6.141 +    }
   6.142 +
   6.143 +    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
   6.144 +    XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);  
   6.145    }
   6.146 -  
   6.147 +  else
   6.148 +  {
   6.149 +    xppdd->restart_on_resume = FALSE;
   6.150 +  }
   6.151 +
   6.152    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.153    
   6.154    return status;