summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/soc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/soc.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/soc.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/soc.c b/drivers/gpu/nvgpu/common/linux/soc.c
index 6a2bc7c0..22645381 100644
--- a/drivers/gpu/nvgpu/common/linux/soc.c
+++ b/drivers/gpu/nvgpu/common/linux/soc.c
@@ -13,8 +13,13 @@
13 13
14#include <soc/tegra/chip-id.h> 14#include <soc/tegra/chip-id.h>
15#include <soc/tegra/tegra_bpmp.h> 15#include <soc/tegra/tegra_bpmp.h>
16#ifdef CONFIG_TEGRA_HV_MANAGER
17#include <soc/tegra/virt/syscalls.h>
18#endif
16 19
17#include <nvgpu/soc.h> 20#include <nvgpu/soc.h>
21#include "os_linux.h"
22#include "platform_gk20a.h"
18 23
19bool nvgpu_platform_is_silicon(struct gk20a *g) 24bool nvgpu_platform_is_silicon(struct gk20a *g)
20{ 25{
@@ -40,3 +45,57 @@ bool nvgpu_is_bpmp_running(struct gk20a *g)
40{ 45{
41 return tegra_bpmp_running(); 46 return tegra_bpmp_running();
42} 47}
48
49#ifdef CONFIG_TEGRA_HV_MANAGER
50/* When nvlink is enabled on dGPU, we need to use physical memory addresses.
51 * There is no SMMU translation. However, the device initially enumerates as a
52 * PCIe device. As such, when allocation memory for this PCIe device, the DMA
53 * framework ends up allocating memory using SMMU (if enabled in device tree).
54 * As a result, when we switch to nvlink, we need to use underlying physical
55 * addresses, even if memory mappings exist in SMMU.
56 * In addition, when stage-2 SMMU translation is enabled (for instance when HV
57 * is enabled), the addresses we get from dma_alloc are IPAs. We need to
58 * convert them to PA.
59 */
60static u64 nvgpu_tegra_hv_ipa_pa(struct gk20a *g, u64 ipa)
61{
62 struct device *dev = dev_from_gk20a(g);
63 struct gk20a_platform *platform = gk20a_get_platform(dev);
64 struct hyp_ipa_pa_info info;
65 int err;
66 u64 pa = 0ULL;
67
68 err = hyp_read_ipa_pa_info(&info, platform->vmid, ipa);
69 if (err < 0) {
70 nvgpu_err(g, "ipa=%llx translation failed vmid=%u err=%d",
71 ipa, platform->vmid, err);
72 } else {
73 pa = info.base + info.offset;
74 nvgpu_log(g, gpu_dbg_map_v,
75 "ipa=%llx vmid=%d -> pa=%llx "
76 "base=%llx offset=%llx size=%llx\n",
77 ipa, platform->vmid, pa, info.base,
78 info.offset, info.size);
79 }
80 return pa;
81}
82#endif
83
84int nvgpu_init_soc_vars(struct gk20a *g)
85{
86#ifdef CONFIG_TEGRA_HV_MANAGER
87 struct device *dev = dev_from_gk20a(g);
88 struct gk20a_platform *platform = gk20a_get_platform(dev);
89 int err;
90
91 if (nvgpu_is_hypervisor_mode(g)) {
92 err = hyp_read_gid(&platform->vmid);
93 if (err) {
94 nvgpu_err(g, "failed to read vmid");
95 return err;
96 }
97 platform->phys_addr = nvgpu_tegra_hv_ipa_pa;
98 }
99#endif
100 return 0;
101}