summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gv11b/mm_gv11b.c
diff options
context:
space:
mode:
authorSeema Khowala <seemaj@nvidia.com>2017-06-02 12:58:23 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-07-08 14:35:48 -0400
commitaa05648fd6038b69d1ed841f33b24cf1875efd83 (patch)
tree8e9ee6c0f7b937f85b2caa4db70aebcd1e619944 /drivers/gpu/nvgpu/gv11b/mm_gv11b.c
parentcf33b6c26bd054f5fe09be78ed754049821a8737 (diff)
gpu: nvgpu: gv11b: set up for enabling/handling hub intr
-implement mm ops init_mm_setup_hw This will also call *fault*setup* that will do s/w and h/w set up required to get mmu fault info -implement s/w set up for copying mmu faults Two shadow fault buffers are pre allocated which will be used to copy fault info. One for copying from fault snap registers/nonreplayable h/w fault buffers and one for replay h/w fault buffers -implement s/w set up for buffering mmu faults Replayable/Non-replayable fault buffers are mapped in BAR2 virtual/physical address space. These buffers are circular buffers in terms of address calculation. Currently there are num host channels buffers -configure h/w for buffering mmu faults if s/w set up is successful, configure h/w registers to enable buffered mode of mmu faults -if both s/w and h/w set up are successful, enable corresponding hub interrupts -implement new ops, fault_info_buf_deinit This will be called during gk20a_mm_destroy to disable hub intr and de-allocate shadow fault buf that is used to copy mmu fault info during mmu fault handling -implement mm ops remove_bar2_vm This will also unmap and free fault buffers mapped in BAR2 if fault buffers were allocated JIRA GPUT19X-7 JIRA GPUT19X-12 Change-Id: I53a38eddbb0a50a1f2024600583f2aae1f1fba6d Signed-off-by: Seema Khowala <seemaj@nvidia.com> Reviewed-on: https://git-master/r/1492682 Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b/mm_gv11b.c')
-rw-r--r--drivers/gpu/nvgpu/gv11b/mm_gv11b.c198
1 files changed, 192 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/mm_gv11b.c b/drivers/gpu/nvgpu/gv11b/mm_gv11b.c
index cc8dafa3..d6184cee 100644
--- a/drivers/gpu/nvgpu/gv11b/mm_gv11b.c
+++ b/drivers/gpu/nvgpu/gv11b/mm_gv11b.c
@@ -15,13 +15,21 @@
15 15
16#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
17 17
18#include <nvgpu/kmem.h>
19#include <nvgpu/dma.h>
20#include <nvgpu/log.h>
21
18#include "gk20a/gk20a.h" 22#include "gk20a/gk20a.h"
23#include "gk20a/mm_gk20a.h"
19 24
20#include "gp10b/mm_gp10b.h" 25#include "gp10b/mm_gp10b.h"
26#include "gp10b/mc_gp10b.h"
21 27
22#include "mm_gv11b.h" 28#include "mm_gv11b.h"
29#include "fb_gv11b.h"
23 30
24#include <nvgpu/hw/gv11b/hw_fb_gv11b.h> 31#include <nvgpu/hw/gv11b/hw_fb_gv11b.h>
32#include <nvgpu/hw/gv11b/hw_gmmu_gv11b.h>
25 33
26#define NVGPU_L3_ALLOC_BIT 36 34#define NVGPU_L3_ALLOC_BIT 36
27 35
@@ -46,12 +54,187 @@ static void gv11b_init_inst_block(struct nvgpu_mem *inst_block,
46 54
47static bool gv11b_mm_mmu_fault_pending(struct gk20a *g) 55static bool gv11b_mm_mmu_fault_pending(struct gk20a *g)
48{ 56{
49 if (gk20a_readl(g, fb_niso_intr_r()) & 57 return gv11b_fb_mmu_fault_pending(g);
50 (fb_niso_intr_mmu_nonreplayable_fault_notify_pending_f() | 58}
51 fb_niso_intr_mmu_nonreplayable_fault_overflow_pending_f()))
52 return true;
53 59
54 return false; 60static void gv11b_mm_fault_info_mem_destroy(struct gk20a *g)
61{
62 nvgpu_mutex_acquire(&g->mm.hub_isr_mutex);
63
64 gv11b_fb_disable_hub_intr(g, STALL_REG_INDEX, HUB_INTR_TYPE_OTHER |
65 HUB_INTR_TYPE_NONREPLAY | HUB_INTR_TYPE_REPLAY);
66
67 nvgpu_kfree(g, g->mm.fault_info[FAULT_TYPE_OTHER_AND_NONREPLAY]);
68
69 g->mm.fault_info[FAULT_TYPE_OTHER_AND_NONREPLAY] = NULL;
70 g->mm.fault_info[FAULT_TYPE_REPLAY] = NULL;
71
72 nvgpu_mutex_release(&g->mm.hub_isr_mutex);
73 nvgpu_mutex_destroy(&g->mm.hub_isr_mutex);
74}
75
76static int gv11b_mm_mmu_fault_info_buf_init(struct gk20a *g,
77 u32 *hub_intr_types)
78{
79 struct mmu_fault_info *fault_info_mem;
80
81 fault_info_mem = nvgpu_kzalloc(g, sizeof(struct mmu_fault_info) *
82 FAULT_TYPE_NUM);
83 if (!fault_info_mem) {
84 nvgpu_log_info(g, "failed to alloc shadow fault info");
85 return -ENOMEM;
86 }
87 /* shadow buffer for copying mmu fault info */
88 g->mm.fault_info[FAULT_TYPE_OTHER_AND_NONREPLAY] =
89 &fault_info_mem[FAULT_TYPE_OTHER_AND_NONREPLAY];
90
91 g->mm.fault_info[FAULT_TYPE_REPLAY] =
92 &fault_info_mem[FAULT_TYPE_REPLAY];
93
94 *hub_intr_types |= HUB_INTR_TYPE_OTHER;
95 return 0;
96}
97
98static void gv11b_mm_mmu_hw_fault_buf_init(struct gk20a *g,
99 u32 *hub_intr_types)
100{
101 struct vm_gk20a *vm = g->mm.bar2.vm;
102 int err = 0;
103 size_t fb_size;
104
105 /* Max entries take care of 1 entry used for full detection */
106 fb_size = (g->ops.fifo.get_num_fifos(g) + 1) *
107 gmmu_fault_buf_size_v();
108
109 err = nvgpu_dma_alloc_map_sys(vm, fb_size,
110 &g->mm.hw_fault_buf[FAULT_TYPE_OTHER_AND_NONREPLAY]);
111 if (err) {
112 nvgpu_err(g,
113 "Error in hw mmu fault buf [0] alloc in bar2 vm ");
114 /* Fault will be snapped in pri reg but not in buffer */
115 return;
116 }
117
118 g->mm.hw_fault_buf_status[NONREPLAY_REG_INDEX] =
119 HW_FAULT_BUF_STATUS_ALLOC_TRUE;
120 *hub_intr_types |= HUB_INTR_TYPE_NONREPLAY;
121
122 err = nvgpu_dma_alloc_map_sys(vm, fb_size,
123 &g->mm.hw_fault_buf[FAULT_TYPE_REPLAY]);
124 if (err) {
125 nvgpu_err(g,
126 "Error in hw mmu fault buf [1] alloc in bar2 vm ");
127 /* Fault will be snapped in pri reg but not in buffer */
128 return;
129 }
130 g->mm.hw_fault_buf_status[REPLAY_REG_INDEX] =
131 HW_FAULT_BUF_STATUS_ALLOC_TRUE;
132 *hub_intr_types |= HUB_INTR_TYPE_REPLAY;
133}
134
135static void gv11b_mm_mmu_hw_fault_buf_deinit(struct gk20a *g)
136{
137 struct vm_gk20a *vm = g->mm.bar2.vm;
138
139 gv11b_fb_disable_hub_intr(g, STALL_REG_INDEX, HUB_INTR_TYPE_NONREPLAY |
140 HUB_INTR_TYPE_REPLAY);
141
142 g->mm.hub_intr_types &= (~(HUB_INTR_TYPE_NONREPLAY |
143 HUB_INTR_TYPE_REPLAY));
144
145 if ((gv11b_fb_is_fault_buf_enabled(g, NONREPLAY_REG_INDEX))) {
146 gv11b_fb_fault_buf_set_state_hw(g, NONREPLAY_REG_INDEX,
147 FAULT_BUF_DISABLED);
148 }
149
150 if ((gv11b_fb_is_fault_buf_enabled(g, REPLAY_REG_INDEX))) {
151 gv11b_fb_fault_buf_set_state_hw(g, REPLAY_REG_INDEX,
152 FAULT_BUF_DISABLED);
153 }
154
155 if (g->mm.hw_fault_buf_status[NONREPLAY_REG_INDEX] ==
156 HW_FAULT_BUF_STATUS_ALLOC_TRUE) {
157 nvgpu_dma_unmap_free(vm,
158 &g->mm.hw_fault_buf[FAULT_TYPE_OTHER_AND_NONREPLAY]);
159 g->mm.hw_fault_buf_status[NONREPLAY_REG_INDEX] =
160 HW_FAULT_BUF_STATUS_ALLOC_FALSE;
161 }
162
163 if (g->mm.hw_fault_buf_status[REPLAY_REG_INDEX] ==
164 HW_FAULT_BUF_STATUS_ALLOC_TRUE) {
165 nvgpu_dma_unmap_free(vm,
166 &g->mm.hw_fault_buf[FAULT_TYPE_REPLAY]);
167 g->mm.hw_fault_buf_status[REPLAY_REG_INDEX] =
168 HW_FAULT_BUF_STATUS_ALLOC_FALSE;
169 }
170}
171
172static void gv11b_mm_remove_bar2_vm(struct gk20a *g)
173{
174 struct mm_gk20a *mm = &g->mm;
175
176 gv11b_mm_mmu_hw_fault_buf_deinit(g);
177
178 gk20a_free_inst_block(g, &mm->bar2.inst_block);
179 nvgpu_vm_put(mm->bar2.vm);
180}
181
182static void gv11b_mm_mmu_fault_setup_hw(struct gk20a *g)
183{
184 if (g->mm.hw_fault_buf_status[NONREPLAY_REG_INDEX] ==
185 HW_FAULT_BUF_STATUS_ALLOC_TRUE) {
186 gv11b_fb_fault_buf_configure_hw(g, NONREPLAY_REG_INDEX);
187 }
188 if (g->mm.hw_fault_buf_status[REPLAY_REG_INDEX] ==
189 HW_FAULT_BUF_STATUS_ALLOC_TRUE) {
190 gv11b_fb_fault_buf_configure_hw(g, REPLAY_REG_INDEX);
191 }
192}
193
194static int gv11b_mm_mmu_fault_setup_sw(struct gk20a *g)
195{
196 int err;
197
198 nvgpu_mutex_init(&g->mm.hub_isr_mutex);
199
200 g->mm.hw_fault_buf_status[NONREPLAY_REG_INDEX] =
201 HW_FAULT_BUF_STATUS_ALLOC_FALSE;
202 g->mm.hw_fault_buf_status[REPLAY_REG_INDEX] =
203 HW_FAULT_BUF_STATUS_ALLOC_FALSE;
204
205 g->mm.hub_intr_types = HUB_INTR_TYPE_ECC_UNCORRECTED;
206
207 err = gv11b_mm_mmu_fault_info_buf_init(g, &g->mm.hub_intr_types);
208
209 if (!err)
210 gv11b_mm_mmu_hw_fault_buf_init(g, &g->mm.hub_intr_types);
211
212 return err;
213}
214
215static int gv11b_init_mm_setup_hw(struct gk20a *g)
216{
217 int err = 0;
218
219 nvgpu_log_fn(g, "start");
220
221 g->ops.fb.set_mmu_page_size(g);
222 g->ops.fb.init_hw(g);
223
224 err = g->ops.mm.init_bar2_mm_hw_setup(g);
225 if (err)
226 return err;
227
228 if (gk20a_mm_fb_flush(g) || gk20a_mm_fb_flush(g))
229 return -EBUSY;
230
231 err = gv11b_mm_mmu_fault_setup_sw(g);
232 if (!err)
233 gv11b_mm_mmu_fault_setup_hw(g);
234
235 nvgpu_log_fn(g, "end");
236
237 return err;
55} 238}
56 239
57void gv11b_mm_l2_flush(struct gk20a *g, bool invalidate) 240void gv11b_mm_l2_flush(struct gk20a *g, bool invalidate)
@@ -82,8 +265,11 @@ void gv11b_init_mm(struct gpu_ops *gops)
82 gp10b_init_mm(gops); 265 gp10b_init_mm(gops);
83 gops->mm.is_bar1_supported = gv11b_mm_is_bar1_supported; 266 gops->mm.is_bar1_supported = gv11b_mm_is_bar1_supported;
84 gops->mm.init_inst_block = gv11b_init_inst_block; 267 gops->mm.init_inst_block = gv11b_init_inst_block;
85 gops->mm.init_mm_setup_hw = gk20a_init_mm_setup_hw;
86 gops->mm.mmu_fault_pending = gv11b_mm_mmu_fault_pending; 268 gops->mm.mmu_fault_pending = gv11b_mm_mmu_fault_pending;
87 gops->mm.l2_flush = gv11b_mm_l2_flush; 269 gops->mm.l2_flush = gv11b_mm_l2_flush;
88 gops->mm.gpu_phys_addr = gv11b_gpu_phys_addr; 270 gops->mm.gpu_phys_addr = gv11b_gpu_phys_addr;
271 gops->mm.init_mm_setup_hw = gv11b_init_mm_setup_hw;
272 gops->mm.fault_info_mem_destroy =
273 gv11b_mm_fault_info_mem_destroy;
274 gops->mm.remove_bar2_vm = gv11b_mm_remove_bar2_vm;
89} 275}