Skip to content

Commit

Permalink
virtio: Add a Sandbox transport driver
Browse files Browse the repository at this point in the history
This driver provides support for Sandbox implementation of virtio
transport driver which is used for testing purpose only.

Two drivers are provided. The 2nd one is a driver that lacks the
'notify' op.

Signed-off-by: Bin Meng <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
  • Loading branch information
lbmeng authored and sjg20 committed Nov 14, 2018
1 parent 699aae0 commit 640aae0
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/virtio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ config VIRTIO_PCI
This driver provides support for virtio based paravirtual device
drivers over PCI.

config VIRTIO_SANDBOX
bool "Sandbox driver for virtio devices"
depends on SANDBOX
select VIRTIO
help
This driver provides support for Sandbox implementation of virtio
transport driver which is used for testing purpose only.

config VIRTIO_NET
bool "virtio net driver"
depends on VIRTIO
Expand Down
1 change: 1 addition & 0 deletions drivers/virtio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
obj-y += virtio-uclass.o virtio_ring.o
obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
obj-$(CONFIG_VIRTIO_PCI) += virtio_pci_legacy.o virtio_pci_modern.o
obj-$(CONFIG_VIRTIO_SANDBOX) += virtio_sandbox.o
obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
233 changes: 233 additions & 0 deletions drivers/virtio/virtio_sandbox.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018, Bin Meng <[email protected]>
*
* VirtIO Sandbox transport driver, for testing purpose only
*/

#include <common.h>
#include <dm.h>
#include <virtio_types.h>
#include <virtio.h>
#include <virtio_ring.h>
#include <linux/compat.h>
#include <linux/io.h>

struct virtio_sandbox_priv {
u8 id;
u8 status;
u64 device_features;
u64 driver_features;
ulong queue_desc;
ulong queue_available;
ulong queue_used;
};

static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
void *buf, unsigned int len)
{
return 0;
}

static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
const void *buf, unsigned int len)
{
return 0;
}

static int virtio_sandbox_get_status(struct udevice *udev, u8 *status)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);

*status = priv->status;

return 0;
}

static int virtio_sandbox_set_status(struct udevice *udev, u8 status)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);

/* We should never be setting status to 0 */
WARN_ON(status == 0);

priv->status = status;

return 0;
}

static int virtio_sandbox_reset(struct udevice *udev)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);

/* 0 status means a reset */
priv->status = 0;

return 0;
}

static int virtio_sandbox_get_features(struct udevice *udev, u64 *features)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);

*features = priv->device_features;

return 0;
}

static int virtio_sandbox_set_features(struct udevice *udev)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);

priv->driver_features = uc_priv->features;

return 0;
}

static struct virtqueue *virtio_sandbox_setup_vq(struct udevice *udev,
unsigned int index)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);
struct virtqueue *vq;
ulong addr;
int err;

/* Create the vring */
vq = vring_create_virtqueue(index, 4, 4096, udev);
if (!vq) {
err = -ENOMEM;
goto error_new_virtqueue;
}

addr = virtqueue_get_desc_addr(vq);
priv->queue_desc = addr;

addr = virtqueue_get_avail_addr(vq);
priv->queue_available = addr;

addr = virtqueue_get_used_addr(vq);
priv->queue_used = addr;

return vq;

error_new_virtqueue:
return ERR_PTR(err);
}

static void virtio_sandbox_del_vq(struct virtqueue *vq)
{
vring_del_virtqueue(vq);
}

static int virtio_sandbox_del_vqs(struct udevice *udev)
{
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
struct virtqueue *vq, *n;

list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
virtio_sandbox_del_vq(vq);

return 0;
}

static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,
struct virtqueue *vqs[])
{
int i;

for (i = 0; i < nvqs; ++i) {
vqs[i] = virtio_sandbox_setup_vq(udev, i);
if (IS_ERR(vqs[i])) {
virtio_sandbox_del_vqs(udev);
return PTR_ERR(vqs[i]);
}
}

return 0;
}

static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
{
return 0;
}

static int virtio_sandbox_probe(struct udevice *udev)
{
struct virtio_sandbox_priv *priv = dev_get_priv(udev);
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);

/* fake some information for testing */
priv->device_features = VIRTIO_F_VERSION_1;
uc_priv->device = VIRTIO_ID_BLOCK;
uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';

return 0;
}

/* check virtio device driver's remove routine was called to reset the device */
static int virtio_sandbox_child_post_remove(struct udevice *vdev)
{
u8 status;

virtio_get_status(vdev, &status);
if (status)
panic("virtio device was not reset\n");

return 0;
}

static const struct dm_virtio_ops virtio_sandbox1_ops = {
.get_config = virtio_sandbox_get_config,
.set_config = virtio_sandbox_set_config,
.get_status = virtio_sandbox_get_status,
.set_status = virtio_sandbox_set_status,
.reset = virtio_sandbox_reset,
.get_features = virtio_sandbox_get_features,
.set_features = virtio_sandbox_set_features,
.find_vqs = virtio_sandbox_find_vqs,
.del_vqs = virtio_sandbox_del_vqs,
.notify = virtio_sandbox_notify,
};

static const struct udevice_id virtio_sandbox1_ids[] = {
{ .compatible = "sandbox,virtio1" },
{ }
};

U_BOOT_DRIVER(virtio_sandbox1) = {
.name = "virtio-sandbox1",
.id = UCLASS_VIRTIO,
.of_match = virtio_sandbox1_ids,
.ops = &virtio_sandbox1_ops,
.probe = virtio_sandbox_probe,
.child_post_remove = virtio_sandbox_child_post_remove,
.priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
};

/* this one without notify op */
static const struct dm_virtio_ops virtio_sandbox2_ops = {
.get_config = virtio_sandbox_get_config,
.set_config = virtio_sandbox_set_config,
.get_status = virtio_sandbox_get_status,
.set_status = virtio_sandbox_set_status,
.reset = virtio_sandbox_reset,
.get_features = virtio_sandbox_get_features,
.set_features = virtio_sandbox_set_features,
.find_vqs = virtio_sandbox_find_vqs,
.del_vqs = virtio_sandbox_del_vqs,
};

static const struct udevice_id virtio_sandbox2_ids[] = {
{ .compatible = "sandbox,virtio2" },
{ }
};

U_BOOT_DRIVER(virtio_sandbox2) = {
.name = "virtio-sandbox2",
.id = UCLASS_VIRTIO,
.of_match = virtio_sandbox2_ids,
.ops = &virtio_sandbox2_ops,
.probe = virtio_sandbox_probe,
.priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
};

0 comments on commit 640aae0

Please sign in to comment.