Revision: 19472
http://sourceforge.net/p/edk2/code/19472
Author: hwu1225
Date: 2015-12-23 01:37:22 +0000 (Wed, 23 Dec 2015)
Log Message:
-----------
MdeModulePkg ScsiDiskDxe: Add retry scheme for async SCSI I/O command
Some SCSI devices will return EFI_DEVICE_ERROR or EFI_TIMEOUT when the
data length of a SCSI I/O command is too large.
This commit will repeatedly retry sending the SCSI command with a data
length half of its previous value.
(Sync patch r19451 from main trunk.)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <[email protected]>
Reviewed-by: Feng Tian <[email protected]>
Revision Links:
--------------
http://sourceforge.net/p/edk2/code/19451
Modified Paths:
--------------
branches/UDK2015/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
Modified: branches/UDK2015/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
===================================================================
--- branches/UDK2015/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
2015-12-23 01:37:00 UTC (rev 19471)
+++ branches/UDK2015/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
2015-12-23 01:37:22 UTC (rev 19472)
@@ -2674,15 +2674,40 @@
}
if (EFI_ERROR (Status)) {
//
- // Free the SCSI_BLKIO2_REQUEST structure only when the first SCSI
- // command fails. Otherwise, it will be freed in the callback function
- // ScsiDiskNotify().
+ // Some devices will return EFI_DEVICE_ERROR or EFI_TIMEOUT when the data
+ // length of a SCSI I/O command is too large.
+ // In this case, we retry sending the SCSI command with a data length
+ // half of its previous value.
//
+ if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {
+ if ((MaxBlock > 1) && (SectorCount > 1)) {
+ MaxBlock = MIN (MaxBlock, SectorCount) >> 1;
+ continue;
+ }
+ }
+
if (IsListEmpty (&BlkIo2Req->ScsiRWQueue)) {
+ //
+ // Free the SCSI_BLKIO2_REQUEST structure only when there is no other
+ // SCSI sub-task running. Otherwise, it will be freed in the callback
+ // function ScsiDiskNotify().
+ //
RemoveEntryList (&BlkIo2Req->Link);
FreePool (BlkIo2Req);
+
+ //
+ // It is safe to return error status to the caller, since there is no
+ // previous SCSI sub-task executing.
+ //
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // There are previous SCSI commands still running, EFI_SUCCESS should
+ // be returned to make sure that the caller does not free resources
+ // still using by these SCSI commands.
+ //
+ return EFI_SUCCESS;
}
- return EFI_DEVICE_ERROR;
}
//
@@ -2837,15 +2862,40 @@
}
if (EFI_ERROR (Status)) {
//
- // Free the SCSI_BLKIO2_REQUEST structure only when the first SCSI
- // command fails. Otherwise, it will be freed in the callback function
- // ScsiDiskNotify().
+ // Some devices will return EFI_DEVICE_ERROR or EFI_TIMEOUT when the data
+ // length of a SCSI I/O command is too large.
+ // In this case, we retry sending the SCSI command with a data length
+ // half of its previous value.
//
+ if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {
+ if ((MaxBlock > 1) && (SectorCount > 1)) {
+ MaxBlock = MIN (MaxBlock, SectorCount) >> 1;
+ continue;
+ }
+ }
+
if (IsListEmpty (&BlkIo2Req->ScsiRWQueue)) {
+ //
+ // Free the SCSI_BLKIO2_REQUEST structure only when there is no other
+ // SCSI sub-task running. Otherwise, it will be freed in the callback
+ // function ScsiDiskNotify().
+ //
RemoveEntryList (&BlkIo2Req->Link);
FreePool (BlkIo2Req);
+
+ //
+ // It is safe to return error status to the caller, since there is no
+ // previous SCSI sub-task executing.
+ //
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // There are previous SCSI commands still running, EFI_SUCCESS should
+ // be returned to make sure that the caller does not free resources
+ // still using by these SCSI commands.
+ //
+ return EFI_SUCCESS;
}
- return EFI_DEVICE_ERROR;
}
//
------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits