From 2ad015f7a57af59864d650bb2eed1f74ad8a9c84 Mon Sep 17 00:00:00 2001 From: Vedashree Vidwans Date: Thu, 21 May 2020 16:06:04 -0700 Subject: [PATCH] gpu: nvgpu: modify nvgpu_writel check and loop Currently, nvgpu_writel_loop() writes to a register and immediately checks if register value is updated. It might take some time for hardware registers to get updated with value written by software. Modify nvgpu_writel_loop() to accept number of retries to check if register value is updated and assert with nvgpu_assert(). Also, move nvgpu_writel_loop() to common code and use generic nvgpu_readl() and nvgpu_writel() APIs. JIRA NVGPU-5490 Change-Id: Iaaf24203a91eee3d05de7d0c7dea18113367de5f Signed-off-by: Vedashree Vidwans Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2348628 Reviewed-by: automaticguardword Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: Vaibhav Kachore Reviewed-by: Deepak Nibade Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/io/io.c | 17 ++++++++++++++++- drivers/gpu/nvgpu/hal/gr/zbc/zbc_gp10b.c | 19 +++++++++++++------ drivers/gpu/nvgpu/include/nvgpu/io.h | 5 +++-- drivers/gpu/nvgpu/os/linux/linux-io.c | 18 +----------------- drivers/gpu/nvgpu/os/posix/posix-io.c | 5 ----- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/nvgpu/common/io/io.c b/drivers/gpu/nvgpu/common/io/io.c index 371e0e0aa..fb47520ac 100644 --- a/drivers/gpu/nvgpu/common/io/io.c +++ b/drivers/gpu/nvgpu/common/io/io.c @@ -23,6 +23,7 @@ #include #include #include +#include #include void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) @@ -34,6 +35,20 @@ void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) if (v != read_val) { nvgpu_err(g, "r=0x%x rd=0x%x wr=0x%x (mismatch)", r, read_val, v); - BUG_ON(1); + nvgpu_assert(v == read_val); } } + +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v, u32 retries) +{ + u32 reg_val = 0U; + + nvgpu_writel(g, r, v); + + do { + retries = nvgpu_safe_sub_u32(retries, 1U); + reg_val = nvgpu_readl(g, r); + } while ((reg_val != v) && (retries > 0U)); + + nvgpu_assert(reg_val == v); +} diff --git a/drivers/gpu/nvgpu/hal/gr/zbc/zbc_gp10b.c b/drivers/gpu/nvgpu/hal/gr/zbc/zbc_gp10b.c index 61c45c73e..ca2596e69 100644 --- a/drivers/gpu/nvgpu/hal/gr/zbc/zbc_gp10b.c +++ b/drivers/gpu/nvgpu/hal/gr/zbc/zbc_gp10b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,6 +28,8 @@ #include +#define NVGPU_WRITEL_LOOP_ZBC_RETRIES 20U + u32 gp10b_gr_zbc_get_gpcs_swdx_dss_zbc_c_format_reg(struct gk20a *g) { return gr_gpcs_swdx_dss_zbc_c_01_to_04_format_r(); @@ -46,18 +48,23 @@ int gp10b_gr_zbc_add_color(struct gk20a *g, g->ops.gr.zbc.get_gpcs_swdx_dss_zbc_c_format_reg(g); nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_r_r(index), - nvgpu_gr_zbc_get_entry_color_ds(color_val, 0)); + nvgpu_gr_zbc_get_entry_color_ds(color_val, 0), + NVGPU_WRITEL_LOOP_ZBC_RETRIES); nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_g_r(index), - nvgpu_gr_zbc_get_entry_color_ds(color_val, 1)); + nvgpu_gr_zbc_get_entry_color_ds(color_val, 1), + NVGPU_WRITEL_LOOP_ZBC_RETRIES); nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_b_r(index), - nvgpu_gr_zbc_get_entry_color_ds(color_val, 2)); + nvgpu_gr_zbc_get_entry_color_ds(color_val, 2), + NVGPU_WRITEL_LOOP_ZBC_RETRIES); nvgpu_writel_loop(g, gr_gpcs_swdx_dss_zbc_color_a_r(index), - nvgpu_gr_zbc_get_entry_color_ds(color_val, 3)); + nvgpu_gr_zbc_get_entry_color_ds(color_val, 3), + NVGPU_WRITEL_LOOP_ZBC_RETRIES); zbc_c = nvgpu_readl(g, zbc_c_format_reg + (index & ~3U)); zbc_c &= ~(0x7fU << ((index % 4U) * 7U)); zbc_c |= nvgpu_gr_zbc_get_entry_format(color_val) << ((index % 4U) * 7U); - nvgpu_writel_loop(g, zbc_c_format_reg + (index & ~3U), zbc_c); + nvgpu_writel_loop(g, zbc_c_format_reg + (index & ~3U), zbc_c, + NVGPU_WRITEL_LOOP_ZBC_RETRIES); return 0; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/io.h b/drivers/gpu/nvgpu/include/nvgpu/io.h index 90093d5e6..4e65bece8 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/io.h +++ b/drivers/gpu/nvgpu/include/nvgpu/io.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -118,13 +118,14 @@ void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v); * @param g [in] GPU super structure. * @param r [in] Register offset in GPU IO space. * @param v [in] Value to write at the offset. + * @param retries [in] Number of retries before failing. * * This is a blocking call. It keeps on writing a 32-bit value to a GPU * register and reads it back until read/write values are not match. * * @return None. */ -void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v); +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v, u32 retries); /** * @brief Write a value to an already mapped bar1 io-region. diff --git a/drivers/gpu/nvgpu/os/linux/linux-io.c b/drivers/gpu/nvgpu/os/linux/linux-io.c index efe4af28a..ad8769a55 100644 --- a/drivers/gpu/nvgpu/os/linux/linux-io.c +++ b/drivers/gpu/nvgpu/os/linux/linux-io.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2020, 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, @@ -75,22 +75,6 @@ u32 nvgpu_readl_impl(struct gk20a *g, u32 r) return v; } -void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) -{ - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - if (unlikely(!l->regs)) { - nvgpu_warn_on_no_regs(); - nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); - } else { - nvgpu_wmb(); - do { - writel_relaxed(v, l->regs + r); - } while (readl(l->regs + r) != v); - nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); - } -} - void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) { struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); diff --git a/drivers/gpu/nvgpu/os/posix/posix-io.c b/drivers/gpu/nvgpu/os/posix/posix-io.c index ce05b9e7b..2b969106a 100644 --- a/drivers/gpu/nvgpu/os/posix/posix-io.c +++ b/drivers/gpu/nvgpu/os/posix/posix-io.c @@ -107,11 +107,6 @@ u32 nvgpu_readl(struct gk20a *g, u32 r) return access.value; } -void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) -{ - BUG(); -} - u32 nvgpu_readl_impl(struct gk20a *g, u32 r) { struct nvgpu_posix_io_callbacks *callbacks =