MdeModulePkg/NvmExpressDxe: Fix some bugs

1) The Queue size field in create I/O submission/completion queue cmds is 0-based. the current code is 1-based.
2) a typo on allocated memory page size. it's inconsistent that some places is using 4 pages, but a place is using 6 pages.
3) a typo on PRP/SGL mechanism judgment. should directly use Psdt field rather than Opc field.
4) some platforms may not support UINT64 width access on MMIO register. Fix it to use two 32-bit width access.

Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Kinney Michael <michael.d.kinney@intel.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14657 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Feng Tian 2013-09-11 06:57:53 +00:00 committed by erictian
parent ad3f365641
commit 7b8883c6a9
5 changed files with 95 additions and 38 deletions

View File

@ -214,6 +214,15 @@ EnumerateNvmeDevNamespace (
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
); );
//
// Dump NvmExpress Identify Namespace Data
//
DEBUG ((EFI_D_INFO, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId));
DEBUG ((EFI_D_INFO, " NSZE : 0x%x\n", NamespaceData->Nsze));
DEBUG ((EFI_D_INFO, " NCAP : 0x%x\n", NamespaceData->Ncap));
DEBUG ((EFI_D_INFO, " NUSE : 0x%x\n", NamespaceData->Nuse));
DEBUG ((EFI_D_INFO, " LBAF0.LBADS : 0x%x\n", (NamespaceData->LbaFormat[0].Lbads)));
// //
// Build controller name for Component Name (2) protocol. // Build controller name for Component Name (2) protocol.
// //
@ -657,7 +666,7 @@ NvmExpressDriverBindingStart (
PciIo, PciIo,
AllocateAnyPages, AllocateAnyPages,
EfiBootServicesData, EfiBootServicesData,
6, 4,
(VOID**)&Private->Buffer, (VOID**)&Private->Buffer,
0 0
); );

View File

@ -56,11 +56,11 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiV
#define PCI_CLASS_MASS_STORAGE_NVM 0x08 // mass storage sub-class non-volatile memory. #define PCI_CLASS_MASS_STORAGE_NVM 0x08 // mass storage sub-class non-volatile memory.
#define PCI_IF_NVMHCI 0x02 // mass storage programming interface NVMHCI. #define PCI_IF_NVMHCI 0x02 // mass storage programming interface NVMHCI.
#define NVME_ASQ_SIZE 2 // Number of admin submission queue entries #define NVME_ASQ_SIZE 1 // Number of admin submission queue entries, which is 0-based
#define NVME_ACQ_SIZE 2 // Number of admin completion queue entries #define NVME_ACQ_SIZE 1 // Number of admin completion queue entries, which is 0-based
#define NVME_CSQ_SIZE 2 // Number of I/O submission queue entries #define NVME_CSQ_SIZE 1 // Number of I/O submission queue entries, which is 0-based
#define NVME_CCQ_SIZE 2 // Number of I/O completion queue entries #define NVME_CCQ_SIZE 1 // Number of I/O completion queue entries, which is 0-based
#define NVME_MAX_IO_QUEUES 2 // Number of I/O queues supported by the driver #define NVME_MAX_IO_QUEUES 2 // Number of I/O queues supported by the driver

View File

