[PATCH 2/4] gpu: host1x: Add locking to syncpt
From: Mikko Perttunen <hidden>
Date: 2016-11-08 17:51:33
Also in:
dri-devel
Subsystem:
drm drivers, drm drivers for nvidia tegra, the rest · Maintainers:
David Airlie, Simona Vetter, Thierry Reding, Mikko Perttunen, Linus Torvalds
Possibly related (same subject, not in this thread)
- 2016-11-11 · Re: [PATCH 2/4] gpu: host1x: Add locking to syncpt · Thierry Reding <hidden>
From: Arto Merilainen <redacted> 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 <redacted> Reviewed-by: Shridhar Rasal <redacted> Signed-off-by: Mikko Perttunen <redacted> --- drivers/gpu/host1x/dev.h | 3 ++- drivers/gpu/host1x/syncpt.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 5220510..06dd4f8 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h@@ -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;
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 9558932..f3b04ed 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c@@ -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 err_alloc_syncpt; if (flags & HOST1X_SYNCPT_HAS_BASE) { sp->base = host1x_syncpt_base_request(host); if (!sp->base) - return NULL; + goto err_alloc_base; } name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id, dev ? dev_name(dev) : NULL); if (!name) - return NULL; + goto err_alloc_name; sp->dev = dev; sp->name = name;
@@ -86,7 +88,17 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, else sp->client_managed = false; + mutex_unlock(&host->syncpt_mutex); return sp; + +err_alloc_name: + host1x_syncpt_base_free(sp->base); + sp->base = NULL; +err_alloc_base: + sp = NULL; +err_alloc_syncpt: + mutex_unlock(&host->syncpt_mutex); + return NULL; } u32 host1x_syncpt_id(struct host1x_syncpt *sp)
@@ -378,6 +390,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 +418,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);
--
2.9.3