diff --git a/drivers/gpu/nvgpu/common/io/io.c b/drivers/gpu/nvgpu/common/io/io.c index e77771596..2f541c370 100644 --- a/drivers/gpu/nvgpu/common/io/io.c +++ b/drivers/gpu/nvgpu/common/io/io.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2021, 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"), @@ -24,6 +24,114 @@ #include #include #include +#include + +static void nvgpu_warn_on_no_regs(struct gk20a *g) +{ + nvgpu_warn(g, "Attempted access to GPU regs after unmapping!"); +} + +void nvgpu_writel(struct gk20a *g, u32 r, u32 v) +{ + if (unlikely(!g->regs)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); + } else { + nvgpu_os_writel(v, g->regs + r); + nvgpu_wmb(); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); + } +} + +#ifdef CONFIG_NVGPU_DGPU +void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v) +{ + if (unlikely(!g->regs)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); + } else { + nvgpu_os_writel_relaxed(v, g->regs + r); + } +} +#endif + +u32 nvgpu_readl(struct gk20a *g, u32 r) +{ + u32 v = nvgpu_readl_impl(g, r); + + if (v == 0xffffffff) + nvgpu_check_gpu_state(g); + + return v; +} + +u32 nvgpu_readl_impl(struct gk20a *g, u32 r) +{ + u32 v = 0xffffffff; + + if (unlikely(!g->regs)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); + } else { + v = nvgpu_os_readl(g->regs + r); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); + } + + return v; +} + +#ifdef CONFIG_NVGPU_NON_FUSA +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) +{ + if (unlikely(!g->regs)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); + } else { + nvgpu_wmb(); + do { + nvgpu_os_writel(v, g->regs + r); + } while (nvgpu_os_readl(g->regs + r) != v); + nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); + } +} +#endif + +void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) +{ + if (unlikely(!g->bar1)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); + } else { + nvgpu_wmb(); + nvgpu_os_writel(v, g->bar1 + b); + nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x", b, v); + } +} + +u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) +{ + u32 v = 0xffffffff; + + if (unlikely(!g->bar1)) { + nvgpu_warn_on_no_regs(g); + nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); + } else { + v = nvgpu_os_readl(g->bar1 + b); + nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x", b, v); + } + + return v; +} + +bool nvgpu_io_exists(struct gk20a *g) +{ + return g->regs != 0U; +} + +bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) +{ + return r < g->regs_size; +} void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) { diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 6483dff50..489ae1c3f 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -336,6 +336,22 @@ struct gk20a { */ void (*gfree)(struct gk20a *g); + /** Starting virtual address of mapped bar0 io region. */ + uintptr_t regs; + u64 regs_size; + u64 regs_bus_addr; + + /** Starting virtual address of mapped bar1 io region. */ + uintptr_t bar1; + + /** Starting virtual address of usermode registers io region. */ + uintptr_t usermode_regs; + u64 usermode_regs_bus_addr; + + uintptr_t regs_saved; + uintptr_t bar1_saved; + uintptr_t usermode_regs_saved; + /** * Handle to access nvhost APIs. */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/io.h b/drivers/gpu/nvgpu/include/nvgpu/io.h index e9cda7e82..de53b825c 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/io.h +++ b/drivers/gpu/nvgpu/include/nvgpu/io.h @@ -24,6 +24,44 @@ #include +/** + * @brief Read a value from a register. + * + * @param addr [in] Register cpu virtual address. + * + * Read a 32-bit value from the register cpu virtuall address. + * OS layer much implement this function. + * + * @return Value of the given register. + */ +u32 nvgpu_os_readl(uintptr_t addr); +/** + * @brief Write a value to a register with an ordering constraint. + * + * @param v [in] Value to write at the offset. + * @param addr [in] Register cpu virtual address. + * + * Write a 32-bit value to the register cpu virtual address with an + * ordering constraint on memory operations. + * OS layer much implement this function. + * + * @return None. + */ +void nvgpu_os_writel(u32 v, uintptr_t addr); +/** + * @brief Write a value to a register without an ordering constraint. + * + * @param v [in] Value to write at the offset. + * @param addr [in] Register cpu virtual address. + * + * Write a 32-bit value to the register cpu virtual address without an + * ordering constraint on memory operations. + * OS layer much implement this function. + * + * @return None. + */ +void nvgpu_os_writel_relaxed(u32 v, uintptr_t addr); + /** * @file * @@ -65,8 +103,7 @@ void nvgpu_writel(struct gk20a *g, u32 r, u32 v); * @param v [in] Value to write at the offset. * * Write a 32-bit value to register offset in GPU IO space without - * an ordering constraint on memory operations. This function is - * implemented by the OS layer. + * an ordering constraint on memory operations. * * @return None. */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/io.h b/drivers/gpu/nvgpu/include/nvgpu/posix/io.h index 4e82dd985..07b5f1963 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/posix/io.h +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/io.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2021, 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"), @@ -72,6 +72,18 @@ struct nvgpu_posix_io_callbacks *nvgpu_posix_register_io( struct gk20a *g, struct nvgpu_posix_io_callbacks *io_callbacks); +/** + * The high 4 bits of the register mapped address are used for identify which + * register aperture it tries to access. + * In nvgpu_os_writel/readl, it uses the high 4 bits to call different + * callbacks, like nvgpu_readl/writel or nvgpu_bar1_readl/writel. + */ +#define NVGPU_POSIX_REG_SHIFT 60 +#define NVGPU_POSIX_REG_MASK 0xfULL +#define NVGPU_POSIX_REG_BAR0 1ULL +#define NVGPU_POSIX_REG_BAR1 2ULL +#define NVGPU_POSIX_REG_USERMODE 3ULL + struct nvgpu_posix_io_reg_space { u32 base; u32 size; diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/probe.h b/drivers/gpu/nvgpu/include/nvgpu/posix/probe.h index 0b823fe6a..71a71ac06 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/posix/probe.h +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/probe.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2021, 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"), @@ -36,6 +36,7 @@ struct gk20a; +struct gk20a *nvgpu_posix_current_device(void); struct gk20a *nvgpu_posix_probe(void); void nvgpu_posix_cleanup(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 5e44ad529..1f1daf957 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -82,8 +82,8 @@ static void nvgpu_init_vars(struct gk20a *g) nvgpu_mutex_init(&l->ctrl_privs_lock); nvgpu_init_list_node(&l->ctrl_privs); - l->regs_saved = l->regs; - l->bar1_saved = l->bar1; + g->regs_saved = g->regs; + g->bar1_saved = g->bar1; g->emc3d_ratio = EMC3D_DEFAULT_RATIO; diff --git a/drivers/gpu/nvgpu/os/linux/io_usermode.c b/drivers/gpu/nvgpu/os/linux/io_usermode.c index 9132b372e..b851f176b 100644 --- a/drivers/gpu/nvgpu/os/linux/io_usermode.c +++ b/drivers/gpu/nvgpu/os/linux/io_usermode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2021, 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, @@ -19,9 +19,8 @@ void nvgpu_usermode_writel(struct gk20a *g, u32 r, u32 v) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - void __iomem *reg = l->usermode_regs + (r - g->ops.usermode.base(g)); + uintptr_t reg = g->usermode_regs + (r - g->ops.usermode.base(g)); - writel_relaxed(v, reg); + nvgpu_os_writel_relaxed(v, reg); nvgpu_log(g, gpu_dbg_reg, "usermode r=0x%x v=0x%x", r, v); } diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 16770d021..a5d5a4dbe 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -2278,7 +2278,7 @@ int gk20a_ctrl_dev_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); err = io_remap_pfn_range(vma, vma->vm_start, - l->usermode_regs_bus_addr >> PAGE_SHIFT, + g->usermode_regs_bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); if (!err) { priv->usermode_vma.vma = vma; @@ -2297,7 +2297,6 @@ static void alter_usermode_mapping(struct gk20a *g, struct gk20a_ctrl_priv *priv, bool poweroff) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct vm_area_struct *vma = priv->usermode_vma.vma; bool vma_mapped = priv->usermode_vma.vma_mapped; int err; @@ -2335,7 +2334,7 @@ static void alter_usermode_mapping(struct gk20a *g, } else if (!poweroff && !vma_mapped) { vma->vm_flags = priv->usermode_vma.flags; err = io_remap_pfn_range(vma, vma->vm_start, - l->usermode_regs_bus_addr >> PAGE_SHIFT, + g->usermode_regs_bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); if (err != 0) { nvgpu_err(g, "can't restore usermode mapping"); diff --git a/drivers/gpu/nvgpu/os/linux/linux-io.c b/drivers/gpu/nvgpu/os/linux/linux-io.c index efe4af28a..8613950c9 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-2021, 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, @@ -12,125 +12,20 @@ */ #include -#include -#include -#include #include "os_linux.h" -static void nvgpu_warn_on_no_regs(void) +u32 nvgpu_os_readl(uintptr_t addr) { - WARN_ONCE(true, "Attempted access to GPU regs after unmapping!"); + return readl((void __iomem *)addr); } -void nvgpu_writel(struct gk20a *g, u32 r, u32 v) +void nvgpu_os_writel(u32 v, uintptr_t addr) { - 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 { - writel_relaxed(v, l->regs + r); - nvgpu_wmb(); - nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); - } + writel(v, (void __iomem *)addr); } -void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v) +void nvgpu_os_writel_relaxed(u32 v, uintptr_t addr) { - 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 { - writel_relaxed(v, l->regs + r); - } -} - -u32 nvgpu_readl(struct gk20a *g, u32 r) -{ - u32 v = nvgpu_readl_impl(g, r); - - if (v == 0xffffffff) - nvgpu_check_gpu_state(g); - - return v; -} - -u32 nvgpu_readl_impl(struct gk20a *g, u32 r) -{ - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - u32 v = 0xffffffff; - - 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 { - v = readl(l->regs + r); - nvgpu_log(g, gpu_dbg_reg, "r=0x%x v=0x%x", r, v); - } - - 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); - - if (unlikely(!l->bar1)) { - nvgpu_warn_on_no_regs(); - nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); - } else { - nvgpu_wmb(); - writel_relaxed(v, l->bar1 + b); - nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x", b, v); - } -} - -u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) -{ - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - u32 v = 0xffffffff; - - if (unlikely(!l->bar1)) { - nvgpu_warn_on_no_regs(); - nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); - } else { - v = readl(l->bar1 + b); - nvgpu_log(g, gpu_dbg_reg, "b=0x%x v=0x%x", b, v); - } - - return v; -} - -bool nvgpu_io_exists(struct gk20a *g) -{ - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - return l->regs != NULL; -} - -bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) -{ - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - return r < resource_size(l->regs); + writel_relaxed(v, (void __iomem *)addr); } diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 610a5c9d0..88b104d30 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -229,10 +229,8 @@ void gk20a_idle(struct gk20a *g) */ static int gk20a_restore_registers(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - l->regs = l->regs_saved; - l->bar1 = l->bar1_saved; + g->regs = g->regs_saved; + g->bar1 = g->bar1_saved; nvgpu_restore_usermode_registers(g); @@ -547,10 +545,8 @@ done: */ static int gk20a_lockout_registers(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - l->regs = NULL; - l->bar1 = NULL; + g->regs = 0U; + g->bar1 = 0U; nvgpu_lockout_usermode_registers(g); @@ -1014,37 +1010,41 @@ static int gk20a_init_support(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gk20a *g = get_gk20a(dev); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); + void __iomem *addr; int err = -ENOMEM; #ifdef CONFIG_NVGPU_VPR tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); #endif - l->regs = nvgpu_devm_ioremap_resource(pdev, + addr = nvgpu_devm_ioremap_resource(pdev, GK20A_BAR0_IORESOURCE_MEM, &l->reg_mem); - if (IS_ERR(l->regs)) { + if (IS_ERR(addr)) { nvgpu_err(g, "failed to remap gk20a registers"); - err = PTR_ERR(l->regs); + err = PTR_ERR(addr); goto fail; } + g->regs = (uintptr_t)addr; + g->regs_size = resource_size(l->reg_mem); - l->regs_bus_addr = nvgpu_resource_addr(pdev, + g->regs_bus_addr = nvgpu_resource_addr(pdev, GK20A_BAR0_IORESOURCE_MEM); - if (!l->regs_bus_addr) { + if (!g->regs_bus_addr) { nvgpu_err(g, "failed to read register bus offset"); err = -ENODEV; goto fail; } - l->bar1 = nvgpu_devm_ioremap_resource(pdev, + addr = nvgpu_devm_ioremap_resource(pdev, GK20A_BAR1_IORESOURCE_MEM, &l->bar1_mem); - if (IS_ERR(l->bar1)) { + if (IS_ERR(addr)) { nvgpu_err(g, "failed to remap gk20a bar1"); - err = PTR_ERR(l->bar1); + err = PTR_ERR(addr); goto fail; } + g->bar1 = (uintptr_t)addr; err = nvgpu_init_sim_support_linux(g, pdev); if (err) @@ -1059,11 +1059,11 @@ static int gk20a_init_support(struct platform_device *pdev) fail_sim: nvgpu_remove_sim_support_linux(g); fail: - if (l->regs) - l->regs = NULL; + if (g->regs) + g->regs = 0U; - if (l->bar1) - l->bar1 = NULL; + if (g->bar1) + g->bar1 = 0U; return err; } diff --git a/drivers/gpu/nvgpu/os/linux/module_usermode.c b/drivers/gpu/nvgpu/os/linux/module_usermode.c index 2babce43f..073518991 100644 --- a/drivers/gpu/nvgpu/os/linux/module_usermode.c +++ b/drivers/gpu/nvgpu/os/linux/module_usermode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2021, 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, @@ -27,9 +27,7 @@ */ void nvgpu_lockout_usermode_registers(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - l->usermode_regs = NULL; + g->usermode_regs = 0U; } /* @@ -37,33 +35,27 @@ void nvgpu_lockout_usermode_registers(struct gk20a *g) */ void nvgpu_restore_usermode_registers(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - l->usermode_regs = l->usermode_regs_saved; + g->usermode_regs = g->usermode_regs_saved; } void nvgpu_remove_usermode_support(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - - if (l->usermode_regs) { - l->usermode_regs = NULL; + if (g->usermode_regs) { + g->usermode_regs = 0U; } } void nvgpu_init_usermode_support(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - if (g->ops.usermode.base == NULL) { return; } - if (l->usermode_regs == NULL) { - l->usermode_regs = l->regs + g->ops.usermode.bus_base(g); - l->usermode_regs_saved = l->usermode_regs; + if (g->usermode_regs == 0U) { + g->usermode_regs = g->regs + g->ops.usermode.bus_base(g); + g->usermode_regs_saved = g->usermode_regs; } - l->usermode_regs_bus_addr = l->regs_bus_addr + + g->usermode_regs_bus_addr = g->regs_bus_addr + g->ops.usermode.bus_base(g); } diff --git a/drivers/gpu/nvgpu/os/linux/os_linux.h b/drivers/gpu/nvgpu/os/linux/os_linux.h index 439f907ea..329a29d0f 100644 --- a/drivers/gpu/nvgpu/os/linux/os_linux.h +++ b/drivers/gpu/nvgpu/os/linux/os_linux.h @@ -96,17 +96,7 @@ struct nvgpu_os_linux { struct workqueue_struct *nonstall_work_queue; struct resource *reg_mem; - void __iomem *regs; - void __iomem *regs_saved; - u64 regs_bus_addr; - struct resource *bar1_mem; - void __iomem *bar1; - void __iomem *bar1_saved; - - void __iomem *usermode_regs; - void __iomem *usermode_regs_saved; - u64 usermode_regs_bus_addr; struct nvgpu_os_linux_ops ops; diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index b1e72528a..6484dfbc8 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c @@ -354,31 +354,34 @@ static int nvgpu_pci_init_support(struct pci_dev *pdev) { int err = 0; struct gk20a *g = get_gk20a(&pdev->dev); - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct device *dev = &pdev->dev; + void __iomem *addr; - l->regs = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 0), + addr = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (IS_ERR(l->regs)) { + if (IS_ERR(addr)) { nvgpu_err(g, "failed to remap gk20a registers"); - err = PTR_ERR(l->regs); + err = PTR_ERR(addr); goto fail; } + g->regs = (uintptr_t)addr; + g->regs_size = pci_resource_len(pdev, 0); - l->regs_bus_addr = pci_resource_start(pdev, 0); - if (!l->regs_bus_addr) { + g->regs_bus_addr = pci_resource_start(pdev, 0); + if (!g->regs_bus_addr) { nvgpu_err(g, "failed to read register bus offset"); err = -ENODEV; goto fail; } - l->bar1 = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 1), + addr = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); - if (IS_ERR(l->bar1)) { + if (IS_ERR(addr)) { nvgpu_err(g, "failed to remap gk20a bar1"); - err = PTR_ERR(l->bar1); + err = PTR_ERR(addr); goto fail; } + g->bar1 = (uintptr_t)addr; err = nvgpu_init_sim_support_linux_pci(g); if (err) @@ -392,11 +395,11 @@ static int nvgpu_pci_init_support(struct pci_dev *pdev) fail_sim: nvgpu_remove_sim_support_linux_pci(g); fail: - if (l->regs) - l->regs = NULL; + if (g->regs) + g->regs = 0U; - if (l->bar1) - l->bar1 = NULL; + if (g->bar1) + g->bar1 = 0U; return err; } diff --git a/drivers/gpu/nvgpu/os/linux/sim_pci.c b/drivers/gpu/nvgpu/os/linux/sim_pci.c index 9ff72f935..ef55f447c 100644 --- a/drivers/gpu/nvgpu/os/linux/sim_pci.c +++ b/drivers/gpu/nvgpu/os/linux/sim_pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2021, 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,7 +75,6 @@ void nvgpu_remove_sim_support_linux_pci(struct gk20a *g) int nvgpu_init_sim_support_linux_pci(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct sim_nvgpu_linux *sim_linux; int err = -ENOMEM; bool is_simulation; @@ -91,7 +90,7 @@ int nvgpu_init_sim_support_linux_pci(struct gk20a *g) return err; g->sim = &sim_linux->sim; g->sim->g = g; - sim_linux->regs = l->regs + sim_r(); + sim_linux->regs = (void __iomem *)g->regs + sim_r(); sim_linux->remove_support_linux = nvgpu_remove_sim_support_linux_pci; return 0; diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c b/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c index ba0bdfec8..f6afb3c99 100644 --- a/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c @@ -33,7 +33,6 @@ int gv11b_vgpu_probe(struct device *dev) struct gk20a_platform *platform = dev_get_drvdata(dev); struct resource *r; void __iomem *regs; - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(platform->g); struct gk20a *g = platform->g; #ifdef CONFIG_TEGRA_GK20A_NVHOST int ret; @@ -49,14 +48,14 @@ int gv11b_vgpu_probe(struct device *dev) nvgpu_err(g, "failed to map usermode regs"); return PTR_ERR(regs); } - l->usermode_regs = regs; + g->usermode_regs = (uintptr_t)regs; - l->usermode_regs_bus_addr = r->start; + g->usermode_regs_bus_addr = r->start; #ifdef CONFIG_TEGRA_GK20A_NVHOST ret = nvgpu_get_nvhost_dev(g); if (ret) { - l->usermode_regs = NULL; + g->usermode_regs = 0U; return ret; } diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c index 5665eb012..c154c5886 100644 --- a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c +++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c @@ -72,15 +72,13 @@ struct vgpu_priv_data *vgpu_get_priv_data(struct gk20a *g) static void vgpu_remove_support(struct gk20a *g) { - struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - vgpu_remove_support_common(g); /* free mappings to registers, etc*/ - if (l->bar1) { - iounmap(l->bar1); - l->bar1 = NULL; + if (g->bar1) { + iounmap((void __iomem *)g->bar1); + g->bar1 = 0U; } } @@ -101,8 +99,8 @@ static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) nvgpu_mutex_init(&l->ctrl_privs_lock); nvgpu_init_list_node(&l->ctrl_privs); - l->regs_saved = l->regs; - l->bar1_saved = l->bar1; + g->regs_saved = g->regs; + g->bar1_saved = g->bar1; nvgpu_atomic_set(&g->clk_arb_global_nr, 0); @@ -140,7 +138,7 @@ static int vgpu_init_support(struct platform_device *pdev) err = PTR_ERR(regs); goto fail; } - l->bar1 = regs; + g->bar1 = (uintptr_t)regs; l->bar1_mem = r; } diff --git a/drivers/gpu/nvgpu/os/posix/nvgpu.c b/drivers/gpu/nvgpu/os/posix/nvgpu.c index 0331223bf..c16d027ea 100644 --- a/drivers/gpu/nvgpu/os/posix/nvgpu.c +++ b/drivers/gpu/nvgpu/os/posix/nvgpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2021, 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"), @@ -218,6 +218,12 @@ static void nvgpu_posix_load_regs(struct gk20a *g) } } +static __thread struct gk20a *g_saved; +struct gk20a *nvgpu_posix_current_device(void) +{ + return g_saved; +} + /* * This function aims to initialize enough stuff to make unit testing worth * while. There are several interfaces and APIs that rely on the struct gk20a's @@ -251,6 +257,12 @@ struct gk20a *nvgpu_posix_probe(void) g->log_mask = NVGPU_DEFAULT_DBG_MASK; g->mm.g = g; + g_saved = g; + + g->regs = NVGPU_POSIX_REG_BAR0 << NVGPU_POSIX_REG_SHIFT; + g->bar1 = NVGPU_POSIX_REG_BAR1 << NVGPU_POSIX_REG_SHIFT; + g->usermode_regs = NVGPU_POSIX_REG_USERMODE << NVGPU_POSIX_REG_SHIFT; + if (nvgpu_kmem_init(g) != 0) { goto fail_kmem; } diff --git a/drivers/gpu/nvgpu/os/posix/posix-io.c b/drivers/gpu/nvgpu/os/posix/posix-io.c index 202193acc..078ee02b7 100644 --- a/drivers/gpu/nvgpu/os/posix/posix-io.c +++ b/drivers/gpu/nvgpu/os/posix/posix-io.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2021, 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"), @@ -26,6 +26,7 @@ #include #include +#include #include "os_posix.h" @@ -59,7 +60,7 @@ struct nvgpu_posix_io_callbacks *nvgpu_posix_register_io( return old_io; } -void nvgpu_writel(struct gk20a *g, u32 r, u32 v) +static void nvgpu_posix_writel(struct gk20a *g, u32 r, u32 v) { struct nvgpu_posix_io_callbacks *callbacks = nvgpu_os_posix_from_gk20a(g)->callbacks; @@ -76,14 +77,7 @@ void nvgpu_writel(struct gk20a *g, u32 r, u32 v) callbacks->writel(g, &access); } -#ifdef CONFIG_NVGPU_DGPU -void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v) -{ - nvgpu_writel(g, r, v); -} -#endif - -u32 nvgpu_readl(struct gk20a *g, u32 r) +static u32 nvgpu_posix_readl(struct gk20a *g, u32 r) { struct nvgpu_posix_io_callbacks *callbacks = nvgpu_os_posix_from_gk20a(g)->callbacks; @@ -109,33 +103,7 @@ u32 nvgpu_readl(struct gk20a *g, u32 r) return access.value; } -#ifdef CONFIG_NVGPU_NON_FUSA -void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) -{ - BUG(); -} -#endif - -u32 nvgpu_readl_impl(struct gk20a *g, u32 r) -{ - struct nvgpu_posix_io_callbacks *callbacks = - nvgpu_os_posix_from_gk20a(g)->callbacks; - - struct nvgpu_reg_access access = { - .addr = r, - .value = 0L - }; - - if (callbacks == NULL || callbacks->__readl == NULL) { - BUG(); - } - - callbacks->__readl(g, &access); - - return access.value; -} - -void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) +static void nvgpu_posix_bar1_writel(struct gk20a *g, u32 b, u32 v) { struct nvgpu_posix_io_callbacks *callbacks = nvgpu_os_posix_from_gk20a(g)->callbacks; @@ -152,7 +120,7 @@ void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) callbacks->bar1_writel(g, &access); } -u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) +static u32 nvgpu_posix_bar1_readl(struct gk20a *g, u32 b) { struct nvgpu_posix_io_callbacks *callbacks = nvgpu_os_posix_from_gk20a(g)->callbacks; @@ -188,14 +156,44 @@ void nvgpu_usermode_writel(struct gk20a *g, u32 r, u32 v) callbacks->usermode_writel(g, &access); } -bool nvgpu_io_exists(struct gk20a *g) +u32 nvgpu_os_readl(uintptr_t addr) { - return false; + struct gk20a *g = nvgpu_posix_current_device(); + u32 r, type; + + r = (u32)(addr & ~(NVGPU_POSIX_REG_MASK << NVGPU_POSIX_REG_SHIFT)); + type = (u32)(addr >> NVGPU_POSIX_REG_SHIFT); + switch (type) { + case NVGPU_POSIX_REG_BAR0: + return nvgpu_posix_readl(g, r); + case NVGPU_POSIX_REG_BAR1: + return nvgpu_posix_bar1_readl(g, r); + default: + BUG(); + } } -bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) +void nvgpu_os_writel(u32 v, uintptr_t addr) { - return false; + struct gk20a *g = nvgpu_posix_current_device(); + u32 r; + u64 type; + + r = (u32)(addr & ~(NVGPU_POSIX_REG_MASK << NVGPU_POSIX_REG_SHIFT)); + type = addr >> NVGPU_POSIX_REG_SHIFT; + switch (type) { + case NVGPU_POSIX_REG_BAR0: + return nvgpu_posix_writel(g, r, v); + case NVGPU_POSIX_REG_BAR1: + return nvgpu_posix_bar1_writel(g, r, v); + default: + BUG(); + } +} + +void nvgpu_os_writel_relaxed(u32 v, uintptr_t addr) +{ + nvgpu_os_writel(v, addr); } void nvgpu_posix_io_init_reg_space(struct gk20a *g)