[PATCH] gpio: virtio: convert to immutable irq_chip
From: Francesco Valla
Date: Tue Oct 27 2026 - 09:20:21 EST
The kernel has been warning about non-immutable irq_chips for quite some
time, printing messages such as the following one during initialization:
gpio gpiochip6: (virtio2): not an immutable chip, please consider fixing it!
Convert the gpio-virtio irq_chip to immutable and add the relevant
helpers. The exposed name is kept the same as before through the
.irq_print_chip callback.
Signed-off-by: Francesco Valla <francesco@xxxxxxxx>
---
drivers/gpio/gpio-virtio.c | 41 ++++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/drivers/gpio/gpio-virtio.c b/drivers/gpio/gpio-virtio.c
index ed6e0e90fa8a..d443b8c0e813 100644
--- a/drivers/gpio/gpio-virtio.c
+++ b/drivers/gpio/gpio-virtio.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/virtio_config.h>
#include <uapi/linux/virtio_gpio.h>
@@ -243,6 +244,8 @@ static void virtio_gpio_irq_enable(struct irq_data *d)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
+ gpiochip_enable_irq(gc, d->hwirq);
+
raw_spin_lock(&vgpio->eventq_lock);
irq_line->disabled = false;
irq_line->masked = false;
@@ -265,6 +268,8 @@ static void virtio_gpio_irq_disable(struct irq_data *d)
raw_spin_unlock(&vgpio->eventq_lock);
irq_line->update_pending = true;
+
+ gpiochip_disable_irq(gc, d->hwirq);
}
static void virtio_gpio_irq_mask(struct irq_data *d)
@@ -532,11 +537,30 @@ static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
return names;
}
+static void virtio_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ seq_puts(p, dev_name(gc->parent));
+}
+
+static const struct irq_chip virtio_gpio_irqchip = {
+ .irq_enable = virtio_gpio_irq_enable,
+ .irq_disable = virtio_gpio_irq_disable,
+ .irq_mask = virtio_gpio_irq_mask,
+ .irq_unmask = virtio_gpio_irq_unmask,
+ .irq_set_type = virtio_gpio_irq_set_type,
+ .irq_bus_lock = virtio_gpio_irq_bus_lock,
+ .irq_bus_sync_unlock = virtio_gpio_irq_bus_sync_unlock,
+ .irq_print_chip = virtio_gpio_irq_print_chip,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
static int virtio_gpio_probe(struct virtio_device *vdev)
{
struct device *dev = &vdev->dev;
struct virtio_gpio *vgpio;
- struct irq_chip *gpio_irq_chip;
u32 gpio_names_size;
u16 ngpio;
int ret, i;
@@ -588,26 +612,13 @@ static int virtio_gpio_probe(struct virtio_device *vdev)
if (!vgpio->irq_lines)
return -ENOMEM;
- gpio_irq_chip = devm_kzalloc(dev, sizeof(*gpio_irq_chip), GFP_KERNEL);
- if (!gpio_irq_chip)
- return -ENOMEM;
-
- gpio_irq_chip->name = dev_name(dev);
- gpio_irq_chip->irq_enable = virtio_gpio_irq_enable;
- gpio_irq_chip->irq_disable = virtio_gpio_irq_disable;
- gpio_irq_chip->irq_mask = virtio_gpio_irq_mask;
- gpio_irq_chip->irq_unmask = virtio_gpio_irq_unmask;
- gpio_irq_chip->irq_set_type = virtio_gpio_irq_set_type;
- gpio_irq_chip->irq_bus_lock = virtio_gpio_irq_bus_lock;
- gpio_irq_chip->irq_bus_sync_unlock = virtio_gpio_irq_bus_sync_unlock;
-
/* The event comes from the outside so no parent handler */
vgpio->gc.irq.parent_handler = NULL;
vgpio->gc.irq.num_parents = 0;
vgpio->gc.irq.parents = NULL;
vgpio->gc.irq.default_type = IRQ_TYPE_NONE;
vgpio->gc.irq.handler = handle_level_irq;
- vgpio->gc.irq.chip = gpio_irq_chip;
+ gpio_irq_chip_set_chip(&vgpio->gc.irq, &virtio_gpio_irqchip);
for (i = 0; i < ngpio; i++) {
vgpio->irq_lines[i].type = VIRTIO_GPIO_IRQ_TYPE_NONE;
---
base-commit: d135ab453a7400a34930bdda1ef4bdc8acfac80e
change-id: 20261018-virtio-gpio-irqchip-immutable-9b69717cba4c
Best regards,
--
Francesco Valla <francesco@xxxxxxxx>