[USBSTOR] Refactor device reset and pipe reset code.
authorVictor Perevertkin <victor@perevertkin.ru>
Sat, 13 Apr 2019 12:48:14 +0000 (15:48 +0300)
committerVictor Perevertkin <victor@perevertkin.ru>
Tue, 11 Jun 2019 01:39:43 +0000 (04:39 +0300)
Return correct status codes from completion routines.
Reject requests while the device is being reset

drivers/usb/usbstor/error.c
drivers/usb/usbstor/fdo.c
drivers/usb/usbstor/queue.c
drivers/usb/usbstor/scsi.c
drivers/usb/usbstor/usbstor.c
drivers/usb/usbstor/usbstor.h

index 571c89d..3964b2c 100644 (file)
@@ -5,6 +5,7 @@
  * COPYRIGHT:   2005-2006 James Tabor
  *              2011-2012 Michael Martin (michael.martin@reactos.org)
  *              2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
+ *              2019 Victor Perevertkin (victor.perevertkin@reactos.org)
  */
 
 #include "usbstor.h"
@@ -69,104 +70,97 @@ USBSTOR_ResetPipeWithHandle(
     return Status;
 }
 
-NTSTATUS
-USBSTOR_HandleTransferError(
-    PDEVICE_OBJECT DeviceObject,
-    PIRP_CONTEXT Context)
+VOID
+NTAPI
+USBSTOR_ResetPipeWorkItemRoutine(
+    IN PDEVICE_OBJECT FdoDevice,
+    IN PVOID Ctx)
 {
-    PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    NTSTATUS Status = STATUS_SUCCESS;
-    PIO_STACK_LOCATION Stack;
-    PSCSI_REQUEST_BLOCK Request;
-    PCDB pCDB;
+    NTSTATUS Status;
+    PIRP_CONTEXT Context = (PIRP_CONTEXT)Ctx;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FdoDevice->DeviceExtension;
 
-    ASSERT(Context);
-    ASSERT(Context->Irp);
+    // clear stall on the corresponding pipe
+    Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle);
+    DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
 
-    // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
-    Status = USBSTOR_ResetDevice(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension);
-    if (NT_SUCCESS(Status))
-    {
-        // step 2 reset bulk in pipe section 5.3.4
-        Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
-        if (NT_SUCCESS(Status))
-        {
-            // finally reset bulk out pipe
-            Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
-        }
-    }
+    // now resend the csw as the stall got cleared
+    USBSTOR_SendCSWRequest(Context, Context->Irp);
+}
 
-    Stack = IoGetCurrentIrpStackLocation(Context->Irp);
-    ASSERT(Stack->DeviceObject);
-    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)Stack->DeviceObject->DeviceExtension;
+VOID
+NTAPI
+USBSTOR_ResetDeviceWorkItemRoutine(
+    IN PDEVICE_OBJECT FdoDevice,
+    IN PVOID Context)
+{
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    UINT32 ix;
+    NTSTATUS Status;
+    KIRQL OldIrql;
 
-    Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
-    ASSERT(Request);
+    DPRINT("USBSTOR_ResetDeviceWorkItemRoutine\n");
 
-    // obtain request type
-    pCDB = (PCDB)Request->Cdb;
-    ASSERT(pCDB);
+    FDODeviceExtension = FdoDevice->DeviceExtension;
 
-    if (!NT_SUCCESS(Status))
+    for (ix = 0; ix < 3; ++ix)
     {
-        // Complete the master IRP
-        Context->Irp->IoStatus.Status = Status;
-        Context->Irp->IoStatus.Information = 0;
-        USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Context->Irp);
-        IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
-
-        // Start the next request
-        USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
-
-        // srb handling finished
-        Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
-
-        // clear timer srb
-        Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
+        // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
+        Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
+        if (NT_SUCCESS(Status))
+        {
+            // step 2 reset bulk in pipe section 5.3.4
+            Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
+            if (NT_SUCCESS(Status))
+            {
+                // finally reset bulk out pipe
+                Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
+                if (NT_SUCCESS(Status))
+                {
+                    break;
+                }
+            }
+        }
     }
 
