diff options
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 34 | ||||
-rw-r--r-- | drivers/gpu/host1x/job.c | 15 | ||||
-rw-r--r-- | include/linux/host1x.h | 17 |
3 files changed, 52 insertions, 14 deletions
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index d2f88cc3134f..564ef60f67c2 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -27,17 +27,43 @@ static void tegra_bo_put(struct host1x_bo *bo) drm_gem_object_put_unlocked(&obj->gem); } -static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) +static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo, + dma_addr_t *phys) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); + struct sg_table *sgt; + int err; + + if (phys) + *phys = obj->iova; - *sgt = obj->sgt; + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); - return obj->iova; + if (obj->pages) { + err = sg_alloc_table_from_pages(sgt, obj->pages, obj->num_pages, + 0, obj->gem.size, GFP_KERNEL); + if (err < 0) + goto free; + } else { + err = dma_get_sgtable(dev, sgt, obj->vaddr, obj->iova, + obj->gem.size); + if (err < 0) + goto free; + } + + return sgt; + +free: + kfree(sgt); + return ERR_PTR(err); } -static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt) +static void tegra_bo_unpin(struct device *dev, struct sg_table *sgt) { + sg_free_table(sgt); + kfree(sgt); } static void *tegra_bo_mmap(struct host1x_bo *bo) diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index eaa5c3352c13..90dd592fdfca 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -99,6 +99,7 @@ EXPORT_SYMBOL(host1x_job_add_gather); static unsigned int pin_job(struct host1x *host, struct host1x_job *job) { + struct device *dev = job->client->dev; unsigned int i; int err; @@ -115,7 +116,11 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } - phys_addr = host1x_bo_pin(reloc->target.bo, &sgt); + sgt = host1x_bo_pin(dev, reloc->target.bo, &phys_addr); + if (IS_ERR(sgt)) { + err = PTR_ERR(sgt); + goto unpin; + } job->addr_phys[job->num_unpins] = phys_addr; job->unpins[job->num_unpins].bo = reloc->target.bo; @@ -139,7 +144,11 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } - phys_addr = host1x_bo_pin(g->bo, &sgt); + sgt = host1x_bo_pin(host->dev, g->bo, &phys_addr); + if (IS_ERR(sgt)) { + err = PTR_ERR(sgt); + goto unpin; + } if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { for_each_sg(sgt->sgl, sg, sgt->nents, j) @@ -566,7 +575,7 @@ void host1x_job_unpin(struct host1x_job *job) iova_pfn(&host->iova, job->addr_phys[i])); } - host1x_bo_unpin(unpin->bo, unpin->sgt); + host1x_bo_unpin(host->dev, unpin->bo, unpin->sgt); host1x_bo_put(unpin->bo); } diff --git a/include/linux/host1x.h b/include/linux/host1x.h index df6e613ba715..1ba23a6a2021 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -67,8 +67,9 @@ struct sg_table; struct host1x_bo_ops { struct host1x_bo *(*get)(struct host1x_bo *bo); void (*put)(struct host1x_bo *bo); - dma_addr_t (*pin)(struct host1x_bo *bo, struct sg_table **sgt); - void (*unpin)(struct host1x_bo *bo, struct sg_table *sgt); + struct sg_table *(*pin)(struct device *dev, struct host1x_bo *bo, + dma_addr_t *phys); + void (*unpin)(struct device *dev, struct sg_table *sgt); void *(*mmap)(struct host1x_bo *bo); void (*munmap)(struct host1x_bo *bo, void *addr); void *(*kmap)(struct host1x_bo *bo, unsigned int pagenum); @@ -95,15 +96,17 @@ static inline void host1x_bo_put(struct host1x_bo *bo) bo->ops->put(bo); } -static inline dma_addr_t host1x_bo_pin(struct host1x_bo *bo, - struct sg_table **sgt) +static inline struct sg_table *host1x_bo_pin(struct device *dev, + struct host1x_bo *bo, + dma_addr_t *phys) { - return bo->ops->pin(bo, sgt); + return bo->ops->pin(dev, bo, phys); } -static inline void host1x_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt) +static inline void host1x_bo_unpin(struct device *dev, struct host1x_bo *bo, + struct sg_table *sgt) { - bo->ops->unpin(bo, sgt); + bo->ops->unpin(dev, sgt); } static inline void *host1x_bo_mmap(struct host1x_bo *bo) |