Hi, Wenbo

Why we advanced one CQ entry in line 592 whatever the execution result of SQ is 
because there are two cases:
1. If timeout happens and no new completion queue entry is added, the CQH get 
updated to point to next entry. Nvme controller would know a new entry of 
completion queue is available for use.
2. The SQ is completed between line 568 and line 592. If it's such case, 
timeout is return but a completion queue entry is filled.

So I guess the problem is the SQ entry doesn't get aborted at timeout case, 
right? If there is another request, the queue handling is missed up.

Thanks
Feng

-----Original Message-----
From: edk2-devel [mailto:[email protected]] On Behalf Of Wenbo 
Wang
Sent: Monday, September 07, 2015 17:26
To: [email protected]
Cc: Tian, Feng
Subject: [edk2] [NvmExpressDxe] Why update cq head even if command timeout

Hi,

The following code is from NvmExpressPassthru.c, at line 592, the cq head is 
updated even if the command timeout. Is there any reason for this? 

If completion queue is empty, this operation may corrupt the queue.

Thanks,
-Wenbo



======== Code Copied from the latest NvmExpressPassthru.c =============
    
 // Command has been submitted

553   Status = gBS->SetTimer(TimerEvent, TimerRelative, Packet->CommandTimeout);
554
555   if (EFI_ERROR(Status)) {
556     goto EXIT;
557   }
558
559   //
560   // Wait for completion queue to get filled in.
561   //
562   Status = EFI_TIMEOUT;
563   while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) {
564     if (Cq->Pt != Private->Pt[QueueType]) {
565       Status = EFI_SUCCESS;
566       break;
567     }
568   }
569
570   //
571   // Check the NVMe cmd execution result
572   //
573   if (Status != EFI_TIMEOUT) {
574     if ((Cq->Sct == 0) && (Cq->Sc == 0)) {
575       Status = EFI_SUCCESS;
576     } else {
577       Status = EFI_DEVICE_ERROR;
578       //
579       // Copy the Respose Queue entry for this command to the callers 
response buffer
580       //
581       CopyMem(Packet->NvmeCompletion, Cq, 
sizeof(EFI_NVM_EXPRESS_COMPLETION));
582
583       //
584       // Dump every completion entry status for debugging.
585       //
586       DEBUG_CODE_BEGIN();
587         NvmeDumpStatus(Cq);
588       DEBUG_CODE_END();
589     }
590   }
591
592   if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {    <- cq head is 
updated even if command timeout
593     Private->Pt[QueueType] ^= 1;
594   }
595
596   Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueType]);
597   PciIo->Mem.Write (
598                PciIo,
599                EfiPciIoWidthUint32,
600                NVME_BAR,
601                NVME_CQHDBL_OFFSET(QueueType, Private->Cap.Dstrd),
602                1,
603                &Data
604                );


_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to