@ -172,10 +172,12 @@ NvmeRead (
UINT32 BlockSize; UINT32 BlockSize;
NVME_CONTROLLER_PRIVATE_DATA *Controller; NVME_CONTROLLER_PRIVATE_DATA *Controller;
UINT32 MaxTransferBlocks; UINT32 MaxTransferBlocks;
UINTN OrginalBlocks;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
Controller = Device->Controller; Controller = Device->Controller;
BlockSize = Device->Media.BlockSize; BlockSize = Device->Media.BlockSize;
OrginalBlocks = Blocks;
if (Controller->ControllerData->Mdts != 0) { if (Controller->ControllerData->Mdts != 0) {
MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize; MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize;
@ -200,7 +202,7 @@ NvmeRead (
} }
} }
DEBUG ((EFI_D_INFO, "NvmeRead() Lba = %8d, Blocks = %8d, BlockSize = %d Status = %r\n", Lba, Blocks, BlockSize, Status)); DEBUG ((EFI_D_INFO, "NvmeRead() Lba = 0x%08x, Original = 0x%08x, Remaining = 0x%08x, BlockSize = 0x%x Status = %r\n", Lba, OrginalBlocks, Blocks, BlockSize, Status));
return Status; return Status;
} }
@ -229,10 +231,12 @@ NvmeWrite (
UINT32 BlockSize; UINT32 BlockSize;
NVME_CONTROLLER_PRIVATE_DATA *Controller; NVME_CONTROLLER_PRIVATE_DATA *Controller;
UINT32 MaxTransferBlocks; UINT32 MaxTransferBlocks;
UINTN OrginalBlocks;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
Controller = Device->Controller; Controller = Device->Controller;
BlockSize = Device->Media.BlockSize; BlockSize = Device->Media.BlockSize;
OrginalBlocks = Blocks;
if (Controller->ControllerData->Mdts != 0) { if (Controller->ControllerData->Mdts != 0) {
MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize; MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize;
@ -257,7 +261,7 @@ NvmeWrite (
} }
} }
DEBUG ((EFI_D_INFO, "NvmeWrite() Lba = %8d, Blocks = %8d, BlockSize = %d Status = %r\n", Lba, Blocks, BlockSize, Status)); DEBUG ((EFI_D_INFO, "NvmeWrite() Lba = 0x%08x, Original = 0x%08x, Remaining = 0x%08x, BlockSize = 0x%x Status = %r\n", Lba, OrginalBlocks, Blocks, BlockSize, Status));
return Status; return Status;
} }

View File

