https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7bb93db3728d721556f17…
commit 7bb93db3728d721556f17f350d8813f97fd7cea7
Author: Victor Perevertkin <victor(a)perevertkin.ru>
AuthorDate: Sat Apr 13 15:48:14 2019 +0300
Commit: Victor Perevertkin <victor(a)perevertkin.ru>
CommitDate: Tue Jun 11 04:39:43 2019 +0300
[USBSTOR] Refactor device reset and pipe reset code.
Return correct status codes from completion routines.
Reject requests while the device is being reset
---
drivers/usb/usbstor/error.c | 146 ++++++++++++++++++++----------------------
drivers/usb/usbstor/fdo.c | 12 ++++
drivers/usb/usbstor/queue.c | 21 +++---
drivers/usb/usbstor/scsi.c | 129 +++++++++++++++----------------------
drivers/usb/usbstor/usbstor.c | 2 +
drivers/usb/usbstor/usbstor.h | 35 ++++++----
6 files changed, 168 insertions(+), 177 deletions(-)
diff --git a/drivers/usb/usbstor/error.c b/drivers/usb/usbstor/error.c
index 571c89dab42..3964b2c7b4d 100644
--- a/drivers/usb/usbstor/error.c
+++ b/drivers/usb/usbstor/error.c
@@ -5,6 +5,7 @@
* COPYRIGHT: 2005-2006 James Tabor
* 2011-2012 Michael Martin (michael.martin(a)reactos.org)
* 2011-2013 Johannes Anderwald (johannes.anderwald(a)reactos.org)
+ * 2019 Victor Perevertkin (victor.perevertkin(a)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)
{
diff --git a/drivers/usb/usbstor/fdo.c b/drivers/usb/usbstor/fdo.c
index 3dff594dccb..16e00da1964 100644
--- a/drivers/usb/usbstor/fdo.c
+++ b/drivers/usb/usbstor/fdo.c
@@ -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);
diff --git a/drivers/usb/usbstor/queue.c b/drivers/usb/usbstor/queue.c
index 8babc987912..ba36022f4ba 100644
--- a/drivers/usb/usbstor/queue.c
+++ b/drivers/usb/usbstor/queue.c
@@ -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;
}
diff --git a/drivers/usb/usbstor/scsi.c b/drivers/usb/usbstor/scsi.c
index 002b8f29768..f917e0345e0 100644
--- a/drivers/usb/usbstor/scsi.c
+++ b/drivers/usb/usbstor/scsi.c
@@ -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
diff --git a/drivers/usb/usbstor/usbstor.c b/drivers/usb/usbstor/usbstor.c
index 0076c519d38..99392f7e092 100644
--- a/drivers/usb/usbstor/usbstor.c
+++ b/drivers/usb/usbstor/usbstor.c
@@ -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
diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h
index d2a72eccc96..9fc3101ef2c 100644
--- a/drivers/usb/usbstor/usbstor.h
+++ b/drivers/usb/usbstor/usbstor.h
@@ -25,6 +25,10 @@
((((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_ */