]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/PvScsiDxe: Report the number of targets and LUNs
authorLiran Alon <liran.alon@oracle.com>
Sat, 28 Mar 2020 20:00:49 +0000 (23:00 +0300)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 30 Mar 2020 16:45:07 +0000 (16:45 +0000)
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>
OvmfPkg/OvmfPkg.dec
OvmfPkg/PvScsiDxe/PvScsi.c
OvmfPkg/PvScsiDxe/PvScsi.h
OvmfPkg/PvScsiDxe/PvScsiDxe.inf

index 913345d49e1f006c55ba9e6c3af590422bcb2180..adb7ac2e2309e573c5334c0e0c0e4116969a78a8 100644 (file)
   gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6\r
   gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7\r
 \r
+  ## Sets the *inclusive* number of targets and LUNs that PvScsi exposes for\r
+  #  scan by ScsiBusDxe.\r
+  #  As specified above for VirtioScsi, ScsiBusDxe scans all MaxTarget * MaxLun\r
+  #  possible devices, which can take extremely long. Thus, the below constants\r
+  #  are used so that scanning the number of devices given by their product\r
+  #  is still acceptably fast.\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxTargetLimit|64|UINT8|0x36\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxLunLimit|0|UINT8|0x37\r
+\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa\r
index 04c08036b799be6adfb74f85ca179a3f98f90061..7f51ada19a1a924da3e5738e6abb40eb394ac15e 100644 (file)
@@ -11,6 +11,7 @@
 \r
 #include <IndustryStandard/Pci.h>\r
 #include <IndustryStandard/PvScsi.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 //\r
 #define PVSCSI_BINDING_VERSION      0x10\r
 \r
+//\r
+// Ext SCSI Pass Thru utilities\r
+//\r
+\r
+/**\r
+  Check if Target argument to EXT_SCSI_PASS_THRU.GetNextTarget() and\r
+  EXT_SCSI_PASS_THRU.GetNextTargetLun() is initialized\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsTargetInitialized (\r
+  IN UINT8                                          *Target\r
+  )\r
+{\r
+  UINTN Idx;\r
+\r
+  for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {\r
+    if (Target[Idx] != 0xFF) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 //\r
 // Ext SCSI Pass Thru\r
 //\r
@@ -52,7 +77,54 @@ PvScsiGetNextTargetLun (
   IN OUT UINT64                                     *Lun\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  UINT8      *TargetPtr;\r
+  UINT8      LastTarget;\r
+  PVSCSI_DEV *Dev;\r
+\r
+  if (Target == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // The Target input parameter is unnecessarily a pointer-to-pointer\r
+  //\r
+  TargetPtr = *Target;\r
+\r
+  //\r
+  // If target not initialized, return first target & LUN\r
+  //\r
+  if (!IsTargetInitialized (TargetPtr)) {\r
+    ZeroMem (TargetPtr, TARGET_MAX_BYTES);\r
+    *Lun = 0;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // We only use first byte of target identifer\r
+  //\r
+  LastTarget = *TargetPtr;\r
+\r
+  //\r
+  // Increment (target, LUN) pair if valid on input\r
+  //\r
+  Dev = PVSCSI_FROM_PASS_THRU (This);\r
+  if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*Lun < Dev->MaxLun) {\r
+    ++*Lun;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (LastTarget < Dev->MaxTarget) {\r
+    *Lun = 0;\r
+    ++LastTarget;\r
+    *TargetPtr = LastTarget;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
 }\r
 \r
 STATIC\r
@@ -111,7 +183,47 @@ PvScsiGetNextTarget (
   IN OUT UINT8                                      **Target\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  UINT8      *TargetPtr;\r
+  UINT8      LastTarget;\r
+  PVSCSI_DEV *Dev;\r
+\r
+  if (Target == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // The Target input parameter is unnecessarily a pointer-to-pointer\r
+  //\r
+  TargetPtr = *Target;\r
+\r
+  //\r
+  // If target not initialized, return first target\r
+  //\r
+  if (!IsTargetInitialized (TargetPtr)) {\r
+    ZeroMem (TargetPtr, TARGET_MAX_BYTES);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // We only use first byte of target identifer\r
+  //\r
+  LastTarget = *TargetPtr;\r
+\r
+  //\r
+  // Increment target if valid on input\r
+  //\r
+  Dev = PVSCSI_FROM_PASS_THRU (This);\r
+  if (LastTarget > Dev->MaxTarget) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (LastTarget < Dev->MaxTarget) {\r
+    ++LastTarget;\r
+    *TargetPtr = LastTarget;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
 }\r
 \r
 STATIC\r
@@ -120,6 +232,12 @@ PvScsiInit (
   IN OUT PVSCSI_DEV *Dev\r
   )\r
 {\r
+  //\r
+  // Init configuration\r
+  //\r
+  Dev->MaxTarget = PcdGet8 (PcdPvScsiMaxTargetLimit);\r
+  Dev->MaxLun = PcdGet8 (PcdPvScsiMaxLunLimit);\r
+\r
   //\r
   // Populate the exported interface's attributes\r
   //\r
index 3940b4c20019cf9787a70fac76914d93bd29aacd..dd3e0c68e6da24bfd13ab80bf35d1211d1411ce5 100644 (file)
@@ -19,6 +19,8 @@
 \r
 typedef struct {\r
   UINT32                          Signature;\r
+  UINT8                           MaxTarget;\r
+  UINT8                           MaxLun;\r
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;\r
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;\r
 } PVSCSI_DEV;\r
index f4d452c6c3d2fe804626be8d8968efc09d392e07..fcffc90d46c8269a2ff7a30c674a84f36e8e24c2 100644 (file)
@@ -26,6 +26,7 @@
   OvmfPkg/OvmfPkg.dec\r
 \r
 [LibraryClasses]\r
+  BaseMemoryLib\r
   DebugLib\r
   MemoryAllocationLib\r
   UefiBootServicesTableLib\r
@@ -35,3 +36,7 @@
 [Protocols]\r
   gEfiExtScsiPassThruProtocolGuid   ## BY_START\r
   gEfiPciIoProtocolGuid             ## TO_START\r
+\r
+[Pcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxLunLimit       ## CONSUMES\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdPvScsiMaxTargetLimit    ## CONSUMES\r