FAILED: patch "[PATCH] virtio_mmio: disable IRQ wake before free_irq" failed to apply to 6.6-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x d14d693adb055e98ca705822ba6daebc18602d9a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091637-greeting-apple-1005@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d14d693adb055e98ca705822ba6daebc18602d9a Mon Sep 17 00:00:00 2001
From: Xiong Weimin <[email protected]>
Date: Wed, 5 Aug 2026 11:29:37 +0800
Subject: [PATCH] virtio_mmio: disable IRQ wake before free_irq
When the DT node has "wakeup-source", vm_find_vqs() calls enable_irq_wake() on the shared IRQ, but vm_del_vqs() freed that IRQ without a matching disable_irq_wake(). That leaves a wake reference behind and can warn on later free_irq()/request_irq() cycles.
Record whether enable_irq_wake() succeeded, and disable it in vm_del_vqs() before free_irq().
Message-ID: <[email protected]>
drivers/virtio/virtio_mmio.c +13 -3
@@ -88,6 +88,9 @@ struct virtio_mmio_device {void __iomem *base;unsigned long version; + +/* True if enable_irq_wake() succeeded for the shared IRQ. */ +bool wake_irq_enabled; };/* Configuration interface */
@@ -336,11 +339,17 @@ static void vm_del_vqs(struct virtio_device *vdev) {struct virtio_mmio_device *vm_dev =to_virtio_mmio_device (vdev);struct virtqueue *vq, *n; +int irq =platform_get_irq (vm_dev->pdev,0 );list_for_each_entry_safe (vq, n, &vdev->vqs, list)vm_del_vq (vq); -free_irq (platform_get_irq (vm_dev->pdev,0 ), vm_dev); +if (vm_dev->wake_irq_enabled) { +disable_irq_wake (irq); + vm_dev->wake_irq_enabled = false; + } + +free_irq (irq, vm_dev); }static void vm_synchronize_cbs (struct virtio_device *vdev)
@@ -467,8 +476,9 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs,if (err)return err; -if (of_property_read_bool (vm_dev->pdev->dev.of_node,"wakeup-source" )) -enable_irq_wake (irq); +if (of_property_read_bool (vm_dev->pdev->dev.of_node,"wakeup-source" ) && + !enable_irq_wake (irq)) + vm_dev->wake_irq_enabled = true;for (i =0 ; i < nvqs; ++i) {struct virtqueue_info *vqi = &vqs_info[i];
Sasha Levin
maintainerPATCH 1/2 virtio-mmio: Remove virtqueue list from mmio device
From: Viresh Kumar <[email protected]>
[ Upstream commit 564a69ad90d15c782176e1a8c9e1c95661e1aed0 ]
The MMIO transport implementation creates a list of virtqueues for a virtio device, while the same is already available in the struct virtio_device.
Don't create a duplicate list, and use the other one instead.
While at it, fix the virtio_device_for_each_vq() macro to accept an argument like "&vm_dev->vdev" (which currently fails to build).
Message-Id: <3e56c6f74002987e22f364d883cbad177cd9ad9c.1747827066.git.viresh.kumar@linaro.org>
Stable-dep-of: d14d693adb05 ("virtio_mmio: disable IRQ wake before free_irq")
--- drivers/virtio/virtio_mmio.c | 52 +++--------------------------------- include/linux/virtio.h | 2 +- 2 files changed, 4 insertions(+), 50 deletions(-)
drivers/virtio/virtio_mmio.c +3 -49
@@ -65,7 +65,6 @@#include <linux/platform_device.h> #include <linux/pm.h> #include <linux/slab.h> -#include <linux/spinlock.h> #include <linux/virtio.h> #include <linux/virtio_config.h> #include <uapi/linux/virtio_mmio.h>
@@ -88,22 +87,8 @@ struct virtio_mmio_device {void __iomem *base;unsigned long version; - -/* a list of queues so we can dispatch IRQs */ -spinlock_t lock; -struct list_head virtqueues; -}; - -struct virtio_mmio_vq_info { -/* the actual virtqueue */ -struct virtqueue *vq; - -/* the list node for the virtqueues list */ -struct list_head node; }; - -/* Configuration interface */ static u64 vm_get_features (struct virtio_device *vdev)
@@ -300,9 +285,8 @@ static bool vm_notify_with_data(struct virtqueue *vq)static irqreturn_t vm_interrupt (int irq,void *opaque) {struct virtio_mmio_device *vm_dev = opaque; -struct virtio_mmio_vq_info *info; +struct virtqueue *vq;unsigned long status; -unsigned long flags;irqreturn_t ret =IRQ_NONE ;/* Read and acknowledge interrupts */
@@ -315,10 +299,8 @@ static irqreturn_t vm_interrupt(int irq, void *opaque) }if (likely (status &VIRTIO_MMIO_INT_VRING )) { -spin_lock_irqsave (&vm_dev->lock, flags); -list_for_each_entry (info, &vm_dev->virtqueues, node) - ret |=vring_interrupt (irq, info->vq); -spin_unlock_irqrestore (&vm_dev->lock, flags); +virtio_device_for_each_vq (&vm_dev->vdev, vq) + ret |=vring_interrupt (irq, vq); }return ret;
@@ -329,14 +311,8 @@ static irqreturn_t vm_interrupt(int irq, void *opaque)static void vm_del_vq (struct virtqueue *vq) {struct virtio_mmio_device *vm_dev =to_virtio_mmio_device (vq->vdev); -struct virtio_mmio_vq_info *info = vq->priv; -unsigned long flags;unsigned int index = vq->index; -spin_lock_irqsave (&vm_dev->lock, flags); -list_del (&info->node); -spin_unlock_irqrestore (&vm_dev->lock, flags); -/* Select and deactivate the queue */ writel (index, vm_dev->base +VIRTIO_MMIO_QUEUE_SEL );if (vm_dev->version ==1 ) {
@@ -347,8 +323,6 @@ static void vm_del_vq(struct virtqueue *vq) }vring_del_virtqueue (vq); - -kfree (info); }static void vm_del_vqs (struct virtio_device *vdev)
@@ -375,9 +349,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in {struct virtio_mmio_device *vm_dev =to_virtio_mmio_device (vdev);bool (*notify)(struct virtqueue *vq); -struct virtio_mmio_vq_info *info;struct virtqueue *vq; -unsigned long flags;unsigned int num;int err;
@@ -399,13 +371,6 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in goto error_available; } -/* Allocate and fill out our active queue description */ - info =kmalloc (sizeof (*info),GFP_KERNEL ); -if (!info) { - err = -ENOMEM ; - goto error_kmalloc; - } - num =readl (vm_dev->base +VIRTIO_MMIO_QUEUE_NUM_MAX );if (num ==0 ) { err = -ENOENT ;
@@ -463,13 +428,6 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int inwritel (1 , vm_dev->base +VIRTIO_MMIO_QUEUE_READY ); } - vq->priv = info; - info->vq = vq; - -spin_lock_irqsave (&vm_dev->lock, flags); -list_add (&info->node, &vm_dev->virtqueues); -spin_unlock_irqrestore (&vm_dev->lock, flags); -return vq; error_bad_pfn:
@@ -481,8 +439,6 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int inwritel (0 , vm_dev->base +VIRTIO_MMIO_QUEUE_READY );WARN_ON (readl (vm_dev->base +VIRTIO_MMIO_QUEUE_READY )); } -kfree (info); -error_kmalloc: error_available:return ERR_PTR (err); }
@@ -627,8 +583,6 @@ static int virtio_mmio_probe(struct platform_device *pdev) vm_dev->vdev.dev.release = virtio_mmio_release_dev; vm_dev->vdev.config = &virtio_mmio_config_ops; vm_dev->pdev = pdev; -INIT_LIST_HEAD (&vm_dev->virtqueues); -spin_lock_init (&vm_dev->lock); vm_dev->base =devm_platform_ioremap_resource (pdev,0 );if (IS_ERR (vm_dev->base)) {
include/linux/virtio.h +1 -1
@@ -158,7 +158,7 @@ void virtio_reset_device(struct virtio_device *dev);size_t virtio_max_dma_size (const struct virtio_device *vdev);#define virtio_device_for_each_vq (vdev, vq) \ - list_for_each_entry(vq, &vdev->vqs, list) + list_for_each_entry(vq, &(vdev)->vqs, list)/** * struct virtio_driver - operations for a virtio I/O driver
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 virtio_mmio: disable IRQ wake before free_irq
From: Xiong Weimin <[email protected]>
[ Upstream commit d14d693adb055e98ca705822ba6daebc18602d9a ]
When the DT node has "wakeup-source", vm_find_vqs() calls enable_irq_wake() on the shared IRQ, but vm_del_vqs() freed that IRQ without a matching disable_irq_wake(). That leaves a wake reference behind and can warn on later free_irq()/request_irq() cycles.
Record whether enable_irq_wake() succeeded, and disable it in vm_del_vqs() before free_irq().
Message-ID: <[email protected]>
--- drivers/virtio/virtio_mmio.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
drivers/virtio/virtio_mmio.c +13 -3
@@ -87,6 +87,9 @@ struct virtio_mmio_device {void __iomem *base;unsigned long version; + +/* True if enable_irq_wake() succeeded for the shared IRQ. */ +bool wake_irq_enabled; };/* Configuration interface */
@@ -329,11 +332,17 @@ static void vm_del_vqs(struct virtio_device *vdev) {struct virtio_mmio_device *vm_dev =to_virtio_mmio_device (vdev);struct virtqueue *vq, *n; +int irq =platform_get_irq (vm_dev->pdev,0 );list_for_each_entry_safe (vq, n, &vdev->vqs, list)vm_del_vq (vq); -free_irq (platform_get_irq (vm_dev->pdev,0 ), vm_dev); +if (vm_dev->wake_irq_enabled) { +disable_irq_wake (irq); + vm_dev->wake_irq_enabled = false; + } + +free_irq (irq, vm_dev); }static void vm_synchronize_cbs (struct virtio_device *vdev)
@@ -462,8 +471,9 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs,if (err)return err; -if (of_property_read_bool (vm_dev->pdev->dev.of_node,"wakeup-source" )) -enable_irq_wake (irq); +if (of_property_read_bool (vm_dev->pdev->dev.of_node,"wakeup-source" ) && + !enable_irq_wake (irq)) + vm_dev->wake_irq_enabled = true;for (i =0 ; i < nvqs; ++i) {if (!names[i]) {
Signature · 1 line
2.53.0