]> xenbits.xensource.com Git - pvdrivers/win/xenvif.git/commitdiff
Make sure XENBUS interfaces are released when going into S4
authorPaul Durrant <paul.durrant@citrix.com>
Thu, 3 Dec 2015 12:23:27 +0000 (12:23 +0000)
committerPaul Durrant <paul.durrant@citrix.com>
Thu, 3 Dec 2015 12:27:46 +0000 (12:27 +0000)
Because a transition into and out of S4 means a new domain is built, it's
crucial that all XENBUS interfaces are released (so that things like
event channels, grant tables and the xenstore ring get re-constructed).

This patch fixes code paths where this was not being done.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xenvif/receiver.c
src/xenvif/transmitter.c
src/xenvif/vif.c

index 20ce0de43b9fcc35e0b8f6030bb7c6775e5caa75..fa27a08fbe9dc6f322ea4459534f2254aaffc391 100644 (file)
@@ -2033,7 +2033,6 @@ __ReceiverRingInitialize(
     )
 {
     PXENVIF_FRONTEND            Frontend;
-    CHAR                        Name[MAXNAMELEN];
     NTSTATUS                    status;
 
     Frontend = Receiver->Frontend;
@@ -2057,86 +2056,14 @@ __ReceiverRingInitialize(
 
     KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
 
-    status = RtlStringCbPrintfA(Name,
-                                sizeof (Name),
-                                "%s_receiver_packet",
-                                (*Ring)->Path);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    for (Index = 0; Name[Index] != '\0'; Index++)
-        if (Name[Index] == '/')
-            Name[Index] = '_';
-
-    status = XENBUS_CACHE(Create,
-                          &Receiver->CacheInterface,
-                          Name,
-                          sizeof (XENVIF_RECEIVER_PACKET),
-                          0,
-                          ReceiverPacketCtor,
-                          ReceiverPacketDtor,
-                          ReceiverRingAcquireLock,
-                          ReceiverRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->PacketCache);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = RtlStringCbPrintfA(Name,
-                                sizeof (Name),
-                                "%s_receiver_fragment",
-                                (*Ring)->Path);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    for (Index = 0; Name[Index] != '\0'; Index++)
-        if (Name[Index] == '/')
-            Name[Index] = '_';
-
-    status = XENBUS_CACHE(Create,
-                          &Receiver->CacheInterface,
-                          Name,
-                          sizeof (XENVIF_RECEIVER_FRAGMENT),
-                          0,
-                          ReceiverFragmentCtor,
-                          ReceiverFragmentDtor,
-                          ReceiverRingAcquireLock,
-                          ReceiverRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->FragmentCache);
-    if (!NT_SUCCESS(status))
-        goto fail6;
-
     status = ThreadCreate(ReceiverRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail3;
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Receiver->CacheInterface,
-                 (*Ring)->FragmentCache);
-    (*Ring)->FragmentCache = NULL;
-
-fail6:
-    Error("fail6\n");
-
-fail5:
-    Error("fail5\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Receiver->CacheInterface,
-                 (*Ring)->PacketCache);
-    (*Ring)->PacketCache = NULL;
-
-fail4:
-    Error("fail4\n");
-
 fail3:
     Error("fail3\n");
 
@@ -2183,7 +2110,7 @@ __ReceiverRingConnect(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver",
+                                "%s_receiver_packet",
                                 Ring->Path);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -2192,6 +2119,56 @@ __ReceiverRingConnect(
         if (Name[Index] == '/')
             Name[Index] = '_';
 
+    status = XENBUS_CACHE(Create,
+                          &Receiver->CacheInterface,
+                          Name,
+                          sizeof (XENVIF_RECEIVER_PACKET),
+                          0,
+                          ReceiverPacketCtor,
+                          ReceiverPacketDtor,
+                          ReceiverRingAcquireLock,
+                          ReceiverRingReleaseLock,
+                          Ring,
+                          &Ring->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RtlStringCbPrintfA(Name,
+                                sizeof (Name),
+                                "%s_receiver_fragment",
+                                Ring->Path);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    for (Index = 0; Name[Index] != '\0'; Index++)
+        if (Name[Index] == '/')
+            Name[Index] = '_';
+
+    status = XENBUS_CACHE(Create,
+                          &Receiver->CacheInterface,
+                          Name,
+                          sizeof (XENVIF_RECEIVER_FRAGMENT),
+                          0,
+                          ReceiverFragmentCtor,
+                          ReceiverFragmentDtor,
+                          ReceiverRingAcquireLock,
+                          ReceiverRingReleaseLock,
+                          Ring,
+                          &Ring->FragmentCache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    status = RtlStringCbPrintfA(Name,
+                                sizeof (Name),
+                                "%s_receiver",
+                                Ring->Path);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    for (Index = 0; Name[Index] != '\0'; Index++)
+        if (Name[Index] == '/')
+            Name[Index] = '_';
+
     status = XENBUS_GNTTAB(CreateCache,
                            &Receiver->GnttabInterface,
                            Name,
@@ -2201,13 +2178,13 @@ __ReceiverRingConnect(
                            Ring,
                            &Ring->GnttabCache);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail6;
 
     Ring->Mdl = __AllocatePage();
 
     status = STATUS_NO_MEMORY;
     if (Ring->Mdl == NULL)
-        goto fail3;
+        goto fail7;
 
     Ring->Shared = MmGetSystemAddressForMdlSafe(Ring->Mdl, NormalPagePriority);
     ASSERT(Ring->Shared != NULL);
@@ -2227,14 +2204,14 @@ __ReceiverRingConnect(
                            FALSE,
                            &Ring->Entry);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail8;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 __MODULE__ "|RECEIVER[%u]",
                                 Ring->Index);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail9;
 
     ASSERT(!Ring->Connected);
 
@@ -2248,7 +2225,7 @@ __ReceiverRingConnect(
 
     status = STATUS_UNSUCCESSFUL;
     if (Ring->Channel == NULL)
-        goto fail6;
+        goto fail10;
 
     status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
     ASSERT(NT_SUCCESS(status));
@@ -2275,12 +2252,12 @@ __ReceiverRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail11;
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
+fail11:
+    Error("fail11\n");
 
     Ring->Connected = FALSE;
 
@@ -2291,11 +2268,11 @@ fail7:
 
     Ring->Events = 0;
 
-fail6:
-    Error("fail6\n");
+fail10:
+    Error("fail10\n");
 
-fail5:
-    Error("fail5\n");
+fail9:
+    Error("fail9\n");
 
     (VOID) XENBUS_GNTTAB(RevokeForeignAccess,
                          &Receiver->GnttabInterface,
@@ -2304,8 +2281,8 @@ fail5:
                          Ring->Entry);
     Ring->Entry = NULL;
 
-fail4:
-    Error("fail4\n");
+fail8:
+    Error("fail8\n");
 
     RtlZeroMemory(&Ring->Front, sizeof (netif_rx_front_ring_t));
     RtlZeroMemory(Ring->Shared, PAGE_SIZE);
@@ -2314,14 +2291,36 @@ fail4:
     __FreePage(Ring->Mdl);
     Ring->Mdl = NULL;
 
-fail3:
-    Error("fail3\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_GNTTAB(DestroyCache,
                   &Receiver->GnttabInterface,
                   Ring->GnttabCache);
     Ring->GnttabCache = NULL;
 
+fail6:
+    Error("fail6\n");
+
+fail5:
+    Error("fail5\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Receiver->CacheInterface,
+                 Ring->FragmentCache);
+    Ring->FragmentCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Receiver->CacheInterface,
+                 Ring->PacketCache);
+    Ring->PacketCache = NULL;
+
 fail2:
     Error("fail2\n");
 
@@ -2494,6 +2493,16 @@ __ReceiverRingDisconnect(
                   &Receiver->GnttabInterface,
                   Ring->GnttabCache);
     Ring->GnttabCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Receiver->CacheInterface,
+                 Ring->FragmentCache);
+    Ring->FragmentCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Receiver->CacheInterface,
+                 Ring->PacketCache);
+    Ring->PacketCache = NULL;
 }
 
 static FORCEINLINE VOID
@@ -2516,16 +2525,6 @@ __ReceiverRingTeardown(
     ThreadJoin(Ring->WatchdogThread);
     Ring->WatchdogThread = NULL;
 
-    XENBUS_CACHE(Destroy,
-                 &Receiver->CacheInterface,
-                 Ring->FragmentCache);
-    Ring->FragmentCache = NULL;
-
-    XENBUS_CACHE(Destroy,
-                 &Receiver->CacheInterface,
-                 Ring->PacketCache);
-    Ring->PacketCache = NULL;
-
     ASSERT(IsListEmpty(&Ring->PacketList));
     RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));
 
@@ -2664,17 +2663,13 @@ ReceiverInitialize(
 
     (*Receiver)->Frontend = Frontend;
 
-    status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
     (*Receiver)->MaxQueues = FrontendGetMaxQueues(Frontend);
     (*Receiver)->Ring = __ReceiverAllocate(sizeof (PXENVIF_RECEIVER_RING) *
                                            (*Receiver)->MaxQueues);
 
     status = STATUS_NO_MEMORY;
     if ((*Receiver)->Ring == NULL)
-        goto fail3;
+        goto fail2;
 
     Index = 0;
     while (Index < (*Receiver)->MaxQueues) {
@@ -2682,7 +2677,7 @@ ReceiverInitialize(
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail3;
 
         (*Receiver)->Ring[Index] = Ring;
         Index++;
@@ -2690,8 +2685,8 @@ ReceiverInitialize(
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
+fail3:
+    Error("fail3\n");
 
     while (--Index >= 0) {
         PXENVIF_RECEIVER_RING   Ring = (*Receiver)->Ring[Index];
@@ -2701,18 +2696,13 @@ fail4:
     }
 
     __ReceiverFree((*Receiver)->Ring);
-    (*Receiver)->Ring = NULL;
-
-fail3:
-    Error("fail3\n");
-
-    (*Receiver)->MaxQueues = 0;
 
-    XENBUS_CACHE(Release, &(*Receiver)->CacheInterface);
+    (*Receiver)->Ring = NULL;
 
 fail2:
     Error("fail2\n");
 
+    (*Receiver)->MaxQueues = 0;
     (*Receiver)->Frontend = NULL;
 
     RtlZeroMemory(&(*Receiver)->EvtchnInterface,
@@ -2774,10 +2764,14 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = XENBUS_GNTTAB(Acquire, &Receiver->GnttabInterface);
+    status = XENBUS_CACHE(Acquire, &Receiver->CacheInterface);
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = XENBUS_GNTTAB(Acquire, &Receiver->GnttabInterface);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     status = XENBUS_STORE(Read,
                           &Receiver->StoreInterface,
                           NULL,
@@ -2803,7 +2797,7 @@ ReceiverConnect(
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail6;
 
         Index++;
     }    
@@ -2815,18 +2809,18 @@ ReceiverConnect(
                           Receiver,
                           &Receiver->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     Index = Receiver->NumQueues;
 
-fail5:
-    Error("fail5\n");
+fail6:
+    Error("fail6\n");
 
     while (--Index >= 0) {
         PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
@@ -2838,6 +2832,11 @@ fail5:
 
     XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_CACHE(Release, &Receiver->CacheInterface);
+
 fail4:
     Error("fail4\n");
 
@@ -3116,6 +3115,8 @@ ReceiverDisconnect(
 
     XENBUS_GNTTAB(Release, &Receiver->GnttabInterface);
 
+    XENBUS_CACHE(Release, &Receiver->CacheInterface);
+
     XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
 
     XENBUS_STORE(Release, &Receiver->StoreInterface);
@@ -3151,8 +3152,6 @@ ReceiverTeardown(
     Receiver->Ring = NULL;
     Receiver->MaxQueues = 0;
 
-    XENBUS_CACHE(Release, &Receiver->CacheInterface);
-
     Receiver->Frontend = NULL;
 
     RtlZeroMemory(&Receiver->EvtchnInterface,
index 54c74eca6aeef6b428190dfec84d11044d944e04..4b47fd878c6c24f9063ade5a8a823b20f7145a6a 100644 (file)
@@ -3089,7 +3089,6 @@ __TransmitterRingInitialize(
     )
 {
     PXENVIF_FRONTEND                Frontend;
-    CHAR                            Name[MAXNAMELEN];
     NTSTATUS                        status;
 
     Frontend = Transmitter->Frontend;
@@ -3113,12 +3112,66 @@ __TransmitterRingInitialize(
 
     KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
+    status = ThreadCreate(TransmitterRingWatchdog,
+                          *Ring,
+                          &(*Ring)->WatchdogThread);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
+    RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));
+    RtlZeroMemory(&(*Ring)->RequestQueue, sizeof (LIST_ENTRY));
+    RtlZeroMemory(&(*Ring)->PacketQueue, sizeof (LIST_ENTRY));
+
+    FrontendFreePath(Frontend, (*Ring)->Path);
+    (*Ring)->Path = NULL;
+
+fail2:
+    Error("fail2\n");
+
+    (*Ring)->Index = 0;
+    (*Ring)->Transmitter = NULL;
+
+    ASSERT(IsZeroMemory(*Ring, sizeof (XENVIF_TRANSMITTER_RING)));
+    __TransmitterFree(*Ring);
+    *Ring = NULL;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static FORCEINLINE NTSTATUS
+__TransmitterRingConnect(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    PXENVIF_TRANSMITTER             Transmitter;
+    PXENVIF_FRONTEND                Frontend;
+    PFN_NUMBER                      Pfn;
+    CHAR                            Name[MAXNAMELEN];
+    ULONG                           Index;
+    PROCESSOR_NUMBER                ProcNumber;
+    NTSTATUS                        status;
+
+    ASSERT(!Ring->Connected);
+
+    Transmitter = Ring->Transmitter;
+    Frontend = Transmitter->Frontend;
+
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_buffer",
-                                (*Ring)->Path);
+                                Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail1;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3133,17 +3186,17 @@ __TransmitterRingInitialize(
                           TransmitterBufferDtor,
                           TransmitterRingAcquireLock,
                           TransmitterRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->BufferCache);
+                          Ring,
+                          &Ring->BufferCache);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail2;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_multicast_control",
-                                (*Ring)->Path);
+                                Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3158,17 +3211,17 @@ __TransmitterRingInitialize(
                           TransmitterMulticastControlDtor,
                           TransmitterRingAcquireLock,
                           TransmitterRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->MulticastControlCache);
+                          Ring,
+                          &Ring->MulticastControlCache);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_req_id",
-                                (*Ring)->Path);
+                                Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3177,24 +3230,24 @@ __TransmitterRingInitialize(
     status = XENBUS_RANGE_SET(Create,
                               &Transmitter->RangeSetInterface,
                               Name,
-                              &(*Ring)->RangeSet);
+                              &Ring->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail6;
 
     status = XENBUS_RANGE_SET(Put,
                               &Transmitter->RangeSetInterface,
-                              (*Ring)->RangeSet,
+                              Ring->RangeSet,
                               1,
                               XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail7;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_fragment",
-                                (*Ring)->Path);
+                                Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail8;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3209,17 +3262,17 @@ __TransmitterRingInitialize(
                           TransmitterFragmentDtor,
                           TransmitterRingAcquireLock,
                           TransmitterRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->FragmentCache);
+                          Ring,
+                          &Ring->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail9;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_request",
-                                (*Ring)->Path);
+                                Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail10;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3234,135 +3287,17 @@ __TransmitterRingInitialize(
                           TransmitterRequestDtor,
                           TransmitterRingAcquireLock,
                           TransmitterRingReleaseLock,
-                          *Ring,
-                          &(*Ring)->RequestCache);
-    if (!NT_SUCCESS(status))
-        goto fail13;
-
-    status = ThreadCreate(TransmitterRingWatchdog,
-                          *Ring,
-                          &(*Ring)->WatchdogThread);
+                          Ring,
+                          &Ring->RequestCache);
     if (!NT_SUCCESS(status))
-        goto fail14;
-
-    return STATUS_SUCCESS;
-
-fail14:
-    Error("fail14\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 (*Ring)->RequestCache);
-    (*Ring)->RequestCache = NULL;
-
-fail13:
-    Error("fail13\n");
-
-fail12:
-    Error("fail12\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 (*Ring)->FragmentCache);
-    (*Ring)->FragmentCache = NULL;
-
-fail11:
-    Error("fail11\n");
-
-fail10:
-    Error("fail10\n");
-
-    (VOID) XENBUS_RANGE_SET(Get,
-                            &Transmitter->RangeSetInterface,
-                            (*Ring)->RangeSet,
-                            1,
-                            XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
-
-fail9:
-    Error("fail9\n");
-
-    XENBUS_RANGE_SET(Destroy,
-                     &Transmitter->RangeSetInterface,
-                     (*Ring)->RangeSet);
-    (*Ring)->RangeSet = NULL;
-
-fail8:
-    Error("fail8\n");
-
-fail7:
-    Error("fail7\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 (*Ring)->MulticastControlCache);
-    (*Ring)->MulticastControlCache = NULL;
-
-fail6:
-    Error("fail6\n");
-
-fail5:
-    Error("fail5\n");
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 (*Ring)->BufferCache);
-    (*Ring)->BufferCache = NULL;
-
-fail4:
-    Error("fail4\n");
-
-fail3:
-    Error("fail3\n");
-
-    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
-
-    RtlZeroMemory(&(*Ring)->PacketComplete, sizeof (LIST_ENTRY));
-    RtlZeroMemory(&(*Ring)->RequestQueue, sizeof (LIST_ENTRY));
-    RtlZeroMemory(&(*Ring)->PacketQueue, sizeof (LIST_ENTRY));
-
-    FrontendFreePath(Frontend, (*Ring)->Path);
-    (*Ring)->Path = NULL;
-
-fail2:
-    Error("fail2\n");
-
-    (*Ring)->Index = 0;
-    (*Ring)->Transmitter = NULL;
-
-    ASSERT(IsZeroMemory(*Ring, sizeof (XENVIF_TRANSMITTER_RING)));
-    __TransmitterFree(*Ring);
-    *Ring = NULL;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-static FORCEINLINE NTSTATUS
-__TransmitterRingConnect(
-    IN  PXENVIF_TRANSMITTER_RING    Ring
-    )
-{
-    PXENVIF_TRANSMITTER             Transmitter;
-    PXENVIF_FRONTEND                Frontend;
-    PFN_NUMBER                      Pfn;
-    CHAR                            Name[MAXNAMELEN];
-    ULONG                           Index;
-    PROCESSOR_NUMBER                ProcNumber;
-    NTSTATUS                        status;
-
-    ASSERT(!Ring->Connected);
-
-    Transmitter = Ring->Transmitter;
-    Frontend = Transmitter->Frontend;
+        goto fail11;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter",
                                 Ring->Path);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail12;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -3377,13 +3312,13 @@ __TransmitterRingConnect(
                            Ring,
                            &Ring->GnttabCache);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail13;
 
     Ring->Mdl = __AllocatePage();
 
     status = STATUS_NO_MEMORY;
     if (Ring->Mdl == NULL)
-        goto fail3;
+        goto fail14;
 
     Ring->Shared = MmGetSystemAddressForMdlSafe(Ring->Mdl, NormalPagePriority);
     ASSERT(Ring->Shared != NULL);
@@ -3403,14 +3338,14 @@ __TransmitterRingConnect(
                            FALSE,
                            &Ring->Entry);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail15;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 __MODULE__ "|TRANSMITTER[%u]",
                                 Ring->Index);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail16;
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
@@ -3425,7 +3360,7 @@ __TransmitterRingConnect(
 
         status = STATUS_UNSUCCESSFUL;
         if (Ring->Channel == NULL)
-            goto fail6;
+            goto fail17;
 
         status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
         ASSERT(NT_SUCCESS(status));
@@ -3451,14 +3386,14 @@ __TransmitterRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail18;
 
     Ring->Connected = TRUE;
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
+fail18:
+    Error("fail18\n");
 
     XENBUS_EVTCHN(Close,
                   &Transmitter->EvtchnInterface,
@@ -3467,11 +3402,11 @@ fail7:
 
     Ring->Events = 0;
 
-fail6:
-    Error("fail6\n");
+fail17:
+    Error("fail17\n");
 
-fail5:
-    Error("fail5\n");
+fail16:
+    Error("fail16\n");
 
     (VOID) XENBUS_GNTTAB(RevokeForeignAccess,
                          &Transmitter->GnttabInterface,
@@ -3480,8 +3415,8 @@ fail5:
                          Ring->Entry);
     Ring->Entry = NULL;
 
-fail4:
-    Error("fail4\n");
+fail15:
+    Error("fail15\n");
 
     RtlZeroMemory(&Ring->Front, sizeof (netif_tx_front_ring_t));
     RtlZeroMemory(Ring->Shared, PAGE_SIZE);
@@ -3490,14 +3425,78 @@ fail4:
     __FreePage(Ring->Mdl);
     Ring->Mdl = NULL;
 
-fail3:
-    Error("fail3\n");
+fail14:
+    Error("fail14\n");
 
     XENBUS_GNTTAB(DestroyCache,
                   &Transmitter->GnttabInterface,
                   Ring->GnttabCache);
     Ring->GnttabCache = NULL;
 
+fail13:
+    Error("fail13\n");
+
+fail12:
+    Error("fail12\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->RequestCache);
+    Ring->RequestCache = NULL;
+
+fail11:
+    Error("fail11\n");
+
+fail10:
+    Error("fail10\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->FragmentCache);
+    Ring->FragmentCache = NULL;
+
+fail9:
+    Error("fail9\n");
+
+fail8:
+    Error("fail8\n");
+
+    (VOID) XENBUS_RANGE_SET(Get,
+                            &Transmitter->RangeSetInterface,
+                            Ring->RangeSet,
+                            1,
+                            XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
+
+fail7:
+    Error("fail7\n");
+
+    XENBUS_RANGE_SET(Destroy,
+                     &Transmitter->RangeSetInterface,
+                     Ring->RangeSet);
+    Ring->RangeSet = NULL;
+
+fail6:
+    Error("fail6\n");
+
+fail5:
+    Error("fail5\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->MulticastControlCache);
+    Ring->MulticastControlCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->BufferCache);
+    Ring->BufferCache = NULL;
+
 fail2:
     Error("fail2\n");
 
@@ -3729,6 +3728,37 @@ __TransmitterRingDisconnect(
                   &Transmitter->GnttabInterface,
                   Ring->GnttabCache);
     Ring->GnttabCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->RequestCache);
+    Ring->RequestCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->FragmentCache);
+    Ring->FragmentCache = NULL;
+
+    (VOID) XENBUS_RANGE_SET(Get,
+                            &Transmitter->RangeSetInterface,
+                            Ring->RangeSet,
+                            1,
+                            XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
+
+    XENBUS_RANGE_SET(Destroy,
+                     &Transmitter->RangeSetInterface,
+                     Ring->RangeSet);
+    Ring->RangeSet = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->MulticastControlCache);
+    Ring->MulticastControlCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Ring->BufferCache);
+    Ring->BufferCache = NULL;
 }
 
 static FORCEINLINE VOID
@@ -3763,37 +3793,6 @@ __TransmitterRingTeardown(
     ThreadJoin(Ring->WatchdogThread);
     Ring->WatchdogThread = NULL;
 
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 Ring->RequestCache);
-    Ring->RequestCache = NULL;
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 Ring->FragmentCache);
-    Ring->FragmentCache = NULL;
-
-    (VOID) XENBUS_RANGE_SET(Get,
-                            &Transmitter->RangeSetInterface,
-                            Ring->RangeSet,
-                            1,
-                            XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
-
-    XENBUS_RANGE_SET(Destroy,
-                     &Transmitter->RangeSetInterface,
-                     Ring->RangeSet);
-    Ring->RangeSet = NULL;
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 Ring->MulticastControlCache);
-    Ring->MulticastControlCache = NULL;
-
-    XENBUS_CACHE(Destroy,
-                 &Transmitter->CacheInterface,
-                 Ring->BufferCache);
-    Ring->BufferCache = NULL;
-
     ASSERT(IsListEmpty(&Ring->PacketComplete));
     RtlZeroMemory(&Ring->PacketComplete, sizeof (LIST_ENTRY));
 
@@ -4126,21 +4125,13 @@ TransmitterInitialize(
     (*Transmitter)->Frontend = Frontend;
     KeInitializeSpinLock(&(*Transmitter)->Lock);
 
-    status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = XENBUS_CACHE(Acquire, &(*Transmitter)->CacheInterface);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
     (*Transmitter)->MaxQueues = FrontendGetMaxQueues(Frontend);
     (*Transmitter)->Ring = __TransmitterAllocate(sizeof (PXENVIF_TRANSMITTER_RING) *
                                                  (*Transmitter)->MaxQueues);
 
     status = STATUS_NO_MEMORY;
     if ((*Transmitter)->Ring == NULL)
-        goto fail4;
+        goto fail2;
 
     Index = 0;
     while (Index < (*Transmitter)->MaxQueues) {
@@ -4148,7 +4139,7 @@ TransmitterInitialize(
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail3;
 
         (*Transmitter)->Ring[Index] = Ring;
         Index++;
@@ -4156,8 +4147,8 @@ TransmitterInitialize(
 
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
+fail3:
+    Error("fail3\n");
 
     while (--Index > 0) {
         PXENVIF_TRANSMITTER_RING    Ring = (*Transmitter)->Ring[Index];
@@ -4169,21 +4160,11 @@ fail5:
     __TransmitterFree((*Transmitter)->Ring);
     (*Transmitter)->Ring = NULL;
 
-fail4:
-    Error("fail4\n");
-
-    (*Transmitter)->MaxQueues = 0;
-
-    XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
-
-fail3:
-    Error("fail3\n");
-
-    XENBUS_RANGE_SET(Release, &(*Transmitter)->RangeSetInterface);
-
 fail2:
     Error("fail2\n");
 
+    (*Transmitter)->MaxQueues = 0;
+
     (*Transmitter)->Frontend = NULL;
 
     RtlZeroMemory(&(*Transmitter)->Lock,
@@ -4244,16 +4225,24 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = XENBUS_GNTTAB(Acquire, &Transmitter->GnttabInterface);
+    status = XENBUS_RANGE_SET(Acquire, &Transmitter->RangeSetInterface);
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = XENBUS_CACHE(Acquire, &Transmitter->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    status = XENBUS_GNTTAB(Acquire, &Transmitter->GnttabInterface);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
                                 "%s_transmitter_packet",
                                 FrontendGetPath(Frontend));
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail7;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -4271,7 +4260,7 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->PacketCache);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     status = XENBUS_STORE(Read,
                           &Transmitter->StoreInterface,
@@ -4314,7 +4303,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail7;
+            goto fail9;
 
         Index++;
     }    
@@ -4326,18 +4315,18 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail10;
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail8:
-    Error("fail8\n");
+fail10:
+    Error("fail10\n");
 
     Index = Transmitter->NumQueues;
 
-fail7:
-    Error("fail7\n");
+fail9:
+    Error("fail9\n");
 
     while (--Index >= 0) {
         PXENVIF_TRANSMITTER_RING    Ring;
@@ -4354,13 +4343,23 @@ fail7:
                  Transmitter->PacketCache);
     Transmitter->PacketCache = NULL;
 
+fail8:
+    Error("fail8\n");
+
+fail7:
+    Error("fail7\n");
+
+    XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface);
+
 fail6:
     Error("fail6\n");
 
+    XENBUS_CACHE(Release, &Transmitter->CacheInterface);
+
 fail5:
     Error("fail5\n");
 
-    XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface);
+    XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
 
 fail4:
     Error("fail4\n");
@@ -4503,6 +4502,10 @@ TransmitterDisconnect(
 
     XENBUS_GNTTAB(Release, &Transmitter->GnttabInterface);
 
+    XENBUS_CACHE(Release, &Transmitter->CacheInterface);
+
+    XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
+
     XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
@@ -4537,10 +4540,6 @@ TransmitterTeardown(
     Transmitter->Ring = NULL;
     Transmitter->MaxQueues = 0;
 
-    XENBUS_CACHE(Release, &Transmitter->CacheInterface);
-
-    XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
-
     Transmitter->Frontend = NULL;
 
     RtlZeroMemory(&Transmitter->Lock,
index b2bbf058e68c782324f89907325457a998373ab1..de39b027f72c27df344e513dac1e590506c1ebc8 100644 (file)
@@ -115,6 +115,26 @@ VifMac(
     return STATUS_SUCCESS;
 }
 
+static DECLSPEC_NOINLINE VOID
+VifSuspendCallbackLate(
+    IN  PVOID           Argument
+    )
+{
+    PXENVIF_VIF_CONTEXT Context = Argument;
+    NTSTATUS            status;
+
+    if (!Context->Enabled)
+        return;
+
+    status = FrontendSetState(Context->Frontend, FRONTEND_ENABLED);
+    ASSERT(NT_SUCCESS(status));
+
+    // We do this three times to make sure switches take note
+    FrontendAdvertiseIpAddresses(Context->Frontend);
+    FrontendAdvertiseIpAddresses(Context->Frontend);
+    FrontendAdvertiseIpAddresses(Context->Frontend);
+}
+
 static NTSTATUS
 VifEnable(
     IN  PINTERFACE          Interface,
@@ -124,11 +144,13 @@ VifEnable(
 {
     PXENVIF_VIF_CONTEXT     Context = Interface->Context;
     KIRQL                   Irql;
+    BOOLEAN                 Exclusive;
     NTSTATUS                status;
 
     Trace("====>\n");
 
     AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    Exclusive = TRUE;
 
     if (Context->Enabled)
         goto done;
@@ -140,24 +162,74 @@ VifEnable(
 
     KeMemoryBarrier();
 
-    status = FrontendSetState(Context->Frontend, FRONTEND_ENABLED);
+    status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    status = FrontendSetState(Context->Frontend, FRONTEND_ENABLED);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = XENBUS_SUSPEND(Register,
+                            &Context->SuspendInterface,
+                            SUSPEND_CALLBACK_LATE,
+                            VifSuspendCallbackLate,
+                            Context,
+                            &Context->SuspendCallbackLate);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
 done:
+    ASSERT(Exclusive);
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
+    (VOID) FrontendSetState(Context->Frontend, FRONTEND_CONNECTED);
+
+    ReleaseMrswLockExclusive(&Context->Lock, Irql, TRUE);
+    Exclusive = FALSE;
+
+    ReceiverWaitForPackets(FrontendGetReceiver(Context->Frontend));
+    TransmitterAbortPackets(FrontendGetTransmitter(Context->Frontend));
+
+    Trace("waiting for mac thread..\n");
+
+    KeClearEvent(&Context->MacEvent);
+    ThreadWake(Context->MacThread);
+
+    (VOID) KeWaitForSingleObject(&Context->MacEvent,
+                                 Executive,
+                                 KernelMode,
+                                 FALSE,
+                                 NULL);
+
+    Trace("done\n");
+
+fail2:
+    Error("fail2\n");
+
+    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    Context->Enabled = FALSE;
+
+    KeMemoryBarrier();
+
     Context->Argument = NULL;
     Context->Callback = NULL;
 
-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    if (Exclusive)
+        ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    else
+        ReleaseMrswLockShared(&Context->Lock);
 
     return status;
 }
@@ -183,6 +255,11 @@ VifDisable(
 
     KeMemoryBarrier();
 
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
+
     (VOID) FrontendSetState(Context->Frontend, FRONTEND_CONNECTED);
 
     ReleaseMrswLockExclusive(&Context->Lock, Irql, TRUE);
@@ -203,6 +280,8 @@ VifDisable(
 
     Trace("done\n");
 
+    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
+
     Context->Argument = NULL;
     Context->Callback = NULL;
 
@@ -592,26 +671,6 @@ VifTransmitterQueryRingSize(
     ReleaseMrswLockShared(&Context->Lock);
 }
 
-static DECLSPEC_NOINLINE VOID
-VifSuspendCallbackLate(
-    IN  PVOID           Argument
-    )
-{
-    PXENVIF_VIF_CONTEXT Context = Argument;
-    NTSTATUS            status;
-
-    if (!Context->Enabled)
-        return;
-
-    status = FrontendSetState(Context->Frontend, FRONTEND_ENABLED);
-    ASSERT(NT_SUCCESS(status));
-
-    // We do this three times to make sure switches take note
-    FrontendAdvertiseIpAddresses(Context->Frontend);
-    FrontendAdvertiseIpAddresses(Context->Frontend);
-    FrontendAdvertiseIpAddresses(Context->Frontend);
-}
-
 static NTSTATUS
 VifAcquire(
     PINTERFACE              Interface
@@ -619,7 +678,6 @@ VifAcquire(
 {
     PXENVIF_VIF_CONTEXT     Context = Interface->Context;
     KIRQL                   Irql;
-    NTSTATUS                status;
 
     AcquireMrswLockExclusive(&Context->Lock, &Irql);
 
@@ -628,19 +686,6 @@ VifAcquire(
 
     Trace("====>\n");
 
-    status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
-    if (!NT_SUCCESS(status))
-        goto fail1;   
-
-    status = XENBUS_SUSPEND(Register,
-                            &Context->SuspendInterface,
-                            SUSPEND_CALLBACK_LATE,
-                            VifSuspendCallbackLate,
-                            Context,
-                            &Context->SuspendCallbackLate);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
     Context->Frontend = PdoGetFrontend(Context->Pdo);
 
     Trace("<====\n");
@@ -649,20 +694,6 @@ done:
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
 
     return STATUS_SUCCESS;
-
-fail2:
-    Error("fail2\n");
-
-    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    --Context->References;
-    ASSERT3U(Context->References, ==, 0);
-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
-
-    return status;
 }
 
 VOID
@@ -684,13 +715,6 @@ VifRelease(
 
     Context->Frontend = NULL;
 
-    XENBUS_SUSPEND(Deregister,
-                   &Context->SuspendInterface,
-                   Context->SuspendCallbackLate);
-    Context->SuspendCallbackLate = NULL;
-
-    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
-
     Trace("<====\n");
 
 done: