]> git.karo-electronics.de Git - linux-beck.git/commitdiff
gpu: host1x: Add locking to syncpt
authorArto Merilainen <amerilainen@nvidia.com>
Tue, 8 Nov 2016 17:51:33 +0000 (19:51 +0200)
committerThierry Reding <treding@nvidia.com>
Fri, 11 Nov 2016 14:33:13 +0000 (15:33 +0100)
Currently syncpoints are not locked by mutex and this causes races
if we are aggressively freeing and allocating syncpoints.

This patch adds missing mutex protection to syncpoint structures.

Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
[treding@nvidia.com: use better label names, don't reset local variable]
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/host1x/dev.h
drivers/gpu/host1x/syncpt.c

index 5220510f39dae91c219b29d40062b3e689fcb815..06dd4f85125fb16a625b2355c55751cc3dbefed2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, NVIDIA Corporation.
+ * Copyright (c) 2012-2015, NVIDIA Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -120,6 +120,7 @@ struct host1x {
 
        struct host1x_syncpt *nop_sp;
 
+       struct mutex syncpt_mutex;
        struct mutex chlist_mutex;
        struct host1x_channel chlist;
        unsigned long allocated_channels;
index 95589328ad52a27a7ba345f097a5740cca67d34f..25c11a85050baf3df430336d87a87dd1af2ef894 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Tegra host1x Syncpoints
  *
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2015, NVIDIA Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -61,22 +61,24 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
        struct host1x_syncpt *sp = host->syncpt;
        char *name;
 
+       mutex_lock(&host->syncpt_mutex);
+
        for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++)
                ;
 
        if (i >= host->info->nb_pts)
-               return NULL;
+               goto unlock;
 
        if (flags & HOST1X_SYNCPT_HAS_BASE) {
                sp->base = host1x_syncpt_base_request(host);
                if (!sp->base)
-                       return NULL;
+                       goto unlock;
        }
 
        name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id,
                        dev ? dev_name(dev) : NULL);
        if (!name)
-               return NULL;
+               goto free_base;
 
        sp->dev = dev;
        sp->name = name;
@@ -86,7 +88,15 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
        else
                sp->client_managed = false;
 
+       mutex_unlock(&host->syncpt_mutex);
        return sp;
+
+free_base:
+       host1x_syncpt_base_free(sp->base);
+       sp->base = NULL;
+unlock:
+       mutex_unlock(&host->syncpt_mutex);
+       return NULL;
 }
 
 u32 host1x_syncpt_id(struct host1x_syncpt *sp)
@@ -378,6 +388,7 @@ int host1x_syncpt_init(struct host1x *host)
        for (i = 0; i < host->info->nb_bases; i++)
                bases[i].id = i;
 
+       mutex_init(&host->syncpt_mutex);
        host->syncpt = syncpt;
        host->bases = bases;
 
@@ -405,12 +416,16 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
        if (!sp)
                return;
 
+       mutex_lock(&sp->host->syncpt_mutex);
+
        host1x_syncpt_base_free(sp->base);
        kfree(sp->name);
        sp->base = NULL;
        sp->dev = NULL;
        sp->name = NULL;
        sp->client_managed = false;
+
+       mutex_unlock(&sp->host->syncpt_mutex);
 }
 EXPORT_SYMBOL(host1x_syncpt_free);