- Rewrite request queuing
authorCameron Gutman <aicommander@gmail.com>
Fri, 8 Jan 2010 19:15:03 +0000 (19:15 +0000)
committerCameron Gutman <aicommander@gmail.com>
Fri, 8 Jan 2010 19:15:03 +0000 (19:15 +0000)
 - We now use the documented members of NDIS_MINIPORT_BLOCK
 - It also fixes the issue of determining if the miniport is currently processing a request
 - Remove unneeded IRQL raises
 - Half-plement MiniSendResourcesAvailable (NdisMSendResourcesAvailable)
 - Comment out the code inside ProSendPackets (only used by protocols, not miniports)

svn path=/branches/aicom-network-branch/; revision=45009

drivers/network/ndis/include/miniport.h
drivers/network/ndis/ndis/miniport.c
drivers/network/ndis/ndis/protocol.c

index 32aab60..69fa9a2 100644 (file)
@@ -90,8 +90,6 @@ typedef struct _NDIS_WRAPPER_CONTEXT {
 typedef struct _LOGICAL_ADAPTER
 {
     NDIS_MINIPORT_BLOCK         NdisMiniportBlock;      /* NDIS defined fields */
 typedef struct _LOGICAL_ADAPTER
 {
     NDIS_MINIPORT_BLOCK         NdisMiniportBlock;      /* NDIS defined fields */
-    PNDIS_MINIPORT_WORK_ITEM    WorkQueueHead;          /* Head of work queue */
-    PNDIS_MINIPORT_WORK_ITEM    WorkQueueTail;          /* Tail of work queue */
     LIST_ENTRY                  ListEntry;              /* Entry on global list */
     LIST_ENTRY                  MiniportListEntry;      /* Entry on miniport driver list */
     LIST_ENTRY                  ProtocolListHead;       /* List of bound protocols */
     LIST_ENTRY                  ListEntry;              /* Entry on global list */
     LIST_ENTRY                  MiniportListEntry;      /* Entry on miniport driver list */
     LIST_ENTRY                  ProtocolListHead;       /* List of bound protocols */
@@ -142,20 +140,22 @@ MiniQueryInformation(
     PVOID               Buffer,
     PULONG              BytesWritten);
 
     PVOID               Buffer,
     PULONG              BytesWritten);
 
-VOID
-FASTCALL
-MiniQueueWorkItem(
+NDIS_STATUS
+MiniBeginRequest(
     PLOGICAL_ADAPTER    Adapter,
     NDIS_WORK_ITEM_TYPE WorkItemType,
     PLOGICAL_ADAPTER    Adapter,
     NDIS_WORK_ITEM_TYPE WorkItemType,
-    PVOID               WorkItemContext,
-    BOOLEAN             Top);
+    PVOID               WorkItemContext);
 
 NDIS_STATUS
 
 NDIS_STATUS
-FASTCALL
-MiniDequeueWorkItem(
+MiniQueueWorkItemHead(
+    PLOGICAL_ADAPTER    Adapter,
+    NDIS_WORK_ITEM_TYPE WorkItemType,
+    PVOID               WorkItemContext);
+
+VOID
+MiniEndRequest(
     PLOGICAL_ADAPTER    Adapter,
     PLOGICAL_ADAPTER    Adapter,
-    NDIS_WORK_ITEM_TYPE *WorkItemType,
-    PVOID               *WorkItemContext);
+    NDIS_WORK_ITEM_TYPE WorkItemType);
 
 NDIS_STATUS
 MiniDoRequest(
 
 NDIS_STATUS
 MiniDoRequest(
index 05c750d..aa5f7b2 100644 (file)
@@ -121,55 +121,6 @@ MiniDisplayPacket2(
 #endif /* DBG */
 }
 
 #endif /* DBG */
 }
 
-PNDIS_MINIPORT_WORK_ITEM
-MiniGetFirstWorkItem(
-    PLOGICAL_ADAPTER Adapter,
-    NDIS_WORK_ITEM_TYPE Type)
-{
-    PNDIS_MINIPORT_WORK_ITEM CurrentEntry = Adapter->WorkQueueHead;
-
-    while (CurrentEntry)
-    {
-      if (CurrentEntry->WorkItemType == Type)
-          return CurrentEntry;
-
-      CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
-    }
-
-    return NULL;
-}
-
-BOOLEAN
-MiniIsBusy(
-    PLOGICAL_ADAPTER Adapter,
-    NDIS_WORK_ITEM_TYPE Type)
-{
-    BOOLEAN Busy = FALSE;
-    KIRQL OldIrql;
-
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-
-    if (Type == NdisWorkItemRequest &&
-        (Adapter->NdisMiniportBlock.PendingRequest || MiniGetFirstWorkItem(Adapter, NdisWorkItemRequest)))
-    {
-       Busy = TRUE;
-    }
-    else if (Type == NdisWorkItemSend &&
-             (Adapter->NdisMiniportBlock.FirstPendingPacket || MiniGetFirstWorkItem(Adapter, NdisWorkItemSend)))
-    {
-       Busy = TRUE;
-    }
-    else if (Type == NdisWorkItemResetRequested &&
-             (Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING || MiniGetFirstWorkItem(Adapter, NdisWorkItemResetRequested)))
-    {
-       Busy = TRUE;
-    }
-
-    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-    return Busy;
-}
-
 \f
 VOID
 MiniIndicateData(
 \f
 VOID
 MiniIndicateData(
@@ -316,6 +267,7 @@ MiniIndicateReceivePacket(
               if (!LookAheadBuffer)
               {
                   NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
               if (!LookAheadBuffer)
               {
                   NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
+                  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
                   return;
               }
 
                   return;
               }
 
@@ -357,6 +309,8 @@ MiniResetComplete(
     PADAPTER_BINDING AdapterBinding;
     KIRQL OldIrql;
 
     PADAPTER_BINDING AdapterBinding;
     KIRQL OldIrql;
 
+    MiniEndRequest(Adapter, NdisWorkItemResetRequested);
+
     if (AddressingReset)
         MiniDoAddressingReset(Adapter);
 
     if (AddressingReset)
         MiniDoAddressingReset(Adapter);
 
@@ -365,8 +319,6 @@ MiniResetComplete(
 
     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
 
 
     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
 
-    Adapter->NdisMiniportBlock.ResetStatus = Status;
-
     CurrentEntry = Adapter->ProtocolListHead.Flink;
 
     while (CurrentEntry != &Adapter->ProtocolListHead)
     CurrentEntry = Adapter->ProtocolListHead.Flink;
 
     while (CurrentEntry != &Adapter->ProtocolListHead)
@@ -395,11 +347,11 @@ MiniRequestComplete(
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-
-    KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
     Request = Adapter->NdisMiniportBlock.PendingRequest;
     Request = Adapter->NdisMiniportBlock.PendingRequest;
-    KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+    MiniEndRequest(Adapter, NdisWorkItemRequest);
 
     MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
 
 
     MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
 
@@ -409,12 +361,22 @@ MiniRequestComplete(
             Request,
             Status);
     }
             Request,
             Status);
     }
+}
 
 
-    KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-    Adapter->NdisMiniportBlock.PendingRequest = NULL;
-    KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+VOID NTAPI
+MiniIndicateComplete(
+    IN  NDIS_HANDLE     MiniportAdapterHandle,
+    IN  PNDIS_PACKET    Packet,
+    IN  NDIS_STATUS     Status)
+{
+    PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
+
+    MiniEndRequest(MiniportAdapterHandle, NdisWorkItemSendLoopback);
 
 
-    KeLowerIrql(OldIrql);
+    (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
+        AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+        Packet,
+        Status);
 }
 
 VOID NTAPI
 }
 
 VOID NTAPI
@@ -440,8 +402,6 @@ MiniSendComplete(
 
     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
 
 
     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
 
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-
     if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
     {
         NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
     if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
     {
         NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
@@ -449,35 +409,51 @@ MiniSendComplete(
         SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                                   ScatterGatherListPacketInfo);
 
         SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                                   ScatterGatherListPacketInfo);
 
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
         Adapter->NdisMiniportBlock.SystemAdapterObject->
             DmaOperations->PutScatterGatherList(
                            Adapter->NdisMiniportBlock.SystemAdapterObject,
                            SGList,
                            TRUE);
 
         Adapter->NdisMiniportBlock.SystemAdapterObject->
             DmaOperations->PutScatterGatherList(
                            Adapter->NdisMiniportBlock.SystemAdapterObject,
                            SGList,
                            TRUE);
 
+        KeLowerIrql(OldIrql);
+
         NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                          ScatterGatherListPacketInfo) = NULL;
     }
 
         NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
                                          ScatterGatherListPacketInfo) = NULL;
     }
 
+    MiniEndRequest(Adapter, NdisWorkItemSend);
+
     (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
         Status);
     (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
         Status);
-
-    KeLowerIrql(OldIrql);
 }
 
 }
 
