]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gpu: host1x: Put gather's BO on pinning error
authorDmitry Osipenko <digetx@gmail.com>
Mon, 29 Jun 2020 03:18:40 +0000 (06:18 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Sep 2020 09:29:20 +0000 (11:29 +0200)
[ 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

index a10643aa89aa5afe2581cbd92ac37ad54e9219aa..2ac5a99406d984aa97b2558eeb92afa0e690e549 100644 (file)
@@ -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;