[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: [PATCH V10] virtio-gpio: Add support for interrupts
This patch adds support for interrupts to the virtio-gpio specification.
This uses the feature bit 0 for the same.
Fixes: https://github.com/oasis-tcs/virtio-spec/issues/114
Cc: Marc Zyngier <maz@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
V9 -> V10:
- Mandatory for the interrupt to be enabled before being unmasked.
- Remove unnecessary stuff from Device Initialization and clean it up.
- Minor cleanup (s/enabled/negotiated, etc).
V8 -> V9:
- The patch for base GPIO specification is already merged, sending this
separately now.
- Differentiate properly between enabling/disabling and masking/unmasking of the
interrupt.
- Specify how a trigger type should be changed, i.e. by disabling interrupt
first.
- No fixed sequence for enabling/unmasking of the interrupt, any of them can be
done first. The interrupt is only delivered once it is enabled and unmasked.
- Use normative text only in normative sections.
- Guest side Linux driver's IRQ implementation:
https://lore.kernel.org/linux-gpio/96223fb8143a4eaa9b183d376ff46e5cd8ef54b4.1628590591.git.viresh.kumar@linaro.org/
conformance.tex | 2 +
virtio-gpio.tex | 245 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 246 insertions(+), 1 deletion(-)
diff --git a/conformance.tex b/conformance.tex
index c52f1a40be2d..64bcc12d1199 100644
--- a/conformance.tex
+++ b/conformance.tex
@@ -310,6 +310,7 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets}
\begin{itemize}
\item \ref{drivernormative:Device Types / GPIO Device / requestq Operation}
+\item \ref{drivernormative:Device Types / GPIO Device / eventq Operation}
\end{itemize}
\conformance{\section}{Device Conformance}\label{sec:Conformance / Device Conformance}
@@ -568,6 +569,7 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets}
\begin{itemize}
\item \ref{devicenormative:Device Types / GPIO Device / requestq Operation}
+\item \ref{devicenormative:Device Types / GPIO Device / eventq Operation}
\end{itemize}
\conformance{\section}{Legacy Interface: Transitional Device and Transitional Driver Conformance}\label{sec:Conformance / Legacy Interface: Transitional Device and Transitional Driver Conformance}
diff --git a/virtio-gpio.tex b/virtio-gpio.tex
index 3c614ec97b92..55c553f92a14 100644
--- a/virtio-gpio.tex
+++ b/virtio-gpio.tex
@@ -11,11 +11,17 @@ \subsection{Virtqueues}\label{sec:Device Types / GPIO Device / Virtqueues}
\begin{description}
\item[0] requestq
+\item[1] eventq
\end{description}
+The \field{eventq} virtqueue is available only if the \field{VIRTIO_GPIO_F_IRQ}
+feature is offered by the device.
+
\subsection{Feature bits}\label{sec:Device Types / GPIO Device / Feature bits}
-None currently defined.
+\begin{description}
+\item[VIRTIO_GPIO_F_IRQ (0)] The device supports interrupts on GPIO lines.
+\end{description}
\subsection{Device configuration layout}\label{sec:Device Types / GPIO Device / Device configuration layout}
@@ -46,6 +52,9 @@ \subsection{Device Initialization}\label{sec:Device Types / GPIO Device / Device
\begin{itemize}
\item The driver configures and initializes the \field{requestq} virtqueue.
+
+\item The driver configures and initializes the \field{eventq} virtqueue, if the
+ \field{VIRTIO_GPIO_F_IRQ} feature has been negotiated.
\end{itemize}
\subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / requestq Operation}
@@ -105,11 +114,20 @@ \subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / r
#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003
#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004
#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005
+#define VIRTIO_GPIO_MSG_SET_IRQ_TYPE 0x0006
/* GPIO Direction types */
#define VIRTIO_GPIO_DIRECTION_NONE 0x00
#define VIRTIO_GPIO_DIRECTION_OUT 0x01
#define VIRTIO_GPIO_DIRECTION_IN 0x02
+
+/* GPIO interrupt types */
+#define VIRTIO_GPIO_IRQ_TYPE_NONE 0x00
+#define VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING 0x01
+#define VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING 0x02
+#define VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH 0x03
+#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04
+#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW 0x08
\end{lstlisting}
\subsubsection{requestq Operation: Get Line Names}\label{sec:Device Types / GPIO Device / requestq Operation / Get Line Names}
@@ -270,6 +288,73 @@ \subsubsection{requestq Operation: Set Value}\label{sec:Device Types / GPIO Devi
\hline
\end{tabularx}
+\subsubsection{requestq Operation: Set IRQ Type}\label{sec:Device Types / GPIO Device / requestq Operation / Set IRQ Type}
+
+This request is allowed only if the \field{VIRTIO_GPIO_F_IRQ} feature has been
+negotiated.
+
+The interrupt configuration is divided into two steps, enabling or disabling of
+the interrupt at the device and masking or unmasking of the interrupt for
+delivery at the driver. This request only pertains to enabling or disabling of
+the interrupt at the device, the masking and unmasking of the interrupt is
+handled by a separate request that takes place over the \field{eventq}
+virtqueue.
+
+The driver sends the \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message over the
+\field{requestq} virtqueue to enable or disable interrupt for a GPIO line at
+the device.
+
+The driver sends this message with trigger type set to any valid value other
+than \field{VIRTIO_GPIO_IRQ_TYPE_NONE}, to enable the interrupt for a GPIO line,
+this doesn't unmask the interrupt for delivery at the driver though. For edge
+trigger type, the device should latch the interrupt events from this point
+onward and notify it to the driver once the interrupt is unmasked. For level
+trigger type, the device should notify the driver once the interrupt signal on a
+line is sensed and the interrupt is unmasked for the line.
+
+The driver sends this message with trigger type set to
+\field{VIRTIO_GPIO_IRQ_TYPE_NONE}, to disable the interrupt for a GPIO line. The
+device should discard any latched interrupt event associated with it. In order
+to change the trigger type of an already enabled interrupt, the driver should
+first disable the interrupt and then re-enable it with appropriate trigger type.
+
+The interrupts are masked at initialization and the driver unmasks them by
+queuing a pair of buffers, of type \field{virtio_gpio_irq_request} and
+\field{virtio_gpio_irq_response}, over the \field{eventq} virtqueue for a GPIO
+line. A separate pair of buffers must be queued for each GPIO line, the driver
+wants to configure for interrupts. Once an already enabled interrupt is unmasked
+by the driver, the device can notify the driver of an active interrupt signal on
+the GPIO line. This is done by updating the \field{struct
+virtio_gpio_irq_response} buffer's \field{status} with
+\field{VIRTIO_GPIO_IRQ_STATUS_VALID} and returning the updated buffers to the
+driver. The interrupt is masked automatically at this point until the buffers
+are available again at the device.
+
+The interrupt for a GPIO line should not be unmasked before being enabled by the
+driver.
+
+If the interrupt is disabled by the driver, by setting the trigger type to
+\field{VIRTIO_GPIO_IRQ_TYPE_NONE}, or the interrupt is unmasked without being
+enabled first, the device should return any unused pair of buffers for the GPIO
+line, over the \field{eventq} virtqueue, after setting the \field{status} field
+to \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}. This also masks the interrupt.
+
+\begin{tabularx}{\textwidth}{ |l||X|X|X| }
+\hline
+\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
+\hline
+& \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} & line number & one of \field{VIRTIO_GPIO_IRQ_TYPE_*} \\
+\hline
+\end{tabularx}
+
+\begin{tabularx}{\textwidth}{ |l||X|X| }
+\hline
+\textbf{Response} & \field{status} & \field{value} \\
+\hline
+& \field{VIRTIO_GPIO_STATUS_*} & 0 \\
+\hline
+\end{tabularx}
+
\subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO Device / requestq Operation / Message Flow}
\begin{itemize}
@@ -313,6 +398,20 @@ \subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO D
\item The driver MAY send multiple messages for same or different GPIO lines in
parallel.
+
+\item The driver MUST NOT send IRQ messages if the \field{VIRTIO_GPIO_F_IRQ}
+ feature has not been negotiated.
+
+\item The driver MUST NOT send IRQ messages for a GPIO line configured for
+ output.
+
+\item The driver MUST set the IRQ trigger type to
+ \field{VIRTIO_GPIO_IRQ_TYPE_NONE} once it is done using the GPIO line
+ configured for interrupts.
+
+\item In order to change the trigger type of an already enabled interrupt, the
+ driver MUST first disable the interrupt and then re-enable it with
+ appropriate trigger type.
\end{itemize}
\devicenormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation}
@@ -344,4 +443,148 @@ \subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO D
\item The device MUST discard all state information corresponding to a GPIO
line, once the driver has requested to set its direction to
\field{VIRTIO_GPIO_DIRECTION_NONE}.
+
+\item The device MUST latch an edge interrupt if the interrupt is enabled but
+ still masked.
+
+\item The device MUST NOT latch an level interrupt if the interrupt is enabled
+ but still masked.
+
+\item The device MUST discard any latched interrupt for a GPIO line, once
+ interrupt is disabled for the same.
+\end{itemize}
+
+\subsection{Device Operation: eventq}\label{sec:Device Types / GPIO Device / eventq Operation}
+
+The \field{eventq} virtqueue is used by the driver to unmask the interrupts and
+used by the device to notify the driver of newly sensed interrupts. In order to
+unmask interrupt on a GPIO line, the driver queues a pair of buffers,
+\field{struct virtio_gpio_irq_request} (filled by driver) and \field{struct
+virtio_gpio_irq_response} (to be filled by device later), to the \field{eventq}
+virtqueue. A separate pair of buffers must be queued for each GPIO line, the
+driver wants to configure for interrupts. The device, on sensing an interrupt,
+returns the pair of buffers for the respective GPIO line, which also masks the
+interrupts. The driver can queue the buffers again to unmask the interrupt.
+
+\begin{lstlisting}
+struct virtio_gpio_irq_request {
+ le16 gpio;
+};
+\end{lstlisting}
+
+This structure is filled by the driver and read by the device.
+
+\begin{description}
+\item[\field{gpio}] is the GPIO line number, i.e. 0 <= \field{gpio} <
+ \field{ngpio}.
+\end{description}
+
+\begin{lstlisting}
+struct virtio_gpio_irq_response {
+ u8 status;
+};
+
+/* Possible values of the interrupt status field */
+#define VIRTIO_GPIO_IRQ_STATUS_INVALID 0x0
+#define VIRTIO_GPIO_IRQ_STATUS_VALID 0x1
+\end{lstlisting}
+
+This structure is filled by the device and read by the driver.
+
+\begin{description}
+\item[\field{status}] of the interrupt event,
+ \field{VIRTIO_GPIO_IRQ_STATUS_VALID} on interrupt and
+ \field{VIRTIO_GPIO_IRQ_STATUS_INVALID} to return the buffers back to the
+ driver after interrupt is disabled.
+\end{description}
+
+\subsubsection{eventq Operation: Message Flow}\label{sec:Device Types / GPIO Device / eventq Operation / Message Flow}
+
+\begin{itemize}
+\item The virtio-gpio driver is requested by a client driver to enable interrupt
+ for a GPIO line and configure it to a particular trigger type.
+
+\item The driver sends the \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, over
+ the \field{requestq} virtqueue, and the device configures the GPIO line for
+ the requested trigger type and enables the interrupt. The interrupt is still
+ masked for delivery though. The device shall latch the interrupt from now
+ onward for edge trigger type.
+
+\item The driver unmasks the interrupt by queuing a pair of buffers to the
+ \field{eventq} virtqueue for the GPIO line. The driver can do this before
+ enabling the interrupt as well, though the interrupt must be both unmasked
+ and enabled to get delivered at the driver.
+
+\item The driver notifies the device of the presence of new buffers on the
+ \field{eventq} virtqueue. The interrupt is fully configured at this point.
+
+\item The device, on sensing an active interrupt on the GPIO line, finds the
+ matching buffers (based on GPIO line number) from the \field{eventq}
+ virtqueue and update its \field{struct virtio_gpio_irq_response} buffer's
+ \field{status} with \field{VIRTIO_GPIO_IRQ_STATUS_VALID} and returns the
+ pair of buffers to the device. This results in masking the interrupt as
+ well.
+
+\item The device notifies the driver of the presence of returned buffers on the
+ \field{eventq} virtqueue.
+
+\item If the GPIO line is configured for level interrupts, the device ignores
+ any further interrupt signals on this GPIO line, until the interrupt is
+ unmasked again by the driver by making the buffers available to the device.
+ Once the interrupt is unmasked again and the interrupt on the line is still
+ active, the device shall notify the driver again.
+
+\item If the GPIO line is configured for edge interrupts, the device latches
+ the interrupt received for this GPIO line, until the interrupt is unmasked
+ again by the driver by making the buffers available to the device. Once the
+ interrupt is unmasked again and an interrupt was latched earlier, the
+ device shall notify the driver again.
+
+\item The driver on receiving the notification from the device, processes the
+ interrupt. The interrupt is masked at the device until the buffers are
+ queued again by the driver.
+
+\item In a typical guest operating system kernel, the virtio-gpio driver
+ notifies the client driver, that is associated with this GPIO line, to
+ process the event. In the case of a level triggered interrupt, the client
+ driver shall fully process and acknowledge the event at its source to return
+ the line to its inactive state before the interrupt is unmasked again to
+ avoid a spurious interrupt.
+
+\item Once the interrupt is handled, the driver may queue a pair of buffers for
+ the GPIO line to unmask the interrupt again.
+
+\item The driver can also disable the interrupt by sending the
+ \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, with
+ \field{VIRTIO_GPIO_IRQ_TYPE_NONE} trigger type. In that case, the device
+ shall return the unused pair of buffers for the GPIO line after setting the
+ \field{status} field with \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}.
+\end{itemize}
+
+\drivernormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation}
+
+\begin{itemize}
+\item The driver MUST both enable and unmask the interrupt in order to get
+ notified for the same.
+
+\item The driver MUST enable the interrupt before unmasking it.
+
+\item To unmask the interrupt, the driver MUST queue a separate pair of buffers
+ to the \field{eventq} virtqueue for each GPIO line.
+
+\item The driver MUST NOT add multiple pairs of buffers for the same GPIO line
+ on the \field{eventq} virtqueue.
+\end{itemize}
+
+\devicenormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation}
+
+\begin{itemize}
+\item The device MUST NOT send an interrupt event to the driver for a GPIO
+ line unless the interrupt has been both unmasked and enabled by the
+ driver.
+
+\item On receiving \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, with
+ \field{VIRTIO_GPIO_IRQ_TYPE_NONE} trigger type, the device MUST return the
+ buffers, if they were received earlier, after setting the \field{status}
+ field to \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}.
\end{itemize}
--
2.31.1.272.g89b43f80a514
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]