-    FreeItem(Context);
+    KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
+    FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
+    KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
 
-    DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
-    return Status;
+    USBSTOR_QueueNextRequest(FdoDevice);
 }
 
 VOID
 NTAPI
-USBSTOR_ResetHandlerWorkItemRoutine(
-    PVOID Context)
+USBSTOR_QueueResetPipe(
+    IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+    IN PIRP_CONTEXT Context)
 {
-    NTSTATUS Status;
-    PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+    DPRINT("USBSTOR_QueueResetPipe\n");
 
-    // clear stall on BulkIn pipe
-    Status = USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
-    DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
-
-    // now resend the csw as the stall got cleared
-    USBSTOR_SendCSWRequest(WorkItemData->Context, WorkItemData->Irp);
+    IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
+                    USBSTOR_ResetPipeWorkItemRoutine,
+                    CriticalWorkQueue,
+                    Context);
 }
 
 VOID
 NTAPI
-ErrorHandlerWorkItemRoutine(
-    PVOID Context)
+USBSTOR_QueueResetDevice(
+    IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
 {
-    PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+    KIRQL OldIrql;
 
-    if (WorkItemData->Context->ErrorIndex == 2)
-    {
-        // reset device
-        USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
-    }
-    else
-    {
-        // clear stall
-        USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
-    }
+    DPRINT("USBSTOR_QueueResetDevice\n");
 
-    // Free Work Item Data
-    ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
+    KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
+    FDODeviceExtension->Flags |= USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
+    KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
+
+    IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
+                    USBSTOR_ResetDeviceWorkItemRoutine,
+                    CriticalWorkQueue,
+                    NULL);
 }
 
 VOID
