Merge tag 'i3c/for-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / umc_v6_7.c
1 /*
2  * Copyright 2021 Advanced Micro Devices, Inc.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "umc_v6_7.h"
24 #include "amdgpu_ras.h"
25 #include "amdgpu_umc.h"
26 #include "amdgpu.h"
27
28 #include "umc/umc_6_7_0_offset.h"
29 #include "umc/umc_6_7_0_sh_mask.h"
30
31 const uint32_t
32         umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
33                 {28, 20, 24, 16, 12, 4, 8, 0},
34                 {6, 30, 2, 26, 22, 14, 18, 10},
35                 {19, 11, 15, 7, 3, 27, 31, 23},
36                 {9, 1, 5, 29, 25, 17, 21, 13}
37 };
38 const uint32_t
39         umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
40                 {19, 11, 15, 7, 3, 27, 31, 23},
41                 {9, 1, 5, 29, 25, 17, 21, 13},
42                 {28, 20, 24, 16, 12, 4, 8, 0},
43                 {6, 30, 2, 26, 22, 14, 18, 10},
44 };
45
46 static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev,
47                                               uint32_t umc_inst,
48                                               uint32_t ch_inst)
49 {
50         uint32_t index = umc_inst * adev->umc.channel_inst_num + ch_inst;
51
52         /* adjust umc and channel index offset,
53          * the register address is not linear on each umc instace */
54         umc_inst = index / 4;
55         ch_inst = index % 4;
56
57         return adev->umc.channel_offs * ch_inst + UMC_V6_7_INST_DIST * umc_inst;
58 }
59
60 static void umc_v6_7_query_error_status_helper(struct amdgpu_device *adev,
61                                                   uint64_t mc_umc_status, uint32_t umc_reg_offset)
62 {
63         uint32_t mc_umc_addr;
64         uint64_t reg_value;
65
66         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1)
67                 dev_info(adev->dev, "Deferred error, no user action is needed.\n");
68
69         if (mc_umc_status)
70                 dev_info(adev->dev, "MCA STATUS 0x%llx, umc_reg_offset 0x%x\n", mc_umc_status, umc_reg_offset);
71
72         /* print IPID registers value */
73         mc_umc_addr =
74                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_IPIDT0);
75         reg_value = RREG64_PCIE((mc_umc_addr + umc_reg_offset) * 4);
76         if (reg_value)
77                 dev_info(adev->dev, "MCA IPID 0x%llx, umc_reg_offset 0x%x\n", reg_value, umc_reg_offset);
78
79         /* print SYND registers value */
80         mc_umc_addr =
81                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_SYNDT0);
82         reg_value = RREG64_PCIE((mc_umc_addr + umc_reg_offset) * 4);
83         if (reg_value)
84                 dev_info(adev->dev, "MCA SYND 0x%llx, umc_reg_offset 0x%x\n", reg_value, umc_reg_offset);
85
86         /* print MISC0 registers value */
87         mc_umc_addr =
88                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_MISC0T0);
89         reg_value = RREG64_PCIE((mc_umc_addr + umc_reg_offset) * 4);
90         if (reg_value)
91                 dev_info(adev->dev, "MCA MISC0 0x%llx, umc_reg_offset 0x%x\n", reg_value, umc_reg_offset);
92 }
93
94 static void umc_v6_7_ecc_info_query_correctable_error_count(struct amdgpu_device *adev,
95                                                    uint32_t umc_inst, uint32_t ch_inst,
96                                                    unsigned long *error_count)
97 {
98         uint64_t mc_umc_status;
99         uint32_t eccinfo_table_idx;
100         uint32_t umc_reg_offset;
101         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
102
103         umc_reg_offset = get_umc_v6_7_reg_offset(adev,
104                                                 umc_inst, ch_inst);
105
106         eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
107         /* check for SRAM correctable error
108           MCUMC_STATUS is a 64 bit register */
109         mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
110         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
111             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) {
112                 *error_count += 1;
113
114                 umc_v6_7_query_error_status_helper(adev, mc_umc_status, umc_reg_offset);
115
116                 if (ras->umc_ecc.record_ce_addr_supported)      {
117                         uint64_t err_addr, soc_pa;
118                         uint32_t channel_index =
119                                 adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
120
121                         err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_ceumc_addr;
122                         err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
123                         /* translate umc channel address to soc pa, 3 parts are included */
124                         soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
125                                         ADDR_OF_256B_BLOCK(channel_index) |
126                                         OFFSET_IN_256B_BLOCK(err_addr);
127
128                         /* The umc channel bits are not original values, they are hashed */
129                         SET_CHANNEL_HASH(channel_index, soc_pa);
130
131                         dev_info(adev->dev, "Error Address(PA): 0x%llx\n", soc_pa);
132                 }
133         }
134 }
135
136 static void umc_v6_7_ecc_info_querry_uncorrectable_error_count(struct amdgpu_device *adev,
137                                                           uint32_t umc_inst, uint32_t ch_inst,
138                                                       unsigned long *error_count)
139 {
140         uint64_t mc_umc_status;
141         uint32_t eccinfo_table_idx;
142         uint32_t umc_reg_offset;
143         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
144
145         umc_reg_offset = get_umc_v6_7_reg_offset(adev,
146                                                 umc_inst, ch_inst);
147
148         eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
149         /* check the MCUMC_STATUS */
150         mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
151         if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
152             (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
153             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
154             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
155             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
156             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)) {
157                 *error_count += 1;
158
159                 umc_v6_7_query_error_status_helper(adev, mc_umc_status, umc_reg_offset);
160         }
161 }
162
163 static int umc_v6_7_ecc_info_querry_ecc_error_count(struct amdgpu_device *adev,
164                                         uint32_t node_inst, uint32_t umc_inst,
165                                         uint32_t ch_inst, void *data)
166 {
167         struct ras_err_data *err_data = (struct ras_err_data *)data;
168
169         umc_v6_7_ecc_info_query_correctable_error_count(adev,
170                 umc_inst, ch_inst,
171                 &(err_data->ce_count));
172
173         umc_v6_7_ecc_info_querry_uncorrectable_error_count(adev,
174                 umc_inst, ch_inst,
175                 &(err_data->ue_count));
176
177         return 0;
178 }
179
180 static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
181                                            void *ras_error_status)
182 {
183         amdgpu_umc_loop_channels(adev,
184                 umc_v6_7_ecc_info_querry_ecc_error_count, ras_error_status);
185 }
186
187 void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
188                                     struct ras_err_data *err_data, uint64_t err_addr,
189                                     uint32_t ch_inst, uint32_t umc_inst)
190 {
191         uint32_t channel_index;
192         uint64_t soc_pa, retired_page, column;
193
194         channel_index =
195                 adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
196         /* translate umc channel address to soc pa, 3 parts are included */
197         soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
198                         ADDR_OF_256B_BLOCK(channel_index) |
199                         OFFSET_IN_256B_BLOCK(err_addr);
200
201         /* The umc channel bits are not original values, they are hashed */
202         SET_CHANNEL_HASH(channel_index, soc_pa);
203
204         /* clear [C4 C3 C2] in soc physical address */
205         soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT);
206
207         /* loop for all possibilities of [C4 C3 C2] */
208         for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) {
209                 retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT);
210                 dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
211                 amdgpu_umc_fill_error_record(err_data, err_addr,
212                         retired_page, channel_index, umc_inst);
213
214                 /* shift R14 bit */
215                 retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT);
216                 dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
217                 amdgpu_umc_fill_error_record(err_data, err_addr,
218                         retired_page, channel_index, umc_inst);
219         }
220 }
221
222 static int umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev,
223                                         uint32_t node_inst, uint32_t umc_inst,
224                                         uint32_t ch_inst, void *data)
225 {
226         uint64_t mc_umc_status, err_addr;
227         uint32_t eccinfo_table_idx;
228         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
229         struct ras_err_data *err_data = (struct ras_err_data *)data;
230
231         eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
232         mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
233
234         if (mc_umc_status == 0)
235                 return 0;
236
237         if (!err_data->err_addr)
238                 return 0;
239
240         /* calculate error address if ue error is detected */
241         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
242             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
243
244                 err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr;
245                 err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
246
247                 umc_v6_7_convert_error_address(adev, err_data, err_addr,
248                                         ch_inst, umc_inst);
249         }
250
251         return 0;
252 }
253
254 static void umc_v6_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev,
255                                              void *ras_error_status)
256 {
257         amdgpu_umc_loop_channels(adev,
258             umc_v6_7_ecc_info_query_error_address, ras_error_status);
259 }
260
261 static void umc_v6_7_query_correctable_error_count(struct amdgpu_device *adev,
262                                                    uint32_t umc_reg_offset,
263                                                    unsigned long *error_count,
264                                                    uint32_t ch_inst,
265                                                    uint32_t umc_inst)
266 {
267         uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
268         uint32_t ecc_err_cnt, ecc_err_cnt_addr;
269         uint64_t mc_umc_status;
270         uint32_t mc_umc_status_addr;
271
272         /* UMC 6_1_1 registers */
273         ecc_err_cnt_sel_addr =
274                 SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_EccErrCntSel);
275         ecc_err_cnt_addr =
276                 SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_EccErrCnt);
277         mc_umc_status_addr =
278                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
279
280         /* select the lower chip and check the error count */
281         ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
282         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
283                                         EccErrCntCsSel, 0);
284         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
285
286         ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
287         *error_count +=
288                 (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
289                  UMC_V6_7_CE_CNT_INIT);
290
291         /* select the higher chip and check the err counter */
292         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
293                                         EccErrCntCsSel, 1);
294         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
295
296         ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
297         *error_count +=
298                 (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
299                  UMC_V6_7_CE_CNT_INIT);
300
301         /* check for SRAM correctable error
302           MCUMC_STATUS is a 64 bit register */
303         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
304         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
305             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) {
306                 *error_count += 1;
307
308                 umc_v6_7_query_error_status_helper(adev, mc_umc_status, umc_reg_offset);
309
310                 {
311                         uint64_t err_addr, soc_pa;
312                         uint32_t mc_umc_addrt0;
313                         uint32_t channel_index;
314
315                         mc_umc_addrt0 =
316                                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
317
318                         channel_index =
319                                 adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
320
321                         err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
322                         err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
323
324                         /* translate umc channel address to soc pa, 3 parts are included */
325                         soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
326                                         ADDR_OF_256B_BLOCK(channel_index) |
327                                         OFFSET_IN_256B_BLOCK(err_addr);
328
329                         /* The umc channel bits are not original values, they are hashed */
330                         SET_CHANNEL_HASH(channel_index, soc_pa);
331
332                         dev_info(adev->dev, "Error Address(PA): 0x%llx\n", soc_pa);
333                 }
334         }
335 }
336
337 static void umc_v6_7_querry_uncorrectable_error_count(struct amdgpu_device *adev,
338                                                       uint32_t umc_reg_offset,
339                                                       unsigned long *error_count)
340 {
341         uint64_t mc_umc_status;
342         uint32_t mc_umc_status_addr;
343
344         mc_umc_status_addr =
345                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
346
347         /* check the MCUMC_STATUS */
348         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
349         if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
350             (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
351             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
352             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
353             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
354             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)) {
355                 *error_count += 1;
356
357                 umc_v6_7_query_error_status_helper(adev, mc_umc_status, umc_reg_offset);
358         }
359 }
360
361 static int umc_v6_7_reset_error_count_per_channel(struct amdgpu_device *adev,
362                                         uint32_t node_inst, uint32_t umc_inst,
363                                         uint32_t ch_inst, void *data)
364 {
365         uint32_t ecc_err_cnt_addr;
366         uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
367         uint32_t umc_reg_offset =
368                 get_umc_v6_7_reg_offset(adev, umc_inst, ch_inst);
369
370         ecc_err_cnt_sel_addr =
371                 SOC15_REG_OFFSET(UMC, 0,
372                                 regUMCCH0_0_EccErrCntSel);
373         ecc_err_cnt_addr =
374                 SOC15_REG_OFFSET(UMC, 0,
375                                 regUMCCH0_0_EccErrCnt);
376
377         /* select the lower chip */
378         ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
379                                        umc_reg_offset) * 4);
380         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
381                                         UMCCH0_0_EccErrCntSel,
382                                         EccErrCntCsSel, 0);
383         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
384                         ecc_err_cnt_sel);
385
386         /* clear lower chip error count */
387         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
388                         UMC_V6_7_CE_CNT_INIT);
389
390         /* select the higher chip */
391         ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
392                                         umc_reg_offset) * 4);
393         ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
394                                         UMCCH0_0_EccErrCntSel,
395                                         EccErrCntCsSel, 1);
396         WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
397                         ecc_err_cnt_sel);
398
399         /* clear higher chip error count */
400         WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
401                         UMC_V6_7_CE_CNT_INIT);
402
403         return 0;
404 }
405
406 static void umc_v6_7_reset_error_count(struct amdgpu_device *adev)
407 {
408         amdgpu_umc_loop_channels(adev,
409                 umc_v6_7_reset_error_count_per_channel, NULL);
410 }
411
412 static int umc_v6_7_query_ecc_error_count(struct amdgpu_device *adev,
413                                         uint32_t node_inst, uint32_t umc_inst,
414                                         uint32_t ch_inst, void *data)
415 {
416         struct ras_err_data *err_data = (struct ras_err_data *)data;
417         uint32_t umc_reg_offset =
418                 get_umc_v6_7_reg_offset(adev, umc_inst, ch_inst);
419
420         umc_v6_7_query_correctable_error_count(adev,
421                                         umc_reg_offset,
422                                         &(err_data->ce_count),
423                                         ch_inst, umc_inst);
424
425         umc_v6_7_querry_uncorrectable_error_count(adev,
426                                         umc_reg_offset,
427                                         &(err_data->ue_count));
428
429         return 0;
430 }
431
432 static void umc_v6_7_query_ras_error_count(struct amdgpu_device *adev,
433                                            void *ras_error_status)
434 {
435         amdgpu_umc_loop_channels(adev,
436                 umc_v6_7_query_ecc_error_count, ras_error_status);
437
438         umc_v6_7_reset_error_count(adev);
439 }
440
441 static int umc_v6_7_query_error_address(struct amdgpu_device *adev,
442                                         uint32_t node_inst, uint32_t umc_inst,
443                                         uint32_t ch_inst, void *data)
444 {
445         uint32_t mc_umc_status_addr;
446         uint64_t mc_umc_status = 0, mc_umc_addrt0, err_addr;
447         struct ras_err_data *err_data = (struct ras_err_data *)data;
448         uint32_t umc_reg_offset =
449                 get_umc_v6_7_reg_offset(adev, umc_inst, ch_inst);
450
451         mc_umc_status_addr =
452                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
453         mc_umc_addrt0 =
454                 SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
455
456         mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
457
458         if (mc_umc_status == 0)
459                 return 0;
460
461         if (!err_data->err_addr) {
462                 /* clear umc status */
463                 WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
464                 return 0;
465         }
466
467         /* calculate error address if ue error is detected */
468         if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
469             REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
470                 err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
471                 err_addr =
472                         REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
473
474                 umc_v6_7_convert_error_address(adev, err_data, err_addr,
475                                         ch_inst, umc_inst);
476         }
477
478         /* clear umc status */
479         WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
480
481         return 0;
482 }
483
484 static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
485                                              void *ras_error_status)
486 {
487         amdgpu_umc_loop_channels(adev,
488                 umc_v6_7_query_error_address, ras_error_status);
489 }
490
491 static uint32_t umc_v6_7_query_ras_poison_mode_per_channel(
492                                                 struct amdgpu_device *adev,
493                                                 uint32_t umc_reg_offset)
494 {
495         uint32_t ecc_ctrl_addr, ecc_ctrl;
496
497         ecc_ctrl_addr =
498                 SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_EccCtrl);
499         ecc_ctrl = RREG32_PCIE((ecc_ctrl_addr +
500                                         umc_reg_offset) * 4);
501
502         return REG_GET_FIELD(ecc_ctrl, UMCCH0_0_EccCtrl, UCFatalEn);
503 }
504
505 static bool umc_v6_7_query_ras_poison_mode(struct amdgpu_device *adev)
506 {
507         uint32_t umc_reg_offset  = 0;
508
509         /* Enabling fatal error in umc instance0 channel0 will be
510          * considered as fatal error mode
511          */
512         umc_reg_offset = get_umc_v6_7_reg_offset(adev, 0, 0);
513         return !umc_v6_7_query_ras_poison_mode_per_channel(adev, umc_reg_offset);
514 }
515
516 const struct amdgpu_ras_block_hw_ops umc_v6_7_ras_hw_ops = {
517         .query_ras_error_count = umc_v6_7_query_ras_error_count,
518         .query_ras_error_address = umc_v6_7_query_ras_error_address,
519 };
520
521 struct amdgpu_umc_ras umc_v6_7_ras = {
522         .ras_block = {
523                 .hw_ops = &umc_v6_7_ras_hw_ops,
524         },
525         .query_ras_poison_mode = umc_v6_7_query_ras_poison_mode,
526         .ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count,
527         .ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address,
528 };