diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2020-06-29 06:18:40 +0300 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2020-07-17 17:06:14 +0300 |
commit | fd323e9ef0a19112c0c85b85afc4848c0518174b (patch) | |
tree | cfa77c0645c6e90d26c89e5b5aa765a2353557d9 /drivers/gpu/host1x | |
parent | 26c8de5e5dea6f42bb5553ad09aaa94b6139a77b (diff) | |
download | linux-fd323e9ef0a19112c0c85b85afc4848c0518174b.tar.xz |
gpu: host1x: Put gather's BO on pinning error
This patch fixes gather's BO refcounting on a pinning error. Gather's BO
won't be leaked now if something goes wrong.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r-- | drivers/gpu/host1x/job.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index a954bd41aa79..89b6c14b7392 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -105,6 +105,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) { struct host1x_client *client = job->client; struct device *dev = client->dev; + struct host1x_job_gather *g; struct iommu_domain *domain; unsigned int i; int err; @@ -194,7 +195,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) return 0; for (i = 0; i < job->num_gathers; i++) { - struct host1x_job_gather *g = &job->gathers[i]; size_t gather_size = 0; struct scatterlist *sg; struct sg_table *sgt; @@ -204,6 +204,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) dma_addr_t *phys; unsigned int j; + g = &job->gathers[i]; g->bo = host1x_bo_get(g->bo); if (!g->bo) { err = -EINVAL; @@ -223,7 +224,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) sgt = host1x_bo_pin(host->dev, g->bo, phys); if (IS_ERR(sgt)) { err = PTR_ERR(sgt); - goto unpin; + goto put; } if (host->domain) { @@ -236,7 +237,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) host->iova_end >> shift, true); if (!alloc) { err = -ENOMEM; - goto unpin; + goto put; } err = iommu_map_sg(host->domain, @@ -245,7 +246,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) if (err == 0) { __free_iova(&host->iova, alloc); err = -EINVAL; - goto unpin; + goto put; } job->unpins[job->num_unpins].size = gather_size; @@ -255,7 +256,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) DMA_TO_DEVICE); if (!err) { err = -ENOMEM; - goto unpin; + goto put; } job->unpins[job->num_unpins].dir = DMA_TO_DEVICE; @@ -273,6 +274,8 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) return 0; +put: + host1x_bo_put(g->bo); unpin: host1x_job_unpin(job); return err; |