From: "Alex Bennée" <alex.bennee@linaro.org>
To: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Vincent Guittot <vincent.guittot@linaro.org>,
Jie Deng <jie.deng@intel.com>, Bill Mills <bill.mills@linaro.org>,
qemu-devel@nongnu.org, Arnd Bergmann <arnd.bergmann@linaro.com>,
Mike Holmes <mike.holmes@linaro.org>,
stratos-dev@op-lists.linaro.org
Subject: Re: [PATCH 1/5] hw/virtio: add boilerplate for vhost-user-i2c device
Date: Mon, 29 Mar 2021 16:13:27 +0100 [thread overview]
Message-ID: <87lfa6xa32.fsf@linaro.org> (raw)
In-Reply-To: <680d46df15a19a7ccb05f79370cb03226c23d943.1616570702.git.viresh.kumar@linaro.org>
Viresh Kumar <viresh.kumar@linaro.org> writes:
> This creates the QEMU side of the vhost-user-i2c device which connects
> to the remote daemon. It is based of vhost-user-fs code.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> hw/virtio/Kconfig | 5 +
> hw/virtio/meson.build | 1 +
> hw/virtio/vhost-user-i2c.c | 286 ++++++++++++++++++++
> include/hw/virtio/vhost-user-i2c.h | 37 +++
> include/standard-headers/linux/virtio_ids.h | 1 +
> 5 files changed, 330 insertions(+)
> create mode 100644 hw/virtio/vhost-user-i2c.c
> create mode 100644 include/hw/virtio/vhost-user-i2c.h
>
> diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
> index 0eda25c4e1bf..35ab45e2095c 100644
> --- a/hw/virtio/Kconfig
> +++ b/hw/virtio/Kconfig
> @@ -58,3 +58,8 @@ config VIRTIO_MEM
> depends on LINUX
> depends on VIRTIO_MEM_SUPPORTED
> select MEM_DEVICE
> +
> +config VHOST_USER_I2C
> + bool
> + default y
> + depends on VIRTIO && VHOST_USER
> diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
> index fbff9bc9d4de..1a0d736a0db5 100644
> --- a/hw/virtio/meson.build
> +++ b/hw/virtio/meson.build
> @@ -25,6 +25,7 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.
> virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
> virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
> virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
> +virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
>
> virtio_pci_ss = ss.source_set()
> virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
> diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
> new file mode 100644
> index 000000000000..7b0dc24412a4
> --- /dev/null
> +++ b/hw/virtio/vhost-user-i2c.c
> @@ -0,0 +1,286 @@
> +/*
> + * Vhost-user i2c virtio device
> + *
> + * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/virtio/virtio-bus.h"
> +#include "hw/virtio/vhost-user-i2c.h"
> +#include "qemu/error-report.h"
> +#include "standard-headers/linux/virtio_ids.h"
> +
> +static void vu_i2c_start(VirtIODevice *vdev)
> +{
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> + int ret;
> + int i;
> +
> + if (!k->set_guest_notifiers) {
> + error_report("binding does not support guest notifiers");
> + return;
> + }
> +
> + ret = vhost_dev_enable_notifiers(&i2c->vhost_dev, vdev);
> + if (ret < 0) {
> + error_report("Error enabling host notifiers: %d", -ret);
> + return;
> + }
> +
> + ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, true);
> + if (ret < 0) {
> + error_report("Error binding guest notifier: %d", -ret);
> + goto err_host_notifiers;
> + }
> +
> + i2c->vhost_dev.acked_features = vdev->guest_features;
> + ret = vhost_dev_start(&i2c->vhost_dev, vdev);
> + if (ret < 0) {
> + error_report("Error starting vhost-user-i2c: %d", -ret);
> + goto err_guest_notifiers;
> + }
> +
> + /*
> + * guest_notifier_mask/pending not used yet, so just unmask
> + * everything here. virtio-pci will do the right thing by
> + * enabling/disabling irqfd.
> + */
> + for (i = 0; i < i2c->vhost_dev.nvqs; i++) {
> + vhost_virtqueue_mask(&i2c->vhost_dev, vdev, i, false);
> + }
> +
> + return;
> +
> +err_guest_notifiers:
> + k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
> +err_host_notifiers:
> + vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
> +}
> +
> +static void vu_i2c_stop(VirtIODevice *vdev)
> +{
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> + int ret;
> +
> + if (!k->set_guest_notifiers) {
> + return;
> + }
> +
> + vhost_dev_stop(&i2c->vhost_dev, vdev);
> +
> + ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
> + if (ret < 0) {
> + error_report("vhost guest notifier cleanup failed: %d", ret);
> + return;
> + }
> +
> + vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
> +}
> +
> +static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status)
> +{
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> + bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
> +
> + if (!vdev->vm_running) {
> + should_start = false;
> + }
> +
> + if (i2c->vhost_dev.started == should_start) {
> + return;
> + }
> +
> + if (should_start) {
> + vu_i2c_start(vdev);
> + } else {
> + vu_i2c_stop(vdev);
> + }
> +}
> +
> +static uint64_t vu_i2c_get_features(VirtIODevice *vdev,
> + uint64_t requested_features, Error **errp)
> +{
> + /* No feature bits used yet */
> + return requested_features;
> +}
> +
> +static void vu_i2c_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> +{
> + /*
> + * Not normally called; it's the daemon that handles the queue;
> + * however virtio's cleanup path can call this.
> + */
> +}
> +
> +static void vu_i2c_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
> +{
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> +
> + vhost_virtqueue_mask(&i2c->vhost_dev, vdev, idx, mask);
> +}
> +
> +static bool vu_i2c_guest_notifier_pending(VirtIODevice *vdev, int idx)
> +{
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> +
> + return vhost_virtqueue_pending(&i2c->vhost_dev, idx);
> +}
> +
> +static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserI2C *i2c)
> +{
> + vhost_user_cleanup(&i2c->vhost_user);
> + virtio_delete_queue(i2c->req_vq);
> + g_free(i2c->vhost_dev.vqs);
> + virtio_cleanup(vdev);
> + g_free(i2c->vhost_dev.vqs);
This is a double free of the same queue.
> + i2c->vhost_dev.vqs = NULL;
> +}
> +
> +static int vu_i2c_connect(DeviceState *dev)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> +
> + if (i2c->connected) {
> + return 0;
> + }
> + i2c->connected = true;
> +
> + /* restore vhost state */
> + if (virtio_device_started(vdev, vdev->status)) {
> + vu_i2c_start(vdev);
> + }
> +
> + return 0;
> +}
> +
> +static void vu_i2c_disconnect(DeviceState *dev)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> +
> + if (!i2c->connected) {
> + return;
> + }
> + i2c->connected = false;
> +
> + if (i2c->vhost_dev.started) {
> + vu_i2c_stop(vdev);
> + }
> +}
> +
> +static void vu_i2c_event(void *opaque, QEMUChrEvent event)
> +{
> + DeviceState *dev = opaque;
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
> +
> + switch (event) {
> + case CHR_EVENT_OPENED:
> + if (vu_i2c_connect(dev) < 0) {
> + qemu_chr_fe_disconnect(&i2c->conf.chardev);
> + return;
> + }
> + break;
> + case CHR_EVENT_CLOSED:
> + vu_i2c_disconnect(dev);
> + break;
> + case CHR_EVENT_BREAK:
> + case CHR_EVENT_MUX_IN:
> + case CHR_EVENT_MUX_OUT:
> + /* Ignore */
> + break;
> + }
> +}
> +
> +static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostUserI2C *i2c = VHOST_USER_I2C(dev);
> + int ret;
> +
> + if (!i2c->conf.chardev.chr) {
> + error_setg(errp, "missing chardev");
> + return;
> + }
> +
> + if (!vhost_user_init(&i2c->vhost_user, &i2c->conf.chardev, errp)) {
> + return;
> + }
> +
> + virtio_init(vdev, "vhost-user-i2c", VIRTIO_ID_I2C, 0);
> +
> + i2c->req_vq = virtio_add_queue(vdev, 3, vu_i2c_handle_output);
> + i2c->vhost_dev.nvqs = 1;
> + i2c->vhost_dev.vqs = g_new0(struct vhost_virtqueue, i2c->vhost_dev.nvqs);
> + ret = vhost_dev_init(&i2c->vhost_dev, &i2c->vhost_user,
> + VHOST_BACKEND_TYPE_USER, 0);
> + if (ret < 0) {
> + error_setg_errno(errp, -ret, "vhost_dev_init() failed");
> + do_vhost_user_cleanup(vdev, i2c);
> + }
> +
> + qemu_chr_fe_set_handlers(&i2c->conf.chardev, NULL, NULL, vu_i2c_event, NULL,
> + dev, NULL, true);
> +}
> +
> +static void vu_i2c_device_unrealize(DeviceState *dev)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostUserI2C *i2c = VHOST_USER_I2C(dev);
> +
> + /* This will stop vhost backend if appropriate. */
> + vu_i2c_set_status(vdev, 0);
> +
> + vhost_dev_cleanup(&i2c->vhost_dev);
> +
> + do_vhost_user_cleanup(vdev, i2c);
> +}
> +
> +static const VMStateDescription vu_i2c_vmstate = {
> + .name = "vhost-user-i2c",
> + .unmigratable = 1,
> +};
> +
> +static Property vu_i2c_properties[] = {
> + DEFINE_PROP_CHR("chardev", VHostUserI2C, conf.chardev),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void vu_i2c_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> +
> + device_class_set_props(dc, vu_i2c_properties);
> + dc->vmsd = &vu_i2c_vmstate;
> + set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
> + vdc->realize = vu_i2c_device_realize;
> + vdc->unrealize = vu_i2c_device_unrealize;
> + vdc->get_features = vu_i2c_get_features;
> + vdc->set_status = vu_i2c_set_status;
> + vdc->guest_notifier_mask = vu_i2c_guest_notifier_mask;
> + vdc->guest_notifier_pending = vu_i2c_guest_notifier_pending;
> +}
> +
> +static const TypeInfo vu_i2c_info = {
> + .name = TYPE_VHOST_USER_I2C,
> + .parent = TYPE_VIRTIO_DEVICE,
> + .instance_size = sizeof(VHostUserI2C),
> + .class_init = vu_i2c_class_init,
> +};
> +
> +static void vu_i2c_register_types(void)
> +{
> + type_register_static(&vu_i2c_info);
> +}
> +
> +type_init(vu_i2c_register_types)
> diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
> new file mode 100644
> index 000000000000..a5fffcb6096c
> --- /dev/null
> +++ b/include/hw/virtio/vhost-user-i2c.h
> @@ -0,0 +1,37 @@
> +/*
> + * Vhost-user i2c virtio device
> + *
> + * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef _QEMU_VHOST_USER_I2C_H
> +#define _QEMU_VHOST_USER_I2C_H
> +
> +#include "hw/virtio/virtio.h"
> +#include "hw/virtio/vhost.h"
> +#include "hw/virtio/vhost-user.h"
> +#include "chardev/char-fe.h"
> +
> +#define TYPE_VHOST_USER_I2C "vhost-user-i2c-device"
> +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserI2C, VHOST_USER_I2C)
> +
> +typedef struct {
> + CharBackend chardev;
> +} VHostUserI2CConf;
> +
> +struct VHostUserI2C {
> + /*< private >*/
> + VirtIODevice parent;
> + VHostUserI2CConf conf;
> + struct vhost_virtqueue *vhost_vq;
> + struct vhost_dev vhost_dev;
> + VhostUserState vhost_user;
> + VirtQueue *req_vq;
> + bool connected;
> +
> + /*< public >*/
> +};
> +
> +#endif /* _QEMU_VHOST_USER_I2C_H */
> diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h
> index bc1c0621f5ed..aba00c54b9cd 100644
> --- a/include/standard-headers/linux/virtio_ids.h
> +++ b/include/standard-headers/linux/virtio_ids.h
> @@ -54,5 +54,6 @@
> #define VIRTIO_ID_FS 26 /* virtio filesystem */
> #define VIRTIO_ID_PMEM 27 /* virtio pmem */
> #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
> +#define VIRTIO_ID_I2C 34 /* virtio i2c */
This should come in as a separate patch. Generally I run:
./scripts/update-linux-headers.sh ~/lsrc/linux.git
and tag the patch as (!MERGE) as a place holder until it can get picked
up with one of the regular UAPI updates.
>
> #endif /* _LINUX_VIRTIO_IDS_H */
--
Alex Bennée
next prev parent reply other threads:[~2021-03-29 15:19 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-24 7:33 [PATCH 0/5] virtio: Implement generic vhost-user-i2c backend Viresh Kumar
2021-03-24 7:33 ` [PATCH 1/5] hw/virtio: add boilerplate for vhost-user-i2c device Viresh Kumar
2021-03-29 15:13 ` Alex Bennée [this message]
2021-03-24 7:33 ` [PATCH 2/5] hw/virtio: add vhost-user-i2c-pci boilerplate Viresh Kumar
2021-03-29 15:19 ` Alex Bennée
2021-03-24 7:33 ` [PATCH 3/5] tools/vhost-user-i2c: Add backend driver Viresh Kumar
2021-03-25 5:09 ` Jie Deng
2021-03-25 5:22 ` Viresh Kumar
2021-03-25 12:22 ` Alex Bennée
2021-03-30 12:49 ` Alex Bennée
2021-03-25 6:17 ` Jie Deng
2021-03-25 6:36 ` Viresh Kumar
2021-03-25 16:16 ` Arnd Bergmann
2021-03-26 6:01 ` Viresh Kumar
2021-03-26 8:33 ` Arnd Bergmann
2021-03-26 7:14 ` Viresh Kumar
2021-03-26 8:24 ` Arnd Bergmann
2021-03-24 7:33 ` [PATCH 4/5] docs: add a man page for vhost-user-i2c Viresh Kumar
2021-03-24 7:33 ` [PATCH 5/5] MAINTAINERS: Add entry for virtio-i2c Viresh Kumar
2021-03-24 7:42 ` [PATCH 0/5] virtio: Implement generic vhost-user-i2c backend no-reply
2021-03-24 11:05 ` Viresh Kumar
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=87lfa6xa32.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=arnd.bergmann@linaro.com \
--cc=bill.mills@linaro.org \
--cc=jie.deng@intel.com \
--cc=mike.holmes@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=stratos-dev@op-lists.linaro.org \
--cc=vincent.guittot@linaro.org \
--cc=viresh.kumar@linaro.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.