+NDIS_STATUS
+SignalQueue(PLOGICAL_ADAPTER Adapter)
+{
+    PIO_WORKITEM WorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
+
+    ASSERT(WorkItem);
+    if (!WorkItem) return NDIS_STATUS_RESOURCES;
+
+    IoQueueWorkItem(WorkItem,
+                    MiniportWorker,
+                    DelayedWorkQueue,
+                    WorkItem);
+
+    return NDIS_STATUS_SUCCESS;
+}
 
 VOID NTAPI
 MiniSendResourcesAvailable(
     IN  NDIS_HANDLE MiniportAdapterHandle)
 {
 
 VOID NTAPI
 MiniSendResourcesAvailable(
     IN  NDIS_HANDLE MiniportAdapterHandle)
 {
-/*
-    UNIMPLEMENTED
-*/
+    SignalQueue(MiniportAdapterHandle);
 }
 
 }
 
-
 VOID NTAPI
 MiniTransferDataComplete(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
 VOID NTAPI
 MiniTransferDataComplete(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
@@ -486,19 +462,16 @@ MiniTransferDataComplete(
     IN  UINT            BytesTransferred)
 {
     PADAPTER_BINDING AdapterBinding;
     IN  UINT            BytesTransferred)
 {
     PADAPTER_BINDING AdapterBinding;
-    KIRQL OldIrql;
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
 
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
 
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
     (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
         Status,
         BytesTransferred);
     (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
         Status,
         BytesTransferred);
-    KeLowerIrql(OldIrql);
 }
 
 \f
 }
 
 \f
@@ -598,12 +571,6 @@ MiniLocateDevice(
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-  if(IsListEmpty(&AdapterListHead))
-    {
-      NDIS_DbgPrint(MIN_TRACE, ("No registered miniports for protocol to bind to\n"));
-      return NULL;
-    }
-
   KeAcquireSpinLock(&AdapterListLock, &OldIrql);
     {
       CurrentEntry = AdapterListHead.Flink;
   KeAcquireSpinLock(&AdapterListLock, &OldIrql);
     {
       CurrentEntry = AdapterListHead.Flink;
@@ -667,9 +634,15 @@ MiniSetInformation(
   NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
 
   NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
 
+  NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
+  if (!NT_SUCCESS(NdisStatus))
+      return NdisStatus;
+
   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
   /* FIXME: Wait in pending case! */
   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
   /* FIXME: Wait in pending case! */
+  if (NdisStatus != NDIS_STATUS_PENDING)
+      MiniEndRequest(Adapter, NdisWorkItemRequest);
 
   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
 
 
   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
 
@@ -717,9 +690,15 @@ MiniQueryInformation(
   NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
 
   NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
 
+  NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
+  if (!NT_SUCCESS(NdisStatus))
+      return NdisStatus;
+
   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
   /* FIXME: Wait in pending case! */
   NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
   /* FIXME: Wait in pending case! */
+  if (NdisStatus != NDIS_STATUS_PENDING)
+      MiniEndRequest(Adapter, NdisWorkItemRequest);
 
   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
 
 
   ASSERT(NdisStatus != NDIS_STATUS_PENDING);
 
@@ -742,13 +721,10 @@ MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
  */
 {
    BOOLEAN Ret = FALSE;
  */
 {
    BOOLEAN Ret = FALSE;
-   KIRQL OldIrql;
 
 
-   KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
        Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
          Adapter->NdisMiniportBlock.MiniportAdapterContext);
    if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
        Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
          Adapter->NdisMiniportBlock.MiniportAdapterContext);
-   KeLowerIrql(OldIrql);
 
    return Ret;
 }
 
    return Ret;
 }
@@ -779,32 +755,25 @@ MiniReset(
  */
 {
    NDIS_STATUS Status;
  */
 {
    NDIS_STATUS Status;
-   KIRQL OldIrql;
    BOOLEAN AddressingReset = TRUE;
 
    BOOLEAN AddressingReset = TRUE;
 
-   if (MiniIsBusy(Adapter, NdisWorkItemResetRequested)) {
-       MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL, FALSE);
-       return NDIS_STATUS_PENDING;
-   }
+   Status = MiniBeginRequest(Adapter, NdisWorkItemResetRequested, NULL);
+   if (!NT_SUCCESS(Status))
+       return Status;
 
    NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
    NdisMIndicateStatusComplete(Adapter);
 
 
    NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
    NdisMIndicateStatusComplete(Adapter);
 
-   KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
             Adapter->NdisMiniportBlock.MiniportAdapterContext,
             &AddressingReset);
 
    Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
             Adapter->NdisMiniportBlock.MiniportAdapterContext,
             &AddressingReset);
 
-   KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-   Adapter->NdisMiniportBlock.ResetStatus = Status;
-   KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-
-   KeLowerIrql(OldIrql);
-
    if (Status != NDIS_STATUS_PENDING) {
        if (AddressingReset)
            MiniDoAddressingReset(Adapter);
 
    if (Status != NDIS_STATUS_PENDING) {
        if (AddressingReset)
            MiniDoAddressingReset(Adapter);
 
+       MiniEndRequest(Adapter, NdisWorkItemResetRequested);
+
        NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
        NdisMIndicateStatusComplete(Adapter);
    }
        NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
        NdisMIndicateStatusComplete(Adapter);
    }
@@ -827,78 +796,45 @@ MiniportHangDpc(
   }
 }
 
   }
 }
 
-\f
-VOID
-FASTCALL
-MiniQueueWorkItem(
+NDIS_STATUS
+MiniBeginRequest(
     PLOGICAL_ADAPTER     Adapter,
     NDIS_WORK_ITEM_TYPE  WorkItemType,
     PLOGICAL_ADAPTER     Adapter,
     NDIS_WORK_ITEM_TYPE  WorkItemType,
-    PVOID                WorkItemContext,
-    BOOLEAN              Top)
-/*
- * FUNCTION: Queues a work item for execution at a later time
- * ARGUMENTS:
- *     Adapter         = Pointer to the logical adapter object to queue work item on
- *     WorkItemType    = Type of work item to queue
- *     WorkItemContext = Pointer to context information for work item
- * RETURNS:
- *     Status of operation
- */
+    PVOID                WorkItemContext)
 {
 {
-    PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
-    PIO_WORKITEM IoWorkItem;
     KIRQL OldIrql;
     KIRQL OldIrql;
+    BOOLEAN QueueBusy;
+    PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+    PSINGLE_LIST_ENTRY CurrentEntry;
 
 
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
 
 
-    ASSERT(Adapter);
+    QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
 
 
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-    if (Top)
+    MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
+    if (!MiniportWorkItem)
     {
     {
-        if (WorkItemType == NdisWorkItemSend)
-        {
-            NDIS_DbgPrint(MIN_TRACE, ("Requeuing failed packet (%x).\n", WorkItemContext));
-            Adapter->NdisMiniportBlock.FirstPendingPacket = WorkItemContext;
-        }
-        else
-        {
-            //This should never happen
-            ASSERT(FALSE);
-        }
+        NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+        KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+        return NDIS_STATUS_RESOURCES;
     }
     }
-    else
-    {
-        MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
-        if (!MiniportWorkItem)
-        {
-            KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-            NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-            return;
-        }
 
 
-        MiniportWorkItem->WorkItemType    = WorkItemType;
-        MiniportWorkItem->WorkItemContext = WorkItemContext;
+    MiniportWorkItem->WorkItemType    = WorkItemType;
+    MiniportWorkItem->WorkItemContext = WorkItemContext;
+    MiniportWorkItem->Link.Next = NULL;
 
 
-        /* safe due to adapter lock held */
-        MiniportWorkItem->Link.Next = NULL;
-        if (!Adapter->WorkQueueHead)
-        {
-            Adapter->WorkQueueHead = MiniportWorkItem;
-            Adapter->WorkQueueTail = MiniportWorkItem;
-        }
-        else
-        {
-            Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
-            Adapter->WorkQueueTail = MiniportWorkItem;
-        }
-    }
+    CurrentEntry = &Adapter->NdisMiniportBlock.WorkQueue[WorkItemType];
+    while (CurrentEntry->Next)
+       CurrentEntry = CurrentEntry->Next;
 
 
-    IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
-    if (IoWorkItem)
-        IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
+    CurrentEntry->Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
 
     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+    if (QueueBusy)
+        NDIS_DbgPrint(MIN_TRACE, ("Queue %d busy!\n", WorkItemType));
+
+    return (QueueBusy ? NDIS_STATUS_PENDING : NDIS_STATUS_SUCCESS);
 }
 
 \f
 }
 
 \f
@@ -906,7 +842,7 @@ NDIS_STATUS
 FASTCALL
 MiniDequeueWorkItem(
     PLOGICAL_ADAPTER    Adapter,
 FASTCALL
 MiniDequeueWorkItem(
     PLOGICAL_ADAPTER    Adapter,
-    NDIS_WORK_ITEM_TYPE *WorkItemType,
+    NDIS_WORK_ITEM_TYPE WorkItemType,
     PVOID               *WorkItemContext)
 /*
  * FUNCTION: Dequeues a work item from the work queue of a logical adapter
     PVOID               *WorkItemContext)
 /*
  * FUNCTION: Dequeues a work item from the work queue of a logical adapter
@@ -922,42 +858,49 @@ MiniDequeueWorkItem(
  */
 {
     PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
  */
 {
     PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
-    PNDIS_PACKET Packet;
+    KIRQL OldIrql;
 
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
 
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-    MiniportWorkItem = Adapter->WorkQueueHead;
+    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+    MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
+    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
 
-    if ((Packet = Adapter->NdisMiniportBlock.FirstPendingPacket))
+    if (MiniportWorkItem)
     {
     {
-        Adapter->NdisMiniportBlock.FirstPendingPacket = NULL;
+        /* This is VERY IMPORTANT! We dequeue the work item AFTER completion */
 
 
-        *WorkItemType = NdisWorkItemSend;
-        *WorkItemContext = Packet;
+        *WorkItemContext = MiniportWorkItem->WorkItemContext;
 
         return NDIS_STATUS_SUCCESS;
     }
 
         return NDIS_STATUS_SUCCESS;
     }
-    else if (MiniportWorkItem)
+    else
     {
     {
-        /* safe due to adapter lock held */
-        Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)MiniportWorkItem->Link.Next;
+        return NDIS_STATUS_FAILURE;
+    }
+}
 
 
-        if (MiniportWorkItem == Adapter->WorkQueueTail)
-            Adapter->WorkQueueTail = NULL;
+VOID
+MiniEndRequest(
+    PLOGICAL_ADAPTER     Adapter,
+    NDIS_WORK_ITEM_TYPE  WorkItemType)
+{
+    KIRQL OldIrql;
+    BOOLEAN QueueBusy;
+    PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
 
 
-        *WorkItemType    = MiniportWorkItem->WorkItemType;
-        *WorkItemContext = MiniportWorkItem->WorkItemContext;
+    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
 
 
-        ExFreePool(MiniportWorkItem);
+    MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
+    ASSERT(MiniportWorkItem);
+    Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next = MiniportWorkItem->Link.Next;
+    ExFreePool(MiniportWorkItem);
 
 
-        return NDIS_STATUS_SUCCESS;
-    }
-    else
-    {
-        NDIS_DbgPrint(MIN_TRACE, ("No work item to dequeue\n"));
+    QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
+    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
 
-        return NDIS_STATUS_FAILURE;
-    }
+    if (QueueBusy)
+        SignalQueue(Adapter);
 }
 
 \f
 }
 
 \f
@@ -976,13 +919,12 @@ MiniDoRequest(
 {
     NDIS_STATUS Status;
     KIRQL OldIrql;
 {
     NDIS_STATUS Status;
     KIRQL OldIrql;
-    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
 
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
 
-    KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
     Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
     Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
-    KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
     if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
     {
 
     if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
     {
@@ -1021,13 +963,13 @@ MiniDoRequest(
             NdisRequest);
     }
 
             NdisRequest);
     }
 
-    if (Status != NDIS_STATUS_PENDING) {
-        KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+    if (Status != NDIS_STATUS_PENDING)
+    {
+        KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
         Adapter->NdisMiniportBlock.PendingRequest = NULL;
         Adapter->NdisMiniportBlock.PendingRequest = NULL;
-        KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+        KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
     }
 
     }
 
-    KeLowerIrql(OldIrql);
     return Status;
 }
 
     return Status;
 }
 
@@ -1044,12 +986,10 @@ NdisMSetInformationComplete(
 {
   PLOGICAL_ADAPTER Adapter =
        (PLOGICAL_ADAPTER)MiniportAdapterHandle;
 {
   PLOGICAL_ADAPTER Adapter =
        (PLOGICAL_ADAPTER)MiniportAdapterHandle;
-  KIRQL OldIrql;
-  ASSERT(Adapter);
-  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-  if (Adapter->NdisMiniportBlock.SetCompleteHandler)
-     (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
-  KeLowerIrql(OldIrql);
+
+  (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
+
+  MiniEndRequest(Adapter, NdisWorkItemRequest);
 }
 
 \f
 }
 
 \f
@@ -1065,12 +1005,10 @@ NdisMQueryInformationComplete(
 {
     PLOGICAL_ADAPTER Adapter =
        (PLOGICAL_ADAPTER)MiniportAdapterHandle;
 {
     PLOGICAL_ADAPTER Adapter =
        (PLOGICAL_ADAPTER)MiniportAdapterHandle;
-    KIRQL OldIrql;
-    ASSERT(Adapter);
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-    if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
-       (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
-    KeLowerIrql(OldIrql);
+
+    (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
+
+    MiniEndRequest(Adapter, NdisWorkItemRequest);
 }
 
 VOID
 }
 
 VOID
@@ -1078,25 +1016,20 @@ NTAPI
 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 {
   PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 {
   PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
-  KIRQL OldIrql, RaiseOldIrql;
+  KIRQL RaiseOldIrql;
   NDIS_STATUS NdisStatus;
   PVOID WorkItemContext;
   NDIS_WORK_ITEM_TYPE WorkItemType;
   NDIS_STATUS NdisStatus;
   PVOID WorkItemContext;
   NDIS_WORK_ITEM_TYPE WorkItemType;
-  BOOLEAN AddressingReset;
+  BOOLEAN AddressingReset, NextQueue;
 
   IoFreeWorkItem((PIO_WORKITEM)Context);
 
 
   IoFreeWorkItem((PIO_WORKITEM)Context);
 
-  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-
-  NdisStatus =
-      MiniDequeueWorkItem
-      (Adapter, &WorkItemType, &WorkItemContext);
-
-  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-  if (NdisStatus == NDIS_STATUS_SUCCESS)
-    {
-      switch (WorkItemType)
+  for (WorkItemType = 0; WorkItemType < NUMBER_OF_WORK_ITEM_TYPES; WorkItemType++)
+  {
+     NextQueue = FALSE;
+     while (!NextQueue && MiniDequeueWorkItem(Adapter, WorkItemType, &WorkItemContext) == NDIS_STATUS_SUCCESS)
+     {
+        switch (WorkItemType)
         {
           case NdisWorkItemSend:
             /*
         {
           case NdisWorkItemSend:
             /*
@@ -1125,7 +1058,7 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 
                     NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
                     if( NdisStatus == NDIS_STATUS_RESOURCES ) {
 
                     NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
                     if( NdisStatus == NDIS_STATUS_RESOURCES ) {
-                        MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
+                        NextQueue = TRUE;
                         break;
                     }
                 }
                         break;
                     }
                 }
@@ -1151,7 +1084,7 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
                   NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
                   KeLowerIrql(RaiseOldIrql);
                   if( NdisStatus == NDIS_STATUS_RESOURCES ) {
                   NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
                   KeLowerIrql(RaiseOldIrql);
                   if( NdisStatus == NDIS_STATUS_RESOURCES ) {
-                      MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
+                      NextQueue = TRUE;
                       break;
                   }
                 }
                       break;
                   }
                 }
@@ -1171,27 +1104,17 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
             NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
 
             if( NdisStatus != NDIS_STATUS_PENDING )
             NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
 
             if( NdisStatus != NDIS_STATUS_PENDING )
-                MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
+                MiniIndicateComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
             break;
 
           case NdisWorkItemReturnPackets:
             break;
 
           case NdisWorkItemResetRequested:
             break;
 
           case NdisWorkItemReturnPackets:
             break;
 
           case NdisWorkItemResetRequested:
-            NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
-            NdisMIndicateStatusComplete(Adapter);
-
-            KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
                           Adapter->NdisMiniportBlock.MiniportAdapterContext,
                           &AddressingReset);
 
             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
                           Adapter->NdisMiniportBlock.MiniportAdapterContext,
                           &AddressingReset);
 
-            KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-            Adapter->NdisMiniportBlock.ResetStatus = NdisStatus;
-            KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-
-            KeLowerIrql(OldIrql);
-
             if (NdisStatus != NDIS_STATUS_PENDING)
                MiniResetComplete(Adapter, NdisStatus, AddressingReset);
             break;
             if (NdisStatus != NDIS_STATUS_PENDING)
                MiniResetComplete(Adapter, NdisStatus, AddressingReset);
             break;
@@ -1220,15 +1143,18 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 
                 default:
                   NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
 
                 default:
                   NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
+                  MiniEndRequest(Adapter, NdisWorkItemRequest);
                   break;
               }
             break;
 
           default:
                   break;
               }
             break;
 
           default:
+            MiniEndRequest(Adapter, WorkItemType);
             NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
             break;
         }
             NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
             break;
         }
-    }
+     }
+  }
 }
 
 
 }
 
 
@@ -1337,6 +1263,7 @@ NdisMCreateLog(
     if (Adapter->NdisMiniportBlock.Log)
     {
         *LogHandle = NULL;
     if (Adapter->NdisMiniportBlock.Log)
     {
         *LogHandle = NULL;
+        KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
         return NDIS_STATUS_FAILURE;
     }
 
         return NDIS_STATUS_FAILURE;
     }
 
@@ -1344,6 +1271,7 @@ NdisMCreateLog(
     if (!Log)
     {
         *LogHandle = NULL;
     if (!Log)
     {
         *LogHandle = NULL;
+        KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
         return NDIS_STATUS_RESOURCES;
     }
 
         return NDIS_STATUS_RESOURCES;
     }
 
@@ -2231,6 +2159,7 @@ NdisIAddDevice(
   PDEVICE_OBJECT DeviceObject;
   PLOGICAL_ADAPTER Adapter;
   NTSTATUS Status;
   PDEVICE_OBJECT DeviceObject;
   PLOGICAL_ADAPTER Adapter;
   NTSTATUS Status;
+  UINT i;
 
   /*
    * Gain the access to the miniport data structure first.
 
   /*
    * Gain the access to the miniport data structure first.
@@ -2354,6 +2283,9 @@ NdisIAddDevice(
   Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
   Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
 
   Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
   Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
 
+  for (i = 0; i < NUMBER_OF_WORK_ITEM_TYPES; i++)
+       Adapter->NdisMiniportBlock.WorkQueue[i].Next = NULL;
+
   KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
   KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
 
   KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
   KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
 
index dd56c40..aadf0d4 100644 (file)
@@ -325,6 +325,7 @@ ProRequest(
   PADAPTER_BINDING AdapterBinding;
   PLOGICAL_ADAPTER Adapter;
   PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
   PADAPTER_BINDING AdapterBinding;
   PLOGICAL_ADAPTER Adapter;
   PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
+  NDIS_STATUS Status;
 
   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
 
   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
@@ -336,17 +337,15 @@ ProRequest(
 
   MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
 
 
   MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
 
-#if WORKER_TEST
-  MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
-  return NDIS_STATUS_PENDING;
-#else
-  if (MiniIsBusy(Adapter, NdisWorkItemRequest)) {
-      MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
-      return NDIS_STATUS_PENDING;
-  }
+  Status = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
+  if (!NT_SUCCESS(Status))
+      return Status;
 
 
-  return MiniDoRequest(Adapter, NdisRequest);
-#endif
+  Status = MiniDoRequest(Adapter, NdisRequest);
+  if (Status != NDIS_STATUS_PENDING)
+      MiniEndRequest(Adapter, NdisWorkItemRequest);
+
+  return Status;
 }
 
 
 }
 
 
@@ -393,17 +392,12 @@ ScatterGatherSendPacket(
 NDIS_STATUS
 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
 {
 NDIS_STATUS
 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
 {
-#if WORKER_TEST
-   MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
-   return NDIS_STATUS_PENDING;
-#else
    KIRQL RaiseOldIrql;
    NDIS_STATUS NdisStatus;
 
    KIRQL RaiseOldIrql;
    NDIS_STATUS NdisStatus;
 
-   if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
-      MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
-      return NDIS_STATUS_PENDING;
-   }
+   NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemSend, Packet);
+   if (!NT_SUCCESS(NdisStatus))
+       return NdisStatus;
 
    if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
    {
 
    if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
    {
@@ -425,11 +419,15 @@ proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
 
             NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
             if (NdisStatus == NDIS_STATUS_RESOURCES) {
 
             NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
             if (NdisStatus == NDIS_STATUS_RESOURCES) {
-                MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
+                /* We don't need to add to head here because it's already guaranteed to the
+                   the first packet in the queue */
                 NdisStatus = NDIS_STATUS_PENDING;
             }
         }
 
                 NdisStatus = NDIS_STATUS_PENDING;
             }
         }
 
+        if (NdisStatus != NDIS_STATUS_PENDING)
+            MiniEndRequest(Adapter, NdisWorkItemSend);
+
         return NdisStatus;
    } else {
         if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
         return NdisStatus;
    } else {
         if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
@@ -448,14 +446,16 @@ proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
             KeLowerIrql(RaiseOldIrql);
 
             if (NdisStatus == NDIS_STATUS_RESOURCES) {
             KeLowerIrql(RaiseOldIrql);
 
             if (NdisStatus == NDIS_STATUS_RESOURCES) {
-                MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
+                /* See comment above */
                 NdisStatus = NDIS_STATUS_PENDING;
             }
         }
 
                 NdisStatus = NDIS_STATUS_PENDING;
             }
         }
 
+        if (NdisStatus != NDIS_STATUS_PENDING)
+            MiniEndRequest(Adapter, NdisWorkItemSend);
+
         return NdisStatus;
    }
         return NdisStatus;
    }
-#endif
 }
 
 \f
 }
 
 \f
@@ -508,12 +508,7 @@ ProSend(
   if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
       MiniAdapterHasAddress(Adapter, Packet))
     {
   if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
       MiniAdapterHasAddress(Adapter, Packet))
     {
-#if WORKER_TEST
-        MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
-        return NDIS_STATUS_PENDING;
-#else
         return ProIndicatePacket(Adapter, Packet);
         return ProIndicatePacket(Adapter, Packet);
-#endif
     } else {
         if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
         {
     } else {
         if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
         {
@@ -570,11 +565,14 @@ ProSendPackets(
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets)
 {
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets)
 {
+    UNIMPLEMENTED
+#if 0
     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
     KIRQL RaiseOldIrql;
     NDIS_STATUS NdisStatus;
     UINT i;
     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
     KIRQL RaiseOldIrql;
     NDIS_STATUS NdisStatus;
     UINT i;
+    BOOLEAN QueuePackets;
 
     if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
     {
 
     if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
     {
@@ -590,10 +588,15 @@ ProSendPackets(
           (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
           KeLowerIrql(RaiseOldIrql);
           (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
           KeLowerIrql(RaiseOldIrql);
-          for (i = 0; i < NumberOfPackets; i++)
+          for (i = 0, QueuePackets = FALSE; i < NumberOfPackets; i++)
           {
              NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
           {
              NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
-             if (NdisStatus != NDIS_STATUS_PENDING)
+             if (NdisStatus == NDIS_STATUS_RESOURCES)
+                 QueuePackets = TRUE;
+
+             if (QueuePackets)
+                 NdisQueueWorkItemHead(Adapter, NdisWorkItemSend, PacketArray[i]);
+             else
                  MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
           }
        }
                  MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
           }
        }
@@ -624,6 +627,7 @@ ProSendPackets(
          KeLowerIrql(RaiseOldIrql);
        }
      }
          KeLowerIrql(RaiseOldIrql);
        }
      }
+#endif
 }
 
 \f
 }
 
 \f