mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
193 lines
6.2 KiB
C
193 lines
6.2 KiB
C
/*
|
|
* Copyright (c) 2019, 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"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include <unit/unit.h>
|
|
#include <unit/io.h>
|
|
#include <nvgpu/posix/io.h>
|
|
#include <nvgpu/posix/posix-fault-injection.h>
|
|
|
|
#include <nvgpu/gk20a.h>
|
|
#include <nvgpu/io.h>
|
|
#include <nvgpu/nvgpu_init.h>
|
|
#include "hal/mc/mc_gp10b.h"
|
|
#include "hal/fb/fb_gm20b.h"
|
|
#include "hal/fb/fb_gv11b.h"
|
|
#include "hal/fb/intr/fb_intr_gv11b.h"
|
|
#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
|
|
|
|
#include "fb_fusa.h"
|
|
|
|
#define TEST_REG_VALUE 0x8080A0A0
|
|
|
|
int fb_gm20b_tlb_invalidate_test(struct unit_module *m, struct gk20a *g,
|
|
void *args)
|
|
{
|
|
int err;
|
|
struct nvgpu_mem pdb = {0};
|
|
struct nvgpu_posix_fault_inj *timer_fi =
|
|
nvgpu_timers_get_fault_injection();
|
|
|
|
/* Define the operations being tested in this unit test */
|
|
g->ops.fb.tlb_invalidate = gm20b_fb_tlb_invalidate;
|
|
|
|
/* Setup PDB */
|
|
pdb.aperture = APERTURE_SYSMEM;
|
|
|
|
/* First NVGPU is powered off */
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != 0) {
|
|
unit_return_fail(m, "tlb_invalidate failed (1)\n");
|
|
}
|
|
|
|
/* Set NVGPU as powered on */
|
|
g->power_on_state = NVGPU_STATE_POWERED_ON;
|
|
|
|
/* Timeout init fault injection (MMU FIFO space) */
|
|
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"tlb_invalidate did not fail as expected (1)\n");
|
|
}
|
|
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
|
|
|
|
/* Timeout fail on fb_mmu_ctrl_r() read */
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"tlb_invalidate did not fail as expected (2)\n");
|
|
}
|
|
|
|
/*
|
|
* Prevent timeout on fb_mmu_ctrl_r() by setting a non-zero value in
|
|
* the fb_mmu_ctrl_pri_fifo_space_v field.
|
|
*/
|
|
nvgpu_writel(g, fb_mmu_ctrl_r(), 1 << 16U);
|
|
|
|
/* Timeout init fault injection (MMU invalidate) */
|
|
nvgpu_posix_enable_fault_injection(timer_fi, true, 1);
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"tlb_invalidate did not fail as expected (3)\n");
|
|
}
|
|
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
|
|
|
|
/*
|
|
* Timeout on fb_mmu_ctrl_r read after MMU invalidate (does not return
|
|
* a failure)
|
|
*/
|
|
helper_intercept_mmu_write(0);
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != 0) {
|
|
unit_return_fail(m, "tlb_invalidate failed (2)\n");
|
|
}
|
|
|
|
/* Success */
|
|
nvgpu_writel(g, fb_mmu_ctrl_r(), 1 << 16U);
|
|
helper_intercept_mmu_write(1 << 15U);
|
|
err = g->ops.fb.tlb_invalidate(g, &pdb);
|
|
if (err != 0) {
|
|
unit_return_fail(m, "tlb_invalidate failed (3)\n");
|
|
}
|
|
|
|
return UNIT_SUCCESS;
|
|
}
|
|
|
|
int fb_gm20b_mmu_ctrl_test(struct unit_module *m, struct gk20a *g, void *args)
|
|
{
|
|
int err;
|
|
u64 wpr_base, wpr_size;
|
|
struct nvgpu_posix_fault_inj *timer_fi =
|
|
nvgpu_timers_get_fault_injection();
|
|
|
|
/* Define the operations being tested in this unit test */
|
|
g->ops.fb.mmu_ctrl = gm20b_fb_mmu_ctrl;
|
|
g->ops.fb.mmu_debug_ctrl = gm20b_fb_mmu_debug_ctrl;
|
|
g->ops.fb.mmu_debug_wr = gm20b_fb_mmu_debug_wr;
|
|
g->ops.fb.mmu_debug_rd = gm20b_fb_mmu_debug_rd;
|
|
g->ops.fb.vpr_info_fetch = gm20b_fb_vpr_info_fetch;
|
|
g->ops.fb.dump_vpr_info = gm20b_fb_dump_vpr_info;
|
|
g->ops.fb.dump_wpr_info = gm20b_fb_dump_wpr_info;
|
|
g->ops.fb.read_wpr_info = gm20b_fb_read_wpr_info;
|
|
|
|
/* g->ops.mmu_ctrl must return the value in fb_mmu_ctrl_r */
|
|
nvgpu_writel(g, fb_mmu_ctrl_r(), TEST_REG_VALUE);
|
|
if (g->ops.fb.mmu_ctrl(g) != TEST_REG_VALUE) {
|
|
unit_return_fail(m, "ops.mmu_ctrl: incorrect value\n");
|
|
}
|
|
|
|
/* g->ops.mmu_debug_ctrl must return the value in fb_mmu_debug_ctrl_r */
|
|
nvgpu_writel(g, fb_mmu_debug_ctrl_r(), TEST_REG_VALUE);
|
|
if (g->ops.fb.mmu_debug_ctrl(g) != TEST_REG_VALUE) {
|
|
unit_return_fail(m, "ops.mmu_debug_ctrl: incorrect value\n");
|
|
}
|
|
|
|
/* g->ops.mmu_debug_wr must return the value in fb_mmu_debug_wr_r */
|
|
nvgpu_writel(g, fb_mmu_debug_wr_r(), TEST_REG_VALUE);
|
|
if (g->ops.fb.mmu_debug_wr(g) != TEST_REG_VALUE) {
|
|
unit_return_fail(m, "ops.mmu_debug_wr: incorrect value\n");
|
|
}
|
|
|
|
/* g->ops.mmu_debug_rd must return the value in fb_mmu_debug_rd_r */
|
|
nvgpu_writel(g, fb_mmu_debug_rd_r(), TEST_REG_VALUE);
|
|
if (g->ops.fb.mmu_debug_rd(g) != TEST_REG_VALUE) {
|
|
unit_return_fail(m, "ops.mmu_debug_rd: incorrect value\n");
|
|
}
|
|
|
|
/* For code coverage, run the VPR/WPR dump ops */
|
|
g->ops.fb.dump_vpr_info(g);
|
|
g->ops.fb.dump_wpr_info(g);
|
|
g->ops.fb.read_wpr_info(g, &wpr_base, &wpr_size);
|
|
g->ops.fb.vpr_info_fetch(g);
|
|
|
|
/* Error injection for g->ops.fb.vpr_info_fetch */
|
|
nvgpu_posix_enable_fault_injection(timer_fi, true, 0);
|
|
err = g->ops.fb.vpr_info_fetch(g);
|
|
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"vpr_info_fetch did not fail as expected (1)\n");
|
|
}
|
|
|
|
nvgpu_posix_enable_fault_injection(timer_fi, true, 1);
|
|
err = g->ops.fb.vpr_info_fetch(g);
|
|
nvgpu_posix_enable_fault_injection(timer_fi, false, 0);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"vpr_info_fetch did not fail as expected (2)\n");
|
|
}
|
|
|
|
/*
|
|
* Trigger timeout in the gm20b_fb_vpr_info_fetch_wait function on
|
|
* fb_mmu_vpr_info_fetch_v(val) == fb_mmu_vpr_info_fetch_false_v()
|
|
*/
|
|
nvgpu_writel(g, fb_mmu_vpr_info_r(), 1 << 2U);
|
|
err = g->ops.fb.vpr_info_fetch(g);
|
|
if (err != -ETIMEDOUT) {
|
|
unit_return_fail(m,
|
|
"vpr_info_fetch did not fail as expected (3)\n");
|
|
}
|
|
|
|
return UNIT_SUCCESS;
|
|
}
|