@@ -219,12 +213,12 @@ USBSTOR_TimerRoutine(
 
     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
     DPRINT1("[USBSTOR] TimerRoutine entered\n");
-    DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
+    // DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
 
     KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
 
     // is there an active srb and no global reset is in progress
-    if (FDODeviceExtension->ActiveSrb && FDODeviceExtension->ResetInProgress == FALSE && FDODeviceExtension->TimerWorkQueueEnabled)
+    if (FDODeviceExtension->ActiveSrb && /* FDODeviceExtension->ResetInProgress == FALSE && */ FDODeviceExtension->TimerWorkQueueEnabled)
     {
         if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
         {
index 3dff594..16e00da 100644 (file)
@@ -129,6 +129,7 @@ USBSTOR_FdoHandleStartDevice(
     PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
     NTSTATUS Status;
     UCHAR Index = 0;
+    PIO_WORKITEM WorkItem;
 
     // forward irp to lower device
     Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
@@ -138,6 +139,17 @@ USBSTOR_FdoHandleStartDevice(
         return Status;
     }
 
+    if (!DeviceExtension->ResetDeviceWorkItem)
+    {
+        WorkItem = IoAllocateWorkItem(DeviceObject);
+        DeviceExtension->ResetDeviceWorkItem = WorkItem;
+
+        if (!WorkItem)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+
     // initialize irp queue
     USBSTOR_QueueInitialize(DeviceExtension);
 
index 8babc98..ba36022 100644 (file)
@@ -103,7 +103,7 @@ USBSTOR_QueueAddIrp(
     KeClearEvent(&FDODeviceExtension->NoPendingRequests);
 
     // check if queue is freezed
-    IrpListFreeze = FDODeviceExtension->IrpListFreeze;
+    IrpListFreeze = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE);
 
     KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
 
@@ -230,7 +230,7 @@ USBSTOR_QueueNextRequest(
 
     // check first if there's already a request pending or the queue is frozen
     if (FDODeviceExtension->ActiveSrb != NULL ||
-        FDODeviceExtension->IrpListFreeze)
+        BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE))
     {
         // no work to do yet
         return;
@@ -274,7 +274,7 @@ USBSTOR_QueueRelease(
     KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
 
     // clear freezed status
-    FDODeviceExtension->IrpListFreeze = FALSE;
+    FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE;
 
     KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
 
@@ -302,6 +302,7 @@ USBSTOR_StartIo(
     PIRP Irp)
 {
     PIO_STACK_LOCATION IoStack;
+    PSCSI_REQUEST_BLOCK Request;
     PFDO_DEVICE_EXTENSION FDODeviceExtension;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
     KIRQL OldLevel;
@@ -332,26 +333,26 @@ USBSTOR_StartIo(
 
     IoReleaseCancelSpinLock(OldLevel);
 
-    KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
-    ResetInProgress = FDODeviceExtension->ResetInProgress;
-    ASSERT(ResetInProgress == FALSE);
-
-    KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+    KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldLevel);
+    ResetInProgress = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_DEVICE_RESETTING);
+    KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldLevel);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
+    Request = IoStack->Parameters.Scsi.Srb;
     ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
 
-    // TODO: this condition is always false
     if (ResetInProgress)
     {
         // hard reset is in progress
+        Request->SrbStatus = SRB_STATUS_NO_DEVICE;
+        Request->DataTransferLength = 0;
         Irp->IoStatus.Information = 0;
         Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
         USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        USBSTOR_QueueNextRequest(DeviceObject);
         return;
     }
 
index 002b8f2..f917e03 100644 (file)
@@ -116,40 +116,6 @@ USBSTOR_IsCSWValid(
     return TRUE;
 }
 
-NTSTATUS
-USBSTOR_QueueWorkItem(
-    PIRP_CONTEXT Context,
-    PIRP Irp)
-{
-    PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
-
-    ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
-    if (!ErrorHandlerWorkItemData)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    // error handling started
-    Context->FDODeviceExtension->SrbErrorHandlingActive = TRUE;
-
-    // srb error handling finished
-    Context->FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
-
-    // Initialize and queue the work item to handle the error
-    ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
-                         ErrorHandlerWorkItemRoutine,
-                         ErrorHandlerWorkItemData);
-
-    ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
-    ErrorHandlerWorkItemData->Context = Context;
-    ErrorHandlerWorkItemData->Irp = Irp;
-    ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
-
-    DPRINT1("Queuing WorkItemROutine\n");
-    ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
-    return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
 static
 NTSTATUS
 USBSTOR_IssueRequestSense(
@@ -172,12 +138,17 @@ USBSTOR_CSWCompletionRoutine(
     PFDO_DEVICE_EXTENSION FDODeviceExtension;
     PSCSI_REQUEST_BLOCK Request;
     PUFI_CAPACITY_RESPONSE Response;
-    NTSTATUS Status;
 
     Context = (PIRP_CONTEXT)Ctx;
 
     DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
 
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
+    FDODeviceExtension = Context->FDODeviceExtension;
+    Request = IoStack->Parameters.Scsi.Srb;
+    ASSERT(Request);
+
     // first check for Irp errors
     if (!NT_SUCCESS(Irp->IoStatus.Status))
     {
@@ -188,9 +159,7 @@ USBSTOR_CSWCompletionRoutine(
                 ++Context->StallRetryCount;
 
                 // clear stall and resend cbw
-                Context->ErrorIndex = 1;
-                Status = USBSTOR_QueueWorkItem(Context, Irp);
-                ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+                USBSTOR_QueueResetPipe(FDODeviceExtension, Context);
 
                 return STATUS_MORE_PROCESSING_REQUIRED;
             }
@@ -200,29 +169,15 @@ USBSTOR_CSWCompletionRoutine(
             DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
         }
 
-        // perform reset recovery
-        Context->ErrorIndex = 2;
-        Status = USBSTOR_QueueWorkItem(Context, NULL);
-        ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
-        return STATUS_MORE_PROCESSING_REQUIRED;
+        goto ResetRecovery;
     }
 
     // now check the CSW packet validity
     if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
     {
-        // perform reset recovery
-        Context->ErrorIndex = 2;
-        Status = USBSTOR_QueueWorkItem(Context, NULL);
-        ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
-        return STATUS_MORE_PROCESSING_REQUIRED;
+        goto ResetRecovery;
     }
 
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
-    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
-    FDODeviceExtension = Context->FDODeviceExtension;
-    Request = IoStack->Parameters.Scsi.Srb;
-    ASSERT(Request);
-
     // finally check for CSW errors
     if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
     {
@@ -247,7 +202,7 @@ USBSTOR_CSWCompletionRoutine(
             PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
         }
 
-        Status = USBSTOR_SrbStatusToNtStatus(Request);
+        Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request);
     }
     else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
     {
@@ -272,10 +227,9 @@ USBSTOR_CSWCompletionRoutine(
             return STATUS_MORE_PROCESSING_REQUIRED;
         }
 
-        Status = STATUS_IO_DEVICE_ERROR;
+        Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
     }
 
-    Irp->IoStatus.Status = Status;
     Irp->IoStatus.Information = Request->DataTransferLength;
 
     // terminate current request
@@ -283,7 +237,21 @@ USBSTOR_CSWCompletionRoutine(
     USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
 
     ExFreePoolWithTag(Context, USB_STOR_TAG);
-    return Status;
+    return STATUS_CONTINUE_COMPLETION;
+
+ResetRecovery:
+
+    Request = FDODeviceExtension->ActiveSrb;
+    IoStack->Parameters.Scsi.Srb = Request;
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
+    Request->SrbStatus = SRB_STATUS_BUS_RESET;
+
+    USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+    USBSTOR_QueueResetDevice(FDODeviceExtension);
+
+    ExFreePoolWithTag(Context, USB_STOR_TAG);
+    return STATUS_CONTINUE_COMPLETION;
 }
 
 NTSTATUS
@@ -312,15 +280,16 @@ USBSTOR_DataCompletionRoutine(
     PVOID Ctx)
 {
     PIRP_CONTEXT Context;
-    NTSTATUS Status;
     PIO_STACK_LOCATION IoStack;
     PSCSI_REQUEST_BLOCK Request;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
 
     DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
 
     Context = (PIRP_CONTEXT)Ctx;
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     Request = IoStack->Parameters.Scsi.Srb;
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
 
     // for Sense Request a partial MDL was already freed (if existed)
     if (Request == Context->FDODeviceExtension->ActiveSrb &&
@@ -351,16 +320,19 @@ USBSTOR_DataCompletionRoutine(
         Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
 
         // clear stall and resend cbw
-        Context->ErrorIndex = 1;
-        Status = USBSTOR_QueueWorkItem(Context, Irp);
-        ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+        USBSTOR_QueueResetPipe(Context->FDODeviceExtension, Context);
     }
     else
     {
-        // perform reset recovery
-        Context->ErrorIndex = 2;
-        Status = USBSTOR_QueueWorkItem(Context, NULL);
-        ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+        Irp->IoStatus.Information = 0;
+        Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
+        Request->SrbStatus = SRB_STATUS_BUS_RESET;
+
+        USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+        USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
+
+        ExFreePoolWithTag(Context, USB_STOR_TAG);
+        return STATUS_CONTINUE_COMPLETION;
     }
 
     return STATUS_MORE_PROCESSING_REQUIRED;
@@ -378,17 +350,18 @@ USBSTOR_CBWCompletionRoutine(
     PIRP_CONTEXT Context;
     PIO_STACK_LOCATION IoStack;
     PSCSI_REQUEST_BLOCK Request;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
     USBD_PIPE_HANDLE PipeHandle;
     ULONG TransferFlags;
     PMDL Mdl = NULL;
     PVOID TransferBuffer = NULL;
-    NTSTATUS Status;
 
     DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
 
     Context = (PIRP_CONTEXT)Ctx;
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     Request = IoStack->Parameters.Scsi.Srb;
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
 
     if (!NT_SUCCESS(Irp->IoStatus.Status))
     {
@@ -455,13 +428,8 @@ USBSTOR_CBWCompletionRoutine(
     }
     else
     {
+        ASSERT(Request->DataBuffer);
         TransferBuffer = Request->DataBuffer;
-
-        if (!Request->DataBuffer)
-        {
-            DPRINT("USBSTOR_CBWCompletionRoutine: Request->DataBuffer == NULL!\n");
-            return STATUS_INVALID_PARAMETER;
-        }
     }
 
     USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
@@ -477,10 +445,17 @@ USBSTOR_CBWCompletionRoutine(
     return STATUS_MORE_PROCESSING_REQUIRED;
 
 ResetRecovery:
-    Context->ErrorIndex = 2;
-    Status = USBSTOR_QueueWorkItem(Context, NULL);
-    ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
-    return STATUS_MORE_PROCESSING_REQUIRED;
+    Request = Context->FDODeviceExtension->ActiveSrb;
+    IoStack->Parameters.Scsi.Srb = Request;
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
+    Request->SrbStatus = SRB_STATUS_BUS_RESET;
+
+    USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
+    USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
+
+    ExFreePoolWithTag(Context, USB_STOR_TAG);
+    return STATUS_CONTINUE_COMPLETION;
 }
 
 VOID
index 0076c51..99392f7 100644 (file)
@@ -40,6 +40,8 @@ USBSTOR_AddDevice(
     DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
     DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
 
+    KeInitializeSpinLock(&DeviceExtension->CommonLock);
+
     IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension);
 
     // did attaching fail
index d2a72ec..9fc3101 100644 (file)
                   ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
                   ((((unsigned long)(n) & 0xFF000000)) >> 24))
 
+#ifndef BooleanFlagOn
+#define BooleanFlagOn(Flags, SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
+#endif
+
 #define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
        | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
 
@@ -34,6 +38,9 @@ typedef struct __COMMON_DEVICE_EXTENSION__
 
 }USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
 
+#define USBSTOR_FDO_FLAGS_DEVICE_RESETTING   0x00000001 // hard reset is in progress
+#define USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE    0x00000002 // the irp list is freezed
+
 typedef struct
 {
     USBSTOR_COMMON_DEVICE_EXTENSION Common;                                                      // common device extension
@@ -53,8 +60,6 @@ typedef struct
     PDEVICE_OBJECT ChildPDO[16];                                                         // max 16 child pdo devices
     KSPIN_LOCK IrpListLock;                                                              // irp list lock
     LIST_ENTRY IrpListHead;                                                              // irp list head
-    BOOLEAN IrpListFreeze;                                                               // if true the irp list is freezed
-    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
@@ -62,6 +67,9 @@ typedef struct
     ULONG SrbErrorHandlingActive;                                                        // error handling of srb is activated
     ULONG TimerWorkQueueEnabled;                                                         // timer work queue enabled
     ULONG InstanceCount;                                                                 // pdo instance count
+    KSPIN_LOCK CommonLock;
+    PIO_WORKITEM ResetDeviceWorkItem;
+    ULONG Flags;
 }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct
@@ -461,18 +469,6 @@ VOID
 USBSTOR_QueueInitialize(
     PFDO_DEVICE_EXTENSION FDODeviceExtension);
 
-VOID
-NTAPI
-ErrorHandlerWorkItemRoutine(
-       PVOID Context);
-
-VOID
-NTAPI
-ResetHandlerWorkItemRoutine(
-    PVOID Context);
-
-
-
 VOID
 USBSTOR_QueueNextRequest(
     IN PDEVICE_OBJECT DeviceObject);
@@ -500,4 +496,15 @@ USBSTOR_TimerRoutine(
     PDEVICE_OBJECT DeviceObject,
      PVOID Context);
 
+VOID
+NTAPI
+USBSTOR_QueueResetPipe(
+    IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+    IN PIRP_CONTEXT Context);
+
+VOID
+NTAPI
+USBSTOR_QueueResetDevice(
+    IN PFDO_DEVICE_EXTENSION FDODeviceExtension);
+
 #endif /* _USBSTOR_H_ */