summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/pramin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/pramin.c')
-rw-r--r--drivers/gpu/nvgpu/common/pramin.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/pramin.c b/drivers/gpu/nvgpu/common/pramin.c
new file mode 100644
index 00000000..9b04d5a3
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/pramin.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/pramin.h>
24#include <nvgpu/page_allocator.h>
25#include <nvgpu/enabled.h>
26
27#include "gk20a/gk20a.h"
28
29/*
30 * Flip this to force all gk20a_mem* accesses via PRAMIN from the start of the
31 * boot, even for buffers that would work via cpu_va. In runtime, the flag is
32 * in debugfs, called "force_pramin".
33 */
34#define GK20A_FORCE_PRAMIN_DEFAULT false
35
36/*
37 * The PRAMIN range is 1 MB, must change base addr if a buffer crosses that.
38 * This same loop is used for read/write/memset. Offset and size in bytes.
39 * One call to "loop" is done per range, with "arg" supplied.
40 */
41void nvgpu_pramin_access_batched(struct gk20a *g, struct nvgpu_mem *mem,
42 u32 offset, u32 size, pramin_access_batch_fn loop, u32 **arg)
43{
44 struct nvgpu_page_alloc *alloc = NULL;
45 struct nvgpu_sgt *sgt;
46 void *sgl;
47 u32 byteoff, start_reg, until_end, n;
48
49 /*
50 * TODO: Vidmem is not accesible through pramin on shutdown path.
51 * driver should be refactored to prevent this from happening, but for
52 * now it is ok just to ignore the writes
53 */
54 if (!gk20a_io_exists(g) && nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING))
55 return;
56
57 alloc = mem->vidmem_alloc;
58 sgt = &alloc->sgt;
59
60 nvgpu_sgt_for_each_sgl(sgl, sgt) {
61 if (offset >= nvgpu_sgt_get_length(sgt, sgl))
62 offset -= nvgpu_sgt_get_length(sgt, sgl);
63 else
64 break;
65 }
66
67 while (size) {
68 u32 sgl_len = (u32)nvgpu_sgt_get_length(sgt, sgl);
69
70 byteoff = g->ops.pramin.enter(g, mem, sgt, sgl,
71 offset / sizeof(u32));
72 start_reg = g->ops.pramin.data032_r(byteoff / sizeof(u32));
73 until_end = SZ_1M - (byteoff & (SZ_1M - 1));
74
75 n = min3(size, until_end, (u32)(sgl_len - offset));
76
77 loop(g, start_reg, n / sizeof(u32), arg);
78
79 /* read back to synchronize accesses */
80 gk20a_readl(g, start_reg);
81 g->ops.pramin.exit(g, mem, sgl);
82
83 size -= n;
84
85 if (n == (sgl_len - offset)) {
86 sgl = nvgpu_sgt_get_next(sgt, sgl);
87 offset = 0;
88 } else {
89 offset += n;
90 }
91 }
92}
93
94void nvgpu_init_pramin(struct mm_gk20a *mm)
95{
96 mm->pramin_window = 0;
97 nvgpu_spinlock_init(&mm->pramin_window_lock);
98 mm->force_pramin = GK20A_FORCE_PRAMIN_DEFAULT;
99}