diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/soc.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/soc.c | 59 |
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 | ||
19 | bool nvgpu_platform_is_silicon(struct gk20a *g) | 24 | bool 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 | */ | ||
60 | static 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 | |||
84 | int 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 | } | ||