Skip to content

Commit f017f1e

Browse files
cyndisthierryreding
authored andcommitted
gpu: host1x: Syncpoint interrupt sharding
Support sharded syncpoint interrupts on Tegra234+. This feature allows specifying one of eight interrupt lines for each syncpoint to lower processing latency of syncpoint threshold interrupts. Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230901114008.672433-1-cyndis@kapsi.fi
1 parent b7c00cd commit f017f1e

3 files changed

Lines changed: 61 additions & 17 deletions

File tree

drivers/gpu/host1x/dev.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ static int host1x_get_resets(struct host1x *host)
488488
static int host1x_probe(struct platform_device *pdev)
489489
{
490490
struct host1x *host;
491-
int err;
491+
int err, i;
492492

493493
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
494494
if (!host)
@@ -516,9 +516,30 @@ static int host1x_probe(struct platform_device *pdev)
516516
return PTR_ERR(host->regs);
517517
}
518518

519-
host->syncpt_irq = platform_get_irq(pdev, 0);
520-
if (host->syncpt_irq < 0)
521-
return host->syncpt_irq;
519+
for (i = 0; i < ARRAY_SIZE(host->syncpt_irqs); i++) {
520+
char irq_name[] = "syncptX";
521+
522+
sprintf(irq_name, "syncpt%d", i);
523+
524+
err = platform_get_irq_byname_optional(pdev, irq_name);
525+
if (err == -ENXIO)
526+
break;
527+
if (err < 0)
528+
return err;
529+
530+
host->syncpt_irqs[i] = err;
531+
}
532+
533+
host->num_syncpt_irqs = i;
534+
535+
/* Device tree without irq names */
536+
if (i == 0) {
537+
host->syncpt_irqs[0] = platform_get_irq(pdev, 0);
538+
if (host->syncpt_irqs[0] < 0)
539+
return host->syncpt_irqs[0];
540+
541+
host->num_syncpt_irqs = 1;
542+
}
522543

523544
mutex_init(&host->devices_lock);
524545
INIT_LIST_HEAD(&host->devices);

drivers/gpu/host1x/dev.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ struct host1x {
124124
void __iomem *regs;
125125
void __iomem *hv_regs; /* hypervisor region */
126126
void __iomem *common_regs;
127-
int syncpt_irq;
127+
int syncpt_irqs[8];
128+
int num_syncpt_irqs;
128129
struct host1x_syncpt *syncpt;
129130
struct host1x_syncpt_base *bases;
130131
struct device *dev;

drivers/gpu/host1x/hw/intr_hw.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@
1313
#include "../intr.h"
1414
#include "../dev.h"
1515

16+
struct host1x_intr_irq_data {
17+
struct host1x *host;
18+
u32 offset;
19+
};
20+
1621
static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
1722
{
18-
struct host1x *host = dev_id;
23+
struct host1x_intr_irq_data *irq_data = dev_id;
24+
struct host1x *host = irq_data->host;
1925
unsigned long reg;
2026
unsigned int i, id;
2127

22-
for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
28+
for (i = irq_data->offset; i < DIV_ROUND_UP(host->info->nb_pts, 32);
29+
i += host->num_syncpt_irqs) {
2330
reg = host1x_sync_readl(host,
2431
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
2532

@@ -67,26 +74,41 @@ static void intr_hw_init(struct host1x *host, u32 cpm)
6774

6875
/*
6976
* Program threshold interrupt destination among 8 lines per VM,
70-
* per syncpoint. For now, just direct all to the first interrupt
71-
* line.
77+
* per syncpoint. For each group of 32 syncpoints (corresponding to one
78+
* interrupt status register), direct to one interrupt line, going
79+
* around in a round robin fashion.
7280
*/
73-
for (id = 0; id < host->info->nb_pts; id++)
74-
host1x_sync_writel(host, 0, HOST1X_SYNC_SYNCPT_INTR_DEST(id));
81+
for (id = 0; id < host->info->nb_pts; id++) {
82+
u32 reg_offset = id / 32;
83+
u32 irq_index = reg_offset % host->num_syncpt_irqs;
84+
85+
host1x_sync_writel(host, irq_index, HOST1X_SYNC_SYNCPT_INTR_DEST(id));
86+
}
7587
#endif
7688
}
7789

7890
static int
7991
host1x_intr_init_host_sync(struct host1x *host, u32 cpm)
8092
{
81-
int err;
93+
int err, i;
94+
struct host1x_intr_irq_data *irq_data;
95+
96+
irq_data = devm_kcalloc(host->dev, host->num_syncpt_irqs, sizeof(irq_data[0]), GFP_KERNEL);
97+
if (!irq_data)
98+
return -ENOMEM;
8299

83100
host1x_hw_intr_disable_all_syncpt_intrs(host);
84101

85-
err = devm_request_irq(host->dev, host->syncpt_irq,
86-
syncpt_thresh_isr, IRQF_SHARED,
87-
"host1x_syncpt", host);
88-
if (err < 0)
89-
return err;
102+
for (i = 0; i < host->num_syncpt_irqs; i++) {
103+
irq_data[i].host = host;
104+
irq_data[i].offset = i;
105+
106+
err = devm_request_irq(host->dev, host->syncpt_irqs[i],
107+
syncpt_thresh_isr, IRQF_SHARED,
108+
"host1x_syncpt", &irq_data[i]);
109+
if (err < 0)
110+
return err;
111+
}
90112

91113
intr_hw_init(host, cpm);
92114

0 commit comments

Comments
 (0)