From 41e8ff2781f3ca14f73ef5f39e781ccba8cb373d Mon Sep 17 00:00:00 2001 From: yshang1 Date: Mon, 8 Oct 2007 06:14:13 +0000 Subject: Fixed unexpected timeout in Usb MassStorage Driver. Fixed unexpected timeout in Uhci/Ehci driver. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4038 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h | 4 +- .../Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c | 2 +- .../Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h | 43 +++++---- .../Bus/Usb/UsbMassStorageDxe/UsbMassBot.c | 14 +-- .../Bus/Usb/UsbMassStorageDxe/UsbMassBot.h | 20 ++--- .../Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c | 10 +-- .../Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h | 11 ++- .../Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c | 100 +++++++++++++-------- .../Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h | 8 +- 9 files changed, 124 insertions(+), 88 deletions(-) (limited to 'MdeModulePkg/Bus/Usb/UsbMassStorageDxe') diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h index 77dcbb720b..3e7c700510 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h @@ -73,8 +73,8 @@ enum { USB_MASS_STORE_CBI1 = 0x01, // CBI protocol without command completion interrupt USB_MASS_STORE_BOT = 0x50, // Bulk-Only Transport - USB_MASS_STALL_1_MS = 1000, - USB_MASS_STALL_1_S = 1000 * USB_MASS_STALL_1_MS, + USB_MASS_1_MILLISECOND = 1000, + USB_MASS_1_SECOND = 1000 * USB_MASS_1_MILLISECOND, USB_MASS_CMD_SUCCESS = 0, USB_MASS_CMD_FAIL, diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c index 9b8dfd01dd..91fcbec33b 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c @@ -935,7 +935,7 @@ UsbClearEndpointStall ( Request.Value = USB_FEATURE_ENDPOINT_HALT; Request.Index = EndpointAddr; Request.Length = 0; - Timeout = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_1_MILLISECOND; Status = UsbIo->UsbControlTransfer ( UsbIo, diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h index bfef2609ad..136276a515 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h @@ -31,14 +31,13 @@ enum { // The opcodes of various usb boot commands: // INQUIRY/REQUEST_SENSE are "No Timeout Commands" as specified // by MMC command set. Others are "Group 1 Timeout Commands". That - // is they should be retried if driver is ready. - // We can't use the Peripheral Device Type in Inquiry data to + // is they should be retried if driver is ready. + // We can't use the Peripheral Device Type in Inquiry data to // determine the timeout used. For example, both floppy and flash // are likely set their PDT to 0, or Direct Access Device. // USB_BOOT_INQUIRY_OPCODE = 0x12, USB_BOOT_REQUEST_SENSE_OPCODE = 0x03, - USB_BOOT_MODE_SENSE10_OPCODE = 0x5A, USB_BOOT_READ_CAPACITY_OPCODE = 0x25, USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00, @@ -70,45 +69,45 @@ enum { USB_BOOT_ASC_MEDIA_CHANGE = 0x28, // - // Other parameters + // Supported PDT codes, or Peripheral Device Type + // + USB_PDT_DIRECT_ACCESS = 0x00, // Direct access device + USB_PDT_CDROM = 0x05, // CDROM + USB_PDT_OPTICAL = 0x07, // Non-CD optical disks + USB_PDT_SIMPLE_DIRECT = 0x0E, // Simplified direct access device + + // + // Other parameters, Max carried size is 512B * 128 = 64KB // - USB_BOOT_IO_BLOCKS = 64, + USB_BOOT_IO_BLOCKS = 128, // - // Boot Retry times + // Retry mass command times, set by experience // USB_BOOT_COMMAND_RETRY = 5, - USB_BOOT_WAIT_RETRY = 5, + USB_BOOT_INIT_MEDIA_RETRY = 5, // - // Boot Stall time + // Wait for unit ready command, set by experience // - USB_BOOT_UNIT_READY_STALL = 50 * USB_MASS_STALL_1_MS, + USB_BOOT_RETRY_UNIT_READY_STALL = 500 * USB_MASS_1_MILLISECOND, // - // Boot Transfer timeout + // Mass command timeout, refers to specification[USB20-9.2.6.1] // // USB2.0 Spec define the up-limit timeout 5s for all command. USB floppy, // USB CD-Rom and iPod devices are much slower than USB key when reponse // most of commands, So we set 5s as timeout here. // // - USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_STALL_1_S, - - // - // Supported PDT codes, or Peripheral Device Type - // - USB_PDT_DIRECT_ACCESS = 0x00, // Direct access device - USB_PDT_CDROM = 0x05, // CDROM - USB_PDT_OPTICAL = 0x07, // Non-CD optical disks - USB_PDT_SIMPLE_DIRECT = 0x0E // Simplified direct access device + USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_1_SECOND, }; // // The required commands are INQUIRY, READ CAPACITY, TEST UNIT READY, // READ10, WRITE10, and REQUEST SENSE. The BLOCK_IO protocol uses LBA // so it isn't necessary to issue MODE SENSE / READ FORMAT CAPACITY -// command to retrieve the disk gemotrics. +// command to retrieve the disk gemotrics. // #pragma pack(1) typedef struct { @@ -221,7 +220,7 @@ typedef struct { typedef struct { UINT8 ModeDataLen; - UINT8 MediumType; + UINT8 MediumType; UINT8 DevicePara; UINT8 BlkDesLen; } USB_SCSI_MODE_SENSE6_PARA_HEADER; @@ -245,7 +244,7 @@ typedef struct { // #define USB_BOOT_SWAP32(Data32) \ ((((Data32) & 0x000000ff) << 24) | (((Data32) & 0xff000000) >> 24) | \ - (((Data32) & 0x0000ff00) << 8) | (((Data32) & 0x00ff0000) >> 8)) + (((Data32) & 0x0000ff00) << 8) | (((Data32) & 0x00ff0000) >> 8)) #define USB_BOOT_SWAP16(Data16) \ ((((Data16) & 0x00ff) << 8) | (((Data16) & 0xff00) >> 8)) diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c index 6c92da9c71..3f4d0fc4d3 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c @@ -191,7 +191,7 @@ UsbBotSendCommand ( Result = 0; DataLen = sizeof (USB_BOT_CBW); - Timeout = USB_BOT_CBW_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_SEND_CBW_TIMEOUT / USB_MASS_1_MILLISECOND; // // Use the UsbIo to send the command to the device. The default @@ -266,7 +266,7 @@ UsbBotDataTransfer ( } Result = 0; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; Status = UsbBot->UsbIo->UsbBulkTransfer ( UsbBot->UsbIo, @@ -323,14 +323,14 @@ UsbBotGetStatus ( EFI_USB_IO_PROTOCOL *UsbIo; UINT32 Index; UINTN Timeout; - + *CmdStatus = USB_BOT_COMMAND_ERROR; Status = EFI_DEVICE_ERROR; Endpoint = UsbBot->BulkInEndpoint->EndpointAddress; UsbIo = UsbBot->UsbIo; - Timeout = USB_BOT_CSW_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_RECV_CSW_TIMEOUT / USB_MASS_1_MILLISECOND; - for (Index = 0; Index < USB_BOT_GET_STATUS_RETRY; Index++) { + for (Index = 0; Index < USB_BOT_RECV_CSW_RETRY; Index++) { // // Attemp to the read CSW from bulk in endpoint // @@ -499,7 +499,7 @@ UsbBotResetDevice ( Request.Value = 0; Request.Index = UsbBot->Interface.InterfaceNumber; Request.Length = 0; - Timeout = USB_BOT_RESET_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND; Status = UsbBot->UsbIo->UsbControlTransfer ( UsbBot->UsbIo, @@ -521,7 +521,7 @@ UsbBotResetDevice ( // complete. We can use this to sync the device and host. For // now just stall 100ms to wait the device. // - gBS->Stall (USB_BOT_RESET_STALL); + gBS->Stall (USB_BOT_RESET_DEVICE_STALL); // // Clear the Bulk-In and Bulk-Out stall condition. diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h index 8ccc48be23..341ffd0931 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h @@ -46,21 +46,21 @@ enum { USB_BOT_COMMAND_ERROR = 0x02, // Phase error, need to reset the device // - // Usb Bot retry times + // Usb Bot retry to get CSW, refers to specification[BOT10-5.3, it says 2 times] // - USB_BOT_GET_STATUS_RETRY = 3, + USB_BOT_RECV_CSW_RETRY = 3, // - // Usb Bot stall time + // Usb Bot wait device reset complete, set by experience + // + USB_BOT_RESET_DEVICE_STALL = 100 * USB_MASS_1_MILLISECOND, + // - USB_BOT_RESET_STALL = 100 * USB_MASS_STALL_1_MS, - - // - // Usb Bot transfer timeout + // Usb Bot transport timeout, set by experience // - USB_BOT_CBW_TIMEOUT = 1 * USB_MASS_STALL_1_S, - USB_BOT_CSW_TIMEOUT = 1 * USB_MASS_STALL_1_S, - USB_BOT_RESET_TIMEOUT = 3 * USB_MASS_STALL_1_S + USB_BOT_SEND_CBW_TIMEOUT = 3 * USB_MASS_1_SECOND, + USB_BOT_RECV_CSW_TIMEOUT = 3 * USB_MASS_1_SECOND, + USB_BOT_RESET_DEVICE_TIMEOUT = 3 * USB_MASS_1_SECOND, }; // diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c index 5c07c548b9..016235055b 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c @@ -194,7 +194,7 @@ UsbCbiSendCommand ( Request.Length = CmdLen; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) { // @@ -281,7 +281,7 @@ UsbCbiDataTransfer ( Remain = *TransLen; Retry = 0; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; // // Transfer the data, if the device returns NAK, retry it. @@ -376,7 +376,7 @@ UsbCbiGetStatus ( Endpoint = UsbCbi->InterruptEndpoint->EndpointAddress; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; // // Attemp to the read the result from interrupt endpoint @@ -555,7 +555,7 @@ UsbCbiResetDevice ( ResetCmd[0] = 0x1D; ResetCmd[1] = 0x04; - Timeout = USB_CBI_RESET_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_CBI_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND; // // Send the command to the device. Don't use UsbCbiExecCommand here. @@ -570,7 +570,7 @@ UsbCbiResetDevice ( // 50ms to wait it complete // UsbCbiGetStatus (UsbCbi, Timeout, &Result); - gBS->Stall (50 * 1000); + gBS->Stall (USB_CBI_RESET_DEVICE_STALL); // // Clear the Bulk-In and Bulk-Out stall condition and diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h index 61954e6be9..7933c71bf0 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h @@ -30,14 +30,19 @@ enum { USB_CBI_RESET_CMD_LEN = 12, // - // Usb CBI retry times + // Usb Cbi retry C/B/I transport times, set by experience // USB_CBI_MAX_RETRY = 3, // - // Usb Cbi transfer timeout + // Usb Cbi wait device reset complete, set by experience + // + USB_CBI_RESET_DEVICE_STALL = 50 * USB_MASS_1_MILLISECOND, + + // + // Usb Cbi transport timeout, set by experience // - USB_CBI_RESET_TIMEOUT = 1 * USB_MASS_STALL_1_S + USB_CBI_RESET_DEVICE_TIMEOUT = 1 * USB_MASS_1_SECOND, }; // diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c index e3f5c76390..f077e2aaad 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c @@ -91,7 +91,7 @@ UsbMassInitMedia ( // Status = EFI_SUCCESS; - for (Index = 0; Index < USB_BOOT_WAIT_RETRY; Index++) { + for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) { Status = UsbBootGetParams (UsbMass); if ((Status != EFI_MEDIA_CHANGED) @@ -102,7 +102,7 @@ UsbMassInitMedia ( Status = UsbBootIsUnitReady (UsbMass); if (EFI_ERROR (Status)) { - gBS->Stall (USB_BOOT_UNIT_READY_STALL * (Index + 1)); + gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1)); } } @@ -128,9 +128,17 @@ UsbMassReset ( ) { USB_MASS_DEVICE *UsbMass; + EFI_TPL OldTpl; + EFI_STATUS Status; + + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); - return UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification); + Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification); + + gBS->RestoreTPL (OldTpl); + + return Status; } @@ -165,8 +173,10 @@ UsbMassReadBlocks ( USB_MASS_DEVICE *UsbMass; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; + EFI_TPL OldTpl; UINTN TotalBlock; - + + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); Media = &UsbMass->BlockIoMedia; @@ -174,40 +184,47 @@ UsbMassReadBlocks ( // First, validate the parameters // if ((Buffer == NULL) || (BufferSize == 0)) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; } - - // - // If it is a remoable media, such as CD-Rom or Usb-Floppy, - // if, need to detect the media before each rw, while Usb-Flash - // needn't. However, it's hard to identify Usb-Floppy between - // Usb-Flash by now, so detect media every time. - // - Status = UsbBootDetectMedia (UsbMass); - if (EFI_ERROR (Status)) { - DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status)); - return Status; + + // + // If it is a removable media, such as CD-Rom or Usb-Floppy, + // need to detect the media before each rw. While some of + // Usb-Flash is marked as removable media. + // + // + if (Media->RemovableMedia == TRUE) { + Status = UsbBootDetectMedia (UsbMass); + if (EFI_ERROR (Status)) { + DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status)); + goto ON_EXIT; + } } - + // // Make sure BlockSize and LBA is consistent with BufferSize // if ((BufferSize % Media->BlockSize) != 0) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } TotalBlock = BufferSize / Media->BlockSize; if (Lba + TotalBlock - 1 > Media->LastBlock) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } - + Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer); if (EFI_ERROR (Status)) { DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status)); UsbMassReset (This, TRUE); } +ON_EXIT: + gBS->RestoreTPL (OldTpl); return Status; } @@ -243,8 +260,10 @@ UsbMassWriteBlocks ( USB_MASS_DEVICE *UsbMass; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; + EFI_TPL OldTpl; UINTN TotalBlock; + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); Media = &UsbMass->BlockIoMedia; @@ -252,34 +271,39 @@ UsbMassWriteBlocks ( // First, validate the parameters // if ((Buffer == NULL) || (BufferSize == 0)) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; } - - // - // If it is a remoable media, such as CD-Rom or Usb-Floppy, - // if, need to detect the media before each rw, while Usb-Flash - // needn't. However, it's hard to identify Usb-Floppy between - // Usb-Flash by now, so detect media every time. - // - Status = UsbBootDetectMedia (UsbMass); - if (EFI_ERROR (Status)) { - DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status)); - return Status; + + // + // If it is a removable media, such as CD-Rom or Usb-Floppy, + // need to detect the media before each rw. While some of + // Usb-Flash is marked as removable media. + // + // + if (Media->RemovableMedia == TRUE) { + Status = UsbBootDetectMedia (UsbMass); + if (EFI_ERROR (Status)) { + DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status)); + goto ON_EXIT; + } } - + // // Make sure BlockSize and LBA is consistent with BufferSize // if ((BufferSize % Media->BlockSize) != 0) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } TotalBlock = BufferSize / Media->BlockSize; if (Lba + TotalBlock - 1 > Media->LastBlock) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } - + // // Try to write the data even the device is marked as ReadOnly, // and clear the status should the write succeed. @@ -289,7 +313,9 @@ UsbMassWriteBlocks ( DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status)); UsbMassReset (This, TRUE); } - + +ON_EXIT: + gBS->RestoreTPL (OldTpl); return Status; } diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h index eeff1edcda..732861c3ec 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h @@ -33,7 +33,13 @@ typedef struct _USB_MASS_DEVICE USB_MASS_DEVICE; #include "UsbMassBoot.h" enum { - USB_MASS_SIGNATURE= EFI_SIGNATURE_32 ('U', 's', 'b', 'K') + // + // MassStorage raises TPL to TPL_NOTIFY to serialize all its operations + // to protect shared data structures. + // + USB_MASS_TPL = TPL_NOTIFY, + + USB_MASS_SIGNATURE = EFI_SIGNATURE_32 ('U', 's', 'b', 'M'), }; struct _USB_MASS_DEVICE { -- cgit v1.2.3