[NDISUIO]
authorCameron Gutman <aicommander@gmail.com>
Tue, 3 Jan 2012 19:37:03 +0000 (19:37 +0000)
committerCameron Gutman <aicommander@gmail.com>
Tue, 3 Jan 2012 19:37:03 +0000 (19:37 +0000)
- Make reads cancelable
- Fix a bug in IOCTL_CANCEL_READ handling

svn path=/branches/wlan-bringup/; revision=54823

drivers/network/ndisuio/ioctl.c
drivers/network/ndisuio/readwrite.c

index a00c173..0bb191d 100644 (file)
@@ -109,7 +109,7 @@ CancelPacketRead(PIRP Irp, PIO_STACK_LOCATION IrpSp)
     {
         PacketEntry->PacketLength = 0;
         
-        ExInterlockedInsertTailList(&AdapterContext->PacketList,
+        ExInterlockedInsertHeadList(&AdapterContext->PacketList,
                                     &PacketEntry->ListEntry,
                                     &AdapterContext->Spinlock);
         
index 61bfc51..b654971 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+VOID
+NTAPI
+ReadIrpCancel(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+    PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
+    PNDISUIO_PACKET_ENTRY PacketEntry;
+    
+    /* Release the cancel spin lock */
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    /* Indicate a 0-byte packet on the queue to cancel the read */
+    PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY));
+    if (PacketEntry)
+    {
+        PacketEntry->PacketLength = 0;
+        
+        ExInterlockedInsertHeadList(&AdapterContext->PacketList,
+                                    &PacketEntry->ListEntry,
+                                    &AdapterContext->Spinlock);
+        
+        KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
+    }
+}
+
 NTSTATUS
 NTAPI
 NduDispatchRead(PDEVICE_OBJECT DeviceObject,
@@ -19,7 +43,7 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject,
     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
     PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
     PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
-    KIRQL OldIrql;
+    KIRQL OldIrql, OldCancelIrql;
     NTSTATUS Status;
     PLIST_ENTRY ListEntry;
     PNDISUIO_PACKET_ENTRY PacketEntry = NULL;
@@ -36,6 +60,22 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject,
         return STATUS_INVALID_PARAMETER;
     }
 
+    /* Make the read cancellable */
+    IoAcquireCancelSpinLock(&OldCancelIrql);
+    IoSetCancelRoutine(Irp, ReadIrpCancel);
+    if (Irp->Cancel)
+    {
+        IoReleaseCancelSpinLock(OldCancelIrql);
+
+        /* Indicate a 0 byte read */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        
+        return STATUS_SUCCESS;
+    }
+    IoReleaseCancelSpinLock(OldCancelIrql);
+
     while (TRUE)
     {
         KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
@@ -52,10 +92,22 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject,
                                            TRUE,
                                            NULL);
             if (Status != STATUS_SUCCESS)
+            {
+                /* Remove the cancel routine */
+                IoAcquireCancelSpinLock(&OldCancelIrql);
+                IoSetCancelRoutine(Irp, NULL);
+                IoReleaseCancelSpinLock(OldCancelIrql);
+
                 break;
+            }
         }
         else
         {
+            /* Remove the cancel routine */
+            IoAcquireCancelSpinLock(&OldCancelIrql);
+            IoSetCancelRoutine(Irp, NULL);
+            IoReleaseCancelSpinLock(OldCancelIrql);
+            
             /* Remove the first packet in the list */
             ListEntry = RemoveHeadList(&AdapterContext->PacketList);
             PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);