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 <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
This commit is contained in:
Ard Biesheuvel 2017-08-24 20:05:48 +01:00
parent 1696b221b1
commit deef290f95
2 changed files with 72 additions and 6 deletions

View File

@ -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

View File

@ -100,23 +100,61 @@ DmaAllocateBuffer (
OUT VOID **HostAddress 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; return EFI_INVALID_PARAMETER;
} }
// //
// The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
// //
// We used uncached memory to keep coherency
//
if (MemoryType == EfiBootServicesData) { if (MemoryType == EfiBootServicesData) {
*HostAddress = AllocatePages (Pages); *HostAddress = AllocateAlignedPages (Pages, Alignment);
} else if (MemoryType != EfiRuntimeServicesData) { } else if (MemoryType != EfiRuntimeServicesData) {
*HostAddress = AllocateRuntimePages (Pages); *HostAddress = AllocateAlignedRuntimePages (Pages, Alignment);
} else { } else {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
if (*HostAddress == NULL) {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }