diff options
author | David Nieto <dmartineznie@nvidia.com> | 2017-05-05 17:22:06 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-05-11 09:04:33 -0400 |
commit | 8c246cb18df28bac83297df2c9d0c47725b94273 (patch) | |
tree | f0bc4bdd963b14ccafc9c888dd65d3485bb9bf5b /drivers/gpu/nvgpu/gv11b/fb_gv11b.c | |
parent | 44dcc5a53fabc68a32f16a1a3a46a2582b5b192b (diff) |
gpu: nvgpu: gv11b: MMU parity HWW error intr
Adding support for ISR handling of ecc uncorrectable errors
for volta resiliency (Volta-686)
TODO: move interrupt init out of MC
bug 1881052
JIRA: GPUT19X-82
Change-Id: I45db01a6062445dd1f64a8297744cd15105e3344
Signed-off-by: David Nieto <dmartineznie@nvidia.com>
Reviewed-on: http://git-master/r/1476603
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b/fb_gv11b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/fb_gv11b.c | 136 |
1 files changed, 128 insertions, 8 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fb_gv11b.c b/drivers/gpu/nvgpu/gv11b/fb_gv11b.c index 98aad4e0..c3524953 100644 --- a/drivers/gpu/nvgpu/gv11b/fb_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/fb_gv11b.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <nvgpu/hw/gv11b/hw_mc_gv11b.h> | 27 | #include <nvgpu/hw/gv11b/hw_mc_gv11b.h> |
28 | #include <nvgpu/hw/gv11b/hw_fifo_gv11b.h> | 28 | #include <nvgpu/hw/gv11b/hw_fifo_gv11b.h> |
29 | 29 | ||
30 | #include <nvgpu/log.h> | ||
31 | |||
30 | static void gv11b_init_nvlink_soc_credits(struct gk20a *g) | 32 | static void gv11b_init_nvlink_soc_credits(struct gk20a *g) |
31 | { | 33 | { |
32 | void __iomem *soc1 = ioremap(0x02b10010, 4096); | 34 | void __iomem *soc1 = ioremap(0x02b10010, 4096); |
@@ -34,7 +36,7 @@ static void gv11b_init_nvlink_soc_credits(struct gk20a *g) | |||
34 | void __iomem *soc3 = ioremap(0x02b30010, 4096); | 36 | void __iomem *soc3 = ioremap(0x02b30010, 4096); |
35 | void __iomem *soc4 = ioremap(0x02b40010, 4096); | 37 | void __iomem *soc4 = ioremap(0x02b40010, 4096); |
36 | 38 | ||
37 | gk20a_dbg_info("init nvlink soc credits"); | 39 | nvgpu_info(g, "init nvlink soc credits"); |
38 | 40 | ||
39 | writel_relaxed(0x14050000, soc1); | 41 | writel_relaxed(0x14050000, soc1); |
40 | writel_relaxed(0x08020000, soc1 + 4); | 42 | writel_relaxed(0x08020000, soc1 + 4); |
@@ -51,7 +53,7 @@ static void gv11b_fb_reset(struct gk20a *g) | |||
51 | { | 53 | { |
52 | u32 val; | 54 | u32 val; |
53 | 55 | ||
54 | gk20a_dbg_info("reset gv11b fb"); | 56 | nvgpu_info(g, "reset gv11b fb"); |
55 | 57 | ||
56 | g->ops.mc.reset(g, mc_enable_pfb_enabled_f() | | 58 | g->ops.mc.reset(g, mc_enable_pfb_enabled_f() | |
57 | mc_enable_l2_enabled_f() | | 59 | mc_enable_l2_enabled_f() | |
@@ -69,14 +71,14 @@ static void gv11b_fb_reset(struct gk20a *g) | |||
69 | gv11b_init_nvlink_soc_credits(g); | 71 | gv11b_init_nvlink_soc_credits(g); |
70 | 72 | ||
71 | val = gk20a_readl(g, fifo_fb_iface_r()); | 73 | val = gk20a_readl(g, fifo_fb_iface_r()); |
72 | gk20a_dbg_info("fifo_fb_iface val = 0x%x", val); | 74 | nvgpu_info(g, "fifo_fb_iface val = 0x%x", val); |
73 | if (!(val & fifo_fb_iface_control_enable_f() && | 75 | if (!(val & fifo_fb_iface_control_enable_f() && |
74 | val & fifo_fb_iface_status_enabled_f())) { | 76 | val & fifo_fb_iface_status_enabled_f())) { |
75 | gk20a_dbg_info("fifo_fb_iface set control enable"); | 77 | nvgpu_info(g, "fifo_fb_iface set control enable"); |
76 | gk20a_writel(g, fifo_fb_iface_r(), | 78 | gk20a_writel(g, fifo_fb_iface_r(), |
77 | fifo_fb_iface_control_enable_f()); | 79 | fifo_fb_iface_control_enable_f()); |
78 | val = gk20a_readl(g, fifo_fb_iface_r()); | 80 | val = gk20a_readl(g, fifo_fb_iface_r()); |
79 | gk20a_dbg_info("fifo_fb_iface val = 0x%x", val); | 81 | nvgpu_info(g, "fifo_fb_iface val = 0x%x", val); |
80 | } | 82 | } |
81 | } | 83 | } |
82 | 84 | ||
@@ -129,19 +131,137 @@ static void gv11b_init_kind_attr(void) | |||
129 | } | 131 | } |
130 | } | 132 | } |
131 | 133 | ||
134 | static void gv11b_fb_intr_en_set(struct gk20a *g, | ||
135 | unsigned int index, u32 mask) | ||
136 | { | ||
137 | u32 reg_val; | ||
138 | |||
139 | reg_val = gk20a_readl(g, fb_niso_intr_en_set_r(index)); | ||
140 | reg_val |= mask; | ||
141 | gk20a_writel(g, fb_niso_intr_en_set_r(index), reg_val); | ||
142 | } | ||
143 | |||
144 | static void gv11b_fb_intr_en_clr(struct gk20a *g, | ||
145 | unsigned int index, u32 mask) | ||
146 | { | ||
147 | u32 reg_val; | ||
148 | |||
149 | reg_val = gk20a_readl(g, fb_niso_intr_en_clr_r(index)); | ||
150 | reg_val |= mask; | ||
151 | gk20a_writel(g, fb_niso_intr_en_clr_r(index), reg_val); | ||
152 | } | ||
153 | |||
154 | static u32 gv11b_fb_get_hub_intr_clr_mask(struct gk20a *g, | ||
155 | unsigned int intr_type) | ||
156 | { | ||
157 | u32 mask = 0; | ||
158 | |||
159 | if (intr_type == HUB_INTR_TYPE_ALL) { | ||
160 | mask |= | ||
161 | fb_niso_intr_en_clr_mmu_ecc_uncorrected_error_notify_set_f(); | ||
162 | return mask; | ||
163 | } | ||
164 | |||
165 | if (intr_type & HUB_INTR_TYPE_ECC_UNCORRECTED) { | ||
166 | mask |= | ||
167 | fb_niso_intr_en_clr_mmu_ecc_uncorrected_error_notify_set_f(); | ||
168 | } | ||
169 | |||
170 | return mask; | ||
171 | } | ||
172 | |||
173 | static u32 gv11b_fb_get_hub_intr_en_mask(struct gk20a *g, | ||
174 | unsigned int intr_type) | ||
175 | { | ||
176 | u32 mask = 0; | ||
177 | |||
178 | if (intr_type == HUB_INTR_TYPE_ALL) { | ||
179 | mask |= | ||
180 | fb_niso_intr_en_set_mmu_ecc_uncorrected_error_notify_set_f(); | ||
181 | return mask; | ||
182 | } | ||
183 | |||
184 | if (intr_type & HUB_INTR_TYPE_ECC_UNCORRECTED) { | ||
185 | mask |= | ||
186 | fb_niso_intr_en_set_mmu_ecc_uncorrected_error_notify_set_f(); | ||
187 | } | ||
188 | |||
189 | return mask; | ||
190 | } | ||
191 | |||
192 | void gv11b_fb_enable_hub_intr(struct gk20a *g, | ||
193 | unsigned int index, unsigned int intr_type) | ||
194 | { | ||
195 | u32 mask = 0; | ||
196 | |||
197 | mask = gv11b_fb_get_hub_intr_en_mask(g, intr_type); | ||
198 | |||
199 | if (mask) | ||
200 | gv11b_fb_intr_en_set(g, index, mask); | ||
201 | } | ||
202 | |||
203 | void gv11b_fb_disable_hub_intr(struct gk20a *g, | ||
204 | unsigned int index, unsigned int intr_type) | ||
205 | { | ||
206 | u32 mask = 0; | ||
207 | |||
208 | mask = gv11b_fb_get_hub_intr_clr_mask(g, intr_type); | ||
209 | |||
210 | if (mask) | ||
211 | gv11b_fb_intr_en_clr(g, index, mask); | ||
212 | } | ||
213 | |||
132 | static void gv11b_fb_hub_isr(struct gk20a *g) | 214 | static void gv11b_fb_hub_isr(struct gk20a *g) |
133 | { | 215 | { |
216 | u32 status; | ||
134 | u32 niso_intr = gk20a_readl(g, fb_niso_intr_r()); | 217 | u32 niso_intr = gk20a_readl(g, fb_niso_intr_r()); |
135 | 218 | ||
136 | gk20a_dbg_info("enter hub isr, niso_intr = 0x%x", niso_intr); | 219 | nvgpu_info(g, "enter hub isr, niso_intr = 0x%x", niso_intr); |
137 | 220 | ||
138 | if (niso_intr & | 221 | if (niso_intr & |
139 | (fb_niso_intr_hub_access_counter_notify_pending_f() | | 222 | (fb_niso_intr_hub_access_counter_notify_pending_f() | |
140 | fb_niso_intr_hub_access_counter_error_pending_f())) { | 223 | fb_niso_intr_hub_access_counter_error_pending_f())) { |
141 | 224 | ||
142 | gk20a_dbg_info("hub access counter notify/error"); | 225 | nvgpu_info(g, "hub access counter notify/error"); |
226 | } else if (niso_intr & | ||
227 | fb_niso_intr_mmu_ecc_uncorrected_error_notify_pending_f()) { | ||
228 | |||
229 | nvgpu_info(g, "ecc uncorrected error notify"); | ||
230 | |||
231 | /* disable interrupts during handling */ | ||
232 | gv11b_fb_disable_hub_intr(g, STALL_REG_INDEX, | ||
233 | HUB_INTR_TYPE_ECC_UNCORRECTED); | ||
234 | |||
235 | status = gk20a_readl(g, fb_mmu_l2tlb_ecc_status_r()); | ||
236 | if (status) { | ||
237 | nvgpu_info(g, "hub mmu L2 ecc status: 0x%x", | ||
238 | status); | ||
239 | gk20a_writel(g, fb_mmu_l2tlb_ecc_status_r(), | ||
240 | fb_mmu_l2tlb_ecc_status_reset_clear_f()); | ||
241 | } | ||
242 | |||
243 | status = gk20a_readl(g, fb_mmu_hubtlb_ecc_status_r()); | ||
244 | if (status) { | ||
245 | nvgpu_info(g, "hub mmu hub tlb ecc status: 0x%x", | ||
246 | status); | ||
247 | gk20a_writel(g, fb_mmu_hubtlb_ecc_status_r(), | ||
248 | fb_mmu_hubtlb_ecc_status_reset_clear_f()); | ||
249 | } | ||
250 | |||
251 | status = gk20a_readl(g, fb_mmu_fillunit_ecc_status_r()); | ||
252 | if (status) { | ||
253 | nvgpu_info(g, "hub mmu fill unit ecc status: 0x%x", | ||
254 | status); | ||
255 | gk20a_writel(g, fb_mmu_fillunit_ecc_status_r(), | ||
256 | fb_mmu_fillunit_ecc_status_reset_clear_f()); | ||
257 | } | ||
258 | |||
259 | /* re-enable interrupts after handling */ | ||
260 | gv11b_fb_enable_hub_intr(g, STALL_REG_INDEX, | ||
261 | HUB_INTR_TYPE_ECC_UNCORRECTED); | ||
262 | |||
143 | } else { | 263 | } else { |
144 | gk20a_dbg_info("mmu fault : TODO"); | 264 | nvgpu_info(g, "mmu fault : TODO"); |
145 | } | 265 | } |
146 | } | 266 | } |
147 | 267 | ||