From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit fd323e9ef0a19112c0c85b85afc4848c0518174b ]
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 Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/host1x/job.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index a10643aa89aa5..2ac5a99406d98 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -102,6 +102,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; @@ -184,7 +185,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) }
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; @@ -194,6 +194,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; @@ -213,7 +214,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 (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { @@ -226,7 +227,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, @@ -235,7 +236,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; @@ -245,7 +246,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; @@ -263,6 +264,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;