1 Star 0 Fork 61

张梁鹏堃/edk2

forked from src-openEuler/edk2 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0079-VirtioBlk-split-large-IO-according-to-segment_size_m.patch 6.55 KB
一键复制 编辑 原始数据 按行查看 历史
Adttil 提交于 2024-11-29 10:41 +08:00 . vdpa: support vdpa blk/scsi device boot
From 734457162d02f6b4d66b8eb82da0717765fceebe Mon Sep 17 00:00:00 2001
From: Adttil <2429917001@qq.com>
Date: Fri, 29 Nov 2024 09:04:13 +0800
Subject: [PATCH 3/3] VirtioBlk: split large IO according to segment_size_max
When the VirtioBlk device is initialized, the value of SegmentSizeMax
is obtained based on the feature capability. Then delivere the requests
based on the value of SegmentSizeMax.
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
---
MdePkg/Include/Protocol/BlockIo.h | 10 ++
OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 148 +++++++++++++++++++++---------
2 files changed, 117 insertions(+), 41 deletions(-)
diff --git a/MdePkg/Include/Protocol/BlockIo.h b/MdePkg/Include/Protocol/BlockIo.h
index ac9adf7a..ac5e1c2a 100644
--- a/MdePkg/Include/Protocol/BlockIo.h
+++ b/MdePkg/Include/Protocol/BlockIo.h
@@ -197,6 +197,16 @@ typedef struct {
/// granularity as a number of logical blocks.
///
UINT32 OptimalTransferLengthGranularity;
+
+ ///
+ /// Maximum size of any single segment
+ ///
+ UINT32 MaxSegmentSize;
+
+ ///
+ /// Maximum number of segments in a request
+ ///
+ UINT32 MaxSegments;
} EFI_BLOCK_IO_MEDIA;
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index eed56994..6d7c7aef 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -31,6 +31,8 @@
#define MAX_RETRY_TIMES 1000
#define DEVICE_WAIT_INTVL 1000
+#define DEFAULT_MAX_SEGMENTS 32
+
/**
Convenience macros to read and write region 0 IO space elements of the
@@ -460,6 +462,68 @@ FreeHostStatusBuffer:
return Status;
}
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioBlkReadWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN BOOLEAN RequestIsWrite
+ )
+{
+ VBLK_DEV *Dev;
+ EFI_STATUS Status;
+ UINT32 SizeMax;
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
+ Status = VerifyReadWriteRequest (
+ &Dev->BlockIoMedia,
+ Lba,
+ BufferSize,
+ RequestIsWrite
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SizeMax = Dev->BlockIoMedia.MaxSegmentSize;
+ while (BufferSize >= SizeMax) {
+ Status = SynchronousRequest (
+ Dev,
+ Lba,
+ SizeMax,
+ Buffer,
+ RequestIsWrite
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba += SizeMax / Dev->BlockIoMedia.BlockSize;
+ BufferSize -= SizeMax;
+ Buffer = (CHAR8 *)Buffer + SizeMax;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ return SynchronousRequest (
+ Dev,
+ Lba,
+ BufferSize,
+ Buffer,
+ RequestIsWrite
+ );
+}
+
/**
ReadBlocks() operation for virtio-blk.
@@ -487,30 +551,13 @@ VirtioBlkReadBlocks (
OUT VOID *Buffer
)
{
- VBLK_DEV *Dev;
- EFI_STATUS Status;
-
- if (BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
- Status = VerifyReadWriteRequest (
- &Dev->BlockIoMedia,
- Lba,
- BufferSize,
- FALSE // RequestIsWrite
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return SynchronousRequest (
- Dev,
+ return VirtioBlkReadWriteBlocks(
+ This,
+ MediaId,
Lba,
BufferSize,
Buffer,
- FALSE // RequestIsWrite
+ FALSE // RequestIsRead
);
}
@@ -541,26 +588,9 @@ VirtioBlkWriteBlocks (
IN VOID *Buffer
)
{
- VBLK_DEV *Dev;
- EFI_STATUS Status;
-
- if (BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
- Status = VerifyReadWriteRequest (
- &Dev->BlockIoMedia,
- Lba,
- BufferSize,
- TRUE // RequestIsWrite
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return SynchronousRequest (
- Dev,
+ return VirtioBlkReadWriteBlocks(
+ This,
+ MediaId,
Lba,
BufferSize,
Buffer,
@@ -716,6 +746,8 @@ VirtioBlkInit (
UINT8 NextDevStat;
EFI_STATUS Status;
+ UINT32 MaxSegmentSize;
+ UINT32 MaxSegments;
UINT64 Features;
UINT64 NumSectors;
UINT32 BlockSize;
@@ -814,6 +846,36 @@ VirtioBlkInit (
BlockSize = 512;
}
+ if (Features & VIRTIO_BLK_F_SIZE_MAX) {
+ Status = VIRTIO_CFG_READ (Dev, SizeMax, &MaxSegmentSize);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (MaxSegmentSize == 0) {
+ //
+ // We need at least one 4KB page.
+ //
+ MaxSegmentSize = SIZE_4KB;
+ }
+ } else {
+ MaxSegmentSize = SIZE_512KB;
+ }
+
+ if (Features & VIRTIO_BLK_F_SEG_MAX) {
+ Status = VIRTIO_CFG_READ (Dev, SegMax, &MaxSegments);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (MaxSegments == 0) {
+ //
+ // We need at least one SG element, whatever they say.
+ //
+ MaxSegments = 1;
+ }
+ } else {
+ MaxSegments = DEFAULT_MAX_SEGMENTS;
+ }
+
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
Status = VIRTIO_CFG_READ (
Dev,
@@ -955,6 +1017,8 @@ VirtioBlkInit (
Dev->BlockIoMedia.ReadOnly = (BOOLEAN)((Features & VIRTIO_BLK_F_RO) != 0);
Dev->BlockIoMedia.WriteCaching = (BOOLEAN)((Features & VIRTIO_BLK_F_FLUSH) != 0);
Dev->BlockIoMedia.BlockSize = BlockSize;
+ Dev->BlockIoMedia.MaxSegments = MaxSegments;
+ Dev->BlockIoMedia.MaxSegmentSize = MaxSegmentSize;
Dev->BlockIoMedia.IoAlign = 0;
Dev->BlockIoMedia.LastBlock = DivU64x32 (
NumSectors,
@@ -968,6 +1032,8 @@ VirtioBlkInit (
Dev->BlockIoMedia.BlockSize,
Dev->BlockIoMedia.LastBlock + 1
));
+ DEBUG ((DEBUG_INFO, "%a: MaxSegments=0x%x[B] MaxSegmentSize=0x%x[B]\n",
+ __FUNCTION__, Dev->BlockIoMedia.MaxSegments, Dev->BlockIoMedia.MaxSegmentSize));
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
--
2.43.0
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhang-liang-pengkun/edk2.git
git@gitee.com:zhang-liang-pengkun/edk2.git
zhang-liang-pengkun
edk2
edk2
master

搜索帮助