lkml.org 
[lkml]   [2021]   [Feb]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 11/13] vdpa: add vdpa simulator for block device
    Date
    From: Max Gurtovoy <mgurtovoy@nvidia.com>

    This will allow running vDPA for virtio block protocol.

    It's a preliminary implementation with a simple request handling:
    for each request, only the status (last byte) is set.
    It's always set to VIRTIO_BLK_S_OK.

    Also input validation is missing and will be added in the next commits.

    Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com>
    [sgarzare: various cleanups/fixes]
    Acked-by: Jason Wang <jasowang@redhat.com>
    Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
    ---
    v3:
    - updated Mellanox copyright to NVIDIA [Max]
    - explained in the commit message that inputs are validated in subsequent
    patches [Stefan]

    v2:
    - rebased on top of other changes (dev_attr, get_config(), notify(), etc.)
    - memset to 0 the config structure in vdpasim_blk_get_config()
    - used vdpasim pointer in vdpasim_blk_get_config()

    v1:
    - Removed unused headers
    - Used cpu_to_vdpasim*() to store config fields
    - Replaced 'select VDPA_SIM' with 'depends on VDPA_SIM' since selected
    option can not depend on other [Jason]
    - Start with a single queue for now [Jason]
    - Add comments to memory barriers
    ---
    drivers/vdpa/vdpa_sim/vdpa_sim_blk.c | 145 +++++++++++++++++++++++++++
    drivers/vdpa/Kconfig | 7 ++
    drivers/vdpa/vdpa_sim/Makefile | 1 +
    3 files changed, 153 insertions(+)
    create mode 100644 drivers/vdpa/vdpa_sim/vdpa_sim_blk.c

    diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
    new file mode 100644
    index 000000000000..9822f9edc511
    --- /dev/null
    +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
    @@ -0,0 +1,145 @@
    +// SPDX-License-Identifier: GPL-2.0-only
    +/*
    + * VDPA simulator for block device.
    + *
    + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
    + *
    + */
    +
    +#include <linux/init.h>
    +#include <linux/module.h>
    +#include <linux/device.h>
    +#include <linux/kernel.h>
    +#include <linux/sched.h>
    +#include <linux/vringh.h>
    +#include <linux/vdpa.h>
    +#include <uapi/linux/virtio_blk.h>
    +
    +#include "vdpa_sim.h"
    +
    +#define DRV_VERSION "0.1"
    +#define DRV_AUTHOR "Max Gurtovoy <mgurtovoy@nvidia.com>"
    +#define DRV_DESC "vDPA Device Simulator for block device"
    +#define DRV_LICENSE "GPL v2"
    +
    +#define VDPASIM_BLK_FEATURES (VDPASIM_FEATURES | \
    + (1ULL << VIRTIO_BLK_F_SIZE_MAX) | \
    + (1ULL << VIRTIO_BLK_F_SEG_MAX) | \
    + (1ULL << VIRTIO_BLK_F_BLK_SIZE) | \
    + (1ULL << VIRTIO_BLK_F_TOPOLOGY) | \
    + (1ULL << VIRTIO_BLK_F_MQ))
    +
    +#define VDPASIM_BLK_CAPACITY 0x40000
    +#define VDPASIM_BLK_SIZE_MAX 0x1000
    +#define VDPASIM_BLK_SEG_MAX 32
    +#define VDPASIM_BLK_VQ_NUM 1
    +
    +static struct vdpasim *vdpasim_blk_dev;
    +
    +static void vdpasim_blk_work(struct work_struct *work)
    +{
    + struct vdpasim *vdpasim = container_of(work, struct vdpasim, work);
    + u8 status = VIRTIO_BLK_S_OK;
    + int i;
    +
    + spin_lock(&vdpasim->lock);
    +
    + if (!(vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK))
    + goto out;
    +
    + for (i = 0; i < VDPASIM_BLK_VQ_NUM; i++) {
    + struct vdpasim_virtqueue *vq = &vdpasim->vqs[i];
    +
    + if (!vq->ready)
    + continue;
    +
    + while (vringh_getdesc_iotlb(&vq->vring, &vq->out_iov,
    + &vq->in_iov, &vq->head,
    + GFP_ATOMIC) > 0) {
    + int write;
    +
    + vq->in_iov.i = vq->in_iov.used - 1;
    + write = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
    + &status, 1);
    + if (write <= 0)
    + break;
    +
    + /* Make sure data is wrote before advancing index */
    + smp_wmb();
    +
    + vringh_complete_iotlb(&vq->vring, vq->head, write);
    +
    + /* Make sure used is visible before rasing the interrupt. */
    + smp_wmb();
    +
    + local_bh_disable();
    + if (vringh_need_notify_iotlb(&vq->vring) > 0)
    + vringh_notify(&vq->vring);
    + local_bh_enable();
    + }
    + }
    +out:
    + spin_unlock(&vdpasim->lock);
    +}
    +
    +static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
    +{
    + struct virtio_blk_config *blk_config =
    + (struct virtio_blk_config *)config;
    +
    + memset(config, 0, sizeof(struct virtio_blk_config));
    +
    + blk_config->capacity = cpu_to_vdpasim64(vdpasim, VDPASIM_BLK_CAPACITY);
    + blk_config->size_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SIZE_MAX);
    + blk_config->seg_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SEG_MAX);
    + blk_config->num_queues = cpu_to_vdpasim16(vdpasim, VDPASIM_BLK_VQ_NUM);
    + blk_config->min_io_size = cpu_to_vdpasim16(vdpasim, 1);
    + blk_config->opt_io_size = cpu_to_vdpasim32(vdpasim, 1);
    + blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
    +}
    +
    +static int __init vdpasim_blk_init(void)
    +{
    + struct vdpasim_dev_attr dev_attr = {};
    + int ret;
    +
    + dev_attr.id = VIRTIO_ID_BLOCK;
    + dev_attr.supported_features = VDPASIM_BLK_FEATURES;
    + dev_attr.nvqs = VDPASIM_BLK_VQ_NUM;
    + dev_attr.config_size = sizeof(struct virtio_blk_config);
    + dev_attr.get_config = vdpasim_blk_get_config;
    + dev_attr.work_fn = vdpasim_blk_work;
    + dev_attr.buffer_size = PAGE_SIZE;
    +
    + vdpasim_blk_dev = vdpasim_create(&dev_attr);
    + if (IS_ERR(vdpasim_blk_dev)) {
    + ret = PTR_ERR(vdpasim_blk_dev);
    + goto out;
    + }
    +
    + ret = vdpa_register_device(&vdpasim_blk_dev->vdpa);
    + if (ret)
    + goto put_dev;
    +
    + return 0;
    +
    +put_dev:
    + put_device(&vdpasim_blk_dev->vdpa.dev);
    +out:
    + return ret;
    +}
    +
    +static void __exit vdpasim_blk_exit(void)
    +{
    + struct vdpa_device *vdpa = &vdpasim_blk_dev->vdpa;
    +
    + vdpa_unregister_device(vdpa);
    +}
    +
    +module_init(vdpasim_blk_init)
    +module_exit(vdpasim_blk_exit)
    +
    +MODULE_VERSION(DRV_VERSION);
    +MODULE_LICENSE(DRV_LICENSE);
    +MODULE_AUTHOR(DRV_AUTHOR);
    +MODULE_DESCRIPTION(DRV_DESC);
    diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
    index 21a23500f430..b8bd92cf04f9 100644
    --- a/drivers/vdpa/Kconfig
    +++ b/drivers/vdpa/Kconfig
    @@ -26,6 +26,13 @@ config VDPA_SIM_NET
    help
    vDPA networking device simulator which loops TX traffic back to RX.

    +config VDPA_SIM_BLOCK
    + tristate "vDPA simulator for block device"
    + depends on VDPA_SIM
    + help
    + vDPA block device simulator which terminates IO request in a
    + memory buffer.
    +
    config IFCVF
    tristate "Intel IFC VF vDPA driver"
    depends on PCI_MSI
    diff --git a/drivers/vdpa/vdpa_sim/Makefile b/drivers/vdpa/vdpa_sim/Makefile
    index 79d4536d347e..d458103302f2 100644
    --- a/drivers/vdpa/vdpa_sim/Makefile
    +++ b/drivers/vdpa/vdpa_sim/Makefile
    @@ -1,3 +1,4 @@
    # SPDX-License-Identifier: GPL-2.0
    obj-$(CONFIG_VDPA_SIM) += vdpa_sim.o
    obj-$(CONFIG_VDPA_SIM_NET) += vdpa_sim_net.o
    +obj-$(CONFIG_VDPA_SIM_BLOCK) += vdpa_sim_blk.o
    --
    2.29.2
    \
     
     \ /
      Last update: 2021-02-04 18:31    [W:5.659 / U:0.212 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site