diff options
author | Seema Khowala <seemaj@nvidia.com> | 2017-06-02 12:58:23 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-07-08 14:35:48 -0400 |
commit | aa05648fd6038b69d1ed841f33b24cf1875efd83 (patch) | |
tree | 8e9ee6c0f7b937f85b2caa4db70aebcd1e619944 /drivers/gpu/nvgpu/gv11b/mm_gv11b.c | |
parent | cf33b6c26bd054f5fe09be78ed754049821a8737 (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.c | 198 |
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 | ||
47 | static bool gv11b_mm_mmu_fault_pending(struct gk20a *g) | 55 | static 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; | 60 | static 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 | |||
76 | static 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 | |||
98 | static 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 | |||
135 | static 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 | |||
172 | static 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 | |||
182 | static 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 | |||
194 | static 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 | |||
215 | static 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 | ||
57 | void gv11b_mm_l2_flush(struct gk20a *g, bool invalidate) | 240 | void 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 | } |