From a9c6f595399074e88c16f3557e5acb29db1d52d5 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 4 Jan 2016 10:28:04 -0800 Subject: gpu: nvgpu: enable semaphore acquire timeout It'll detect dead semaphore acquire. The worst case is when ACQUIRE_SWITCH is disabled, semaphore acquire will poll and consume full gpu timeslicees. The timeout value is set to half of channel WDT. Bug 1636800 Change-Id: Ida6ccc534006a191513edf47e7b82d4b5b758684 Signed-off-by: Richard Zhao Reviewed-on: http://git-master/r/928827 GVS: Gerrit_Virtual_Submit Reviewed-by: Vladislav Buzov --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 42 +++++++++++++++++++++++++++----- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 3 ++- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 8 +++++- drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h | 22 ++++++++++++++++- drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h | 22 ++++++++++++++++- 5 files changed, 87 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index b480c80a..a5c2efb3 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -1,7 +1,7 @@ /* * GK20A Graphics channel * - * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2016, 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, @@ -62,6 +62,8 @@ static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add); static void gk20a_free_error_notifiers(struct channel_gk20a *ch); +static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch); + /* allocate GPU channel */ static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) { @@ -204,6 +206,38 @@ static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, return 0; } +u32 channel_gk20a_pbdma_acquire_val(struct channel_gk20a *c) +{ + u32 val, exp, man; + u64 timeout; + int val_len; + + timeout = gk20a_get_channel_watchdog_timeout(c); + do_div(timeout, 2); /* set acquire timeout to half of channel wdt */ + timeout *= 1000000UL; /* ms -> ns */ + do_div(timeout, 1024); /* in unit of 1024ns */ + val_len = fls(timeout >> 32) + 32; + if (val_len == 32) + val_len = fls(timeout); + if (val_len > 16 + pbdma_acquire_timeout_exp_max_v()) { /* man: 16bits */ + exp = pbdma_acquire_timeout_exp_max_v(); + man = pbdma_acquire_timeout_man_max_v(); + } else if (val_len > 16) { + exp = val_len - 16; + man = timeout >> exp; + } else { + exp = 0; + man = timeout; + } + + val = pbdma_acquire_retry_man_2_f() | + pbdma_acquire_retry_exp_2_f() | + pbdma_acquire_timeout_exp_f(exp) | + pbdma_acquire_timeout_man_f(man) | + pbdma_acquire_timeout_en_enable_f(); + return val; +} + int channel_gk20a_setup_ramfc(struct channel_gk20a *c, u64 gpfifo_base, u32 gpfifo_entries, u32 flags) { @@ -249,11 +283,7 @@ int channel_gk20a_setup_ramfc(struct channel_gk20a *c, gk20a_mem_wr32(inst_ptr, ram_fc_target_w(), pbdma_target_engine_sw_f()); gk20a_mem_wr32(inst_ptr, ram_fc_acquire_w(), - pbdma_acquire_retry_man_2_f() | - pbdma_acquire_retry_exp_2_f() | - pbdma_acquire_timeout_exp_max_f() | - pbdma_acquire_timeout_man_max_f() | - pbdma_acquire_timeout_en_disable_f()); + channel_gk20a_pbdma_acquire_val(c)); gk20a_mem_wr32(inst_ptr, ram_fc_runlist_timeslice_w(), fifo_runlist_timeslice_timeout_128_f() | diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index f62d2731..ddc517b9 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -1,7 +1,7 @@ /* * GK20A graphics channel * - * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2016, 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, @@ -252,6 +252,7 @@ void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a); void channel_gk20a_disable(struct channel_gk20a *ch); int channel_gk20a_alloc_inst(struct gk20a *g, struct channel_gk20a *ch); void channel_gk20a_free_inst(struct gk20a *g, struct channel_gk20a *ch); +u32 channel_gk20a_pbdma_acquire_val(struct channel_gk20a *c); int channel_gk20a_setup_ramfc(struct channel_gk20a *c, u64 gpfifo_base, u32 gpfifo_entries, u32 flags); void channel_gk20a_enable(struct channel_gk20a *ch); diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 1727cf1d..5c99877b 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -1,7 +1,7 @@ /* * GK20A Graphics FIFO (gr host) * - * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2016, 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, @@ -1642,6 +1642,12 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, pbdma_intr_0); } + if (pbdma_intr_0 & pbdma_intr_0_acquire_pending_f()) { + u32 val = gk20a_readl(g, pbdma_acquire_r(pbdma_id)); + val &= ~pbdma_acquire_timeout_en_enable_f(); + gk20a_writel(g, pbdma_acquire_r(pbdma_id), val); + } + if (pbdma_intr_0 & pbdma_intr_0_pbentry_pending_f()) { gk20a_fifo_reset_pbdma_header(g, pbdma_id); gk20a_fifo_reset_pbdma_method(g, pbdma_id, 0); diff --git a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h index e83dbb5c..79a4ef96 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2016, 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, @@ -274,14 +274,34 @@ static inline u32 pbdma_acquire_retry_exp_2_f(void) { return 0x100; } +static inline u32 pbdma_acquire_timeout_exp_f(u32 v) +{ + return (v & 0xf) << 11; +} +static inline u32 pbdma_acquire_timeout_exp_max_v(void) +{ + return 0x0000000f; +} static inline u32 pbdma_acquire_timeout_exp_max_f(void) { return 0x7800; } +static inline u32 pbdma_acquire_timeout_man_f(u32 v) +{ + return (v & 0xffff) << 15; +} +static inline u32 pbdma_acquire_timeout_man_max_v(void) +{ + return 0x0000ffff; +} static inline u32 pbdma_acquire_timeout_man_max_f(void) { return 0x7fff8000; } +static inline u32 pbdma_acquire_timeout_en_enable_f(void) +{ + return 0x80000000; +} static inline u32 pbdma_acquire_timeout_en_disable_f(void) { return 0x0; diff --git a/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h index c03a377a..19b3bc44 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2016, 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, @@ -262,14 +262,34 @@ static inline u32 pbdma_acquire_retry_exp_2_f(void) { return 0x100; } +static inline u32 pbdma_acquire_timeout_exp_f(u32 v) +{ + return (v & 0xf) << 11; +} +static inline u32 pbdma_acquire_timeout_exp_max_v(void) +{ + return 0x0000000f; +} static inline u32 pbdma_acquire_timeout_exp_max_f(void) { return 0x7800; } +static inline u32 pbdma_acquire_timeout_man_f(u32 v) +{ + return (v & 0xffff) << 15; +} +static inline u32 pbdma_acquire_timeout_man_max_v(void) +{ + return 0x0000ffff; +} static inline u32 pbdma_acquire_timeout_man_max_f(void) { return 0x7fff8000; } +static inline u32 pbdma_acquire_timeout_en_enable_f(void) +{ + return 0x80000000; +} static inline u32 pbdma_acquire_timeout_en_disable_f(void) { return 0x0; -- cgit v1.2.2