From: Ard Biesheuvel Date: Thu, 24 Aug 2017 19:05:48 +0000 (+0100) Subject: EmbeddedPkg/DmaLib: add routine to allocate aligned buffers X-Git-Tag: edk2-stable201903~3545 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=deef290f95e0df80549d2a6cbd7edae104c82709 EmbeddedPkg/DmaLib: add routine to allocate aligned buffers DmaLib's purpose is to manage memory that is shared between the host and DMA capable devices. In some cases, this requires a larger alignment than page size, and we currently don't cater for that in DmaLib. So add a variant of DmaAllocateBuffer () that takes an alignment parameter. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- diff --git a/EmbeddedPkg/Include/Library/DmaLib.h b/EmbeddedPkg/Include/Library/DmaLib.h index 3814291c28..1843814c65 100644 --- a/EmbeddedPkg/Include/Library/DmaLib.h +++ b/EmbeddedPkg/Include/Library/DmaLib.h @@ -155,5 +155,33 @@ DmaFreeBuffer ( ); -#endif +/** + Allocates pages that are suitable for an DmaMap() of type + MapOperationBusMasterCommonBuffer mapping, at the requested alignment. + + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param Alignment Alignment in bytes of the base of the returned + buffer (must be a power of 2) + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +DmaAllocateAlignedBuffer ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment, + OUT VOID **HostAddress + ); + + +#endif diff --git a/EmbeddedPkg/Library/NullDmaLib/NullDmaLib.c b/EmbeddedPkg/Library/NullDmaLib/NullDmaLib.c index a0bb57541d..4cbe349190 100644 --- a/EmbeddedPkg/Library/NullDmaLib/NullDmaLib.c +++ b/EmbeddedPkg/Library/NullDmaLib/NullDmaLib.c @@ -100,23 +100,61 @@ DmaAllocateBuffer ( OUT VOID **HostAddress ) { - if (HostAddress == NULL) { + return DmaAllocateAlignedBuffer (MemoryType, Pages, 0, HostAddress); +} + + +/** + Allocates pages that are suitable for an DmaMap() of type + MapOperationBusMasterCommonBuffer mapping, at the requested alignment. + + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param Alignment Alignment in bytes of the base of the returned + buffer (must be a power of 2) + @param HostAddress A pointer to store the base system memory address of the + allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +DmaAllocateAlignedBuffer ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment, + OUT VOID **HostAddress + ) +{ + if (Alignment == 0) { + Alignment = EFI_PAGE_SIZE; + } + + if (HostAddress == NULL || + (Alignment & (Alignment - 1)) != 0) { return EFI_INVALID_PARAMETER; } // // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData // - // We used uncached memory to keep coherency - // if (MemoryType == EfiBootServicesData) { - *HostAddress = AllocatePages (Pages); + *HostAddress = AllocateAlignedPages (Pages, Alignment); } else if (MemoryType != EfiRuntimeServicesData) { - *HostAddress = AllocateRuntimePages (Pages); + *HostAddress = AllocateAlignedRuntimePages (Pages, Alignment); } else { return EFI_INVALID_PARAMETER; } + if (*HostAddress == NULL) { + return EFI_OUT_OF_RESOURCES; + } return EFI_SUCCESS; }