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 19, 2025
1 parent 6a48c3e commit 844e813
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 45 deletions.
106 changes: 75 additions & 31 deletions MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,16 @@ 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) {
// 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;
}
InitializeListHead (&Device->AsyncQueue);

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

if (Private->NSQA > 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 +301,20 @@ EnumerateNvmeDevNamespace (
Device->DevicePath,
&gEfiBlockIoProtocolGuid,
&Device->BlockIo,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
NULL
);

if (Private->NSQA > 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 +508,6 @@ UnregisterNvmeNamespace (
Device->DevicePath,
&gEfiBlockIoProtocolGuid,
&Device->BlockIo,
&gEfiBlockIo2ProtocolGuid,
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
NULL
Expand All @@ -506,6 +525,28 @@ UnregisterNvmeNamespace (
return Status;
}

//
// If BlockIo2 is installed, uninstall it.
//
if (Device->Controller->NSQA > 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 +1153,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) {

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
12 changes: 12 additions & 0 deletions MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ NvmeRead (
BOOLEAN IsEmpty;
EFI_TPL OldTpl;

if (&Device->AsyncQueue == NULL) {
return EFI_UNSUPPORTED;
}

//
// Wait for the device's asynchronous I/O queue to become empty.
//
Expand Down Expand Up @@ -255,6 +259,10 @@ NvmeWrite (
BOOLEAN IsEmpty;
EFI_TPL OldTpl;

if (&Device->AsyncQueue == NULL) {
return EFI_UNSUPPORTED;
}

//
// Wait for the device's asynchronous I/O queue to become empty.
//
Expand Down Expand Up @@ -1540,6 +1548,10 @@ NvmeBlockIoFlushBlocksEx (

Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);

if (&Device->AsyncQueue == NULL) {
return EFI_UNSUPPORTED;
}

//
// Wait for the asynchronous I/O queue to become empty.
//
Expand Down
Loading

0 comments on commit 844e813

Please sign in to comment.