Skip to content

Commit

Permalink
MdeModulePkg: NvmExpressDxe: Request queues from
Browse files Browse the repository at this point in the history
the controller.

Instead of assuming we always want to create two sets of data queues,
we request two and the controller will determine how many are allocated.

Signed-off-by: Vivian Nowka-Keane <[email protected]>

to squash

Remove check for blockIo2 installation

Check for both NSQA and NCQA
  • Loading branch information
VivianNK committed Feb 18, 2025
1 parent 6a48c3e commit 14554ed
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 48 deletions.
107 changes: 76 additions & 31 deletions MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,17 @@ EnumerateNvmeDevNamespace (
Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;
Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks;

//
// Create BlockIo2 Protocol instance
//
Device->BlockIo2.Media = &Device->Media;
Device->BlockIo2.Reset = NvmeBlockIoResetEx;
Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx;
Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx;
Device->BlockIo2.FlushBlocksEx = NvmeBlockIoFlushBlocksEx;
if ((Private->NSQA > 1) && (Private->NCQA > 1)) {
// We have multiple data queues, so we can support the BlockIo2 protocol

// Create BlockIo2 Protocol instance
Device->BlockIo2.Media = &Device->Media;
Device->BlockIo2.Reset = NvmeBlockIoResetEx;
Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx;
Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx;
Device->BlockIo2.FlushBlocksEx = NvmeBlockIoFlushBlocksEx;
}
// TODO - initialize list head so the list it never NULL? Or do NULL check? Or both?
InitializeListHead (&Device->AsyncQueue);

// MU_CHANGE Start - Add Media Sanitize
Expand Down Expand Up @@ -260,8 +263,6 @@ EnumerateNvmeDevNamespace (
Device->DevicePath,
&gEfiBlockIoProtocolGuid,
&Device->BlockIo,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
NULL
Expand All @@ -271,6 +272,19 @@ EnumerateNvmeDevNamespace (
goto Exit;
}

if ((Private->NSQA > 1) && (Private->NCQA > 1)) {
// We have multiple data queues, so we can support the BlockIo2 protocol
Status = gBS->InstallProtocolInterface (
&Device->DeviceHandle,
&gEfiBlockIo2ProtocolGuid,
EFI_NATIVE_INTERFACE, // this is the only option in the enum..?
&Device->BlockIo2
);
if (EFI_ERROR (Status)) {
goto Exit;
}
}

//
// Check if the NVMe controller supports the Security Send and Security Receive commands
//
Expand All @@ -288,12 +302,20 @@ EnumerateNvmeDevNamespace (
Device->DevicePath,
&gEfiBlockIoProtocolGuid,
&Device->BlockIo,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
NULL
);

if ((Private->NSQA > 1) && (Private->NCQA > 1)) {
// We have multiple data queues, so we need to uninstall the BlockIo2 protocol
gBS->UninstallProtocolInterface (
Device->DeviceHandle,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2
);
}

goto Exit;
}
}
Expand Down Expand Up @@ -487,8 +509,6 @@ UnregisterNvmeNamespace (
Device->DevicePath,
&gEfiBlockIoProtocolGuid,
&Device->BlockIo,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
NULL
Expand All @@ -506,6 +526,28 @@ UnregisterNvmeNamespace (
return Status;
}

//
// If BlockIo2 is installed, uninstall it.
//
if ((Device->Controller->NSQA > 1) && (Device->Controller->NCQA > 1)) {
Status = gBS->UninstallProtocolInterface (
Handle,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2
);
if (EFI_ERROR (Status)) {
gBS->OpenProtocol (
Controller,
&gEfiNvmExpressPassThruProtocolGuid,
(VOID **)&DummyInterface,
This->DriverBindingHandle,
Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
return Status;
}
}

//
// If Storage Security Command Protocol is installed, then uninstall this protocol.
//
Expand Down Expand Up @@ -1112,24 +1154,27 @@ NvmExpressDriverBindingStart (
//
// Start the asynchronous I/O completion monitor
//
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
ProcessAsyncTaskList,
Private,
&Private->TimerEvent
);
if (EFI_ERROR (Status)) {
goto Exit;
}
if ((Private->NSQA > 1) && (Private->NCQA > 1)) {

Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
ProcessAsyncTaskList,
Private,
&Private->TimerEvent
);
if (EFI_ERROR (Status)) {
goto Exit;
}

Status = gBS->SetTimer (
Private->TimerEvent,
TimerPeriodic,
NVME_HC_ASYNC_TIMER
);
if (EFI_ERROR (Status)) {
goto Exit;
Status = gBS->SetTimer (
Private->TimerEvent,
TimerPeriodic,
NVME_HC_ASYNC_TIMER
);
if (EFI_ERROR (Status)) {
goto Exit;
}
}

Status = gBS->InstallMultipleProtocolInterfaces (
Expand Down
9 changes: 8 additions & 1 deletion MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiV
//
#define NVME_ASYNC_CCQ_SIZE 255

#define NVME_MAX_QUEUES 3 // Number of queues supported by the driver
// Maximum number of queue pairs supported by the driver, including the admin queues.
#define NVME_MAX_QUEUES 3

// MU_CHANGE Start - Add Media Sanitize
//
Expand Down Expand Up @@ -161,6 +162,12 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
//
NVME_ADMIN_CONTROLLER_DATA *ControllerData;

//
// Number of Queues Allocated by the controller (0-based where 0 is 1 queue)
//
UINT32 NSQA; // Number of Submission Queues Allocated
UINT32 NCQA; // Number of Completion Queues Allocated

//
// 6 x 4kB aligned buffers will be carved out of this buffer.
// 1st 4kB boundary is the start of the admin submission queue.
Expand Down
6 changes: 3 additions & 3 deletions MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ NvmeRead (
//
// Wait for the device's asynchronous I/O queue to become empty.
//
while (TRUE) {
while (&Device->AsyncQueue != NULL) {
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
IsEmpty = IsListEmpty (&Device->AsyncQueue);
gBS->RestoreTPL (OldTpl);
Expand Down Expand Up @@ -258,7 +258,7 @@ NvmeWrite (
//
// Wait for the device's asynchronous I/O queue to become empty.
//
while (TRUE) {
while (&Device->AsyncQueue != NULL) {
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
IsEmpty = IsListEmpty (&Device->AsyncQueue);
gBS->RestoreTPL (OldTpl);
Expand Down Expand Up @@ -1543,7 +1543,7 @@ NvmeBlockIoFlushBlocksEx (
//
// Wait for the asynchronous I/O queue to become empty.
//
while (TRUE) {
while (&Device->AsyncQueue != NULL) {
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
IsEmpty = IsListEmpty (&Device->AsyncQueue);
gBS->RestoreTPL (OldTpl);
Expand Down
Loading

0 comments on commit 14554ed

Please sign in to comment.