MdeModulePkg/NvmExpressDxe: Fix wrong queue size for async IO queues

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2118

When a packet is queued/completed for the asynchronous IO queue, the logic
to roll over to the front of the queue doesn't account for actual size of
the IO Submission/Completion queue.

This causes a device to hang due to doorbell being outside of visible
queue. An example would be if an NVMe drive only supported a queue size of
128 while the driver supports 256.

Cc: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Hao A Wu <hao.a.wu@intel.com>
Acked-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Sean Brogan 2019-09-03 16:52:26 -07:00 committed by mergify[bot]
parent 0b9ad0bc03
commit 7607174192
2 changed files with 5 additions and 3 deletions

View File

@ -672,7 +672,7 @@ ProcessAsyncTaskList (
} }
Private->CqHdbl[QueueId].Cqh++; Private->CqHdbl[QueueId].Cqh++;
if (Private->CqHdbl[QueueId].Cqh > NVME_ASYNC_CCQ_SIZE) { if (Private->CqHdbl[QueueId].Cqh > MIN (NVME_ASYNC_CCQ_SIZE, Private->Cap.Mqes)) {
Private->CqHdbl[QueueId].Cqh = 0; Private->CqHdbl[QueueId].Cqh = 0;
Private->Pt[QueueId] ^= 1; Private->Pt[QueueId] ^= 1;
} }

View File

@ -452,6 +452,7 @@ NvmExpressPassThru (
NVME_SQ *Sq; NVME_SQ *Sq;
NVME_CQ *Cq; NVME_CQ *Cq;
UINT16 QueueId; UINT16 QueueId;
UINT16 QueueSize;
UINT32 Bytes; UINT32 Bytes;
UINT16 Offset; UINT16 Offset;
EFI_EVENT TimerEvent; EFI_EVENT TimerEvent;
@ -540,6 +541,7 @@ NvmExpressPassThru (
Prp = NULL; Prp = NULL;
TimerEvent = NULL; TimerEvent = NULL;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
QueueSize = MIN (NVME_ASYNC_CSQ_SIZE, Private->Cap.Mqes) + 1;
if (Packet->QueueType == NVME_ADMIN_QUEUE) { if (Packet->QueueType == NVME_ADMIN_QUEUE) {
QueueId = 0; QueueId = 0;
@ -552,7 +554,7 @@ NvmExpressPassThru (
// //
// Submission queue full check. // Submission queue full check.
// //
if ((Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1) == if ((Private->SqTdbl[QueueId].Sqt + 1) % QueueSize ==
Private->AsyncSqHead) { Private->AsyncSqHead) {
return EFI_NOT_READY; return EFI_NOT_READY;
} }
@ -701,7 +703,7 @@ NvmExpressPassThru (
// //
if ((Event != NULL) && (QueueId != 0)) { if ((Event != NULL) && (QueueId != 0)) {
Private->SqTdbl[QueueId].Sqt = Private->SqTdbl[QueueId].Sqt =
(Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1); (Private->SqTdbl[QueueId].Sqt + 1) % QueueSize;
} else { } else {
Private->SqTdbl[QueueId].Sqt ^= 1; Private->SqTdbl[QueueId].Sqt ^= 1;
} }