win-pvdrivers

changeset 401:fdb7f8853695

More deadlock prevention changes.
Disconnect xenbus devices before shutdown
author James Harper <james.harper@bendigoit.com.au>
date Fri Jul 18 23:22:01 2008 +1000 (2008-07-18)
parents 099b6e3f3909
children 04883e1dc65c
files common/include/xen_public.h xennet/xennet.c xenpci/xenbus.c xenpci/xenpci.h xenpci/xenpci_fdo.c xenpci/xenpci_pdo.c xenvbd/scsiport.c
line diff
     1.1 --- a/common/include/xen_public.h	Thu Jul 17 21:10:09 2008 +1000
     1.2 +++ b/common/include/xen_public.h	Fri Jul 18 23:22:01 2008 +1000
     1.3 @@ -119,14 +119,16 @@ typedef struct {
     1.4  } XENPCI_VECTORS, *PXENPCI_VECTORS;
     1.5  
     1.6  #define RESUME_STATE_RUNNING            0
     1.7 -#define RESUME_STATE_BACKEND_RESUME     1
     1.8 -#define RESUME_STATE_FRONTEND_RESUME    2
     1.9 +#define RESUME_STATE_SUSPENDING         1
    1.10 +#define RESUME_STATE_BACKEND_RESUME     2
    1.11 +#define RESUME_STATE_FRONTEND_RESUME    3
    1.12  
    1.13  typedef struct {
    1.14    ULONG magic;
    1.15    USHORT length;
    1.16  
    1.17    ULONG resume_state;
    1.18 +  ULONG resume_state_ack;
    1.19  } XENPCI_DEVICE_STATE, *PXENPCI_DEVICE_STATE;
    1.20  
    1.21  #define XEN_INIT_TYPE_END               0
     2.1 --- a/xennet/xennet.c	Thu Jul 17 21:10:09 2008 +1000
     2.2 +++ b/xennet/xennet.c	Fri Jul 18 23:22:01 2008 +1000
     2.3 @@ -140,6 +140,18 @@ XenNet_InterruptDpc(NDIS_HANDLE  Minipor
     2.4  {
     2.5    struct xennet_info *xi = MiniportAdapterContext;
     2.6  
     2.7 +  if (xi->device_state->resume_state != RESUME_STATE_RUNNING)
     2.8 +  {
     2.9 +    KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
    2.10 +    // there should be a better way to synchronise with rx and tx...
    2.11 +    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    2.12 +    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    2.13 +    KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
    2.14 +    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
    2.15 +    xi->device_state->resume_state_ack = xi->device_state->resume_state;
    2.16 +    return;
    2.17 +  }
    2.18 +
    2.19    //FUNCTION_ENTER();
    2.20    if (xi->connected)
    2.21    {
     3.1 --- a/xenpci/xenbus.c	Thu Jul 17 21:10:09 2008 +1000
     3.2 +++ b/xenpci/xenbus.c	Fri Jul 18 23:22:01 2008 +1000
     3.3 @@ -210,7 +210,7 @@ xenbus_msg_reply(
     3.4    xb_write(xpdd, type, id, trans, io, nr_reqs);
     3.5  
     3.6    KeWaitForSingleObject(&xpdd->req_info[id].WaitEvent, Executive, KernelMode, FALSE, NULL);
     3.7 -
     3.8 +  
     3.9    release_xenbus_id(xpdd, id);
    3.10  
    3.11    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.12 @@ -854,7 +854,7 @@ XenBus_Printf(
    3.13    char buf[512];
    3.14    char *retval;
    3.15  
    3.16 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.17 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.18    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
    3.19  
    3.20    va_start(ap, fmt);
    3.21 @@ -862,7 +862,7 @@ XenBus_Printf(
    3.22    va_end(ap);
    3.23    retval = XenBus_Write(xpdd, xbt, path, buf);
    3.24  
    3.25 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.26 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    3.27  
    3.28    return retval;
    3.29  }
     4.1 --- a/xenpci/xenpci.h	Thu Jul 17 21:10:09 2008 +1000
     4.2 +++ b/xenpci/xenpci.h	Fri Jul 18 23:22:01 2008 +1000
     4.3 @@ -369,7 +369,9 @@ NTSTATUS
     4.4  XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
     4.5  
     4.6  NTSTATUS
     4.7 -XenPci_Resume(PDEVICE_OBJECT device_object);
     4.8 +XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object);
     4.9 +NTSTATUS
    4.10 +XenPci_Pdo_Resume(PDEVICE_OBJECT device_object);
    4.11  
    4.12  char *
    4.13  XenBus_Read(PVOID Context, xenbus_transaction_t xbt, const char *path, char **value);
     5.1 --- a/xenpci/xenpci_fdo.c	Thu Jul 17 21:10:09 2008 +1000
     5.2 +++ b/xenpci/xenpci_fdo.c	Fri Jul 18 23:22:01 2008 +1000
     5.3 @@ -338,7 +338,7 @@ XenPci_CompleteResume(PDEVICE_OBJECT dev
     5.4  
     5.5    for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
     5.6    {
     5.7 -    XenPci_Resume(child->context->common.pdo);
     5.8 +    XenPci_Pdo_Resume(child->context->common.pdo);
     5.9      child->context->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
    5.10      // how can we signal children that they are ready to restart again?
    5.11      // maybe we can fake an interrupt?
    5.12 @@ -447,14 +447,23 @@ XenPci_BeginSuspend(PDEVICE_OBJECT devic
    5.13    PSUSPEND_INFO suspend_info;
    5.14    PKDPC Dpc;
    5.15    KIRQL OldIrql;
    5.16 +  PXEN_CHILD child;
    5.17  
    5.18    UNREFERENCED_PARAMETER(context);
    5.19    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    5.20  
    5.21    if (xpdd->suspend_state == SUSPEND_STATE_NONE)
    5.22    {
    5.23 +    xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
    5.24 +    KeMemoryBarrier();
    5.25 +    
    5.26 +    for (child = (PXEN_CHILD)xpdd->child_list.Flink; child != (PXEN_CHILD)&xpdd->child_list; child = (PXEN_CHILD)child->entry.Flink)
    5.27 +    {
    5.28 +      XenPci_Pdo_Suspend(child->context->common.pdo);
    5.29 +    }
    5.30 +
    5.31      XenBus_StopThreads(xpdd);
    5.32 -    xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
    5.33 +
    5.34      suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
    5.35      RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
    5.36      KeInitializeEvent(&suspend_info->stopped_spinning_event, SynchronizationEvent, FALSE);
     6.1 --- a/xenpci/xenpci_pdo.c	Thu Jul 17 21:10:09 2008 +1000
     6.2 +++ b/xenpci/xenpci_pdo.c	Fri Jul 18 23:22:01 2008 +1000
     6.3 @@ -155,25 +155,28 @@ XenPci_BackEndStateHandler(char *Path, P
     6.4  
     6.5    case XenbusStateClosing:
     6.6      KdPrint((__DRIVER_NAME "     Backend State Changed to Closing\n"));
     6.7 -    if (xppdd->common.device_usage_paging
     6.8 -      || xppdd->common.device_usage_dump
     6.9 -      || xppdd->common.device_usage_hibernation)
    6.10 +    if (xpdd->suspend_state == SUSPEND_STATE_NONE)
    6.11      {
    6.12 -      KdPrint((__DRIVER_NAME "     Not closing device because it is in use\n"));
    6.13 -      /* in use by page file, dump file, or hiber file - can't close */
    6.14 -      /* we should probably re-check if the device usage changes in the future */
    6.15 -    }
    6.16 -    else
    6.17 -    {
    6.18 -      if (xppdd->common.current_pnp_state == Started)
    6.19 +      if (xppdd->common.device_usage_paging
    6.20 +        || xppdd->common.device_usage_dump
    6.21 +        || xppdd->common.device_usage_hibernation)
    6.22        {
    6.23 -        KdPrint((__DRIVER_NAME "     Sending RequestDeviceEject\n"));
    6.24 -        xppdd->eject_requested = TRUE;
    6.25 -        IoRequestDeviceEject(xppdd->common.pdo);
    6.26 +        KdPrint((__DRIVER_NAME "     Not closing device because it is in use\n"));
    6.27 +        /* in use by page file, dump file, or hiber file - can't close */
    6.28 +        /* we should probably re-check if the device usage changes in the future */
    6.29        }
    6.30        else
    6.31        {
    6.32 -        KdPrint((__DRIVER_NAME "     Not closing device because it is not started\n"));
    6.33 +        if (xppdd->common.current_pnp_state == Started)
    6.34 +        {
    6.35 +          KdPrint((__DRIVER_NAME "     Sending RequestDeviceEject\n"));
    6.36 +          xppdd->eject_requested = TRUE;
    6.37 +          IoRequestDeviceEject(xppdd->common.pdo);
    6.38 +        }
    6.39 +        else
    6.40 +        {
    6.41 +          KdPrint((__DRIVER_NAME "     Not closing device because it is not started\n"));
    6.42 +        }
    6.43        }
    6.44      }
    6.45      break;
    6.46 @@ -213,7 +216,10 @@ XenPci_ChangeFrontendState(PXENPCI_PDO_D
    6.47    ULONG thiswait;
    6.48    char path[128];
    6.49    
    6.50 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    6.51 +
    6.52    /* Tell backend we're going down */
    6.53 +  //strcpy(path, xppdd->path);
    6.54    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
    6.55    XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
    6.56  
    6.57 @@ -233,6 +239,7 @@ XenPci_ChangeFrontendState(PXENPCI_PDO_D
    6.58        KdPrint((__DRIVER_NAME "     Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
    6.59      }
    6.60    }
    6.61 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    6.62    return STATUS_SUCCESS;
    6.63  }
    6.64  
    6.65 @@ -666,7 +673,7 @@ XenPci_GetBackendAndAddWatch(PDEVICE_OBJ
    6.66  }
    6.67  
    6.68  NTSTATUS
    6.69 -XenPci_Resume(PDEVICE_OBJECT device_object)
    6.70 +XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
    6.71  {
    6.72    NTSTATUS status;
    6.73    PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
    6.74 @@ -687,7 +694,7 @@ XenPci_Resume(PDEVICE_OBJECT device_obje
    6.75    if (!NT_SUCCESS(status))
    6.76      return status;
    6.77    
    6.78 -  if (xppdd->common.current_pnp_state == Started && old_backend_state == XenbusStateConnected)
    6.79 +  if (xppdd->common.current_pnp_state == Started && old_backend_state == XenbusStateClosed)
    6.80    {
    6.81    
    6.82      if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
    6.83 @@ -719,6 +726,43 @@ XenPci_Resume(PDEVICE_OBJECT device_obje
    6.84    return STATUS_SUCCESS;
    6.85  } 
    6.86  
    6.87 +/* called at DISPATCH_LEVEL */
    6.88 +NTSTATUS
    6.89 +XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
    6.90 +{
    6.91 +  NTSTATUS status = STATUS_SUCCESS;
    6.92 +  PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
    6.93 +  LARGE_INTEGER wait_time;
    6.94 +
    6.95 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s | %s)\n", xppdd->path, xppdd->device));
    6.96 +
    6.97 +  if (xppdd->backend_state == XenbusStateConnected)
    6.98 +  {
    6.99 +    xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
   6.100 +    KeMemoryBarrier();
   6.101 +    xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
   6.102 +    KeMemoryBarrier();
   6.103 +    KdPrint((__DRIVER_NAME "     Calling interrupt\n"));
   6.104 +    sw_interrupt((UCHAR)xppdd->irq_vector);
   6.105 +    KdPrint((__DRIVER_NAME "     Back from interrupt call\n"));
   6.106 +    while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
   6.107 +    {
   6.108 +      KdPrint((__DRIVER_NAME "     Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
   6.109 +      wait_time.QuadPart = 5000 * (-1 * 10 * 1000);
   6.110 +      KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
   6.111 +      KdPrint((__DRIVER_NAME "     Done with delay\n"));
   6.112 +    }
   6.113 +    KdPrint((__DRIVER_NAME "     resume_state acknowledged\n"));
   6.114 +
   6.115 +    XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
   6.116 +    XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
   6.117 +  }
   6.118 +  
   6.119 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.120 +  
   6.121 +  return status;
   6.122 +}
   6.123 +
   6.124  static NTSTATUS
   6.125  XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
   6.126  {
     7.1 --- a/xenvbd/scsiport.c	Thu Jul 17 21:10:09 2008 +1000
     7.2 +++ b/xenvbd/scsiport.c	Fri Jul 18 23:22:01 2008 +1000
     7.3 @@ -682,6 +682,14 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
     7.4  
     7.5    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
     7.6  
     7.7 +  if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
     7.8 +  {
     7.9 +    KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
    7.10 +    xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
    7.11 +    KeMemoryBarrier();
    7.12 +    return FALSE;
    7.13 +  }
    7.14 +
    7.15    xvdd->interrupts++;
    7.16    while (more_to_do)
    7.17    {