From: Dmitry Osipenko <dig...@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 <dig...@gmail.com>
Signed-off-by: Thierry Reding <tred...@nvidia.com>
Signed-off-by: Sasha Levin <sas...@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;
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to