Skip to content

Commit

Permalink
gpu: host1x: Request syncpoint IRQs only during probe
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cyndis authored and thierryreding committed Aug 28, 2024
1 parent bad928d commit 4c27ac4
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 35 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/host1x/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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 {
Expand Down
37 changes: 3 additions & 34 deletions drivers/gpu/host1x/hw/intr_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
};
21 changes: 20 additions & 1 deletion drivers/gpu/host1x/intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

#include <linux/clk.h>

#include <linux/interrupt.h>
#include "dev.h"
#include "fence.h"
#include "intr.h"
Expand Down Expand Up @@ -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);

Expand All @@ -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;
}

Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/host1x/intr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
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);

Expand Down

0 comments on commit 4c27ac4

Please sign in to comment.