Re: [PATCH v13] i2c: virtio: add a virtio i2c frontend driver

From: Viresh Kumar
Date: Mon Jul 05 2021 - 04:02:58 EST


Hi Jie.

On 05-07-21, 14:53, Jie Deng wrote:
> diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c
> +static int virtio_i2c_complete_reqs(struct virtqueue *vq,
> + struct virtio_i2c_req *reqs,
> + struct i2c_msg *msgs, int nr,
> + bool fail)
> +{
> + struct virtio_i2c_req *req;
> + bool failed = fail;
> + unsigned int len;
> + int i, j = 0;
> +
> + for (i = 0; i < nr; i++) {
> + /* Detach the ith request from the vq */
> + req = virtqueue_get_buf(vq, &len);

Calling this for cases where virtio_i2c_prepare_reqs() itself has failed will
always return NULL, should we even try to call this then ?

virtqueue_get_buf() returns the next used buffer only, i.e. returned by the host
?

> +
> + /*
> + * Condition (req && req == &reqs[i]) should always meet since
> + * we have total nr requests in the vq.
> + */
> + if (!failed && (WARN_ON(!(req && req == &reqs[i])) ||

Mentioning again for completeness of the review, reqs[i] can never be NULL here
though req can be. And even in that case you never need to check req here.

Feel free to ignore it if you want, we can always send a fixup patch later and
discuss it further :)

> + (req->in_hdr.status != VIRTIO_I2C_MSG_OK)))
> + failed = true;
> +
> + i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
> + if (!failed)
> + j++;
> + }
> +
> + return fail ? 0 : j;

Since you don't return ETIMEDOUT anymore, you can simply return j now. And so we
can work with a single failed argument and don't need both fail and failed.

> +}
> +
> +static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
> +{
> + struct virtio_i2c *vi = i2c_get_adapdata(adap);
> + struct virtqueue *vq = vi->vq;
> + struct virtio_i2c_req *reqs;
> + unsigned long time_left;
> + int ret;
> +
> + reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
> + if (!reqs)
> + return -ENOMEM;
> +
> + ret = virtio_i2c_prepare_reqs(vq, reqs, msgs, num);
> + if (ret != num) {
> + ret = virtio_i2c_complete_reqs(vq, reqs, msgs, ret, true);
> + goto err_free;
> + }
> +
> + reinit_completion(&vi->completion);
> + virtqueue_kick(vq);
> + time_left = wait_for_completion_timeout(&vi->completion, adap->timeout);
> + ret = virtio_i2c_complete_reqs(vq, reqs, msgs, num, !time_left);
> +
> + if (!time_left) {
> + ret = -ETIMEDOUT;
> + dev_err(&adap->dev, "virtio i2c backend timeout.\n");
> + }
> +
> +err_free:
> + kfree(reqs);
> + return ret;
> +}

> diff --git a/include/uapi/linux/virtio_i2c.h b/include/uapi/linux/virtio_i2c.h
> new file mode 100644
> index 0000000..df936a2
> --- /dev/null
> +++ b/include/uapi/linux/virtio_i2c.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
> +/*
> + * Definitions for virtio I2C Adpter
> + *
> + * Copyright (c) 2021 Intel Corporation. All rights reserved.
> + */
> +
> +#ifndef _UAPI_LINUX_VIRTIO_I2C_H
> +#define _UAPI_LINUX_VIRTIO_I2C_H
> +
> +#include <linux/types.h>
> +#include <linux/const.h>

Both of these need to be the uapi headers as Andy said earlier and they better
be in alphabetical order.

#include <uapi/linux/const.h>
#include <uapi/linux/types.h>

Though in your support, I do see a lot of files in uapi/linux using the standard
types.h, which looks wrong as that types.h is not a userspace ABI.

--
viresh