OvmfPkg/PvScsiDxe: Report the number of targets and LUNs

Implement EXT_SCSI_PASS_THRU.GetNextTarget() and
EXT_SCSI_PASS_THRU.GetNextTargetLun().

ScsiBusDxe scans all MaxTarget * MaxLun possible devices.
This can take unnecessarily long for large number of targets.
To deal with this, VirtioScsiDxe has defined PCDs to limit the
MaxTarget & MaxLun to desired values which gives sufficient
performance. It is very important in virtio-scsi as it can have
very big MaxTarget & MaxLun.
Even though a common PVSCSI device has a default MaxTarget=64 and
MaxLun=0, we implement similar mechanism as virtio-scsi for completeness.
This may be useful in the future when PVSCSI will have bigger values
for MaxTarget and MaxLun.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2567
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Message-Id: <20200328200100.60786-7-liran.alon@oracle.com>
Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
This commit is contained in:
Liran Alon 2020-03-28 23:00:49 +03:00 committed by mergify[bot]
parent e497432c2c
commit 7efce2e59c
4 changed files with 136 additions and 2 deletions

View File

@ -134,6 +134,15 @@
gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6 gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6
gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7 gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7
## Sets the *inclusive* number of targets and LUNs that PvScsi exposes for
# scan by ScsiBusDxe.
# As specified above for VirtioScsi, ScsiBusDxe scans all MaxTarget * MaxLun
# possible devices, which can take extremely long. Thus, the below constants
# are used so that scanning the number of devices given by their product
# is still acceptably fast.
gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxTargetLimit|64|UINT8|0x36
gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxLunLimit|0|UINT8|0x37
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa

View File

@ -11,6 +11,7 @@
#include <IndustryStandard/Pci.h> #include <IndustryStandard/Pci.h>
#include <IndustryStandard/PvScsi.h> #include <IndustryStandard/PvScsi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
@ -25,6 +26,30 @@
// //
#define PVSCSI_BINDING_VERSION 0x10 #define PVSCSI_BINDING_VERSION 0x10
//
// Ext SCSI Pass Thru utilities
//
/**
Check if Target argument to EXT_SCSI_PASS_THRU.GetNextTarget() and
EXT_SCSI_PASS_THRU.GetNextTargetLun() is initialized
**/
STATIC
BOOLEAN
IsTargetInitialized (
IN UINT8 *Target
)
{
UINTN Idx;
for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
if (Target[Idx] != 0xFF) {
return TRUE;
}
}
return FALSE;
}
// //
// Ext SCSI Pass Thru // Ext SCSI Pass Thru
// //
@ -52,7 +77,54 @@ PvScsiGetNextTargetLun (
IN OUT UINT64 *Lun IN OUT UINT64 *Lun
) )
{ {
return EFI_UNSUPPORTED; UINT8 *TargetPtr;
UINT8 LastTarget;
PVSCSI_DEV *Dev;
if (Target == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// The Target input parameter is unnecessarily a pointer-to-pointer
//
TargetPtr = *Target;
//
// If target not initialized, return first target & LUN
//
if (!IsTargetInitialized (TargetPtr)) {
ZeroMem (TargetPtr, TARGET_MAX_BYTES);
*Lun = 0;
return EFI_SUCCESS;
}
//
// We only use first byte of target identifer
//
LastTarget = *TargetPtr;
//
// Increment (target, LUN) pair if valid on input
//
Dev = PVSCSI_FROM_PASS_THRU (This);
if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
return EFI_INVALID_PARAMETER;
}
if (*Lun < Dev->MaxLun) {
++*Lun;
return EFI_SUCCESS;
}
if (LastTarget < Dev->MaxTarget) {
*Lun = 0;
++LastTarget;
*TargetPtr = LastTarget;
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
} }
STATIC STATIC
@ -111,7 +183,47 @@ PvScsiGetNextTarget (
IN OUT UINT8 **Target IN OUT UINT8 **Target
) )
{ {
return EFI_UNSUPPORTED; UINT8 *TargetPtr;
UINT8 LastTarget;
PVSCSI_DEV *Dev;
if (Target == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// The Target input parameter is unnecessarily a pointer-to-pointer
//
TargetPtr = *Target;
//
// If target not initialized, return first target
//
if (!IsTargetInitialized (TargetPtr)) {
ZeroMem (TargetPtr, TARGET_MAX_BYTES);
return EFI_SUCCESS;
}
//
// We only use first byte of target identifer
//
LastTarget = *TargetPtr;
//
// Increment target if valid on input
//
Dev = PVSCSI_FROM_PASS_THRU (This);
if (LastTarget > Dev->MaxTarget) {
return EFI_INVALID_PARAMETER;
}
if (LastTarget < Dev->MaxTarget) {
++LastTarget;
*TargetPtr = LastTarget;
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
} }
STATIC STATIC
@ -120,6 +232,12 @@ PvScsiInit (
IN OUT PVSCSI_DEV *Dev IN OUT PVSCSI_DEV *Dev
) )
{ {
//
// Init configuration
//
Dev->MaxTarget = PcdGet8 (PcdPvScsiMaxTargetLimit);
Dev->MaxLun = PcdGet8 (PcdPvScsiMaxLunLimit);
// //
// Populate the exported interface's attributes // Populate the exported interface's attributes
// //

View File

@ -19,6 +19,8 @@
typedef struct { typedef struct {
UINT32 Signature; UINT32 Signature;
UINT8 MaxTarget;
UINT8 MaxLun;
EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;
} PVSCSI_DEV; } PVSCSI_DEV;

View File

@ -26,6 +26,7 @@
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
[LibraryClasses] [LibraryClasses]
BaseMemoryLib
DebugLib DebugLib
MemoryAllocationLib MemoryAllocationLib
UefiBootServicesTableLib UefiBootServicesTableLib
@ -35,3 +36,7 @@
[Protocols] [Protocols]
gEfiExtScsiPassThruProtocolGuid ## BY_START gEfiExtScsiPassThruProtocolGuid ## BY_START
gEfiPciIoProtocolGuid ## TO_START gEfiPciIoProtocolGuid ## TO_START
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxLunLimit ## CONSUMES
gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxTargetLimit ## CONSUMES