Re: [PATCH v3] drivers: gpio: add virtio-gpio guest driver

From: Randy Dunlap
Date: Mon Dec 07 2020 - 18:04:43 EST


On 12/7/20 12:48 PM, Enrico Weigelt, metux IT consult wrote:
> Introducing new GPIO driver for virtual GPIO devices via virtio.

Introduce

>
> The driver allows routing GPIO control into VM guests, eg. brigding
> virtual gpios to specific host gpios, or attaching simulators for
> automatic application testing.
>

These ...

> Changes v3:
> * spec: fixed type names
> * spec: replace "host"/"guest" by "device"/"cpu"
> * spec: change terminology from "events" to "messages"
> * driver: fixed missing can_sleep flag
> * driver: select VIRTIO instead of depends on
> * driver: drop references to qemu in Kconfig
> * driver: fixed incomplete error handling and possible deadlock
> in case of sending buf failed
> * driver: dropped unneeded WARN_ON
> * driver: fixed retval of virtio_gpio_xmit()
> * driver: dynamically allocate virtio buffers
> * driver: added locking on gpio operations
> * driver: added irq_chip functions
>
> Changes v2:
> * uapi: fixed header license
> * driver: sorted include's
> * driver: fixed formatting
> * driver: fixed unneeded devm allocation - plain kzalloc/kfree is enough
> * driver: fixed missing devm_kzalloc fail check
> * driver: use devm_kcalloc() for array allocation
> * spec: added virtio-gpio protocol specification

... Vx change descriptions go after the following "---" line.
I usually put them before the diffstat, with one blank line
separating them.

>
> Signed-off-by: Enrico Weigelt, metux IT consult <info@xxxxxxxxx>
> ---
> Documentation/gpio/virtio-gpio.rst | 176 +++++++++++++++++
> MAINTAINERS | 6 +
> drivers/gpio/Kconfig | 7 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-virtio.c | 381 +++++++++++++++++++++++++++++++++++++
> include/uapi/linux/virtio_gpio.h | 39 ++++
> include/uapi/linux/virtio_ids.h | 1 +
> 7 files changed, 611 insertions(+)
> create mode 100644 Documentation/gpio/virtio-gpio.rst
> create mode 100644 drivers/gpio/gpio-virtio.c
> create mode 100644 include/uapi/linux/virtio_gpio.h
>
> diff --git a/Documentation/gpio/virtio-gpio.rst b/Documentation/gpio/virtio-gpio.rst
> new file mode 100644
> index 000000000000..e7bf01ec1ce7
> --- /dev/null
> +++ b/Documentation/gpio/virtio-gpio.rst
> @@ -0,0 +1,176 @@
> +"""""""""""""""""
> +Virtio-GPIO protocol specification
> +"""""""""""""""""
> +...........
> +Specification for virtio-based virtiual GPIO devices

virtual
although it seems redundant.

> +...........
> +
> ++------------
> ++Version_ 1.0
> ++------------
> +
> +===================
> +General
> +===================
> +
> +The virtio-gpio protocol provides access to general purpose IO devices
> +to virtual machine guests. These virtualized GPIOs could be either provided

in (?)

> +by some simulator (eg. virtual HIL), routed to some external device or

