[edk2-devel] [PATCH v2 5/5] DesignWare/DwEmmcDxe: Force DMA buffer to allocate below 4GB
John Chew
yuinyee.chew at starfivetech.com
Mon Oct 23 07:17:15 UTC 2023
The buffer address passed into the read/write block function sometimes
larger than 4GB. This driver only support 32-bit DMA addressing.
MMC timeout will occur if DMA buffer is allocated in 64-bit address.
Cc: Sunil V L <sunilvl at ventanamicro.com>
Cc: Leif Lindholm <quic_llindhol at quicinc.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Cc: Cc: Li Yong <yong.li at intel.com>
Signed-off-by: John Chew <yuinyee.chew at starfivetech.com>
---
Silicon/Synopsys/DesignWare/Drivers/DwEmmcDxe/DwEmmcDxe.c | 79 ++++++++++++++++----
1 file changed, 64 insertions(+), 15 deletions(-)
diff --git a/Silicon/Synopsys/DesignWare/Drivers/DwEmmcDxe/DwEmmcDxe.c b/Silicon/Synopsys/DesignWare/Drivers/DwEmmcDxe/DwEmmcDxe.c
index 39e4d994fcd4..8233639b0ce8 100644
--- a/Silicon/Synopsys/DesignWare/Drivers/DwEmmcDxe/DwEmmcDxe.c
+++ b/Silicon/Synopsys/DesignWare/Drivers/DwEmmcDxe/DwEmmcDxe.c
@@ -601,27 +601,57 @@ DwEmmcWaitDmaComplete (
return Status;
}
+STATIC
+UINT32 *
+AllocateMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ UINT32 *Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xFFFFFFFF;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Buffer = (UINT32 *)(UINTN)Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
EFI_STATUS
DwEmmcReadBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
)
{
EFI_STATUS Status;
UINT32 DescPages, CountPerPage, Count;
EFI_TPL Tpl;
+ UINT32 *DmaBuf;
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+ DmaBuf = AllocateMemoryBelow4G(Length);
CountPerPage = EFI_PAGE_SIZE / 16;
Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
DescPages = (Count + CountPerPage - 1) / CountPerPage;
- InvalidateDataCacheRange (Buffer, Length);
+ InvalidateDataCacheRange (DmaBuf, Length);
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
+ Status = PrepareDmaData (gpIdmacDesc, Length, DmaBuf);
if (EFI_ERROR (Status)) {
goto out;
}
@@ -637,11 +667,14 @@ DwEmmcReadBlockData (
Status = DwEmmcWaitDmaComplete(This, 1);
if (DWMCI_SD_READ_MASK(mDwEmmcArgument) && (FixedPcdGetBool (PcdDwEmmcDxeCPULittleEndian))) {
- Buffer[3] = SwapBytes32(Buffer[3]);
- Buffer[4] = SwapBytes32(Buffer[4]);
+ DmaBuf[3] = SwapBytes32(DmaBuf[3]);
+ DmaBuf[4] = SwapBytes32(DmaBuf[4]);
}
+ CopyMem(Buffer, DmaBuf, Length);
+
out:
+ FreePages (DmaBuf, EFI_SIZE_TO_PAGES(Length));
// Restore Tpl
gBS->RestoreTPL (Tpl);
return Status;
@@ -649,25 +682,29 @@ out:
EFI_STATUS
DwEmmcWriteBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
)
{
EFI_STATUS Status;
UINT32 DescPages, CountPerPage, Count;
EFI_TPL Tpl;
+ UINT32 *DmaBuf;
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+ DmaBuf = AllocateMemoryBelow4G(Length);
+ CopyMem(DmaBuf, Buffer, Length);
+
CountPerPage = EFI_PAGE_SIZE / 16;
Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
DescPages = (Count + CountPerPage - 1) / CountPerPage;
- WriteBackDataCacheRange (Buffer, Length);
+ WriteBackDataCacheRange (DmaBuf, Length);
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
+ Status = PrepareDmaData (gpIdmacDesc, Length, DmaBuf);
if (EFI_ERROR (Status)) {
goto out;
}
@@ -683,6 +720,7 @@ DwEmmcWriteBlockData (
Status = DwEmmcWaitDmaComplete(This, 0);
out:
+ FreePages (DmaBuf, EFI_SIZE_TO_PAGES(Length));
// Restore Tpl
gBS->RestoreTPL (Tpl);
return Status;
@@ -772,6 +810,7 @@ DwEmmcDxeInitialize (
{
EFI_STATUS Status;
EFI_HANDLE Handle;
+ EFI_PHYSICAL_ADDRESS Address;
if (!FixedPcdGetBool (PcdDwPermitObsoleteDrivers)) {
ASSERT (FALSE);
@@ -781,7 +820,17 @@ DwEmmcDxeInitialize (
Handle = NULL;
DwEmmcAdjustFifoThreshold ();
- gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES);
+
+ Address = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ DWEMMC_MAX_DESC_PAGES,
+ &Address
+ );
+ gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)(UINTN)Address;
+ ZeroMem (gpIdmacDesc, DWEMMC_MAX_DESC_PAGES);
+
if (gpIdmacDesc == NULL) {
return EFI_BUFFER_TOO_SMALL;
}
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#109895): https://edk2.groups.io/g/devel/message/109895
Mute This Topic: https://groups.io/mt/102130696/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-
More information about the edk2-devel-archive
mailing list