gpu: nvgpu: acquire mutex for notifier read
Deepak Nibade [Mon, 27 Feb 2017 10:53:21 +0000 (15:53 +0530)]
We use &ch->error_notifier_mutex to protect writes and free of error
notifier. But we currently do not protect reading of notifier in
gk20a_fifo_set_ctx_mmu_error() and vgpu_fifo_set_ctx_mmu_error().
Add new API gk20a_set_error_notifier_locked() which is same as
gk20a_set_error_notifier() but without the locks.
In *_fifo_set_ctx_mmu_error() APIs, acquire the mutex explicitly,
and then use this new API gk20a_set_error_notifier() will now just
call gk20a_set_error_notifier_locked() within a mutex

Bug 1824788
Bug 1844312
Bug 200270206

Change-Id: I1f3831dc63fe1daa761b2e17e4de3c155f505d6f
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Signed-off-by: Gagan Grover <ggrover@nvidia.com>
Reviewed-on: http://git-master/r/1273471
(cherry picked from commit 505b442551a2e27aa3bc9e608c5a2bc9fccecbc4)
Reviewed-on: http://git-master/r/1311857
Reviewed-on: http://git-master/r/1324991
GVS: Gerrit_Virtual_Submit
Tested-by: Sandipan Patra <spatra@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>

drivers/gpu/nvgpu/gk20a/channel_gk20a.c
drivers/gpu/nvgpu/gk20a/channel_gk20a.h
drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
drivers/gpu/nvgpu/vgpu/fifo_vgpu.c

index d53e45d..b9ca9d1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A Graphics channel
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -638,11 +638,12 @@ static int gk20a_init_error_notifier(struct channel_gk20a *ch,
        return 0;
 }
 
-void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error)
+/**
+ * gk20a_set_error_notifier_locked()
+ * Should be called with ch->error_notifier_mutex held
+ */
+void gk20a_set_error_notifier_locked(struct channel_gk20a *ch, __u32 error)
 {
-       bool notifier_set = false;
-
-       mutex_lock(&ch->error_notifier_mutex);
        if (ch->error_notifier_ref) {
                struct timespec time_data;
                u64 nsec;
@@ -656,13 +657,16 @@ void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error)
                ch->error_notifier->info32 = error;
                ch->error_notifier->status = 0xffff;
 
-               notifier_set = true;
-       }
-       mutex_unlock(&ch->error_notifier_mutex);
-
-       if (notifier_set)
                gk20a_err(dev_from_gk20a(ch->g),
                    "error notifier set to %d for ch %d", error, ch->hw_chid);
+       }
+}
+
+void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error)
+{
+       mutex_lock(&ch->error_notifier_mutex);
+       gk20a_set_error_notifier_locked(ch, error);
+       mutex_unlock(&ch->error_notifier_mutex);
 }
 
 static void gk20a_free_error_notifiers(struct channel_gk20a *ch)
index 465fe64..ee9598c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A graphics channel
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -206,6 +206,7 @@ void gk20a_disable_channel(struct channel_gk20a *ch);
 void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
 int gk20a_channel_finish(struct channel_gk20a *ch, unsigned long timeout);
 void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error);
+void gk20a_set_error_notifier_locked(struct channel_gk20a *ch, __u32 error);
 void gk20a_channel_semaphore_wakeup(struct gk20a *g);
 int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 size,
                             struct priv_cmd_entry **entry);
index 7bd98f5..ae02ee5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A Graphics FIFO (gr host)
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -829,7 +829,8 @@ static bool gk20a_fifo_set_ctx_mmu_error(struct gk20a *g,
        if (!ch)
                return verbose;
 
-       if (ch->error_notifier) {
+       mutex_lock(&ch->error_notifier_mutex);
+       if (ch->error_notifier_ref) {
                u32 err = ch->error_notifier->info32;
                if (ch->error_notifier->status == 0xffff) {
                        /* If error code is already set, this mmu fault
@@ -840,10 +841,12 @@ static bool gk20a_fifo_set_ctx_mmu_error(struct gk20a *g,
                        if (err == NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT)
                                verbose = ch->timeout_debug_dump;
                } else {
-                       gk20a_set_error_notifier(ch,
+                       gk20a_set_error_notifier_locked(ch,
                                NVGPU_CHANNEL_FIFO_ERROR_MMU_ERR_FLT);
                }
        }
+       mutex_unlock(&ch->error_notifier_mutex);
+
        /* mark channel as faulted */
        ch->has_timedout = true;
        wmb();
index 343d86e..a5c5b46 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Virtualized GPU Fifo
  *
- * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -508,17 +508,20 @@ static int vgpu_fifo_wait_engine_idle(struct gk20a *g)
 static void vgpu_fifo_set_ctx_mmu_error(struct gk20a *g,
                struct channel_gk20a *ch)
 {
-       if (ch->error_notifier) {
+       mutex_lock(&ch->error_notifier_mutex);
+       if (ch->error_notifier_ref) {
                if (ch->error_notifier->status == 0xffff) {
                        /* If error code is already set, this mmu fault
                         * was triggered as part of recovery from other
                         * error condition.
                         * Don't overwrite error flag. */
                } else {
-                       gk20a_set_error_notifier(ch,
+                       gk20a_set_error_notifier_locked(ch,
                                NVGPU_CHANNEL_FIFO_ERROR_MMU_ERR_FLT);
                }
        }
+       mutex_unlock(&ch->error_notifier_mutex);
+
        /* mark channel as faulted */
        ch->has_timedout = true;
        wmb();