Skip to content

Commit 1c08614

Browse files
committed
MdeModulePkg: Allocate Io Queue buffer after setting
the number of queues with the controller.
1 parent 8630be9 commit 1c08614

File tree

6 files changed

+571
-110
lines changed

6 files changed

+571
-110
lines changed

MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c

+83-12
Original file line numberDiff line numberDiff line change
@@ -1011,9 +1011,11 @@ NvmExpressDriverBindingStart (
10111011
EFI_PHYSICAL_ADDRESS MappedAddr;
10121012
UINTN Bytes;
10131013
EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;
1014-
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1015-
UINTN QueuePageCount = PcdGetBool (PcdSupportAlternativeQueueSize) ?
1016-
NVME_ALTERNATIVE_TOTAL_QUEUE_BUFFER_IN_PAGES : 6;
1014+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
1015+
NVME_AQA *Aqa;
1016+
UINTN AdminQueuePageCount; // MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1017+
1018+
// MU_CHANGE [END] - Allocate IO Queue Buffer
10171019

10181020
DEBUG ((DEBUG_INFO, "NvmExpressDriverBindingStart: start\n"));
10191021

@@ -1087,9 +1089,41 @@ NvmExpressDriverBindingStart (
10871089

10881090
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
10891091

1092+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
10901093
//
1091-
// Depending on PCD disablement, either support the default or alternative
1092-
// queue sizes.
1094+
// Set the Admin Queue Atttributes
1095+
//
1096+
Aqa = AllocateZeroPool (sizeof (NVME_AQA));
1097+
1098+
if (Aqa == NULL) {
1099+
DEBUG ((DEBUG_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Aqa Data failed!\n"));
1100+
Status = EFI_OUT_OF_RESOURCES;
1101+
goto Exit;
1102+
}
1103+
1104+
// Set the sizes of the admin submission & completion queues in number of entries
1105+
Aqa->Asqs = PcdGetBool (PcdSupportAlternativeQueueSize) ? MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes) : NVME_ASQ_SIZE;
1106+
Aqa->Rsvd1 = 0;
1107+
Aqa->Acqs = PcdGetBool (PcdSupportAlternativeQueueSize) ? MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes) : NVME_ACQ_SIZE;
1108+
Aqa->Rsvd2 = 0;
1109+
1110+
//
1111+
// Save Queue Pair Data for admin queues in controller data structure
1112+
//
1113+
Private->SqData[0].NumberOfEntries = Aqa->Asqs;
1114+
Private->CqData[0].NumberOfEntries = Aqa->Acqs;
1115+
1116+
//
1117+
// Set admin queue entry size to default
1118+
//
1119+
Private->SqData[0].EntrySize = NVME_IOSQES_MIN;
1120+
Private->CqData[0].EntrySize = NVME_IOCQES_MIN;
1121+
1122+
// Calculate the number of pages required for the admin queues
1123+
// TODO create helper functions for calculating num pages for a queue.
1124+
AdminQueuePageCount = EFI_SIZE_TO_PAGES (Private->SqData[0].NumberOfEntries * LShiftU64 (2, Private->SqData[0].EntrySize))
1125+
+ EFI_SIZE_TO_PAGES (Private->CqData[0].NumberOfEntries * LShiftU64 (2, CqData[0].EntrySize));
1126+
// MU_CHANGE [END] - Allocate IO Queue Buffer
10931127
//
10941128
// Default:
10951129
// 6 x 4kB aligned buffers will be carved out of this buffer.
@@ -1113,20 +1147,26 @@ NvmExpressDriverBindingStart (
11131147
//
11141148
// Allocate 15 pages of memory, then map it for bus master read and write.
11151149
//
1150+
1151+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
1152+
//
1153+
// Allocate Admin Queues
1154+
//
11161155
Status = PciIo->AllocateBuffer (
11171156
PciIo,
11181157
AllocateAnyPages,
11191158
EfiBootServicesData,
1120-
QueuePageCount,
1159+
AdminQueuePageCount,
11211160
(VOID **)&Private->Buffer,
11221161
0
11231162
);
1163+
// MU_CHANGE [END] - Allocate IO Queue Buffer
11241164
if (EFI_ERROR (Status)) {
11251165
goto Exit;
11261166
}
11271167

11281168
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1129-
Bytes = EFI_PAGES_TO_SIZE (QueuePageCount);
1169+
Bytes = EFI_PAGES_TO_SIZE (AdminQueuePageCount); // MU_CHANGE - Allocate IO Queue Buffer
11301170
Status = PciIo->Map (
11311171
PciIo,
11321172
EfiPciIoOperationBusMasterCommonBuffer,
@@ -1137,7 +1177,8 @@ NvmExpressDriverBindingStart (
11371177
);
11381178

11391179
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1140-
if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (QueuePageCount))) {
1180+
if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (AdminQueuePageCount))) {
1181+
// MU_CHANGE - Allocate IO Queue Buffer
11411182
goto Exit;
11421183
}
11431184

@@ -1158,7 +1199,7 @@ NvmExpressDriverBindingStart (
11581199
InitializeListHead (&Private->AsyncPassThruQueue);
11591200
InitializeListHead (&Private->UnsubmittedSubtasks);
11601201

1161-
Status = NvmeControllerInit (Private);
1202+
Status = NvmeControllerInit (Private, Aqa); // MU_CHANGE - Allocate IO Queue Buffer
11621203
if (EFI_ERROR (Status)) {
11631204
goto Exit;
11641205
}
@@ -1256,7 +1297,14 @@ NvmExpressDriverBindingStart (
12561297

12571298
if ((Private != NULL) && (Private->Buffer != NULL)) {
12581299
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1259-
PciIo->FreeBuffer (PciIo, QueuePageCount, Private->Buffer);
1300+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
1301+
Status = PciIo->FreeBuffer (PciIo, AdminQueuePageCount, Private->Buffer);
1302+
1303+
if (EFI_STATUS_ERROR (Status)) {
1304+
DEBUG ((DEBUG_ERROR, "%a(%d): FreeBuffer failed with %r\n", __FILE__, __LINE__, Status));
1305+
}
1306+
1307+
// MU_CHANGE [END] - Allocate IO Queue Buffer
12601308
}
12611309

12621310
if ((Private != NULL) && (Private->ControllerData != NULL)) {
@@ -1333,8 +1381,8 @@ NvmExpressDriverBindingStop (
13331381
BOOLEAN IsEmpty;
13341382
EFI_TPL OldTpl;
13351383
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
1336-
UINT16 QueuePageCount = PcdGetBool (PcdSupportAlternativeQueueSize) ?
1337-
NVME_ALTERNATIVE_TOTAL_QUEUE_BUFFER_IN_PAGES : 6;
1384+
// MU_CHANGE - Allocate IO Queue Buffer
1385+
UINTN QueuePageCount;
13381386

13391387
if (NumberOfChildren == 0) {
13401388
Status = gBS->OpenProtocol (
@@ -1380,11 +1428,34 @@ NvmExpressDriverBindingStop (
13801428
Private->PciIo->Unmap (Private->PciIo, Private->Mapping);
13811429
}
13821430

1431+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
1432+
QueuePageCount = EFI_SIZE_TO_PAGES (Private->SqData[0].NumberOfEntries * LShiftU64 (2, Private->SqData[0].EntrySize))
1433+
+ EFI_SIZE_TO_PAGES (Private->CqData[0].NumberOfEntries * LShiftU64 (2, Private->CqData[0].EntrySize));
1434+
// MU_CHANGE [END] - Allocate IO Queue Buffer
13831435
if (Private->Buffer != NULL) {
13841436
// MU_CHANGE - Support alternative hardware queue sizes in NVME driver
13851437
Private->PciIo->FreeBuffer (Private->PciIo, QueuePageCount, Private->Buffer);
13861438
}
13871439

1440+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
1441+
if (Private->DataQueueMapping != NULL) {
1442+
Status = Private->PciIo->Unmap (Private->PciIo, Private->DataQueueMapping);
1443+
1444+
if (EFI_ERROR (Status)) {
1445+
DEBUG ((DEBUG_ERROR, "%a(%d): Unmap DataQueueMapping failed %r\n", __FILE__, __LINE__, Status));
1446+
}
1447+
}
1448+
1449+
if (Private->DataQueueBuffer != NULL) {
1450+
Status = Private->PciIo->FreeBuffer (Private->PciIo, QueuePageCount*Private->NumberOfDataQueuePairs, Private->DataQueueBuffer);
1451+
1452+
if (EFI_ERROR (Status)) {
1453+
DEBUG ((DEBUG_ERROR, "%a(%d): FreeBuffer DataQueueBuffer failed %r\n", __FILE__, __LINE__, Status));
1454+
}
1455+
}
1456+
1457+
// MU_CHANGE [END] - Allocate IO Queue Buffer
1458+
13881459
FreePool (Private->ControllerData);
13891460
FreePool (Private);
13901461
}

MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h

+30
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
typedef struct _NVME_CONTROLLER_PRIVATE_DATA NVME_CONTROLLER_PRIVATE_DATA;
4949
typedef struct _NVME_DEVICE_PRIVATE_DATA NVME_DEVICE_PRIVATE_DATA;
50+
typedef struct _NVME_QUEUE_SIZE_DATA NVME_QUEUE_SIZE_DATA; // MU_CHANGE - Allocate IO Queue Buffer
5051

5152
#include "NvmExpressBlockIo.h"
5253
#include "NvmExpressDiskInfo.h"
@@ -67,6 +68,11 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiV
6768
#define NVME_CSQ_SIZE 1 // Number of I/O submission queue entries, which is 0-based
6869
#define NVME_CCQ_SIZE 1 // Number of I/O completion queue entries, which is 0-based
6970

71+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
72+
#define NVME_IOSQES_MIN 6 // Minimum I/O submission queue entry size (Figure 280)
73+
#define NVME_IOCQES_MIN 4 // Minimum I/O completion queue entry size
74+
// MU_CHANGE [END] - Allocate IO Queue Buffer
75+
7076
//
7177
// Number of asynchronous I/O submission queue entries, which is 0-based.
7278
// The asynchronous I/O submission queue size is 4kB in total.
@@ -143,6 +149,16 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiV
143149
// Unique signature for private data structure.
144150
//
145151
#define NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('N','V','M','E')
152+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
153+
//
154+
// Nvme queue data
155+
//
156+
struct _NVME_QUEUE_SIZE_DATA {
157+
UINT32 NumberOfEntries; // in number of entries
158+
UINT8 EntrySize; // in bytes, as a power of 2
159+
};
160+
161+
// MU_CHANGE [END] - Allocate IO Queue Buffer
146162

147163
//
148164
// Nvme private data structure.
@@ -177,6 +193,14 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
177193
UINT32 NumberOfDataQueuePairs;
178194
// MU_CHANGE [END] - Request Number of Queues from Controller
179195

196+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
197+
//
198+
// Queue Size Data
199+
//
200+
NVME_QUEUE_SIZE_DATA SqData[NVME_MAX_QUEUES];
201+
NVME_QUEUE_SIZE_DATA CqData[NVME_MAX_QUEUES];
202+
// MU_CHANGE [END] - Allocate IO Queue Buffer
203+
180204
//
181205
// 6 x 4kB aligned buffers will be carved out of this buffer.
182206
// 1st 4kB boundary is the start of the admin submission queue.
@@ -189,6 +213,11 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
189213
UINT8 *Buffer;
190214
UINT8 *BufferPciAddr;
191215

216+
// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
217+
UINT8 *DataQueueBuffer;
218+
UINT8 *DataQueueBufferPciAddr;
219+
// MU_CHANGE [END] - Allocate IO Queue Buffer
220+
192221
//
193222
// Pointers to 4kB aligned submission & completion queues.
194223
//
@@ -218,6 +247,7 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
218247
NVME_CAP Cap;
219248

220249
VOID *Mapping;
250+
VOID *DataQueueMapping; // MU_CHANGE - Allocate IO Queue Buffer
221251

222252
//
223253
// For Non-blocking operations.

MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ NvmeBlockIoReset (
10061006

10071007
Private = Device->Controller;
10081008

1009-
Status = NvmeControllerInit (Private);
1009+
Status = NvmeControllerReset (Private); // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer
10101010

10111011
if (EFI_ERROR (Status)) {
10121012
Status = EFI_DEVICE_ERROR;
@@ -1274,7 +1274,7 @@ NvmeBlockIoResetEx (
12741274

12751275
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
12761276

1277-
Status = NvmeControllerInit (Private);
1277+
Status = NvmeControllerReset (Private); // MU_CHANGE - Allocate IO Queue Buffer
12781278

12791279
if (EFI_ERROR (Status)) {
12801280
Status = EFI_DEVICE_ERROR;

0 commit comments

Comments
 (0)