diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h index 36527a523f..decd4418af 100644 --- a/OvmfPkg/Include/Library/VirtioLib.h +++ b/OvmfPkg/Include/Library/VirtioLib.h @@ -2,7 +2,7 @@ Declarations of utility functions used by virtio device drivers. - Copyright (C) 2012, Red Hat, Inc. + Copyright (C) 2012-2016, Red Hat, Inc. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this @@ -167,6 +167,12 @@ VirtioAppendDesc ( Indices->HeadDescIdx identifies the head descriptor of the descriptor chain. + @param[out] UsedLen On success, the total number of bytes, consecutively + across the buffers linked by the descriptor chain, + that the host wrote. May be NULL if the caller + doesn't care, or can compute the same information + from device-specific request structures linked by the + descriptor chain. @return Error code from VirtIo->SetQueueNotify() if it fails. @@ -179,7 +185,8 @@ VirtioFlush ( IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT16 VirtQueueId, IN OUT VRING *Ring, - IN DESC_INDICES *Indices + IN DESC_INDICES *Indices, + OUT UINT32 *UsedLen OPTIONAL ); #endif // _VIRTIO_LIB_H_ diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c index 54cf225c98..4b1d78b5a0 100644 --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c @@ -2,7 +2,7 @@ Utility functions used by virtio device drivers. - Copyright (C) 2012, Red Hat, Inc. + Copyright (C) 2012-2016, Red Hat, Inc. Portion of Copyright (C) 2013, ARM Ltd. This program and the accompanying materials are licensed and made available @@ -249,6 +249,12 @@ VirtioAppendDesc ( Indices->HeadDescIdx identifies the head descriptor of the descriptor chain. + @param[out] UsedLen On success, the total number of bytes, consecutively + across the buffers linked by the descriptor chain, + that the host wrote. May be NULL if the caller + doesn't care, or can compute the same information + from device-specific request structures linked by the + descriptor chain. @return Error code from VirtIo->SetQueueNotify() if it fails. @@ -261,10 +267,12 @@ VirtioFlush ( IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT16 VirtQueueId, IN OUT VRING *Ring, - IN DESC_INDICES *Indices + IN DESC_INDICES *Indices, + OUT UINT32 *UsedLen OPTIONAL ) { UINT16 NextAvailIdx; + UINT16 LastUsedIdx; EFI_STATUS Status; UINTN PollPeriodUsecs; @@ -276,6 +284,11 @@ VirtioFlush ( // head descriptor of any given descriptor chain. // NextAvailIdx = *Ring->Avail.Idx; + // + // (Due to our lock-step progress, this is where the host will produce the + // used element with the head descriptor's index in it.) + // + LastUsedIdx = NextAvailIdx; Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] = Indices->HeadDescIdx % Ring->QueueSize; @@ -315,5 +328,14 @@ VirtioFlush ( } MemoryFence(); + + if (UsedLen != NULL) { + volatile CONST VRING_USED_ELEM *UsedElem; + + UsedElem = &Ring->Used.UsedElem[LastUsedIdx % Ring->QueueSize]; + ASSERT (UsedElem->Id == Indices->HeadDescIdx); + *UsedLen = UsedElem->Len; + } + return EFI_SUCCESS; } diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 75f85ca6e0..50511a1e44 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -324,7 +324,8 @@ SynchronousRequest ( // // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D). // - if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS && + if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, + NULL) == EFI_SUCCESS && HostStatus == VIRTIO_BLK_S_OK) { return EFI_SUCCESS; } diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index e1e12039b3..f5f412a32e 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -470,7 +470,7 @@ VirtioScsiPassThru ( // caller retry. // if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring, - &Indices) != EFI_SUCCESS) { + &Indices, NULL) != EFI_SUCCESS) { Packet->InTransferLength = 0; Packet->OutTransferLength = 0; Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;