]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
gpu: host1x: Request syncpoint IRQs only during probe
authorMikko Perttunen <mperttunen@nvidia.com>
Fri, 31 May 2024 07:07:18 +0000 (10:07 +0300)
committerThierry Reding <treding@nvidia.com>
Wed, 28 Aug 2024 15:28:48 +0000 (17:28 +0200)
Syncpoint IRQs are currently requested in a code path that runs
during resume. Due to this, we get multiple overlapping registered
interrupt handlers as host1x is suspended and resumed.

Rearrange interrupt code to only request IRQs during initialization.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240531070719.2138-1-cyndis@kapsi.fi
drivers/gpu/host1x/dev.h
drivers/gpu/host1x/hw/intr_hw.c
drivers/gpu/host1x/intr.c
drivers/gpu/host1x/intr.h

index 925a118db23f5751cbbe50db317e98fd4c543414..92031b240a1796e37dfd3f287b2485c18048bc8b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/device.h>
 #include <linux/iommu.h>
 #include <linux/iova.h>
+#include <linux/irqreturn.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
 
@@ -81,6 +82,7 @@ struct host1x_intr_ops {
        void (*disable_syncpt_intr)(struct host1x *host, unsigned int id);
        void (*disable_all_syncpt_intrs)(struct host1x *host);
        int (*free_syncpt_irq)(struct host1x *host);
+       irqreturn_t (*isr)(int irq, void *dev_id);
 };
 
 struct host1x_sid_entry {
index 9880e0c47235e1c82bae7b329f60e6ac147fffb9..415f8d7e42021b791550ca719adafa088cd34101 100644 (file)
@@ -6,18 +6,11 @@
  * Copyright (c) 2010-2013, NVIDIA Corporation.
  */
 
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
 
 #include "../intr.h"
 #include "../dev.h"
 
-struct host1x_intr_irq_data {
-       struct host1x *host;
-       u32 offset;
-};
-
 static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
 {
        struct host1x_intr_irq_data *irq_data = dev_id;
@@ -54,7 +47,8 @@ static void host1x_intr_disable_all_syncpt_intrs(struct host1x *host)
        }
 }
 
-static void intr_hw_init(struct host1x *host, u32 cpm)
+static int
+host1x_intr_init_host_sync(struct host1x *host, u32 cpm)
 {
 #if HOST1X_HW < 6
        /* disable the ip_busy_timeout. this prevents write drops */
@@ -85,32 +79,6 @@ static void intr_hw_init(struct host1x *host, u32 cpm)
                host1x_sync_writel(host, irq_index, HOST1X_SYNC_SYNCPT_INTR_DEST(id));
        }
 #endif
-}
-
-static int
-host1x_intr_init_host_sync(struct host1x *host, u32 cpm)
-{
-       int err, i;
-       struct host1x_intr_irq_data *irq_data;
-
-       irq_data = devm_kcalloc(host->dev, host->num_syncpt_irqs, sizeof(irq_data[0]), GFP_KERNEL);
-       if (!irq_data)
-               return -ENOMEM;
-
-       host1x_hw_intr_disable_all_syncpt_intrs(host);
-
-       for (i = 0; i < host->num_syncpt_irqs; i++) {
-               irq_data[i].host = host;
-               irq_data[i].offset = i;
-
-               err = devm_request_irq(host->dev, host->syncpt_irqs[i],
-                                      syncpt_thresh_isr, IRQF_SHARED,
-                                      "host1x_syncpt", &irq_data[i]);
-               if (err < 0)
-                       return err;
-       }
-
-       intr_hw_init(host, cpm);
 
        return 0;
 }
@@ -144,4 +112,5 @@ static const struct host1x_intr_ops host1x_intr_ops = {
        .enable_syncpt_intr = host1x_intr_enable_syncpt_intr,
        .disable_syncpt_intr = host1x_intr_disable_syncpt_intr,
        .disable_all_syncpt_intrs = host1x_intr_disable_all_syncpt_intrs,
+       .isr = syncpt_thresh_isr,
 };
index 995bfa980837a475b4faed443c9351b0506e3642..b3285dd101804c59e05b4ea82746d35f3652519d 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <linux/clk.h>
-
+#include <linux/interrupt.h>
 #include "dev.h"
 #include "fence.h"
 #include "intr.h"
@@ -100,7 +100,9 @@ void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id)
 
 int host1x_intr_init(struct host1x *host)
 {
+       struct host1x_intr_irq_data *irq_data;
        unsigned int id;
+       int i, err;
 
        mutex_init(&host->intr_mutex);
 
@@ -111,6 +113,23 @@ int host1x_intr_init(struct host1x *host)
                INIT_LIST_HEAD(&syncpt->fences.list);
        }
 
+       irq_data = devm_kcalloc(host->dev, host->num_syncpt_irqs, sizeof(irq_data[0]), GFP_KERNEL);
+       if (!irq_data)
+               return -ENOMEM;
+
+       host1x_hw_intr_disable_all_syncpt_intrs(host);
+
+       for (i = 0; i < host->num_syncpt_irqs; i++) {
+               irq_data[i].host = host;
+               irq_data[i].offset = i;
+
+               err = devm_request_irq(host->dev, host->syncpt_irqs[i],
+                                      host->intr_op->isr, IRQF_SHARED,
+                                      "host1x_syncpt", &irq_data[i]);
+               if (err < 0)
+                       return err;
+       }
+
        return 0;
 }
 
index 3b5610b525e5867ec279c91b40a2e43c56e0820e..11cdf13e32fe2a19714d33c2ef4b42dbb91294f2 100644 (file)
 struct host1x;
 struct host1x_syncpt_fence;
 
+struct host1x_intr_irq_data {
+       struct host1x *host;
+       u32 offset;
+};
+
 /* Initialize host1x sync point interrupt */
 int host1x_intr_init(struct host1x *host);