gpu: nvgpu: acquire mutex for notifier read

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

Change-Id: I1f3831dc63fe1daa761b2e17e4de3c155f505d6f
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1273471
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Richard Zhao <rizhao@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
This commit is contained in:
Deepak Nibade
2016-12-19 16:31:43 +05:30
committed by mobile promotions
parent f3d2dd4fd2
commit 505b442551
4 changed files with 24 additions and 13 deletions

View File

@@ -827,11 +827,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;
@@ -845,13 +846,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)

View File

@@ -235,6 +235,7 @@ void gk20a_disable_channel(struct channel_gk20a *ch);
void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
void gk20a_channel_abort_clean_up(struct channel_gk20a *ch);
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, bool post_events);
int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 size,
struct priv_cmd_entry *entry);

View File

@@ -1219,7 +1219,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
@@ -1230,10 +1231,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();

View File

@@ -678,17 +678,20 @@ static int vgpu_fifo_force_reset_ch(struct channel_gk20a *ch,
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();