win-pvdrivers

changeset 811:bf1b18b4728b

Fixes to properly support Hibernation without crashing
author James Harper <james.harper@bendigoit.com.au>
date Sat Aug 28 13:52:40 2010 +1000 (2010-08-28)
parents 1293cb31aa0b
children 551d17b09bc1
files xennet/xennet.c xennet/xennet.h xennet/xennet_oid.c
line diff
     1.1 --- a/xennet/xennet.c	Wed Aug 11 09:10:15 2010 +1000
     1.2 +++ b/xennet/xennet.c	Sat Aug 28 13:52:40 2010 +1000
     1.3 @@ -275,7 +275,7 @@ XenNet_SuspendResume(PKDPC dpc, PVOID co
     1.4    case SR_STATE_SUSPENDING:
     1.5      KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
     1.6      KeAcquireSpinLock(&xi->rx_lock, &old_irql);
     1.7 -    if (xi->tx_id_free == NET_TX_RING_SIZE)
     1.8 +    if (xi->rx_id_free == NET_TX_RING_SIZE)
     1.9      {  
    1.10        xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
    1.11        KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
    1.12 @@ -325,8 +325,133 @@ XenNet_HandleEvent(PVOID context)
    1.13    return TRUE;
    1.14  }
    1.15  
    1.16 +VOID
    1.17 +XenNet_SetPower(PDEVICE_OBJECT device_object, PVOID context)
    1.18 +{
    1.19 +  NTSTATUS status = STATUS_SUCCESS;
    1.20 +  KIRQL old_irql;
    1.21 +  struct xennet_info *xi = context;
    1.22 +  
    1.23 +  FUNCTION_ENTER();
    1.24 +  UNREFERENCED_PARAMETER(device_object);
    1.25 +
    1.26 +  switch (xi->new_power_state)
    1.27 +  {
    1.28 +  case NdisDeviceStateD0:
    1.29 +    KdPrint(("       NdisDeviceStateD0\n"));
    1.30 +    status = XenNet_D0Entry(xi);
    1.31 +    break;
    1.32 +  case NdisDeviceStateD1:
    1.33 +    KdPrint(("       NdisDeviceStateD1\n"));
    1.34 +    if (xi->power_state == NdisDeviceStateD0)
    1.35 +      status = XenNet_D0Exit(xi);
    1.36 +    break;
    1.37 +  case NdisDeviceStateD2:
    1.38 +    KdPrint(("       NdisDeviceStateD2\n"));
    1.39 +    if (xi->power_state == NdisDeviceStateD0)
    1.40 +      status = XenNet_D0Exit(xi);
    1.41 +    break;
    1.42 +  case NdisDeviceStateD3:
    1.43 +    KdPrint(("       NdisDeviceStateD3\n"));
    1.44 +    if (xi->power_state == NdisDeviceStateD0)
    1.45 +      status = XenNet_D0Exit(xi);
    1.46 +    break;
    1.47 +  default:
    1.48 +    KdPrint(("       NdisDeviceState??\n"));
    1.49 +    status = NDIS_STATUS_NOT_SUPPORTED;
    1.50 +    break;
    1.51 +  }
    1.52 +  xi->power_state = xi->new_power_state;
    1.53 +
    1.54 +  old_irql = KeRaiseIrqlToDpcLevel();
    1.55 +  NdisMSetInformationComplete(xi->adapter_handle, status);
    1.56 +  KeLowerIrql(old_irql);
    1.57 +  
    1.58 +  FUNCTION_EXIT();
    1.59 +}
    1.60 +
    1.61 +NDIS_STATUS
    1.62 +XenNet_D0Entry(struct xennet_info *xi)
    1.63 +{
    1.64 +  NDIS_STATUS status;
    1.65 +  PUCHAR ptr;
    1.66 +  CHAR buf[128];
    1.67 +  
    1.68 +  FUNCTION_ENTER();
    1.69 +
    1.70 +  xi->shutting_down = FALSE;
    1.71 +  
    1.72 +  ptr = xi->config_page;
    1.73 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL, NULL);
    1.74 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL, NULL);
    1.75 +  #pragma warning(suppress:4054)
    1.76 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL, "event-channel", (PVOID)XenNet_HandleEvent, xi);
    1.77 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL, NULL);
    1.78 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-sg", NULL, NULL);
    1.79 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-gso-tcpv4", NULL, NULL);
    1.80 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1", NULL);
    1.81 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1", NULL);
    1.82 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
    1.83 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf, NULL);
    1.84 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
    1.85 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf, NULL);
    1.86 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
    1.87 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf, NULL);
    1.88 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
    1.89 +  __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
    1.90 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
    1.91 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
    1.92 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
    1.93 +  __ADD_XEN_INIT_UCHAR(&ptr, 20);
    1.94 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
    1.95 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
    1.96 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
    1.97 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
    1.98 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
    1.99 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   1.100 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   1.101 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   1.102 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
   1.103 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
   1.104 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   1.105 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   1.106 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
   1.107 +
   1.108 +  status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
   1.109 +  if (!NT_SUCCESS(status))
   1.110 +  {
   1.111 +    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   1.112 +    return status;
   1.113 +  }
   1.114 +
   1.115 +  status = XenNet_ConnectBackend(xi);
   1.116 +  
   1.117 +  if (!NT_SUCCESS(status))
   1.118 +  {
   1.119 +    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   1.120 +    return status;
   1.121 +  }
   1.122 +
   1.123 +  if (!xi->config_sg)
   1.124 +  {
   1.125 +    /* without SG, GSO can be a maximum of PAGE_SIZE */
   1.126 +    xi->config_gso = min(xi->config_gso, PAGE_SIZE);
   1.127 +  }
   1.128 +
   1.129 +  XenNet_TxInit(xi);
   1.130 +  XenNet_RxInit(xi);
   1.131 +
   1.132 +  xi->connected = TRUE;
   1.133 +
   1.134 +  KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
   1.135 +
   1.136 +  FUNCTION_EXIT();
   1.137 +
   1.138 +  return status;
   1.139 +}
   1.140 +
   1.141  // Called at <= DISPATCH_LEVEL
   1.142 -static DDKAPI NDIS_STATUS
   1.143 +static NDIS_STATUS
   1.144  XenNet_Init(
   1.145    OUT PNDIS_STATUS OpenErrorStatus,
   1.146    OUT PUINT SelectedMediumIndex,
   1.147 @@ -353,7 +478,7 @@ XenNet_Init(
   1.148    UCHAR type;
   1.149    PCHAR setting, value;
   1.150    ULONG length;
   1.151 -  CHAR buf[128];
   1.152 +  //CHAR buf[128];
   1.153    PVOID network_address;
   1.154    UINT network_address_length;
   1.155    BOOLEAN qemu_hide_filter = FALSE;
   1.156 @@ -365,8 +490,6 @@ XenNet_Init(
   1.157  
   1.158    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.159  
   1.160 -  length = NdisReadPciSlotInformation(MiniportAdapterHandle, 0, 0, &buf, 128);
   1.161 -  KdPrint((__DRIVER_NAME "     NdisReadPciSlotInformation = %d\n", length));
   1.162    /* deal with medium stuff */
   1.163    for (i = 0; i < MediumArraySize; i++)
   1.164    {
   1.165 @@ -509,12 +632,6 @@ XenNet_Init(
   1.166        KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   1.167        xi->device_state = (PXENPCI_DEVICE_STATE)value;
   1.168        break;
   1.169 -#if 0
   1.170 -    case XEN_INIT_TYPE_ACTIVE:
   1.171 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_ACTIVE\n"));
   1.172 -      xi->inactive = FALSE;
   1.173 -      break;
   1.174 -#endif
   1.175      case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   1.176        qemu_hide_flags_value = PtrToUlong(value);
   1.177        break;
   1.178 @@ -530,6 +647,9 @@ XenNet_Init(
   1.179    if ((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) || qemu_hide_filter)
   1.180      xi->inactive = FALSE;
   1.181  
   1.182 +  xi->power_state = NdisDeviceStateD0;
   1.183 +  xi->power_workitem = IoAllocateWorkItem(xi->fdo);
   1.184 +
   1.185    // now build config page
   1.186    
   1.187    NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
   1.188 @@ -642,10 +762,8 @@ XenNet_Init(
   1.189    
   1.190    NdisCloseConfiguration(config_handle);
   1.191  
   1.192 +#if 0
   1.193    ptr = xi->config_page;
   1.194 -  // two XEN_INIT_TYPE_RUNs means go straight to XenbusStateConnected - skip XenbusStateInitialised
   1.195 -  //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
   1.196 -  //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
   1.197    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL, NULL);
   1.198    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL, NULL);
   1.199    #pragma warning(suppress:4054)
   1.200 @@ -680,39 +798,16 @@ XenNet_Init(
   1.201    __ADD_XEN_INIT_UCHAR(&ptr, 50);
   1.202    __ADD_XEN_INIT_UCHAR(&ptr, 0);
   1.203    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
   1.204 -  
   1.205 -  status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
   1.206 +#endif
   1.207 +
   1.208 +  status = XenNet_D0Entry(xi);
   1.209    if (!NT_SUCCESS(status))
   1.210    {
   1.211 -    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   1.212 -    goto err;
   1.213 -  }
   1.214 -
   1.215 -  status = XenNet_ConnectBackend(xi);
   1.216 -  
   1.217 -  if (!NT_SUCCESS(status))
   1.218 -  {
   1.219 -    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   1.220 +    KdPrint(("Failed to go to D0 (%08x)\n", status));
   1.221      goto err;
   1.222    }
   1.223 -
   1.224 -  if (!xi->config_sg)
   1.225 -  {
   1.226 -    /* without SG, GSO can be a maximum of PAGE_SIZE */
   1.227 -    xi->config_gso = min(xi->config_gso, PAGE_SIZE);
   1.228 -  }
   1.229 -
   1.230 -  XenNet_TxInit(xi);
   1.231 -  XenNet_RxInit(xi);
   1.232 -
   1.233 -  xi->connected = TRUE;
   1.234 -
   1.235 -  KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
   1.236 -
   1.237 -  FUNCTION_EXIT();
   1.238 -
   1.239    return NDIS_STATUS_SUCCESS;
   1.240 -
   1.241 +  
   1.242  err:
   1.243    NdisFreeMemory(xi, 0, 0);
   1.244    *OpenErrorStatus = status;
   1.245 @@ -772,6 +867,19 @@ XenNet_Halt(
   1.246  
   1.247    FUNCTION_ENTER();
   1.248    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.249 +  
   1.250 +  XenNet_D0Exit(xi);
   1.251 +
   1.252 +  NdisFreeMemory(xi, 0, 0);
   1.253 +
   1.254 +  FUNCTION_EXIT();
   1.255 +}
   1.256 +
   1.257 +NDIS_STATUS
   1.258 +XenNet_D0Exit(struct xennet_info *xi)
   1.259 +{
   1.260 +  FUNCTION_ENTER();
   1.261 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   1.262  
   1.263    xi->shutting_down = TRUE;
   1.264    KeMemoryBarrier(); /* make sure everyone sees that we are now shutting down */
   1.265 @@ -784,14 +892,16 @@ XenNet_Halt(
   1.266  
   1.267    xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
   1.268  
   1.269 +  #if 0
   1.270    if (!xi->config_sg)
   1.271    {
   1.272      NdisMFreeMapRegisters(xi->adapter_handle);
   1.273    }
   1.274 -
   1.275 -  NdisFreeMemory(xi, 0, 0);
   1.276 +  #endif
   1.277  
   1.278    FUNCTION_EXIT();
   1.279 +  
   1.280 +  return STATUS_SUCCESS;
   1.281  }
   1.282  
   1.283  NDIS_STATUS 
     2.1 --- a/xennet/xennet.h	Wed Aug 11 09:10:15 2010 +1000
     2.2 +++ b/xennet/xennet.h	Sat Aug 28 13:52:40 2010 +1000
     2.3 @@ -252,6 +252,9 @@ struct xennet_info
     2.4    uint8_t perm_mac_addr[ETH_ALEN];
     2.5    uint8_t curr_mac_addr[ETH_ALEN];
     2.6    ULONG current_lookahead;
     2.7 +  NDIS_DEVICE_POWER_STATE new_power_state;
     2.8 +  NDIS_DEVICE_POWER_STATE power_state;
     2.9 +  PIO_WORKITEM power_workitem;
    2.10  
    2.11    /* Misc. Xen vars */
    2.12    XENPCI_VECTORS vectors;
    2.13 @@ -399,6 +402,13 @@ XenNet_SetInformation(
    2.14    OUT PULONG BytesNeeded
    2.15    );
    2.16  
    2.17 +NDIS_STATUS
    2.18 +XenNet_D0Entry(struct xennet_info *xi);
    2.19 +NDIS_STATUS
    2.20 +XenNet_D0Exit(struct xennet_info *xi);
    2.21 +IO_WORKITEM_ROUTINE
    2.22 +XenNet_SetPower;
    2.23 +
    2.24  /* return values */
    2.25  #define PARSE_OK 0
    2.26  #define PARSE_TOO_SMALL 1 /* first buffer is too small */
     3.1 --- a/xennet/xennet_oid.c	Wed Aug 11 09:10:15 2010 +1000
     3.2 +++ b/xennet/xennet_oid.c	Sat Aug 28 13:52:40 2010 +1000
     3.3 @@ -758,25 +758,9 @@ XenNet_SetInformation(
     3.4        break;
     3.5      case OID_PNP_SET_POWER:
     3.6        KdPrint(("     Set OID_PNP_SET_POWER\n"));
     3.7 -      switch (*(PNDIS_DEVICE_POWER_STATE )InformationBuffer)
     3.8 -      {
     3.9 -      case NdisDeviceStateD0:
    3.10 -        KdPrint(("       NdisDeviceStateD0\n"));
    3.11 -        break;
    3.12 -      case NdisDeviceStateD1:
    3.13 -        KdPrint(("       NdisDeviceStateD1\n"));
    3.14 -        break;
    3.15 -      case NdisDeviceStateD2:
    3.16 -        KdPrint(("       NdisDeviceStateD2\n"));
    3.17 -        break;
    3.18 -      case NdisDeviceStateD3:
    3.19 -        KdPrint(("       NdisDeviceStateD3\n"));
    3.20 -        break;
    3.21 -      default:
    3.22 -        KdPrint(("       NdisDeviceState??\n"));
    3.23 -        break;
    3.24 -      }
    3.25 -      status = NDIS_STATUS_SUCCESS;
    3.26 +      xi->new_power_state = *(PNDIS_DEVICE_POWER_STATE)InformationBuffer;
    3.27 +      IoQueueWorkItem(xi->power_workitem, XenNet_SetPower, DelayedWorkQueue, xi);
    3.28 +      status = NDIS_STATUS_PENDING;
    3.29        break;
    3.30      default:
    3.31        KdPrint(("Set Unknown OID 0x%x\n", Oid));