gpu: nvgpu: Add timeout to L2 flush

Add a timeout mechanism to the L2 flushing code for gm20b.
Previously the code could spin forever in a loop if some
issue were to occur with the L2 causing the flush to fail.

Change-Id: I742c7671bac92aeb8e9674c43d30c45b2de4a836
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: http://git-master/r/423842
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Alex Waterman
2014-06-16 12:41:24 -07:00
committed by Dan Willemsen
parent d46c8e4003
commit 2680d6be57

View File

@@ -14,6 +14,7 @@
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/jiffies.h>
#include "hw_ltc_gm20b.h" #include "hw_ltc_gm20b.h"
#include "hw_top_gm20b.h" #include "hw_top_gm20b.h"
@@ -256,6 +257,19 @@ u32 gm20b_ltc_cbc_fix_config(struct gk20a *g, int base)
void gm20b_flush_ltc(struct gk20a *g) void gm20b_flush_ltc(struct gk20a *g)
{ {
u32 op_pending; u32 op_pending;
unsigned long now, timeout;
#define __timeout_init() \
do { \
now = jiffies; timeout = now + HZ; \
} while (0)
#define __timeout_check() \
do { \
if (tegra_platform_is_silicon() && time_after(now, timeout)) { \
gk20a_err(dev_from_gk20a(g), "L2 flush timeout!"); \
break; \
} \
} while (0)
/* Clean... */ /* Clean... */
gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt1_r(), gk20a_writel(g, ltc_ltcs_ltss_tstg_cmgmt1_r(),
@@ -267,13 +281,17 @@ void gm20b_flush_ltc(struct gk20a *g)
ltc_ltcs_ltss_tstg_cmgmt1_clean_evict_first_class_true_f()); ltc_ltcs_ltss_tstg_cmgmt1_clean_evict_first_class_true_f());
/* Wait on each LTC individually. */ /* Wait on each LTC individually. */
__timeout_init();
do { do {
op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt1_r()); op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt1_r());
__timeout_check();
} while (op_pending & } while (op_pending &
ltc_ltc0_ltss_tstg_cmgmt1_clean_pending_f()); ltc_ltc0_ltss_tstg_cmgmt1_clean_pending_f());
__timeout_init();
do { do {
op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt1_r()); op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt1_r());
__timeout_check();
} while (op_pending & } while (op_pending &
ltc_ltc1_ltss_tstg_cmgmt1_clean_pending_f()); ltc_ltc1_ltss_tstg_cmgmt1_clean_pending_f());
@@ -286,13 +304,17 @@ void gm20b_flush_ltc(struct gk20a *g)
ltc_ltcs_ltss_tstg_cmgmt0_invalidate_evict_first_class_true_f()); ltc_ltcs_ltss_tstg_cmgmt0_invalidate_evict_first_class_true_f());
/* Wait on each LTC individually. */ /* Wait on each LTC individually. */
__timeout_init();
do { do {
op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt0_r()); op_pending = gk20a_readl(g, ltc_ltc0_ltss_tstg_cmgmt0_r());
__timeout_check();
} while (op_pending & } while (op_pending &
ltc_ltc0_ltss_tstg_cmgmt0_invalidate_pending_f()); ltc_ltc0_ltss_tstg_cmgmt0_invalidate_pending_f());
__timeout_init();
do { do {
op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt0_r()); op_pending = gk20a_readl(g, ltc_ltc1_ltss_tstg_cmgmt0_r());
__timeout_check();
} while (op_pending & } while (op_pending &
ltc_ltc1_ltss_tstg_cmgmt0_invalidate_pending_f()); ltc_ltc1_ltss_tstg_cmgmt0_invalidate_pending_f());
} }