diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 4b90f58f..424c8a67 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -706,6 +706,46 @@ static int host1x_get_assigned_resources(struct host1x *host) return 0; } +static int host1x_get_syncpt_pools(struct host1x *host) +{ + struct device_node *np = host->dev->of_node; + int err, i; + + err = of_property_count_strings(np, "nvidia,syncpoint-pool-names"); + if (err == -EINVAL) + return 0; + if (err < 0) { + dev_err(host->dev, "invalid nvidia,syncpoint-pool-names property: %d\n", err); + return err; + } + + host->num_pools = err; + host->pools = devm_kcalloc(host->dev, host->num_pools, sizeof(struct host1x_syncpt_pool), + GFP_KERNEL); + if (!host->pools) + return -ENOMEM; + + for (i = 0; i < host->num_pools; i++) { + struct host1x_syncpt_pool *pool = &host->pools[i]; + + err = of_property_read_string_index(np, "nvidia,syncpoint-pool-names", i, &pool->name); + if (err) + return err; + + err = of_property_read_u32_index(np, "nvidia,syncpoint-pools", i*2+0, &pool->base); + if (!err) + err = of_property_read_u32_index(np, "nvidia,syncpoint-pools", i*2+1, &pool->end); + if (err) { + dev_err(host->dev, "invalid nvidia,syncpoint-pools property: %d\n", err); + return err; + } + + pool->end = pool->base + pool->end; + } + + return 0; +} + static int host1x_probe(struct platform_device *pdev) { struct host1x *host; @@ -768,6 +808,10 @@ static int host1x_probe(struct platform_device *pdev) if (err) return err; + err = host1x_get_syncpt_pools(host); + if (err) + return err; + host->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) { err = PTR_ERR(host->clk); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 87e8c273..25e3f770 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -118,6 +118,12 @@ struct host1x_info { bool reserve_vblank_syncpts; }; +struct host1x_syncpt_pool { + const char *name; + unsigned int base; + unsigned int end; +}; + struct host1x { const struct host1x_info *info; @@ -136,6 +142,10 @@ struct host1x { unsigned int syncpt_base, syncpt_end; unsigned int channel_base, num_channels; + /* Restricted syncpoint pools */ + struct host1x_syncpt_pool *pools; + unsigned int num_pools; + struct iommu_group *group; struct iommu_domain *domain; struct iova_domain iova; diff --git a/drivers/gpu/host1x/include/linux/host1x-next.h b/drivers/gpu/host1x/include/linux/host1x-next.h index 69a4044e..3e67ed56 100644 --- a/drivers/gpu/host1x/include/linux/host1x-next.h +++ b/drivers/gpu/host1x/include/linux/host1x-next.h @@ -198,6 +198,7 @@ static inline void host1x_bo_munmap(struct host1x_bo *bo, void *addr) #define HOST1X_SYNCPT_CLIENT_MANAGED (1 << 0) #define HOST1X_SYNCPT_HAS_BASE (1 << 1) +#define HOST1X_SYNCPT_GPU (1 << 2) struct host1x_syncpt_base; struct host1x_syncpt; diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 26b59b31..9375000f 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -60,17 +60,34 @@ struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, unsigned long flags, const char *name) { - struct host1x_syncpt *sp = host->syncpt; + struct host1x_syncpt *sp = host->syncpt + host->syncpt_base; + struct host1x_syncpt_pool *pool = NULL; char *full_name; unsigned int i; if (!name) return NULL; + if (flags & HOST1X_SYNCPT_GPU) { + for (i = 0; i < host->num_pools; i++) { + if (!strcmp(host->pools[i].name, "gpu")) { + pool = &host->pools[i]; + break; + } + } + + /* If no GPU pool configured, any syncpoint is OK. */ + } + mutex_lock(&host->syncpt_mutex); - for (i = host->syncpt_base; i < host->syncpt_end && kref_read(&sp->ref); i++, sp++) - ; + for (i = host->syncpt_base; i < host->syncpt_end; i++, sp++) { + if (sp->pool != pool) + continue; + + if (kref_read(&sp->ref) == 0) + break; + } if (i >= host->syncpt_end) goto unlock; @@ -322,6 +339,14 @@ int host1x_syncpt_init(struct host1x *host) for (i = 0; i < host->info->nb_bases; i++) bases[i].id = i; + for (i = 0; i < host->num_pools; i++) { + struct host1x_syncpt_pool *pool = &host->pools[i]; + unsigned int j; + + for (j = pool->base; j < pool->end; j++) + syncpt[j].pool = pool; + } + mutex_init(&host->syncpt_mutex); host->syncpt = syncpt; host->bases = bases; @@ -332,9 +357,8 @@ int host1x_syncpt_init(struct host1x *host) * this for anything. */ if (host->syncpt_base == 0) { - host->nop_sp = host1x_syncpt_alloc(host, 0, "reserved-nop"); - if (!host->nop_sp) - return -ENOMEM; + kref_init(&syncpt[0].ref); + syncpt[0].name = kstrdup("reserved", GFP_KERNEL); } if (host->info->reserve_vblank_syncpts) { diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h index 76e12137..03a686f1 100644 --- a/drivers/gpu/host1x/syncpt.h +++ b/drivers/gpu/host1x/syncpt.h @@ -38,6 +38,7 @@ struct host1x_syncpt { bool client_managed; struct host1x *host; struct host1x_syncpt_base *base; + struct host1x_syncpt_pool *pool; /* interrupt data */ struct host1x_fence_list fences;