From ff208f7adbd45971ed113cacaf328f8eeccc8b8a Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Tue, 17 May 2011 11:26:25 +0000 Subject: [PATCH] [USBSTOR] - Add error handling to USBSTOR_CSWCompletionRoutine for errors that can be recovered via reset of pipe/port/controller. Only pipe reset is attempted. WIP. svn path=/branches/usb-bringup/; revision=51808 --- drivers/usb/usbstor/error.c | 2 +- drivers/usb/usbstor/scsi.c | 70 +++++++++++++++++++++++++++++++++-- drivers/usb/usbstor/usbstor.h | 17 ++++++++- 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/drivers/usb/usbstor/error.c b/drivers/usb/usbstor/error.c index 58d300421f9..936caaef3c2 100644 --- a/drivers/usb/usbstor/error.c +++ b/drivers/usb/usbstor/error.c @@ -103,7 +103,7 @@ USBSTOR_HandleTransferError( break; } - DPRINT1("Failed to reset pipe %x\n"); + DPRINT1("Failed to reset pipe %x\n", Status); // // FIXME: Reset of pipe failed, attempt to reset port diff --git a/drivers/usb/usbstor/scsi.c b/drivers/usb/usbstor/scsi.c index 8e813278fbf..cc58623511b 100644 --- a/drivers/usb/usbstor/scsi.c +++ b/drivers/usb/usbstor/scsi.c @@ -102,6 +102,9 @@ USBSTOR_CSWCompletionRoutine( PREAD_CAPACITY_DATA_EX CapacityDataEx; PREAD_CAPACITY_DATA CapacityData; PUFI_CAPACITY_RESPONSE Response; + PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData; + NTSTATUS Status; + PURB Urb; DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx); @@ -153,16 +156,75 @@ USBSTOR_CSWCompletionRoutine( Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; ASSERT(Request); - // - // FIXME: check status - // - Request->SrbStatus = SRB_STATUS_SUCCESS; + Status = Irp->IoStatus.Status; + + Urb = &Context->Urb; // // get SCSI command data block // pCDB = (PCDB)Request->Cdb; + // + // check status + // + if (!NT_SUCCESS(Status)) + { + DPRINT1("Status %x\n", Status); + DPRINT1("UrbStatus %x\n", Urb->UrbHeader.Status); + + // + // Check for errors that can be handled + // FIXME: Verify all usb errors that can be recovered via pipe reset/port reset/controller reset + // + if ((Urb->UrbHeader.Status & USB_RECOVERABLE_ERRORS) == Urb->UrbHeader.Status) + { + DPRINT1("Attempting Error Recovery\n"); + // + // If a Read Capacity Request free TransferBuffer + // + if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY) + { + FreeItem(Context->TransferData); + } + + // + // Clean up the rest + // + FreeItem(Context->cbw); + FreeItem(Context); + + // + // Allocate Work Item Data + // + ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG); + if (!ErrorHandlerWorkItemData) + { + DPRINT1("Failed to allocate memory\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + // + // Initialize and queue the work item to handle the error + // + ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, + ErrorHandlerWorkItemRoutine, + ErrorHandlerWorkItemData); + + ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject; + ErrorHandlerWorkItemData->Irp = Irp; + ErrorHandlerWorkItemData->Context = Context; + DPRINT1("Queuing WorkItemROutine\n"); + ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue); + + return STATUS_MORE_PROCESSING_REQUIRED; + } + } + } + + Request->SrbStatus = SRB_STATUS_SUCCESS; + // // read capacity needs special work // diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h index 0da2c562ce1..6e12ffe5dda 100644 --- a/drivers/usb/usbstor/usbstor.h +++ b/drivers/usb/usbstor/usbstor.h @@ -35,6 +35,9 @@ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \ ((((unsigned long)(n) & 0xFF000000)) >> 24)) +#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \ + | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH) + NTSTATUS NTAPI IoAttachDeviceToDeviceStackSafe( IN PDEVICE_OBJECT SourceDevice, @@ -278,6 +281,13 @@ typedef struct PKEVENT Event; }IRP_CONTEXT, *PIRP_CONTEXT; +typedef struct _ERRORHANDLER_WORKITEM_DATA +{ + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + PIRP_CONTEXT Context; + WORK_QUEUE_ITEM WorkQueueItem; +} ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA; //--------------------------------------------------------------------- @@ -424,6 +434,11 @@ VOID USBSTOR_QueueInitialize( PFDO_DEVICE_EXTENSION FDODeviceExtension); +VOID +NTAPI +ErrorHandlerWorkItemRoutine( + PVOID Context); + VOID USBSTOR_QueueNextRequest( IN PDEVICE_OBJECT DeviceObject); @@ -431,4 +446,4 @@ USBSTOR_QueueNextRequest( VOID USBSTOR_QueueTerminateRequest( IN PDEVICE_OBJECT DeviceObject, - IN BOOLEAN ModifySrbState); \ No newline at end of file + IN BOOLEAN ModifySrbState);