Because each command has an unique command ID, queue handling shall not miss up even if the completion is returned after timeout.
-----Original Message----- From: Wenbo Wang [mailto:[email protected]] Sent: Tuesday, September 8, 2015 10:23 AM To: 'Tian, Feng'; '[email protected]' Subject: RE: [edk2] [NvmExpressDxe] Why update cq head even if command timeout Thanks Feng. In our test, when the command timeout, the completion queue is empty (head == tail), in this case if the driver moves head (head++), it corrupts the completion queue, the NVMe controller generates error. I think the HW behavior is correct because the driver shall not move head if there is no completion there. line 568 to line 592 is not executed when no timeout happens. Yes, I don't see driver sending abort NVMe command when timeout happens. Thanks, -Wenbo -----Original Message----- From: Tian, Feng [mailto:[email protected]] Sent: Tuesday, September 8, 2015 9:47 AM To: Wenbo Wang; [email protected] Cc: Tian, Feng Subject: RE: [edk2] [NvmExpressDxe] Why update cq head even if command timeout 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

