From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Anthony PERARD <anthony.perard@citrix.com>
Cc: EDK2 devel <edk2-devel@lists.sourceforge.net>,
Xen Devel <xen-devel@lists.xen.org>,
Samuel Thibault <samuel.thibault@eu.citrix.com>
Subject: Re: [PATCH RFC 17/18] OvmfPkg/XenPvBlkDxe: Add BlockFront client.
Date: Wed, 16 Jul 2014 15:41:17 -0400 [thread overview]
Message-ID: <20140716194117.GE8349@laptop.dumpdata.com> (raw)
In-Reply-To: <1405523747-5024-18-git-send-email-anthony.perard@citrix.com>
On Wed, Jul 16, 2014 at 04:15:46PM +0100, Anthony PERARD wrote:
> This is the code that will do the actual communication between OVMF and
> a PV block backend, where the block device lives.
>
> This implementation originally comes from Mini-OS, a part of the Xen
> Project.
>
> Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> OvmfPkg/XenPvBlkDxe/BlockFront.c | 583 ++++++++++++++++++++++++++++++++++++
> OvmfPkg/XenPvBlkDxe/BlockFront.h | 88 ++++++
> OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c | 8 +
> OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf | 2 +
> 4 files changed, 681 insertions(+)
> create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.c
> create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.h
>
> diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.c b/OvmfPkg/XenPvBlkDxe/BlockFront.c
> new file mode 100644
> index 0000000..ff5641c
> --- /dev/null
> +++ b/OvmfPkg/XenPvBlkDxe/BlockFront.c
> @@ -0,0 +1,583 @@
> +/* Minimal block driver for Mini-OS.
> + * Copyright (c) 2007-2008 Samuel Thibault.
> + * Based on netfront.c.
> + */
> +
> +#include <Library/PrintLib.h>
> +#include <Library/DebugLib.h>
> +
> +#include "BlockFront.h"
> +
> +#include <IndustryStandard/Xen/io/protocols.h>
> +#include <IndustryStandard/Xen/io/xenbus.h>
> +
> +#include "inttypes.h"
> +
> +STATIC
> +XENSTORE_STATUS
> +XenbusReadInteger (
> + IN XENBUS_PROTOCOL *This,
> + IN CONST CHAR8 *Node,
> + IN BOOLEAN FromBackend,
> + OUT UINT64 *ValuePtr
> + )
> +{
> + XENSTORE_STATUS Status;
> + CHAR8 *p;
> +
> + if (!FromBackend) {
> + Status = This->XsRead (This, XST_NIL, Node, (VOID**)&p);
> + } else {
> + Status = This->XsBackendRead (This, XST_NIL, Node, (VOID**)&p);
> + }
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + return Status;
> + }
> + // XXX Will assert if p overflow UINT64 ...
> + *ValuePtr = AsciiStrDecimalToUint64 (p);
> + FreePool (p);
> + return Status;
> +}
> +
> +STATIC
> +VOID
> +XenPvBlockFree (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev
> + )
> +{
> + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo;
> +
> + if (Dev->RingRef != 0) {
> + XenbusIo->GrantEndAccess (XenbusIo, Dev->RingRef);
> + }
> + if (Dev->Ring.sring != NULL) {
> + FreePages (Dev->Ring.sring, 1);
> + }
> + if (Dev->EventChannel != 0) {
> + XenbusIo->EventChannelClose (XenbusIo, Dev->EventChannel);
> + }
> + FreePool (Dev);
> +}
> +
> +XENSTORE_STATUS
> +XenPvBlkWaitForBackendState (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev,
> + IN XenbusState WaitedState,
ExpectedState
?
> + OUT XenbusState *LastStatePtr OPTIONAL
> + )
> +{
> + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo;
> + XenbusState State;
> + UINT64 Value;
> + XENSTORE_STATUS Status;
> +
> + while (TRUE) {
> + Status = XenbusReadInteger (XenbusIo, "state", TRUE, &Value);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + return Status;
> + }
> + if (Value > XenbusStateReconfigured) {
> + return XENSTORE_STATUS_EIO;
> + }
> + State = Value;
> + if (State >= WaitedState) {
Not State != WaitedState ?
> + break;
> + }
> + DEBUG ((EFI_D_INFO,
> + "XenPvBlk: waiting backend state %d, current: %d\n",
> + WaitedState, State));
> + XenbusIo->WaitForWatch (XenbusIo, Dev->StateWatchToken);
> + }
> +
> + if (LastStatePtr != NULL) {
> + *LastStatePtr = State;
> + }
> +
> + return XENSTORE_STATUS_SUCCESS;
> +}
> +
> +EFI_STATUS
> +XenPvBlockFrontInitialization (
> + IN XENBUS_PROTOCOL *XenbusIo,
> + IN CONST CHAR8 *NodeName,
> + OUT XEN_BLOCK_FRONT_DEVICE **DevPtr
> + )
> +{
> + XENSTORE_TRANSACTION xbt;
> + CHAR8 *DeviceType;
> + blkif_sring_t *SharedRing;
> + XENSTORE_STATUS Status;
> + XEN_BLOCK_FRONT_DEVICE *Dev;
> + XenbusState State;
> + UINT64 Value;
> +
> + ASSERT (NodeName != NULL);
> +
> + Dev = AllocateZeroPool (sizeof (XEN_BLOCK_FRONT_DEVICE));
> + Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
> + Dev->NodeName = NodeName;
> + Dev->XenbusIo = XenbusIo;
> + Dev->DeviceId = XenbusIo->DeviceId;
> +
> + XenbusIo->XsRead (XenbusIo, XST_NIL, "device-type", (VOID**)&DeviceType);
> + if (AsciiStrCmp (DeviceType, "cdrom") == 0) {
> + Dev->MediaInfo.CdRom = TRUE;
> + } else {
> + Dev->MediaInfo.CdRom = FALSE;
> + }
> + FreePool (DeviceType);
> +
> + Status = XenbusReadInteger (XenbusIo, "backend-id", FALSE, &Value);
> + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT16_MAX) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to get backend-id (%d)\n",
> + Status));
> + goto Error;
> + }
> + Dev->DomainId = Value;
> + XenbusIo->EventChannelAllocate (XenbusIo, Dev->DomainId, &Dev->EventChannel);
> +
> + SharedRing = (blkif_sring_t*) AllocatePages (1);
> + SHARED_RING_INIT (SharedRing);
> + FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE);
> + XenbusIo->GrantAccess (XenbusIo,
> + Dev->DomainId,
> + (INTN) SharedRing >> EFI_PAGE_SHIFT,
> + FALSE,
> + &Dev->RingRef);
> +
> +Again:
> + Status = XenbusIo->XsTransactionStart (XenbusIo, &xbt);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_WARN, "XenPvBlk: Failed to start transaction, %d\n", Status));
.. and do you want to error out?
> + }
> +
> + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName, "ring-ref", "%d",
> + Dev->RingRef);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write ring-ref.\n"));
> + goto AbortTransaction;
> + }
> + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName,
> + "event-channel", "%d", Dev->EventChannel);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write event-channel.\n"));
> + goto AbortTransaction;
> + }
> + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName,
> + "protocol", "%a", XEN_IO_PROTO_ABI_NATIVE);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write protocol.\n"));
> + goto AbortTransaction;
> + }
> +
> + Status = XenbusIo->SetState (XenbusIo, xbt, XenbusStateConnected);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed switch state.\n"));
> + goto AbortTransaction;
> + }
> +
> + Status = XenbusIo->XsTransactionEnd (XenbusIo, xbt, FALSE);
> + if (Status == XENSTORE_STATUS_EAGAIN) {
> + goto Again;
> + }
> +
> + XenbusIo->RegisterWatchBackend (XenbusIo, "state", &Dev->StateWatchToken);
> +
> + // Waiting backend
> + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateConnected, &State);
> + if (Status != XENSTORE_STATUS_SUCCESS || State != XenbusStateConnected) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n",
> + XenbusIo->Type, XenbusIo->DeviceId, Status, State));
> + goto Error2;
> + }
> +
> + Status = XenbusReadInteger (XenbusIo, "info", TRUE, &Value);
> + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) {
> + goto Error2;
> + }
> + Dev->MediaInfo.VDiskInfo = Value;
> + if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) {
> + Dev->MediaInfo.ReadWrite = FALSE;
> + } else {
> + Dev->MediaInfo.ReadWrite = TRUE;
> + }
> +
> + Status = XenbusReadInteger (XenbusIo, "sectors", TRUE, &Dev->MediaInfo.Sectors);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + goto Error2;
> + }
> +
> + Status = XenbusReadInteger (XenbusIo, "sector-size", TRUE, &Value);
> + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) {
> + goto Error2;
> + }
> + Dev->MediaInfo.SectorSize = Value;
Why not &Dev->MediaInfo.SectorSize in XenbusReadInteger?
Is it because of types? If so, please add a comment stating that.
> +
> + // Default value
> + Value = 0;
> + Status = XenbusReadInteger (XenbusIo, "feature-barrier", TRUE, &Value);
> + if (Value == 1) {
> + Dev->MediaInfo.FeatureBarrier = TRUE;
> + } else {
> + Dev->MediaInfo.FeatureBarrier = FALSE;
> + }
> +
> + // Default value
> + Value = 0;
> + XenbusReadInteger (XenbusIo, "feature-flush-cache", TRUE, &Value);
> + if (Value == 1) {
> + Dev->MediaInfo.FeatureFlushCache = TRUE;
> + } else {
> + Dev->MediaInfo.FeatureFlushCache = FALSE;
> + }
> +
> + DEBUG ((EFI_D_INFO, "XenPvBlk: New disk with %d sectors of %d bytes\n",
> + Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize));
> +
> + *DevPtr = Dev;
> + return EFI_SUCCESS;
> +
> +Error2:
> + XenbusIo->UnregisterWatch (XenbusIo, Dev->StateWatchToken);
> + XenbusIo->XsRemove (XenbusIo, XST_NIL, "ring-ref");
> + XenbusIo->XsRemove (XenbusIo, XST_NIL, "event-channel");
XenbusIo->XsRemove (XenbusIo, XST_NIL, "protocol");
?
> + goto Error;
> +AbortTransaction:
> + XenbusIo->XsTransactionEnd (XenbusIo, xbt, TRUE);
> +Error:
> + XenPvBlockFree (Dev);
> + return EFI_DEVICE_ERROR;
> +}
> +
> +VOID
> +XenPvBlockFrontShutdown (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev
> + )
> +{
> + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo;
> + XENSTORE_STATUS Status;
> + UINT64 Value;
> +
> + XenPvBlockSync (Dev);
> +
> + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateClosing);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while changing state to Closing: %d\n",
> + Status));
> + goto Close;
> + }
> +
> + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosing, NULL);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while waiting for closing backend state: %d\n",
> + Status));
> + goto Close;
> + }
> +
> + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateClosed);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while changing state to Closed: %d\n",
> + Status));
> + goto Close;
> + }
> +
> + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosed, NULL);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while waiting for closed backend state: %d\n",
> + Status));
> + goto Close;
> + }
> +
> + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateInitialising);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while changing state to initialising: %d\n",
> + Status));
> + goto Close;
> + }
> +
> + while (TRUE) {
> + Status = XenbusReadInteger (XenbusIo, "state", TRUE, &Value);
> + if (Status != XENSTORE_STATUS_SUCCESS) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: error while waiting for new backend state: %d\n",
> + Status));
> + goto Close;
> + }
> + if (Value < XenbusStateInitWait || Value >= XenbusStateClosed) {
> + break;
> + }
> + DEBUG ((EFI_D_INFO,
> + "XenPvBlk: waiting backend state %d, current: %d\n",
> + XenbusStateInitWait, Value));
> + XenbusIo->WaitForWatch (XenbusIo, Dev->StateWatchToken);
> + }
> +
> +Close:
> + XenbusIo->UnregisterWatch (XenbusIo, Dev->StateWatchToken);
> + XenbusIo->XsRemove (XenbusIo, XST_NIL, "ring-ref");
> + XenbusIo->XsRemove (XenbusIo, XST_NIL, "event-channel");
"protocol"
> +
> + XenPvBlockFree (Dev);
> +}
> +
> +STATIC
> +VOID
> +XenPvBlockWaitSlot (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev
> + )
> +{
> + /* Wait for a slot */
> + if (RING_FULL (&Dev->Ring)) {
> + while (TRUE) {
> + XenPvBlockAsyncIoPoll (Dev);
> + if (!RING_FULL(&Dev->Ring)) {
> + break;
> + }
> + /* Really no slot, go to sleep. */
> + // XXX wait for an event on Dev->EventChannel
> + DEBUG ((EFI_D_INFO, "%a %d, waiting\n", __func__, __LINE__));
> + }
> + }
> +}
> +
> +/* Issue an aio */
> +VOID
> +XenPvBlockAsyncIo (
> + IN OUT XEN_BLOCK_FRONT_IO *IoData,
> + IN BOOLEAN IsWrite
> + )
> +{
> + XEN_BLOCK_FRONT_DEVICE *Dev = IoData->Dev;
> + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo;
> + blkif_request_t *Request;
> + RING_IDX RingIndex;
> + BOOLEAN Notify;
> + INT32 NumSegments, Index;
> + UINTN Start, End;
> +
> + // Can't io at non-sector-aligned location
> + ASSERT(!(IoData->Offset & (Dev->MediaInfo.SectorSize - 1)));
> + // Can't io non-sector-sized amounts
> + ASSERT(!(IoData->Size & (Dev->MediaInfo.SectorSize - 1)));
> + // Can't io non-sector-aligned buffer
> + ASSERT(!((UINTN) IoData->Buffer & (Dev->MediaInfo.SectorSize - 1)));
> +
> + Start = (UINTN) IoData->Buffer & ~EFI_PAGE_MASK;
> + End = ((UINTN) IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
> + IoData->NumRef = NumSegments = (End - Start) / EFI_PAGE_SIZE;
> +
> + // XXX is this comment still true ?
I think it is outdated, as Linux would do max DMA up to the segment
size that is advertised. Ditto for the SCSI stack.
> + /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB,
> + * so max 44KB can't happen */
> + ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
But this check is OK as we can't truly fit more on the ring.
> +
> + XenPvBlockWaitSlot (Dev);
What happens if there are multiple threads calling this
function? Don't we need a mutex to only allow
one thread to grab an RingIndex?
> + RingIndex = Dev->Ring.req_prod_pvt;
> + Request = RING_GET_REQUEST (&Dev->Ring, RingIndex);
> +
> + Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ;
> + Request->nr_segments = NumSegments;
> + Request->handle = Dev->DeviceId;
> + Request->id = (UINTN) IoData;
> + Request->sector_number = IoData->Offset / 512;
> +
> + for (Index = 0; Index < NumSegments; Index++) {
> + Request->seg[Index].first_sect = 0;
Uh?
> + Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1;
Uh? I thought you wanted to use the real sector values?
> + }
> + Request->seg[0].first_sect = ((UINTN) IoData->Buffer & EFI_PAGE_MASK) / 512;
> + Request->seg[NumSegments - 1].last_sect =
> + (((UINTN) IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512;
What about in between 0 and NumSegments? You should also
fill out those values with valid entries.
> + for (Index = 0; Index < NumSegments; Index++) {
> + UINTN Data = Start + Index * EFI_PAGE_SIZE;
> + if (!IsWrite) {
> + /* Trigger CoW if needed */
Not sure I understand that reference?
> + *(CHAR8 *)(Data + (Request->seg[Index].first_sect << 9)) = 0;
> + MemoryFence ();
> + }
> + XenbusIo->GrantAccess (XenbusIo, Dev->DomainId,
> + Data >> EFI_PAGE_SHIFT, IsWrite,
> + &Request->seg[Index].gref);
> + IoData->GrantRef[Index] = Request->seg[Index].gref;
> + }
> +
> + Dev->Ring.req_prod_pvt = RingIndex + 1;
> +
> + MemoryFence ();
> + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
> +
> + if (Notify) {
> + XenbusIo->EventChannelNotify (XenbusIo, Dev->EventChannel);
> + }
> +}
> +
> +STATIC
> +VOID
> +XenPvBlockAsyncIoCallback (
> + IN OUT XEN_BLOCK_FRONT_IO *IoData,
> + IN EFI_STATUS Status
> + )
> +{
> + IoData->Data = (VOID *) 1;
> + IoData->Callback = NULL;
> +}
> +
> +VOID
> +XenPvBlockIo (
> + IN OUT XEN_BLOCK_FRONT_IO *IoData,
> + IN BOOLEAN IsWrite
> + )
> +{
> + ASSERT (IoData->Callback == NULL);
> + // XXX Signal/Event instead ?
Maybe for later versions. I think this is OK for right now, thought
it will mean we can only do one I/O .. and have then to wait
until it is completed.
That limititation should be mentioned in the commit description.
> + IoData->Callback = XenPvBlockAsyncIoCallback;
> + XenPvBlockAsyncIo (IoData, IsWrite);
> + IoData->Data = NULL;
> +
> + while (TRUE) {
> + XenPvBlockAsyncIoPoll (IoData->Dev);
> + if (IoData->Data) {
> + break;
> + }
> + }
> +}
> +
> +STATIC
> +VOID
> +XenPvBlockPushOperation (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev,
> + IN UINT8 Operation,
> + IN UINT64 Id
> + )
> +{
> + INT32 Index;
> + blkif_request_t *Request;
> + BOOLEAN Notify;
> +
> + XenPvBlockWaitSlot (Dev);
How do we make sure that there aren't multiple threads
calling this?
> + Index = Dev->Ring.req_prod_pvt;
> + Request = RING_GET_REQUEST(&Dev->Ring, Index);
> + Request->operation = Operation;
> + Request->nr_segments = 0;
> + Request->handle = Dev->DeviceId;
> + Request->id = Id;
> + /* Not needed anyway, but the backend will check it */
> + Request->sector_number = 0;
> + Dev->Ring.req_prod_pvt = Index + 1;
> + MemoryFence ();
> + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
> + if (Notify) {
> + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo;
> + XenbusIo->EventChannelNotify (XenbusIo, Dev->EventChannel);
> + }
> +}
> +
> +VOID
> +XenPvBlockSync (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev
> + )
> +{
> + if (Dev->MediaInfo.ReadWrite) {
> + if (Dev->MediaInfo.FeatureBarrier) {
> + XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0);
> + }
> +
> + if (Dev->MediaInfo.FeatureFlushCache) {
> + XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
> + }
> + }
> +
> + /* Note: This won't finish if another thread enqueues requests. */
> + while (TRUE) {
> + XenPvBlockAsyncIoPoll (Dev);
> + if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) {
> + break;
> + }
> + }
> +}
> +
> +VOID
> +XenPvBlockAsyncIoPoll (
> + IN XEN_BLOCK_FRONT_DEVICE *Dev
> + )
> +{
> + RING_IDX ProducerIndex, ConsumerIndex;
> + blkif_response_t *Response;
> + INT32 More;
> +
> + do {
> + ProducerIndex = Dev->Ring.sring->rsp_prod;
> + /* Ensure we see queued responses up to 'ProducerIndex'. */
> + MemoryFence ();
> + ConsumerIndex = Dev->Ring.rsp_cons;
> +
> + while (ConsumerIndex != ProducerIndex) {
> + XEN_BLOCK_FRONT_IO *IoData;
> + INT16 Status;
> +
> + Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex);
> +
> + IoData = (VOID *) (UINTN) Response->id;
> + Status = Response->status;
> +
> + switch (Response->operation) {
> + case BLKIF_OP_READ:
> + case BLKIF_OP_WRITE:
> + {
> + INT32 Index;
> +
> + if (Status != BLKIF_RSP_OKAY) {
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: "
> + "%a error %d on %a at offset %Ld, num bytes %Ld\n",
> + Response->operation == BLKIF_OP_READ ? "read" : "write",
> + Status, IoData->Dev->NodeName,
> + IoData->Offset,
> + IoData->Size));
> + }
> +
> + for (Index = 0; Index < IoData->NumRef; Index++) {
> + Dev->XenbusIo->GrantEndAccess (Dev->XenbusIo, IoData->GrantRef[Index]);
> + }
> +
> + break;
> + }
> +
> + case BLKIF_OP_WRITE_BARRIER:
> + if (Status != BLKIF_RSP_OKAY) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: write barrier error %d\n", Status));
> + }
> + break;
> + case BLKIF_OP_FLUSH_DISKCACHE:
> + if (Status != BLKIF_RSP_OKAY) {
> + DEBUG ((EFI_D_ERROR, "XenPvBlk: flush error %d\n", Status));
> + }
> + break;
> +
> + default:
> + DEBUG ((EFI_D_ERROR,
> + "XenPvBlk: unrecognized block operation %d response (status %d)\n",
> + Response->operation, Status));
> + break;
> + }
> +
> + Dev->Ring.rsp_cons = ++ConsumerIndex;
> + /* Nota: callback frees IoData itself */
> + if (IoData && IoData->Callback) {
> + IoData->Callback (IoData, Status ? EFI_DEVICE_ERROR : EFI_SUCCESS);
> + }
> + if (Dev->Ring.rsp_cons != ConsumerIndex) {
> + /* We reentered, we must not continue here */
Uh, how does that happen?
> + break;
> + }
> + }
> +
> + RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More);
> + } while (More != 0);
> +}
next prev parent reply other threads:[~2014-07-16 19:41 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1405523747-5024-1-git-send-email-anthony.perard@citrix.com>
2014-07-16 15:15 ` [PATCH RFC 01/18] OvmfPkg: Add public headers from Xen Project Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 02/18] OvmfPkg: Add basic skeleton for the Xenbus driver Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 03/18] OvmfPkg/XenbusDxe: Add device state struct and create an ExitBoot services event Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 04/18] OvmfPkg/XenbusDxe: Add support to make Xen Hypercalls Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 05/18] OvmfPkg/XenbusDxe: Open PciIo protocol Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 06/18] OvmfPkg: Introduce Xenbus Protocol Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 07/18] OvmfPkg/XenbusDxe: Add InterlockedCompareExchange16 Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 08/18] OvmfPkg/XenbusDxe: Add Grant Table functions Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 09/18] OvmfPkg/XenbusDxe: Add Event Channel Notify Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 10/18] OvmfPkg/XenbusDxe: Add TestAndClearBit Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 11/18] OvmfPkg/XenbusDxe: Add XenStore client implementation Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 12/18] OvmfPkg/XenbusDxe: Add an helper AsciiStrDup Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 13/18] OvmfPkg/XenbusDxe: Add Xenstore function into the Xenbus protocol Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 14/18] OvmfPkg/XenbusDxe: Indroduce XenBus support itself Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 15/18] OvmfPkg/XenbusDxe: Add Event Channel into XenBus protocol Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 16/18] OvmfPkg/XenPvBlkDxe: Xen PV Block device, initial skeleton Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 17/18] OvmfPkg/XenPvBlkDxe: Add BlockFront client Anthony PERARD
2014-07-16 15:15 ` [PATCH RFC 18/18] OvmfPkg/XenPvBlkDxe: Add BlockIo Anthony PERARD
[not found] ` <1405523747-5024-3-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:25 ` [PATCH RFC 02/18] OvmfPkg: Add basic skeleton for the Xenbus driver Konrad Rzeszutek Wilk
2014-07-18 10:30 ` Anthony PERARD
[not found] ` <1405523747-5024-4-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:32 ` [PATCH RFC 03/18] OvmfPkg/XenbusDxe: Add device state struct and create an ExitBoot services event Konrad Rzeszutek Wilk
2014-07-18 10:32 ` Anthony PERARD
[not found] ` <1405523747-5024-5-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:37 ` [PATCH RFC 04/18] OvmfPkg/XenbusDxe: Add support to make Xen Hypercalls Konrad Rzeszutek Wilk
2014-07-17 9:43 ` Wei Liu
[not found] ` <1405523747-5024-6-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:39 ` [PATCH RFC 05/18] OvmfPkg/XenbusDxe: Open PciIo protocol Konrad Rzeszutek Wilk
2014-07-18 10:36 ` Anthony PERARD
[not found] ` <1405523747-5024-7-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:42 ` [PATCH RFC 06/18] OvmfPkg: Introduce Xenbus Protocol Konrad Rzeszutek Wilk
2014-07-18 10:40 ` Anthony PERARD
[not found] ` <1405523747-5024-9-git-send-email-anthony.perard@citrix.com>
2014-07-16 17:48 ` [PATCH RFC 08/18] OvmfPkg/XenbusDxe: Add Grant Table functions Konrad Rzeszutek Wilk
2014-07-18 10:53 ` Anthony PERARD
[not found] ` <1405523747-5024-15-git-send-email-anthony.perard@citrix.com>
2014-07-16 19:04 ` [PATCH RFC 14/18] OvmfPkg/XenbusDxe: Indroduce XenBus support itself Konrad Rzeszutek Wilk
2014-07-18 11:04 ` Anthony PERARD
[not found] ` <1405523747-5024-18-git-send-email-anthony.perard@citrix.com>
2014-07-16 19:41 ` Konrad Rzeszutek Wilk [this message]
2014-07-18 11:58 ` [PATCH RFC 17/18] OvmfPkg/XenPvBlkDxe: Add BlockFront client Anthony PERARD
[not found] ` <20140718115817.GG1582@perard.uk.xensource.com>
2014-07-18 18:36 ` Konrad Rzeszutek Wilk
[not found] ` <1405523747-5024-19-git-send-email-anthony.perard@citrix.com>
2014-07-16 19:57 ` [PATCH RFC 18/18] OvmfPkg/XenPvBlkDxe: Add BlockIo Konrad Rzeszutek Wilk
2014-07-18 12:10 ` Anthony PERARD
2014-07-16 20:10 ` [PATCH RFC 00/18] Introducing Xen PV block driver to OVMF Konrad Rzeszutek Wilk
2014-07-18 12:12 ` Anthony PERARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140716194117.GE8349@laptop.dumpdata.com \
--to=konrad.wilk@oracle.com \
--cc=anthony.perard@citrix.com \
--cc=edk2-devel@lists.sourceforge.net \
--cc=samuel.thibault@eu.citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.