aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2016-11-08 12:51:33 -0500
committerThierry Reding <treding@nvidia.com>2016-11-11 09:33:13 -0500
commitd4b5781890b9329b9e7720f14d3eeb5661348535 (patch)
treea1ce286f7e473f0bd9103f0d59321d1af6d46faf
parentf08ef2d1a1a9aaa756823e847f9eb74f3658393a (diff)
gpu: host1x: Add locking to syncpt
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>
-rw-r--r--drivers/gpu/host1x/dev.h3
-rw-r--r--drivers/gpu/host1x/syncpt.c23
2 files changed, 21 insertions, 5 deletions
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 5220510f39da..06dd4f85125f 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2012-2013, NVIDIA Corporation. 2 * Copyright (c) 2012-2015, NVIDIA Corporation.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -120,6 +120,7 @@ struct host1x {
120 120
121 struct host1x_syncpt *nop_sp; 121 struct host1x_syncpt *nop_sp;
122 122
123 struct mutex syncpt_mutex;
123 struct mutex chlist_mutex; 124 struct mutex chlist_mutex;
124 struct host1x_channel chlist; 125 struct host1x_channel chlist;
125 unsigned long allocated_channels; 126 unsigned long allocated_channels;
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 95589328ad52..25c11a85050b 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Tegra host1x Syncpoints 2 * Tegra host1x Syncpoints
3 * 3 *
4 * Copyright (c) 2010-2013, NVIDIA Corporation. 4 * Copyright (c) 2010-2015, NVIDIA Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * 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,
61 struct host1x_syncpt *sp = host->syncpt; 61 struct host1x_syncpt *sp = host->syncpt;
62 char *name; 62 char *name;
63 63
64 mutex_lock(&host->syncpt_mutex);
65
64 for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++) 66 for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++)
65 ; 67 ;
66 68
67 if (i >= host->info->nb_pts) 69 if (i >= host->info->nb_pts)
68 return NULL; 70 goto unlock;
69 71
70 if (flags & HOST1X_SYNCPT_HAS_BASE) { 72 if (flags & HOST1X_SYNCPT_HAS_BASE) {
71 sp->base = host1x_syncpt_base_request(host); 73 sp->base = host1x_syncpt_base_request(host);
72 if (!sp->base) 74 if (!sp->base)
73 return NULL; 75 goto unlock;
74 } 76 }
75 77
76 name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id, 78 name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id,
77 dev ? dev_name(dev) : NULL); 79 dev ? dev_name(dev) : NULL);
78 if (!name) 80 if (!name)
79 return NULL; 81 goto free_base;
80 82
81 sp->dev = dev; 83 sp->dev = dev;
82 sp->name = name; 84 sp->name = name;
@@ -86,7 +88,15 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
86 else 88 else
87 sp->client_managed = false; 89 sp->client_managed = false;
88 90
91 mutex_unlock(&host->syncpt_mutex);
89 return sp; 92 return sp;
93
94free_base:
95 host1x_syncpt_base_free(sp->base);
96 sp->base = NULL;
97unlock:
98 mutex_unlock(&host->syncpt_mutex);
99 return NULL;
90} 100}
91 101
92u32 host1x_syncpt_id(struct host1x_syncpt *sp) 102u32 host1x_syncpt_id(struct host1x_syncpt *sp)
@@ -378,6 +388,7 @@ int host1x_syncpt_init(struct host1x *host)
378 for (i = 0; i < host->info->nb_bases; i++) 388 for (i = 0; i < host->info->nb_bases; i++)
379 bases[i].id = i; 389 bases[i].id = i;
380 390
391 mutex_init(&host->syncpt_mutex);
381 host->syncpt = syncpt; 392 host->syncpt = syncpt;
382 host->bases = bases; 393 host->bases = bases;
383 394
@@ -405,12 +416,16 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
405 if (!sp) 416 if (!sp)
406 return; 417 return;
407 418
419 mutex_lock(&sp->host->syncpt_mutex);
420
408 host1x_syncpt_base_free(sp->base); 421 host1x_syncpt_base_free(sp->base);
409 kfree(sp->name); 422 kfree(sp->name);
410 sp->base = NULL; 423 sp->base = NULL;
411 sp->dev = NULL; 424 sp->dev = NULL;
412 sp->name = NULL; 425 sp->name = NULL;
413 sp->client_managed = false; 426 sp->client_managed = false;
427
428 mutex_unlock(&sp->host->syncpt_mutex);
414} 429}
415EXPORT_SYMBOL(host1x_syncpt_free); 430EXPORT_SYMBOL(host1x_syncpt_free);
416 431