[USBSTOR] Refactor device reset and pipe reset code.

Return correct status codes from completion routines.
Reject requests while the device is being reset
This commit is contained in:
Victor Perevertkin 2019-04-13 15:48:14 +03:00
parent aaa90f6986
commit 7bb93db372
6 changed files with 175 additions and 184 deletions

View file

@ -5,6 +5,7 @@
* COPYRIGHT: 2005-2006 James Tabor * COPYRIGHT: 2005-2006 James Tabor
* 2011-2012 Michael Martin (michael.martin@reactos.org) * 2011-2012 Michael Martin (michael.martin@reactos.org)
* 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org) * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
* 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
*/ */
#include "usbstor.h" #include "usbstor.h"
@ -69,104 +70,97 @@ USBSTOR_ResetPipeWithHandle(
return Status; return Status;
} }
NTSTATUS
USBSTOR_HandleTransferError(
PDEVICE_OBJECT DeviceObject,
PIRP_CONTEXT Context)
{
PPDO_DEVICE_EXTENSION PDODeviceExtension;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION Stack;
PSCSI_REQUEST_BLOCK Request;
PCDB pCDB;
ASSERT(Context);
ASSERT(Context->Irp);
// 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);
}
}
Stack = IoGetCurrentIrpStackLocation(Context->Irp);
ASSERT(Stack->DeviceObject);
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)Stack->DeviceObject->DeviceExtension;
Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
ASSERT(Request);
// obtain request type
pCDB = (PCDB)Request->Cdb;
ASSERT(pCDB);
if (!NT_SUCCESS(Status))
{
// 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;
}
FreeItem(Context);
DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
return Status;
}
VOID VOID
NTAPI NTAPI
USBSTOR_ResetHandlerWorkItemRoutine( USBSTOR_ResetPipeWorkItemRoutine(
PVOID Context) IN PDEVICE_OBJECT FdoDevice,
IN PVOID Ctx)
{ {
NTSTATUS Status; NTSTATUS Status;
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context; PIRP_CONTEXT Context = (PIRP_CONTEXT)Ctx;
PFDO_DEVICE_EXTENSION FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FdoDevice->DeviceExtension;
// clear stall on BulkIn pipe // clear stall on the corresponding pipe
Status = USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle); Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle);
DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status); DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
// now resend the csw as the stall got cleared // now resend the csw as the stall got cleared
USBSTOR_SendCSWRequest(WorkItemData->Context, WorkItemData->Irp); USBSTOR_SendCSWRequest(Context, Context->Irp);
} }
VOID VOID
NTAPI NTAPI
ErrorHandlerWorkItemRoutine( USBSTOR_ResetDeviceWorkItemRoutine(
PVOID Context) IN PDEVICE_OBJECT FdoDevice,
IN PVOID Context)
{ {
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context; PFDO_DEVICE_EXTENSION FDODeviceExtension;
UINT32 ix;
NTSTATUS Status;
KIRQL OldIrql;
if (WorkItemData->Context->ErrorIndex == 2) DPRINT("USBSTOR_ResetDeviceWorkItemRoutine\n");
FDODeviceExtension = FdoDevice->DeviceExtension;
for (ix = 0; ix < 3; ++ix)
{ {
// reset device // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context); Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
} if (NT_SUCCESS(Status))
else {
{ // step 2 reset bulk in pipe section 5.3.4
// clear stall Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData); 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;
}
}
}
} }
// Free Work Item Data KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
ExFreePoolWithTag(WorkItemData, USB_STOR_TAG); FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
USBSTOR_QueueNextRequest(FdoDevice);
}
VOID
NTAPI
USBSTOR_QueueResetPipe(
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
IN PIRP_CONTEXT Context)
{
DPRINT("USBSTOR_QueueResetPipe\n");
IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
USBSTOR_ResetPipeWorkItemRoutine,
CriticalWorkQueue,
Context);
}
VOID
NTAPI
USBSTOR_QueueResetDevice(
IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
{
KIRQL OldIrql;
DPRINT("USBSTOR_QueueResetDevice\n");
KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
FDODeviceExtension->Flags |= USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
USBSTOR_ResetDeviceWorkItemRoutine,
CriticalWorkQueue,
NULL);
} }
VOID VOID
@ -219,12 +213,12 @@ USBSTOR_TimerRoutine(
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context; FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
DPRINT1("[USBSTOR] TimerRoutine entered\n"); 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); KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
// is there an active srb and no global reset is in progress // 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) if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
{ {

View file

@ -129,6 +129,7 @@ USBSTOR_FdoHandleStartDevice(
PUSB_INTERFACE_DESCRIPTOR InterfaceDesc; PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
NTSTATUS Status; NTSTATUS Status;
UCHAR Index = 0; UCHAR Index = 0;
PIO_WORKITEM WorkItem;
// forward irp to lower device // forward irp to lower device
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
@ -138,6 +139,17 @@ USBSTOR_FdoHandleStartDevice(
return Status; return Status;
} }
if (!DeviceExtension->ResetDeviceWorkItem)
{
WorkItem = IoAllocateWorkItem(DeviceObject);
DeviceExtension->ResetDeviceWorkItem = WorkItem;
if (!WorkItem)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
}
// initialize irp queue // initialize irp queue
USBSTOR_QueueInitialize(DeviceExtension); USBSTOR_QueueInitialize(DeviceExtension);

View file

@ -103,7 +103,7 @@ USBSTOR_QueueAddIrp(
KeClearEvent(&FDODeviceExtension->NoPendingRequests); KeClearEvent(&FDODeviceExtension->NoPendingRequests);
// check if queue is freezed // check if queue is freezed
IrpListFreeze = FDODeviceExtension->IrpListFreeze; IrpListFreeze = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE);
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
@ -230,7 +230,7 @@ USBSTOR_QueueNextRequest(
// check first if there's already a request pending or the queue is frozen // check first if there's already a request pending or the queue is frozen
if (FDODeviceExtension->ActiveSrb != NULL || if (FDODeviceExtension->ActiveSrb != NULL ||
FDODeviceExtension->IrpListFreeze) BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE))
{ {
// no work to do yet // no work to do yet
return; return;
@ -274,7 +274,7 @@ USBSTOR_QueueRelease(
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
// clear freezed status // clear freezed status
FDODeviceExtension->IrpListFreeze = FALSE; FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE;
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
@ -302,6 +302,7 @@ USBSTOR_StartIo(
PIRP Irp) PIRP Irp)
{ {
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request;
PFDO_DEVICE_EXTENSION FDODeviceExtension; PFDO_DEVICE_EXTENSION FDODeviceExtension;
PPDO_DEVICE_EXTENSION PDODeviceExtension; PPDO_DEVICE_EXTENSION PDODeviceExtension;
KIRQL OldLevel; KIRQL OldLevel;
@ -332,26 +333,26 @@ USBSTOR_StartIo(
IoReleaseCancelSpinLock(OldLevel); IoReleaseCancelSpinLock(OldLevel);
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldLevel);
ResetInProgress = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_DEVICE_RESETTING);
ResetInProgress = FDODeviceExtension->ResetInProgress; KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldLevel);
ASSERT(ResetInProgress == FALSE);
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
Request = IoStack->Parameters.Scsi.Srb;
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
// TODO: this condition is always false
if (ResetInProgress) if (ResetInProgress)
{ {
// hard reset is in progress // hard reset is in progress
Request->SrbStatus = SRB_STATUS_NO_DEVICE;
Request->DataTransferLength = 0;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
USBSTOR_QueueTerminateRequest(DeviceObject, Irp); USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
USBSTOR_QueueNextRequest(DeviceObject);
return; return;
} }

View file

@ -116,40 +116,6 @@ USBSTOR_IsCSWValid(
return TRUE; 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 static
NTSTATUS NTSTATUS
USBSTOR_IssueRequestSense( USBSTOR_IssueRequestSense(
@ -172,12 +138,17 @@ USBSTOR_CSWCompletionRoutine(
PFDO_DEVICE_EXTENSION FDODeviceExtension; PFDO_DEVICE_EXTENSION FDODeviceExtension;
PSCSI_REQUEST_BLOCK Request; PSCSI_REQUEST_BLOCK Request;
PUFI_CAPACITY_RESPONSE Response; PUFI_CAPACITY_RESPONSE Response;
NTSTATUS Status;
Context = (PIRP_CONTEXT)Ctx; Context = (PIRP_CONTEXT)Ctx;
DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); 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 // first check for Irp errors
if (!NT_SUCCESS(Irp->IoStatus.Status)) if (!NT_SUCCESS(Irp->IoStatus.Status))
{ {
@ -188,9 +159,7 @@ USBSTOR_CSWCompletionRoutine(
++Context->StallRetryCount; ++Context->StallRetryCount;
// clear stall and resend cbw // clear stall and resend cbw
Context->ErrorIndex = 1; USBSTOR_QueueResetPipe(FDODeviceExtension, Context);
Status = USBSTOR_QueueWorkItem(Context, Irp);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
} }
@ -200,29 +169,15 @@ USBSTOR_CSWCompletionRoutine(
DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status); DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
} }
// perform reset recovery goto ResetRecovery;
Context->ErrorIndex = 2;
Status = USBSTOR_QueueWorkItem(Context, NULL);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED;
} }
// now check the CSW packet validity // now check the CSW packet validity
if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR) if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
{ {
// perform reset recovery goto ResetRecovery;
Context->ErrorIndex = 2;
Status = USBSTOR_QueueWorkItem(Context, NULL);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
return STATUS_MORE_PROCESSING_REQUIRED;
} }
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 // finally check for CSW errors
if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED) if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
{ {
@ -247,7 +202,7 @@ USBSTOR_CSWCompletionRoutine(
PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress); PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
} }
Status = USBSTOR_SrbStatusToNtStatus(Request); Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request);
} }
else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED) else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
{ {
@ -272,10 +227,9 @@ USBSTOR_CSWCompletionRoutine(
return STATUS_MORE_PROCESSING_REQUIRED; 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; Irp->IoStatus.Information = Request->DataTransferLength;
// terminate current request // terminate current request
@ -283,7 +237,21 @@ USBSTOR_CSWCompletionRoutine(
USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
ExFreePoolWithTag(Context, USB_STOR_TAG); 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 NTSTATUS
@ -312,15 +280,16 @@ USBSTOR_DataCompletionRoutine(
PVOID Ctx) PVOID Ctx)
{ {
PIRP_CONTEXT Context; PIRP_CONTEXT Context;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request; PSCSI_REQUEST_BLOCK Request;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
Context = (PIRP_CONTEXT)Ctx; Context = (PIRP_CONTEXT)Ctx;
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
Request = IoStack->Parameters.Scsi.Srb; Request = IoStack->Parameters.Scsi.Srb;
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
// for Sense Request a partial MDL was already freed (if existed) // for Sense Request a partial MDL was already freed (if existed)
if (Request == Context->FDODeviceExtension->ActiveSrb && if (Request == Context->FDODeviceExtension->ActiveSrb &&
@ -351,16 +320,19 @@ USBSTOR_DataCompletionRoutine(
Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength; Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
// clear stall and resend cbw // clear stall and resend cbw
Context->ErrorIndex = 1; USBSTOR_QueueResetPipe(Context->FDODeviceExtension, Context);
Status = USBSTOR_QueueWorkItem(Context, Irp);
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
} }
else else
{ {
// perform reset recovery Irp->IoStatus.Information = 0;
Context->ErrorIndex = 2; Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
Status = USBSTOR_QueueWorkItem(Context, NULL); Request->SrbStatus = SRB_STATUS_BUS_RESET;
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
ExFreePoolWithTag(Context, USB_STOR_TAG);
return STATUS_CONTINUE_COMPLETION;
} }
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
@ -378,17 +350,18 @@ USBSTOR_CBWCompletionRoutine(
PIRP_CONTEXT Context; PIRP_CONTEXT Context;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PSCSI_REQUEST_BLOCK Request; PSCSI_REQUEST_BLOCK Request;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
USBD_PIPE_HANDLE PipeHandle; USBD_PIPE_HANDLE PipeHandle;
ULONG TransferFlags; ULONG TransferFlags;
PMDL Mdl = NULL; PMDL Mdl = NULL;
PVOID TransferBuffer = NULL; PVOID TransferBuffer = NULL;
NTSTATUS Status;
DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
Context = (PIRP_CONTEXT)Ctx; Context = (PIRP_CONTEXT)Ctx;
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
Request = IoStack->Parameters.Scsi.Srb; Request = IoStack->Parameters.Scsi.Srb;
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
if (!NT_SUCCESS(Irp->IoStatus.Status)) if (!NT_SUCCESS(Irp->IoStatus.Status))
{ {
@ -455,13 +428,8 @@ USBSTOR_CBWCompletionRoutine(
} }
else else
{ {
ASSERT(Request->DataBuffer);
TransferBuffer = Request->DataBuffer; TransferBuffer = Request->DataBuffer;
if (!Request->DataBuffer)
{
DPRINT("USBSTOR_CBWCompletionRoutine: Request->DataBuffer == NULL!\n");
return STATUS_INVALID_PARAMETER;
}
} }
USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension, USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
@ -477,10 +445,17 @@ USBSTOR_CBWCompletionRoutine(
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
ResetRecovery: ResetRecovery:
Context->ErrorIndex = 2; Request = Context->FDODeviceExtension->ActiveSrb;
Status = USBSTOR_QueueWorkItem(Context, NULL); IoStack->Parameters.Scsi.Srb = Request;
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED); Irp->IoStatus.Information = 0;
return STATUS_MORE_PROCESSING_REQUIRED; 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 VOID

View file

@ -40,6 +40,8 @@ USBSTOR_AddDevice(
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
KeInitializeSpinLock(&DeviceExtension->CommonLock);
IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension); IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension);
// did attaching fail // did attaching fail

View file

@ -25,6 +25,10 @@
((((unsigned long)(n) & 0xFF0000)) >> 8) | \ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
((((unsigned long)(n) & 0xFF000000)) >> 24)) ((((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 \ #define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
| USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH) | 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; }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 typedef struct
{ {
USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
@ -53,8 +60,6 @@ typedef struct
PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
KSPIN_LOCK IrpListLock; // irp list lock KSPIN_LOCK IrpListLock; // irp list lock
LIST_ENTRY IrpListHead; // irp list head 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 ULONG IrpPendingCount; // count of irp pending
PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB
KEVENT NoPendingRequests; // set if no pending or in progress requests 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 SrbErrorHandlingActive; // error handling of srb is activated
ULONG TimerWorkQueueEnabled; // timer work queue enabled ULONG TimerWorkQueueEnabled; // timer work queue enabled
ULONG InstanceCount; // pdo instance count ULONG InstanceCount; // pdo instance count
KSPIN_LOCK CommonLock;
PIO_WORKITEM ResetDeviceWorkItem;
ULONG Flags;
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct typedef struct
@ -461,18 +469,6 @@ VOID
USBSTOR_QueueInitialize( USBSTOR_QueueInitialize(
PFDO_DEVICE_EXTENSION FDODeviceExtension); PFDO_DEVICE_EXTENSION FDODeviceExtension);
VOID
NTAPI
ErrorHandlerWorkItemRoutine(
PVOID Context);
VOID
NTAPI
ResetHandlerWorkItemRoutine(
PVOID Context);
VOID VOID
USBSTOR_QueueNextRequest( USBSTOR_QueueNextRequest(
IN PDEVICE_OBJECT DeviceObject); IN PDEVICE_OBJECT DeviceObject);
@ -500,4 +496,15 @@ USBSTOR_TimerRoutine(
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PVOID Context); 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_ */ #endif /* _USBSTOR_H_ */