@ -33,21 +33,23 @@ ReadNvmeControllerCapabilities (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
PciIo, PciIo,
EfiPciIoWidthUint64, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_CAP_OFFSET, NVME_CAP_OFFSET,
1, 2,
Cap &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned64 ((UINT64*)Cap, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -69,6 +71,7 @@ ReadNvmeControllerConfiguration (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
@ -77,13 +80,14 @@ ReadNvmeControllerConfiguration (
NVME_BAR, NVME_BAR,
NVME_CC_OFFSET, NVME_CC_OFFSET,
1, 1,
Cc &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned32 ((UINT32*)Cc, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -105,15 +109,17 @@ WriteNvmeControllerConfiguration (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Data = ReadUnaligned32 ((UINT32*)Cc);
Status = PciIo->Mem.Write ( Status = PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint32, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_CC_OFFSET, NVME_CC_OFFSET,
1, 1,
Cc &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -149,6 +155,7 @@ ReadNvmeControllerStatus (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
@ -157,13 +164,14 @@ ReadNvmeControllerStatus (
NVME_BAR, NVME_BAR,
NVME_CSTS_OFFSET, NVME_CSTS_OFFSET,
1, 1,
Csts &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned32 ((UINT32*)Csts, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -185,6 +193,7 @@ ReadNvmeAdminQueueAttributes (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
@ -193,13 +202,14 @@ ReadNvmeAdminQueueAttributes (
NVME_BAR, NVME_BAR,
NVME_AQA_OFFSET, NVME_AQA_OFFSET,
1, 1,
Aqa &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned32 ((UINT32*)Aqa, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -221,15 +231,17 @@ WriteNvmeAdminQueueAttributes (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Data = ReadUnaligned32 ((UINT32*)Aqa);
Status = PciIo->Mem.Write ( Status = PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint32, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_AQA_OFFSET, NVME_AQA_OFFSET,
1, 1,
Aqa &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -260,21 +272,23 @@ ReadNvmeAdminSubmissionQueueBaseAddress (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
PciIo, PciIo,
EfiPciIoWidthUint64, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_ASQ_OFFSET, NVME_ASQ_OFFSET,
1, 2,
Asq &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned64 ((UINT64*)Asq, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -296,15 +310,18 @@ WriteNvmeAdminSubmissionQueueBaseAddress (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Data = ReadUnaligned64 ((UINT64*)Asq);
Status = PciIo->Mem.Write ( Status = PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint64, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_ASQ_OFFSET, NVME_ASQ_OFFSET,
1, 2,
Asq &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -334,21 +351,24 @@ ReadNvmeAdminCompletionQueueBaseAddress (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Status = PciIo->Mem.Read ( Status = PciIo->Mem.Read (
PciIo, PciIo,
EfiPciIoWidthUint64, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_ACQ_OFFSET, NVME_ACQ_OFFSET,
1, 2,
Acq &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
return Status; return Status;
} }
WriteUnaligned64 ((UINT64*)Acq, Data);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -370,15 +390,18 @@ WriteNvmeAdminCompletionQueueBaseAddress (
{ {
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Data;
PciIo = Private->PciIo; PciIo = Private->PciIo;
Data = ReadUnaligned64 ((UINT64*)Acq);
Status = PciIo->Mem.Write ( Status = PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint64, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_ACQ_OFFSET, NVME_ACQ_OFFSET,
1, 2,
Acq &Data
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -921,6 +944,25 @@ NvmeControllerInit (
Private->ControllerData = NULL; Private->ControllerData = NULL;
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
//
// Dump NvmExpress Identify Controller Data
//
Private->ControllerData->Sn[19] = 0;
Private->ControllerData->Mn[39] = 0;
DEBUG ((EFI_D_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
DEBUG ((EFI_D_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid));
DEBUG ((EFI_D_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid));
DEBUG ((EFI_D_INFO, " SN : %a\n", (CHAR8 *)(Private->ControllerData->Sn)));
DEBUG ((EFI_D_INFO, " MN : %a\n", (CHAR8 *)(Private->ControllerData->Mn)));
DEBUG ((EFI_D_INFO, " FR : 0x%x\n", *((UINT64*)Private->ControllerData->Fr)));
DEBUG ((EFI_D_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab));
DEBUG ((EFI_D_INFO, " IEEE : 0x%x\n", *(UINT32*)Private->ControllerData->Ieee_oiu));
DEBUG ((EFI_D_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl));
DEBUG ((EFI_D_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes));
DEBUG ((EFI_D_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes));
DEBUG ((EFI_D_INFO, " NN : 0x%x\n", Private->ControllerData->Nn));
return Status; return Status;
} }

View File

@ -387,6 +387,7 @@ NvmExpressPassThru (
UINT64 *Prp; UINT64 *Prp;
VOID *PrpListHost; VOID *PrpListHost;
UINTN PrpListNo; UINTN PrpListNo;
UINT32 Data;
// //
// check the data fields in Packet parameter. // check the data fields in Packet parameter.
@ -431,8 +432,8 @@ NvmExpressPassThru (
// //
// Currently we only support PRP for data transfer, SGL is NOT supported. // Currently we only support PRP for data transfer, SGL is NOT supported.
// //
ASSERT ((Sq->Opc & BIT15) == 0); ASSERT (Sq->Psdt == 0);
if ((Sq->Opc & BIT15) != 0) { if (Sq->Psdt != 0) {
DEBUG ((EFI_D_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n")); DEBUG ((EFI_D_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n"));
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
@ -534,14 +535,14 @@ NvmExpressPassThru (
// Ring the submission queue doorbell. // Ring the submission queue doorbell.
// //
Private->SqTdbl[Qid].Sqt ^= 1; Private->SqTdbl[Qid].Sqt ^= 1;
Data = ReadUnaligned32 ((UINT32*)&Private->SqTdbl[Qid]);
PciIo->Mem.Write ( PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint32, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_SQTDBL_OFFSET(Qid, Private->Cap.Dstrd), NVME_SQTDBL_OFFSET(Qid, Private->Cap.Dstrd),
1, 1,
&Private->SqTdbl[Qid] &Data
); );
Status = gBS->CreateEvent ( Status = gBS->CreateEvent (
@ -591,13 +592,14 @@ NvmExpressPassThru (
NvmeDumpStatus(Cq); NvmeDumpStatus(Cq);
DEBUG_CODE_END(); DEBUG_CODE_END();
Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[Qid]);
PciIo->Mem.Write ( PciIo->Mem.Write (
PciIo, PciIo,
EfiPciIoWidthUint32, EfiPciIoWidthUint32,
NVME_BAR, NVME_BAR,
NVME_CQHDBL_OFFSET(Qid, Private->Cap.Dstrd), NVME_CQHDBL_OFFSET(Qid, Private->Cap.Dstrd),
1, 1,
&Private->CqHdbl[Qid] &Data
); );
EXIT: EXIT: