]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Input: rmi4 - iterative IRQ handler
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 5 May 2026 04:59:36 +0000 (21:59 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 12 Jun 2026 05:39:27 +0000 (22:39 -0700)
The current IRQ handler uses recursion to drain the attention FIFO,
which can lead to stack overflow on deep queues. Convert it to a
loop.

Fixes: b908d3cd812a ("Input: synaptics-rmi4 - allow to add attention data")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-6-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/rmi4/rmi_driver.c

index 3dc7ab61c2693a4f4220f950b089fe9d3497f087..5eda11bcb59c4f2c0deee279abf3dfff4e9048f4 100644 (file)
@@ -198,24 +198,24 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
        struct rmi4_attn_data attn_data = {0};
        int ret, count;
 
-       count = kfifo_get(&drvdata->attn_fifo, &attn_data);
-       if (count) {
-               *(drvdata->irq_status) = attn_data.irq_status;
-               drvdata->attn_data = attn_data;
-       }
-
-       ret = rmi_process_interrupt_requests(rmi_dev);
-       if (ret)
-               rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
-                       "Failed to process interrupt request: %d\n", ret);
+       do {
+               count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+               if (count) {
+                       *drvdata->irq_status = attn_data.irq_status;
+                       drvdata->attn_data = attn_data;
+               }
 
-       if (count) {
-               kfree(attn_data.data);
-               drvdata->attn_data.data = NULL;
-       }
+               ret = rmi_process_interrupt_requests(rmi_dev);
+               if (ret)
+                       rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+                               "Failed to process interrupt request: %d\n",
+                               ret);
 
-       if (!kfifo_is_empty(&drvdata->attn_fifo))
-               return rmi_irq_fn(irq, dev_id);
+               if (count) {
+                       kfree(attn_data.data);
+                       drvdata->attn_data.data = NULL;
+               }
+       } while (!kfifo_is_empty(&drvdata->attn_fifo));
 
        return IRQ_HANDLED;
 }