[USBSTOR]
authorCameron Gutman <aicommander@gmail.com>
Tue, 31 Jan 2012 15:33:32 +0000 (15:33 +0000)
committerCameron Gutman <aicommander@gmail.com>
Tue, 31 Jan 2012 15:33:32 +0000 (15:33 +0000)
- Fix handling of SRB_FUNCTION_FLUSH and SRB_FUNCTION_SHUTDOWN to prevent data loss

svn path=/branches/usb-bringup-trunk/; revision=55350

drivers/usb/usbstor/disk.c
drivers/usb/usbstor/queue.c
drivers/usb/usbstor/usbstor.h

index 6e4fa0d..b9c1a42 100644 (file)
@@ -175,9 +175,9 @@ USBSTOR_HandleInternalDeviceControl(
             DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE / SRB_FUNCTION_SHUTDOWN\n");
 
             //
-            // flush all requests
+            // wait for pending requests to finish
             //
-            USBSTOR_QueueFlushIrps(PDODeviceExtension->LowerDeviceObject);
+            USBSTOR_QueueWaitForPendingRequests(PDODeviceExtension->LowerDeviceObject);
 
             //
             // set status success
index 63fa534..f31b62b 100644 (file)
@@ -176,12 +176,18 @@ USBSTOR_QueueAddIrp(
         // add irp to queue
         //
         InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
-   }
+    }
+
+    //
+    // increment pending count
+    //
+    FDODeviceExtension->IrpPendingCount++;
+
 
-   //
-   // increment pending count
-   //
-   FDODeviceExtension->IrpPendingCount++;
+    //
+    // clear the no requests pending event
+    //
+    KeClearEvent(&FDODeviceExtension->NoPendingRequests);
 
     //
     // check if queue is freezed
@@ -296,16 +302,10 @@ USBSTOR_RemoveIrp(
 }
 
 VOID
-USBSTOR_QueueFlushIrps(
+USBSTOR_QueueWaitForPendingRequests(
     IN PDEVICE_OBJECT DeviceObject)
 {
-    KIRQL OldLevel;
     PFDO_DEVICE_EXTENSION FDODeviceExtension;
-    PLIST_ENTRY Entry;
-    PIRP Irp;
-    PIO_STACK_LOCATION IoStack;
-    PSCSI_REQUEST_BLOCK Request;
-    KIRQL OldIrql;
 
     //
     // get FDO device extension
@@ -313,88 +313,13 @@ USBSTOR_QueueFlushIrps(
     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
     //
-    // sanity check
+    // perform the wait
     //
-    ASSERT(FDODeviceExtension->Common.IsFDO);
-
-    //
-    // acquire lock
-    //
-    KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
-    //
-    // complete all irps with status cancelled
-    // 
-    while(!IsListEmpty(&FDODeviceExtension->IrpListHead))
-    {
-        //
-        // remove irp
-        //
-        Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
-
-        //
-        // get start of irp structure
-        //
-        Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
-
-        //
-        // remove the cancellation routine
-        //
-        IoAcquireCancelSpinLock(&OldIrql);
-        (void)IoSetCancelRoutine(Irp, NULL);
-        IoReleaseCancelSpinLock(OldIrql);
-
-        //
-        // get current stack location
-        //
-        IoStack = IoGetCurrentIrpStackLocation(Irp);
-
-        //
-        // get request block
-        //
-        Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
-
-        //
-        // sanity check
-        //
-        ASSERT(Request);
-
-        //
-        // set srb status to flushed
-        //
-        Request->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
-
-        //
-        // set unsuccessful status
-        //
-        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-
-        //
-        // release lock
-        //
-        KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
-        //
-        // complete request
-        //
-        USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        
-        //
-        // start next one
-        //
-        USBSTOR_QueueNextRequest(DeviceObject);
-
-        //
-        // acquire lock
-        //
-        KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-    }
-
-    //
-    // release lock
-    //
-    KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+    KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
 }
 
 VOID
@@ -438,6 +363,15 @@ USBSTOR_QueueTerminateRequest(
         FDODeviceExtension->ActiveSrb = NULL;
     }
 
+    //
+    // Set the event if nothing else is pending
+    //
+    if (FDODeviceExtension->IrpPendingCount == 0 &&
+        FDODeviceExtension->ActiveSrb == NULL)
+    {
+        KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE);
+    }
+
     //
     // release lock
     //
index e265067..7c0e0d4 100644 (file)
@@ -67,6 +67,7 @@ typedef struct
     BOOLEAN ResetInProgress;                                                             // if hard reset is in progress
     ULONG IrpPendingCount;                                                               // count of irp pending
     PSCSI_REQUEST_BLOCK ActiveSrb;                                                       // stores the current active SRB
+    KEVENT NoPendingRequests;                                                            // set if no pending or in progress requests
 }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct
@@ -405,7 +406,7 @@ USBSTOR_StartIo(
     PIRP Irp);
 
 VOID
-USBSTOR_QueueFlushIrps(
+USBSTOR_QueueWaitForPendingRequests(
     IN PDEVICE_OBJECT DeviceObject);
 
 VOID