summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/PvScsiDxe/PvScsi.c
diff options
context:
space:
mode:
authorLiran Alon <liran.alon@oracle.com>2020-03-28 23:00:49 +0300
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2020-03-30 16:45:07 +0000
commit7efce2e59c2016f0b2572d4b79845f14a8758475 (patch)
tree21c03199b60998ef4152723a3dfe2c088d330ec6 /OvmfPkg/PvScsiDxe/PvScsi.c
parente497432c2ceadc3924f96e49593c8a77044efea7 (diff)
downloadedk2-7efce2e59c2016f0b2572d4b79845f14a8758475.tar.gz
edk2-7efce2e59c2016f0b2572d4b79845f14a8758475.tar.bz2
edk2-7efce2e59c2016f0b2572d4b79845f14a8758475.zip
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>
Diffstat (limited to 'OvmfPkg/PvScsiDxe/PvScsi.c')
-rw-r--r--OvmfPkg/PvScsiDxe/PvScsi.c122
1 files changed, 120 insertions, 2 deletions
diff --git a/OvmfPkg/PvScsiDxe/PvScsi.c b/OvmfPkg/PvScsiDxe/PvScsi.c
index 04c08036b7..7f51ada19a 100644
--- a/OvmfPkg/PvScsiDxe/PvScsi.c
+++ b/OvmfPkg/PvScsiDxe/PvScsi.c
@@ -11,6 +11,7 @@
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/PvScsi.h>
+#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
@@ -26,6 +27,30 @@
#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
//
@@ -52,7 +77,54 @@ PvScsiGetNextTargetLun (
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
@@ -111,7 +183,47 @@ PvScsiGetNextTarget (
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
@@ -121,6 +233,12 @@ PvScsiInit (
)
{
//
+ // Init configuration
+ //
+ Dev->MaxTarget = PcdGet8 (PcdPvScsiMaxTargetLimit);
+ Dev->MaxLun = PcdGet8 (PcdPvScsiMaxLunLimit);
+
+ //
// Populate the exported interface's attributes
//
Dev->PassThru.Mode = &Dev->PassThruMode;