Add IoMmu support for UFS library

This patch added IoMmu interfaces support for UFS library. It will
allow the library to use DMA buffer for I/O transactions.

Signed-off-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
Maurice Ma 2020-03-18 13:59:06 -07:00
parent 5c95bd52d8
commit 1f50619fa4
5 changed files with 231 additions and 759 deletions

View File

@ -90,10 +90,11 @@ UFS_PEIM_HC_PRIVATE_DATA gUfsHcTemplate = {
0, // TaskTag 0, // TaskTag
0, // UtpTrlBase 0, // UtpTrlBase
0, // Nutrs 0, // Nutrs
NULL, // TrlMapping
0, // UtpTmrlBase 0, // UtpTmrlBase
0, // Nutmrs 0, // Nutmrs
{ NULL, // TmrlMapping
// Luns { // Luns
{ {
UFS_LUN_0, // Ufs Common Lun 0 UFS_LUN_0, // Ufs Common Lun 0
UFS_LUN_1, // Ufs Common Lun 1 UFS_LUN_1, // Ufs Common Lun 1
@ -1298,7 +1299,31 @@ InitializeUfs (
if (DevInitPhase == DevDeinit) { if (DevInitPhase == DevDeinit) {
if (gPrivate != NULL) { if (gPrivate != NULL) {
FreePool (gPrivate); Private = gPrivate;
if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) {
UfsFreeMemPool (Private->Pool);
}
if (Private->UtpTmrlBase != NULL) {
IoMmuFreeBuffer (
EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)),
Private->UtpTmrlBase,
Private->TmrlMapping
);
}
if (Private->UtpTrlBase != NULL) {
IoMmuFreeBuffer (
EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TRD)),
Private->UtpTrlBase,
Private->TrlMapping
);
}
UfsControllerStop (Private);
FreePool (Private);
gPrivate = NULL; gPrivate = NULL;
} }
return EFI_SUCCESS; return EFI_SUCCESS;

View File

@ -1,6 +1,6 @@
/** @file /** @file
Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -22,8 +22,11 @@ UfsAllocMemBlock (
) )
{ {
UFS_PEIM_MEM_BLOCK *Block; UFS_PEIM_MEM_BLOCK *Block;
VOID *BufHost;
VOID *Mapping;
EFI_PHYSICAL_ADDRESS MappedAddr;
EFI_STATUS Status;
VOID *TempPtr; VOID *TempPtr;
EFI_PHYSICAL_ADDRESS Address;
TempPtr = NULL; TempPtr = NULL;
Block = NULL; Block = NULL;
@ -54,14 +57,21 @@ UfsAllocMemBlock (
Block->Bits = (UINT8 *) (UINTN)TempPtr; Block->Bits = (UINT8 *) (UINTN)TempPtr;
Address = (UINTN)AllocatePages (Pages); Status = IoMmuAllocateBuffer (
if ((VOID *) (UINTN)Address == NULL) { Pages,
&BufHost,
&MappedAddr,
&Mapping
);
if (EFI_ERROR (Status)) {
return NULL; return NULL;
} }
ZeroMem ((VOID *) (UINTN)Address, EFI_PAGES_TO_SIZE (Pages)); ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages));
Block->Buf = (UINT8 *) ((UINTN)Address); Block->BufHost = (UINT8 *) (UINTN) BufHost;
Block->Buf = (UINT8 *) (UINTN) MappedAddr;
Block->Mapping = Mapping;
Block->Next = NULL; Block->Next = NULL;
return Block; return Block;
@ -81,6 +91,8 @@ UfsFreeMemBlock (
) )
{ {
ASSERT ((Pool != NULL) && (Block != NULL)); ASSERT ((Pool != NULL) && (Block != NULL));
IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Block->Mapping);
} }
/** /**
@ -200,31 +212,7 @@ UfsIsMemBlockEmpty (
return TRUE; return TRUE;
} }
/**
Unlink the memory block from the pool's list.
@param Head The block list head of the memory's pool.
@param BlockToUnlink The memory block to unlink.
**/
VOID
UfsUnlinkMemBlock (
IN UFS_PEIM_MEM_BLOCK *Head,
IN UFS_PEIM_MEM_BLOCK *BlockToUnlink
)
{
UFS_PEIM_MEM_BLOCK *Block;
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
for (Block = Head; Block != NULL; Block = Block->Next) {
if (Block->Next == BlockToUnlink) {
Block->Next = BlockToUnlink->Next;
BlockToUnlink->Next = NULL;
break;
}
}
}
/** /**
Initialize the memory management pool for the host controller. Initialize the memory management pool for the host controller.
@ -285,8 +273,6 @@ UfsFreeMemPool (
// //
// Unlink all the memory blocks from the pool, then free them. // Unlink all the memory blocks from the pool, then free them.
// UfsUnlinkMemBlock can't be used to unlink and free the
// first block.
// //
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) { for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
UfsFreeMemBlock (Pool, Block); UfsFreeMemBlock (Pool, Block);

View File

@ -1,6 +1,6 @@
/** @file /** @file
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -20,7 +20,9 @@ struct _UFS_PEIM_MEM_BLOCK {
UINT8 *Bits; // Bit array to record which unit is allocated UINT8 *Bits; // Bit array to record which unit is allocated
UINTN BitsLen; UINTN BitsLen;
UINT8 *Buf; UINT8 *Buf;
UINT8 *BufHost;
UINTN BufLen; // Memory size in bytes UINTN BufLen; // Memory size in bytes
VOID *Mapping;
UFS_PEIM_MEM_BLOCK *Next; UFS_PEIM_MEM_BLOCK *Next;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
#include <Library/TimerLib.h> #include <Library/TimerLib.h>
#include <IndustryStandard/Scsi.h> #include <IndustryStandard/Scsi.h>
#include <Library/UfsBlockIoLib.h> #include <Library/UfsBlockIoLib.h>
#include <Library/IoMmuLib.h>
#include <Ppi/BlockIo.h> #include <Ppi/BlockIo.h>
#include "UfsHci.h" #include "UfsHci.h"
@ -137,8 +138,10 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA {
VOID *UtpTrlBase; VOID *UtpTrlBase;
UINT8 Nutrs; UINT8 Nutrs;
VOID *TrlMapping;
VOID *UtpTmrlBase; VOID *UtpTmrlBase;
UINT8 Nutmrs; UINT8 Nutmrs;
VOID *TmrlMapping;
UFS_PEIM_EXPOSED_LUNS Luns; UFS_PEIM_EXPOSED_LUNS Luns;
} UFS_PEIM_HC_PRIVATE_DATA; } UFS_PEIM_HC_PRIVATE_DATA;
@ -328,4 +331,18 @@ UfsFreeMem (
IN UINTN Size IN UINTN Size
); );
/**
Release the memory management pool.
@param Pool The memory pool to free.
@retval EFI_DEVICE_ERROR Fail to free the memory pool.
@retval EFI_SUCCESS The memory pool is freed.
**/
EFI_STATUS
UfsFreeMemPool (
IN UFS_PEIM_MEM_POOL *Pool
);
#endif #endif