(e.g.

> +routed to real GPIOs on the host (eg. virtualized embedded applications).

(e.g.

> +
> +Instead of simulating some existing real GPIO chip within an VMM, this

within a
and why not just "VM"?

> +protocol provides an hardware independent interface between host and guest

a hardware

> +that solely relies on an active virtio connection (no matter which transport
> +actually used), no other buses or additional platform driver logic required.
> +
> +===================
> +Protocol layout
> +===================
> +
> +----------------------
> +Configuration space
> +----------------------
> +
> ++--------+----------+-------------------------------+
> +| Offset | Type | Description |
> ++========+==========+===============================+
> +| 0x00 | u8 | version |
> ++--------+----------+-------------------------------+
> +| 0x02 | u16 | number of GPIO lines |
> ++--------+----------+-------------------------------+
> +| 0x04 | u32 | size of gpio name block |
> ++--------+----------+-------------------------------+
> +| 0x20 | char[32] | device name (0-terminated) |
> ++--------+----------+-------------------------------+
> +| 0x40 | char[] | line names block |
> ++--------+----------+-------------------------------+
> +
> +- for version field currently only value 1 supported.
> +- the line names block holds a stream of zero-terminated strings,
> + holding the individual line names.
> +- unspecified fields are reserved for future use and should be zero.
> +
> +------------------------
> +Virtqueues and messages:
> +------------------------
> +
> +- Queue #0: transmission from device to cpu

CPU

> +- Queue #1: transmission from cpu to device

CPU

> +
> +The queues transport messages of the struct virtio_gpio_msg:
> +
> +Message format:
> +---------------
> +
> ++--------+----------+---------------+
> +| Offset | Type | Description |
> ++========+==========+===============+
> +| 0x00 | uint16 | event type |
> ++--------+----------+---------------+
> +| 0x02 | uint16 | line id |
> ++--------+----------+---------------+
> +| 0x04 | uint32 | value |
> ++--------+----------+---------------+
> +
> +Message types:
> +--------------

Do the Message types go into the "event type" field above?
Please clarify.

> +
> ++-------+----------------------------------------+-----------------------------+
> +| Code | Symbol | |
> ++=======+========================================+=============================+
> +| 0x01 | VIRTIO_GPIO_MSG_GUEST_REQUEST | request gpio line |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x02 | VIRTIO_GPIO_MSG_GUEST_DIRECTION_INPUT | set direction to input |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x03 | VIRTIO_GPIO_MSG_GUEST_DIRECTION_OUTPUT | set direction to output |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x04 | VIRTIO_GPIO_MSG_GUEST_GET_DIRECTION | read current direction |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x05 | VIRTIO_GPIO_MSG_GUEST_GET_VALUE | read current level |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x06 | VIRTIO_GPIO_MSG_GUEST_SET_VALUE | set current (out) level |
> ++-------+---------------------------------------+-----------------------------+
> +| 0x11 | VIRTIO_GPIO_MSG_HOST_LEVEL | state changed (host->guest) |
> ++-------+----------------+-----------------------+-----------------------------+
> +
> +----------------------
> +Data flow:
> +----------------------
> +
> +- all operations, except ``VIRTIO_GPIO_MSG_HOST_LEVEL``, are guest-initiated
> +- host replies ``VIRTIO_GPIO_MSG_HOST_LEVEL`` OR'ed to the ``type`` field
> +- ``VIRTIO_GPIO_MSG_HOST_LEVEL`` is only sent asynchronically from host to guest

asynchronously

> +- in replies, a negative ``value`` field denotes an unix-style errno code

a Unix-style

> +- valid direction values are:> + * 0 = output
> + * 1 = input
> +- valid line state values are:
> + * 0 = inactive
> + * 1 = active
> +
> +VIRTIO_GPIO_MSG_GUEST_REQUEST
> +----------------------------
> +
> +- notify the host that given line# is going to be used
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: unused
> +- reply:
> + * ``value`` field: errno code (0 = success)
> +
> +VIRTIO_GPIO_MSG_GUEST_DIRECTION_INPUT
> +------------------------------------
> +
> +- set line line direction to input
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: unused
> +- reply: value field holds errno
> + * ``value`` field: errno code (0 = success)
> +
> +VIRTIO_GPIO_MSG_GUEST_DIRECTION_OUTPUT
> +-------------------------------------
> +
> +- set line direction to output and given line state
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: output state (0=inactive, 1=active)
> +- reply:
> + * ``value`` field: holds errno
> +
> +VIRTIO_GPIO_MSG_GUEST_GET_DIRECTION
> +----------------------------------
> +
> +- retrieve line direction
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: unused
> +- reply:
> + * ``value`` field: direction (0=output, 1=input) or errno code
> +
> +VIRTIO_GPIO_MSG_GUEST_GET_VALUE
> +------------------------------
> +
> +- retrieve line state value
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: unused
> +- reply:
> + * ``value`` field: line state (0=inactive, 1=active) or errno code
> +
> +VIRTIO_GPIO_MSG_GUEST_SET_VALUE
> +------------------------------
> +
> +- set line state value (output only)
> +- request:
> + * ``line`` field: line number
> + * ``value`` field: line state (0=inactive, 1=active)
> +- reply:
> + * ``value`` field: new line state or errno code
> +
> +VIRTIO_GPIO_MSG_HOST_LEVEL
> +-------------------------
> +
> +- async notification from host to gues: line state changed

guest:

> +- ``line`` field: line number
> +- ``value`` field: new line state (0=inactive, 1=active)


--
~Randy